MKlib_gen.sh revision 1.1
1#!/bin/sh
2#
3# MKlib_gen.sh -- generate sources from curses.h macro definitions
4#
5# $OpenBSD: MKlib_gen.sh,v 1.1 1999/01/18 19:09:32 millert Exp $
6# ($From: MKlib_gen.sh,v 1.11 1998/01/17 14:16:52 Juan.Jose.Garcia.Ripoll Exp $)
7#
8# The XSI Curses standard requires all curses entry points to exist as
9# functions, even though many definitions would normally be shadowed
10# by macros.  Rather than hand-hack all that code, we actually
11# generate functions from the macros.
12#
13# This script accepts a file of prototypes on standard input.  It discards
14# any that don't have a `generated' comment attached. It then parses each
15# prototype (relying on the fact that none of the macros take function 
16# pointer or array arguments) and generates C source from it.
17#
18# Here is what the pipeline stages are doing:
19#
20# 1. sed: extract prototypes of generated functions
21# 2. sed: decorate prototypes with generated arguments a1. a2,...z
22# 3. awk: generate the calls with args matching the formals 
23# 4. sed: prefix function names in prototypes so the preprocessor won't expand
24#         them.
25# 5. cpp: macro-expand the file so the macro calls turn into C calls
26# 6. awk: strip the expansion junk off the front and add the new header
27# 7. sed: squeeze spaces, strip off gen_ prefix, create needed #undef
28#
29
30preprocessor="$1 -I../include"
31AWK="$2"
32ED1=sed1$$.sed
33ED2=sed2$$.sed
34ED3=sed3$$.sed
35AW1=awk1$$.awk
36TMP=gen$$.c
37trap "rm -f $ED1 $ED2 $ED3 $AW1 $TMP" 0 1 2 5 15
38
39(cat <<EOF
40#include <ncurses_cfg.h>
41#include <curses.h>
42
43DECLARATIONS
44
45EOF
46cat >$ED1 <<EOF1
47/^extern.*generated/{
48	h
49	s/^.*generated:\([^ 	*]*\).*/P_#if_USE_\1_SUPPORT/p
50	g
51	s/^extern \([^;]*\);.*/\1/p
52	g
53	s/^.*generated:\([^ 	*]*\).*/P_#endif/p
54}
55EOF1
56
57cat >$ED2 <<EOF2
58/^P_/b nc
59/(void)/b nc
60	s/,/ a1% /
61	s/,/ a2% /
62	s/,/ a3% /
63	s/,/ a4% /
64	s/,/ a5% /
65	s/,/ a6% /
66	s/,/ a7% /
67	s/,/ a8% /
68	s/,/ a9% /
69	s/,/ a10% /
70	s/,/ a11% /
71	s/,/ a12% /
72	s/,/ a13% /
73	s/,/ a14% /
74	s/,/ a15% /
75	s/*/ * /g
76	s/%/ , /g
77	s/)/ z)/
78:nc
79	/(/s// ( /
80	s/)/ )/
81EOF2
82
83cat >$ED3 <<EOF3
84/^P_/{
85	s/^P_#if_/#if /
86	s/^P_//
87	b done
88}
89	s/		*/ /g
90	s/  */ /g
91	s/ ,/,/g
92	s/ )/)/g
93	s/ gen_/ /
94	s/^M_/#undef /
95	/^%%/s//	/
96:done
97EOF3
98
99cat >$AW1 <<\EOF1
100BEGIN	{
101		skip=0;
102	}
103	/^P_#if/ {
104		print "\n"
105		print $0
106		skip=0;
107	}
108	/^P_#endif/ {
109		print $0
110		skip=1;
111	}
112	$0 !~ /^P_/ {
113	if (skip)
114		print "\n"
115	skip=1;
116
117	print "M_" $2
118	print $0;
119	print "{";
120	argcount = 1;
121	if (NF == 5 && $4 == "void")
122		argcount = 0;
123	if (argcount != 0) {
124		for (i = 1; i <= NF; i++)
125			if ($i == ",")
126				argcount++;
127	}
128
129	# suppress trace-code for functions that we cannot do properly here,
130	# since they return data.
131	dotrace = 1;
132	if ($2 == "innstr")
133		dotrace = 0;
134
135	call = "%%T((T_CALLED(\""
136	args = ""
137	comma = ""
138	num = 0;
139	pointer = 0;
140	argtype = ""
141	for (i = 1; i <= NF; i++) {
142		ch = $i;
143		if ( ch == "*" )
144			pointer = 1;
145		else if ( ch == "va_list" )
146			pointer = 1;
147		else if ( ch == "char" )
148			argtype = "char";
149		else if ( ch == "int" )
150			argtype = "int";
151		else if ( ch == "short" )
152			argtype = "short";
153		else if ( ch == "chtype" )
154			argtype = "chtype";
155		else if ( ch == "attr_t" || ch == "NCURSES_ATTR_T" )
156			argtype = "attr";
157
158		if ( ch == "," || ch == ")" ) {
159			if (pointer) {
160				if ( argtype == "char" ) {
161					call = call "%s"
162					comma = comma "_nc_visbuf2(" num ","
163					pointer = 0;
164				} else
165					call = call "%p"
166			} else if (argcount != 0) {
167				if ( argtype == "int" || argtype == "short" ) {
168					call = call "%d"
169					argtype = ""
170				} else if ( argtype != "" ) {
171					call = call "%s"
172					comma = comma "_trace" argtype "2(" num ","
173				} else {
174					call = call "%#lx"
175					comma = comma "(long)"
176				}
177			}
178			if (ch == ",")
179				args = args comma "a" ++num;
180			else if (argcount != 0)
181				args = args comma "z"
182			call = call ch
183			if (pointer == 0 && argcount != 0 && argtype != "" )
184				args = args ")"
185			if (args != "")
186				comma = ", "
187			pointer = 0;
188			argtype = ""
189		}
190		if ( i == 2 || ch == "(" )
191			call = call ch
192	}
193	call = call "\")"
194	if (args != "")
195		call = call ", " args
196	call = call ")); "
197
198	if (dotrace)
199		printf "%s", call
200
201	if (match($0, "^void"))
202		call = ""
203	else if (dotrace)
204		call = "returnCode( ";
205	else
206		call = "%%return ";
207
208	call = call $2 "(";
209	for (i = 1; i < argcount; i++)
210		call = call "a" i ", ";
211	if (argcount != 0)
212		call = call "z";
213	if (!match($0, "^void"))
214		call = call ") ";
215	if (dotrace)
216		call = call ")";
217	print call ";"
218
219	if (match($0, "^void"))
220		print "%%returnVoid;"
221	print "}";
222}
223EOF1
224
225sed -n -f $ED1 | sed -f $ED2 \
226| $AWK -f $AW1 ) \
227| sed \
228	-e '/^\([a-z_][a-z_]*\) /s//\1 gen_/' >$TMP
229  $preprocessor $TMP 2>/dev/null \
230| $AWK '
231BEGIN		{
232	print "/*"
233	print " * DO NOT EDIT THIS FILE BY HAND!"
234	print " * It is generated by MKlib_gen.sh."
235	print " *"
236	print " * This is a file of trivial functions generated from macro"
237	print " * definitions in curses.h to satisfy the XSI Curses requirement"
238	print " * that every macro also exist as a callable function."
239	print " *"
240	print " * It will never be linked unless you call one of the entry"
241	print " * points with its normal macro definition disabled.  In that"
242	print " * case, if you have no shared libraries, it will indirectly"
243	print " * pull most of the rest of the library into your link image."
244	print " */"
245	print "#include <curses.priv.h>"
246	print ""
247		}
248/^DECLARATIONS/	{start = 1; next;}
249		{if (start) print $0;}
250' \
251| sed -f $ED3 \
252| sed \
253	-e 's/^.*T_CALLED.*returnCode( \([a-z].*) \));/	return \1;/' \
254	-e 's/^.*T_CALLED.*returnCode( \((wmove.*) \));/	return \1;/'
255
256