MKlib_gen.sh revision 97049
1105665Srwatson#!/bin/sh 2126256Srwatson# 3126256Srwatson# MKlib_gen.sh -- generate sources from curses.h macro definitions 4105665Srwatson# 5105665Srwatson# ($Id: MKlib_gen.sh,v 1.18 2002/04/30 00:37:55 tom Exp $) 6105665Srwatson# 7105665Srwatson############################################################################## 8105665Srwatson# Copyright (c) 1998-2001,2002 Free Software Foundation, Inc. # 9105665Srwatson# # 10105665Srwatson# Permission is hereby granted, free of charge, to any person obtaining a # 11105665Srwatson# copy of this software and associated documentation files (the "Software"), # 12105665Srwatson# to deal in the Software without restriction, including without limitation # 13105665Srwatson# the rights to use, copy, modify, merge, publish, distribute, distribute # 14105665Srwatson# with modifications, sublicense, and/or sell copies of the Software, and to # 15105665Srwatson# permit persons to whom the Software is furnished to do so, subject to the # 16105665Srwatson# following conditions: # 17105665Srwatson# # 18105665Srwatson# The above copyright notice and this permission notice shall be included in # 19105665Srwatson# all copies or substantial portions of the Software. # 20105665Srwatson# # 21105665Srwatson# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 22105665Srwatson# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 23105665Srwatson# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # 24105665Srwatson# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # 25105665Srwatson# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # 26105665Srwatson# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # 27105665Srwatson# DEALINGS IN THE SOFTWARE. # 28105665Srwatson# # 29105665Srwatson# Except as contained in this notice, the name(s) of the above copyright # 30105665Srwatson# holders shall not be used in advertising or otherwise to promote the sale, # 31105665Srwatson# use or other dealings in this Software without prior written # 32105665Srwatson# authorization. # 33105665Srwatson############################################################################## 34105665Srwatson# 35105665Srwatson# The XSI Curses standard requires all curses entry points to exist as 36285873Strasz# functions, even though many definitions would normally be shadowed 37107780Sru# by macros. Rather than hand-hack all that code, we actually 38105665Srwatson# generate functions from the macros. 39105665Srwatson# 40105665Srwatson# This script accepts a file of prototypes on standard input. It discards 41105665Srwatson# any that don't have a `generated' comment attached. It then parses each 42105665Srwatson# prototype (relying on the fact that none of the macros take function 43105665Srwatson# pointer or array arguments) and generates C source from it. 44105665Srwatson# 45105665Srwatson# Here is what the pipeline stages are doing: 46105665Srwatson# 47105665Srwatson# 1. sed: extract prototypes of generated functions 48105665Srwatson# 2. sed: decorate prototypes with generated arguments a1. a2,...z 49105665Srwatson# 3. awk: generate the calls with args matching the formals 50105665Srwatson# 4. sed: prefix function names in prototypes so the preprocessor won't expand 51107780Sru# them. 52107780Sru# 5. cpp: macro-expand the file so the macro calls turn into C calls 53107780Sru# 6. awk: strip the expansion junk off the front and add the new header 54105665Srwatson# 7. sed: squeeze spaces, strip off gen_ prefix, create needed #undef 55105665Srwatson# 56105665Srwatson 57105665Srwatsonpreprocessor="$1 -I../include" 58105665SrwatsonAWK="$2" 59105665SrwatsonUSE="$3" 60105665Srwatson 61105665SrwatsonPID=$$ 62105665SrwatsonED1=sed1_${PID}.sed 63105665SrwatsonED2=sed2_${PID}.sed 64105665SrwatsonED3=sed3_${PID}.sed 65107780SruED4=sed4_${PID}.sed 66105665SrwatsonAW1=awk1_${PID}.awk 67105665SrwatsonAW2=awk2_${PID}.awk 68107780SruTMP=gen__${PID}.c 69105665Srwatsontrap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP" 0 1 2 5 15 70107780Sru 71107780SruALL=$USE 72107780Sruif test "$USE" = implemented ; then 73105665Srwatson CALL="call_" 74105665Srwatson cat >$ED1 <<EOF1 75105665Srwatson/^extern.*implemented/{ 76105665Srwatson h 77105665Srwatson s/^.*implemented:\([^ *]*\).*/P_#if_USE_\1_SUPPORT/p 78105665Srwatson g 79105665Srwatson s/^extern \([^;]*\);.*/\1/p 80105665Srwatson g 81105665Srwatson s/^.*implemented:\([^ *]*\).*/P_#endif/p 82105665Srwatson} 83105665Srwatson/^extern.*generated/{ 84105665Srwatson h 85105665Srwatson s/^.*generated:\([^ *]*\).*/P_#if_USE_\1_SUPPORT/p 86105665Srwatson g 87105665Srwatson s/^extern \([^;]*\);.*/\1/p 88105665Srwatson g 89105665Srwatson s/^.*generated:\([^ *]*\).*/P_#endif/p 90105665Srwatson} 91105665SrwatsonEOF1 92105665Srwatsonelse 93105665Srwatson CALL="" 94105665Srwatson cat >$ED1 <<EOF1 95105665Srwatson/^extern.*${ALL}/{ 96105665Srwatson h 97105665Srwatson s/^.*${ALL}:\([^ *]*\).*/P_#if_USE_\1_SUPPORT/p 98105665Srwatson g 99105665Srwatson s/^extern \([^;]*\);.*/\1/p 100105665Srwatson g 101105665Srwatson s/^.*${ALL}:\([^ *]*\).*/P_#endif/p 102107780Sru} 103107780SruEOF1 104105665Srwatsonfi 105105665Srwatson 106105665Srwatsoncat >$ED2 <<EOF2 107105665Srwatson/^P_/b nc 108105665Srwatson/(void)/b nc 109105665Srwatson s/,/ a1% / 110105665Srwatson s/,/ a2% / 111105665Srwatson s/,/ a3% / 112105665Srwatson s/,/ a4% / 113105665Srwatson s/,/ a5% / 114105665Srwatson s/,/ a6% / 115105665Srwatson s/,/ a7% / 116105665Srwatson s/,/ a8% / 117105665Srwatson s/,/ a9% / 118105665Srwatson s/,/ a10% / 119105665Srwatson s/,/ a11% / 120105665Srwatson s/,/ a12% / 121105665Srwatson s/,/ a13% / 122105665Srwatson s/,/ a14% / 123105665Srwatson s/,/ a15% / 124105665Srwatson s/*/ * /g 125105665Srwatson s/%/ , /g 126105665Srwatson s/)/ z)/ 127105665Srwatson s/\.\.\. z)/...)/ 128105665Srwatson:nc 129105665Srwatson /(/s// ( / 130105665Srwatson s/)/ )/ 131105665SrwatsonEOF2 132105665Srwatson 133105665Srwatsoncat >$ED3 <<EOF3 134105665Srwatson/^P_/{ 135105665Srwatson s/^P_#if_/#if / 136105665Srwatson s/^P_// 137105665Srwatson b done 138105665Srwatson} 139105665Srwatson s/ */ /g 140105665Srwatson s/ */ /g 141105665Srwatson s/ ,/,/g 142105665Srwatson s/( /(/g 143105665Srwatson s/ )/)/g 144105665Srwatson s/ gen_/ / 145105665Srwatson s/^M_/#undef / 146107780Sru /^%%/s// / 147160261Sjoel:done 148107780SruEOF3 149105665Srwatson 150105665Srwatsonif test "$USE" = generated ; then 151105665Srwatsoncat >$ED4 <<EOF 152107780Sru s/^\(.*\) \(.*\) (\(.*\))\$/NCURSES_EXPORT(\1) \2 (\3)/ 153107795SchrisEOF 154107795Schriselse 155107795Schriscat >$ED4 <<EOF 156141355Sbrueffer/^\(.*\) \(.*\) (\(.*\))\$/ { 157107795Schris h 158107795Schris s/^\(.*\) \(.*\) (\(.*\))\$/extern \1 call_\2 (\3);/ 159107795Schris p 160107795Schris g 161107795Schris s/^\(.*\) \(.*\) (\(.*\))\$/\1 call_\2 (\3)/ 162105665Srwatson } 163105665SrwatsonEOF 164105665Srwatsonfi 165107780Sru 166108936Schriscat >$AW1 <<\EOF1 167160247SjoelBEGIN { 168202386Sru skip=0; 169108936Schris } 170140561Sru/^P_#if/ { 171140561Sru print "\n" 172140561Sru print $0 173140561Sru skip=0; 174140561Sru} 175105665Srwatson/^P_#endif/ { 176147647Shmp print $0 177105665Srwatson skip=1; 178105665Srwatson} 179105665Srwatson$0 !~ /^P_/ { 180105665Srwatson if (skip) 181131530Sru print "\n" 182107780Sru skip=1; 183107780Sru 184107780Sru first=$1 185105665Srwatson for (i = 1; i <= NF; i++) { 186105665Srwatson if ( $i != "NCURSES_CONST" ) { 187107780Sru first = i; 188107780Sru break; 189107780Sru } 190105665Srwatson } 191105665Srwatson second = first + 1; 192108317Sschweikh if ( $first == "chtype" ) { 193105665Srwatson returnType = "Char"; 194105665Srwatson } else if ( $first == "SCREEN" ) { 195105665Srwatson returnType = "SP"; 196105665Srwatson } else if ( $first == "WINDOW" ) { 197105665Srwatson returnType = "Win"; 198126256Srwatson } else if ( $second == "*" ) { 199105665Srwatson returnType = "Ptr"; 200105665Srwatson } else { 201105665Srwatson returnType = "Code"; 202105665Srwatson } 203105665Srwatson myfunc = second; 204126256Srwatson for (i = second; i <= NF; i++) { 205105665Srwatson if ($i != "*") { 206105665Srwatson myfunc = i; 207105665Srwatson break; 208105665Srwatson } 209105665Srwatson } 210105665Srwatson if (using == "generated") { 211105665Srwatson print "M_" $myfunc 212105665Srwatson } 213105665Srwatson print $0; 214124963Sdes print "{"; 215105665Srwatson argcount = 1; 216105665Srwatson check = NF - 1; 217130582Sru if ($check == "void") 218105665Srwatson argcount = 0; 219105665Srwatson if (argcount != 0) { 220126256Srwatson for (i = 1; i <= NF; i++) 221126256Srwatson if ($i == ",") 222105665Srwatson argcount++; 223126256Srwatson } 224105665Srwatson 225126256Srwatson # suppress trace-code for functions that we cannot do properly here, 226106419Srwatson # since they return data. 227106419Srwatson dotrace = 1; 228107478Schris if ($myfunc ~ /innstr/) 229106419Srwatson dotrace = 0; 230106419Srwatson if ($myfunc ~ /innwstr/) 231106419Srwatson dotrace = 0; 232 233 # workaround functions that we do not parse properly 234 if ($myfunc ~ /ripoffline/) { 235 dotrace = 0; 236 argcount = 2; 237 } 238 if ($myfunc ~ /wunctrl/) { 239 dotrace = 0; 240 } 241 242 call = "%%T((T_CALLED(\"" 243 args = "" 244 comma = "" 245 num = 0; 246 pointer = 0; 247 argtype = "" 248 for (i = myfunc; i <= NF; i++) { 249 ch = $i; 250 if ( ch == "*" ) 251 pointer = 1; 252 else if ( ch == "va_list" ) 253 pointer = 1; 254 else if ( ch == "char" ) 255 argtype = "char"; 256 else if ( ch == "int" ) 257 argtype = "int"; 258 else if ( ch == "short" ) 259 argtype = "short"; 260 else if ( ch == "chtype" ) 261 argtype = "chtype"; 262 else if ( ch == "attr_t" || ch == "NCURSES_ATTR_T" ) 263 argtype = "attr"; 264 265 if ( ch == "," || ch == ")" ) { 266 if (pointer) { 267 if ( argtype == "char" ) { 268 call = call "%s" 269 comma = comma "_nc_visbuf2(" num "," 270 pointer = 0; 271 } else 272 call = call "%p" 273 } else if (argcount != 0) { 274 if ( argtype == "int" || argtype == "short" ) { 275 call = call "%d" 276 argtype = "" 277 } else if ( argtype != "" ) { 278 call = call "%s" 279 comma = comma "_trace" argtype "2(" num "," 280 } else { 281 call = call "%#lx" 282 comma = comma "(long)" 283 } 284 } 285 if (ch == ",") 286 args = args comma "a" ++num; 287 else if ( argcount != 0 && $check != "..." ) 288 args = args comma "z" 289 call = call ch 290 if (pointer == 0 && argcount != 0 && argtype != "" ) 291 args = args ")" 292 if (args != "") 293 comma = ", " 294 pointer = 0; 295 argtype = "" 296 } 297 if ( i == 2 || ch == "(" ) 298 call = call ch 299 } 300 call = call "\")" 301 if (args != "") 302 call = call ", " args 303 call = call ")); " 304 305 if (dotrace) 306 printf "%s", call 307 308 if (match($0, "^void")) 309 call = "" 310 else if (dotrace) 311 call = sprintf("return%s( ", returnType); 312 else 313 call = "%%return "; 314 315 call = call $myfunc "("; 316 for (i = 1; i < argcount; i++) { 317 if (i != 1) 318 call = call ", "; 319 call = call "a" i; 320 } 321 if ( argcount != 0 && $check != "..." ) { 322 if (argcount != 1) 323 call = call ", "; 324 call = call "z"; 325 } 326 if (!match($0, "^void")) 327 call = call ") "; 328 if (dotrace) 329 call = call ")"; 330 print call ";" 331 332 if (match($0, "^void")) 333 print "%%returnVoid;" 334 print "}"; 335} 336EOF1 337 338cat >$AW2 <<EOF1 339BEGIN { 340 print "/*" 341 print " * DO NOT EDIT THIS FILE BY HAND!" 342 printf " * It is generated by $0 %s.\n", "$USE" 343 if ( "$USE" == "generated" ) { 344 print " *" 345 print " * This is a file of trivial functions generated from macro" 346 print " * definitions in curses.h to satisfy the XSI Curses requirement" 347 print " * that every macro also exist as a callable function." 348 print " *" 349 print " * It will never be linked unless you call one of the entry" 350 print " * points with its normal macro definition disabled. In that" 351 print " * case, if you have no shared libraries, it will indirectly" 352 print " * pull most of the rest of the library into your link image." 353 } 354 print " */" 355 print "#include <curses.priv.h>" 356 print "" 357 } 358/^DECLARATIONS/ {start = 1; next;} 359 {if (start) print \$0;} 360END { 361 if ( "$USE" != "generated" ) { 362 print "int main(void) { return 0; }" 363 } 364 } 365EOF1 366 367cat >$TMP <<EOF 368#include <ncurses_cfg.h> 369#include <curses.h> 370 371DECLARATIONS 372 373EOF 374 375sed -n -f $ED1 \ 376| sed -e 's/NCURSES_EXPORT(\(.*\)) \(.*\) (\(.*\))/\1 \2(\3)/' \ 377| sed -f $ED2 \ 378| $AWK -f $AW1 using=$USE \ 379| sed -e 's/^\([a-z_][a-z_]*[ *]*\)/\1 gen_/' -e 's/ / /g' >>$TMP 380 381$preprocessor $TMP 2>/dev/null \ 382| sed -e 's/ / /g' -e 's/^ //' \ 383| $AWK -f $AW2 \ 384| sed -f $ED3 \ 385| sed \ 386 -e 's/^.*T_CALLED.*returnCode( \([a-z].*) \));/ return \1;/' \ 387 -e 's/^.*T_CALLED.*returnCode( \((wmove.*) \));/ return \1;/' \ 388| sed -f $ED4 389