MKlib_gen.sh revision 50276
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 29preprocessor="$1 -I../include" 30AWK="$2" 31ED1=sed1$$.sed 32ED2=sed2$$.sed 33ED3=sed3$$.sed 34AW1=awk1$$.awk 35TMP=gen$$.c 36trap "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 42DECLARATIONS 43 44EOF 45cat >$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} 54EOF1 55 56cat >$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/)/ )/ 80EOF2 81 82cat >$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 96EOF3 97 98cat >$AW1 <<\EOF1 99BEGIN { 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} 222EOF1 223 224sed -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 ' 230BEGIN { 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 255