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