summaryrefslogtreecommitdiff
path: root/lib/libcurses/base/MKlib_gen.sh
blob: ad30cb2b1499b0399742fc5860ff78dfd7333338 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
#!/bin/sh
#
# MKlib_gen.sh -- generate sources from curses.h macro definitions
#
# $OpenBSD: MKlib_gen.sh,v 1.3 2001/01/22 18:01:36 millert Exp $
# ($From: MKlib_gen.sh,v 1.13 2000/12/10 00:30:25 tom Exp $)
#
# The XSI Curses standard requires all curses entry points to exist as
# functions, even though many definitions would normally be shadowed
# by macros.  Rather than hand-hack all that code, we actually
# generate functions from the macros.
#
# This script accepts a file of prototypes on standard input.  It discards
# any that don't have a `generated' comment attached. It then parses each
# prototype (relying on the fact that none of the macros take function 
# pointer or array arguments) and generates C source from it.
#
# Here is what the pipeline stages are doing:
#
# 1. sed: extract prototypes of generated functions
# 2. sed: decorate prototypes with generated arguments a1. a2,...z
# 3. awk: generate the calls with args matching the formals 
# 4. sed: prefix function names in prototypes so the preprocessor won't expand
#         them.
# 5. cpp: macro-expand the file so the macro calls turn into C calls
# 6. awk: strip the expansion junk off the front and add the new header
# 7. sed: squeeze spaces, strip off gen_ prefix, create needed #undef
#

preprocessor="$1 -I../include"
AWK="$2"
ED1=sed1$$.sed
ED2=sed2$$.sed
ED3=sed3$$.sed
AW1=awk1$$.awk
TMP=gen$$.c
trap "rm -f $ED1 $ED2 $ED3 $AW1 $TMP" 0 1 2 5 15

(cat <<EOF
#include <ncurses_cfg.h>
#include <curses.h>

DECLARATIONS

EOF
cat >$ED1 <<EOF1
/^extern.*generated/{
	h
	s/^.*generated:\([^ 	*]*\).*/P_#if_USE_\1_SUPPORT/p
	g
	s/^extern \([^;]*\);.*/\1/p
	g
	s/^.*generated:\([^ 	*]*\).*/P_#endif/p
}
EOF1

cat >$ED2 <<EOF2
/^P_/b nc
/(void)/b nc
	s/,/ a1% /
	s/,/ a2% /
	s/,/ a3% /
	s/,/ a4% /
	s/,/ a5% /
	s/,/ a6% /
	s/,/ a7% /
	s/,/ a8% /
	s/,/ a9% /
	s/,/ a10% /
	s/,/ a11% /
	s/,/ a12% /
	s/,/ a13% /
	s/,/ a14% /
	s/,/ a15% /
	s/*/ * /g
	s/%/ , /g
	s/)/ z)/
:nc
	/(/s// ( /
	s/)/ )/
EOF2

cat >$ED3 <<EOF3
/^P_/{
	s/^P_#if_/#if /
	s/^P_//
	b done
}
	s/		*/ /g
	s/  */ /g
	s/ ,/,/g
	s/ )/)/g
	s/ gen_/ /
	s/^M_/#undef /
	/^%%/s//	/
:done
EOF3

cat >$AW1 <<\EOF1
BEGIN	{
		skip=0;
	}
	/^P_#if/ {
		print "\n"
		print $0
		skip=0;
	}
	/^P_#endif/ {
		print $0
		skip=1;
	}
	$0 !~ /^P_/ {
	if (skip)
		print "\n"
	skip=1;

	if ( $1 == "chtype" ) {
		returnType = "Char";
	} else {
		returnType = "Code";
	}
	print "M_" $2
	print $0;
	print "{";
	argcount = 1;
	if (NF == 5 && $4 == "void")
		argcount = 0;
	if (argcount != 0) {
		for (i = 1; i <= NF; i++)
			if ($i == ",")
				argcount++;
	}

	# suppress trace-code for functions that we cannot do properly here,
	# since they return data.
	dotrace = 1;
	if ($2 == "innstr")
		dotrace = 0;

	call = "%%T((T_CALLED(\""
	args = ""
	comma = ""
	num = 0;
	pointer = 0;
	argtype = ""
	for (i = 1; i <= NF; i++) {
		ch = $i;
		if ( ch == "*" )
			pointer = 1;
		else if ( ch == "va_list" )
			pointer = 1;
		else if ( ch == "char" )
			argtype = "char";
		else if ( ch == "int" )
			argtype = "int";
		else if ( ch == "short" )
			argtype = "short";
		else if ( ch == "chtype" )
			argtype = "chtype";
		else if ( ch == "attr_t" || ch == "NCURSES_ATTR_T" )
			argtype = "attr";

		if ( ch == "," || ch == ")" ) {
			if (pointer) {
				if ( argtype == "char" ) {
					call = call "%s"
					comma = comma "_nc_visbuf2(" num ","
					pointer = 0;
				} else
					call = call "%p"
			} else if (argcount != 0) {
				if ( argtype == "int" || argtype == "short" ) {
					call = call "%d"
					argtype = ""
				} else if ( argtype != "" ) {
					call = call "%s"
					comma = comma "_trace" argtype "2(" num ","
				} else {
					call = call "%#lx"
					comma = comma "(long)"
				}
			}
			if (ch == ",")
				args = args comma "a" ++num;
			else if (argcount != 0)
				args = args comma "z"
			call = call ch
			if (pointer == 0 && argcount != 0 && argtype != "" )
				args = args ")"
			if (args != "")
				comma = ", "
			pointer = 0;
			argtype = ""
		}
		if ( i == 2 || ch == "(" )
			call = call ch
	}
	call = call "\")"
	if (args != "")
		call = call ", " args
	call = call ")); "

	if (dotrace)
		printf "%s", call

	if (match($0, "^void"))
		call = ""
	else if (dotrace)
		call = sprintf("return%s( ", returnType);
	else
		call = "%%return ";

	call = call $2 "(";
	for (i = 1; i < argcount; i++)
		call = call "a" i ", ";
	if (argcount != 0)
		call = call "z";
	if (!match($0, "^void"))
		call = call ") ";
	if (dotrace)
		call = call ")";
	print call ";"

	if (match($0, "^void"))
		print "%%returnVoid;"
	print "}";
}
EOF1

sed -n -f $ED1 \
| sed -e 's/NCURSES_EXPORT(\(.*\)) \(.*\) (\(.*\))/\1 \2(\3)/' \
| sed -f $ED2 \
| $AWK -f $AW1 ) \
| sed \
	-e '/^\([a-z_][a-z_]*\) /s//\1 gen_/' >$TMP
  $preprocessor $TMP 2>/dev/null \
| $AWK '
BEGIN		{
	print "/*"
	print " * DO NOT EDIT THIS FILE BY HAND!"
	print " * It is generated by MKlib_gen.sh."
	print " *"
	print " * This is a file of trivial functions generated from macro"
	print " * definitions in curses.h to satisfy the XSI Curses requirement"
	print " * that every macro also exist as a callable function."
	print " *"
	print " * It will never be linked unless you call one of the entry"
	print " * points with its normal macro definition disabled.  In that"
	print " * case, if you have no shared libraries, it will indirectly"
	print " * pull most of the rest of the library into your link image."
	print " */"
	print "#include <curses.priv.h>"
	print ""
		}
/^DECLARATIONS/	{start = 1; next;}
		{if (start) print $0;}
' \
| sed -f $ED3 \
| sed \
	-e 's/^.*T_CALLED.*returnCode( \([a-z].*) \));/	return \1;/' \
	-e 's/^.*T_CALLED.*returnCode( \((wmove.*) \));/	return \1;/' \
| sed \
	-e 's/^\(.*\) \(.*\) (\(.*\))$/NCURSES_EXPORT(\1) \2 (\3)/'