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