maart@cs.vu.nl (Maarten Litmaath) (09/26/89)
Let's try again. Still some limitations, but it seems to work well, albeit a bit slow. ----------8<----------8<----------8<----------8<----------8<---------- #!/bin/sh # # @(#)gencpp 2.0 89/09/26 Maarten Litmaath # generic cpp # as substitution is done even inside quoted strings, you should choose # identifiers which won't collide easily, e.g. # # #define MACHINE_ VAX # # instead of # # #define machine VAX # # don't use `/*' and `*/' to comment out blocks of text, use # # #if 0 # ... # #endif /* 0 */ # # only `<...>' and `"..."' include directives are supported # furthermore cpp predefines certain symbols, e.g. # # #define unix 1 # # which can be overruled using cpp's option `-U' case $1 in -level2) # process included file level=2 shift ;; *) level=1 dirs= export dirs argc=0 optc=0 export optc tab=`echo I | tr I '\11'` for i do case $i in -I*) # include directories dirs="$dirs "`echo "x$i" | sed 's/...//'` ;; -*) optc=`expr $optc + 1` eval optv$optc='"$i"' eval export optv$optc ;; *) # files argc=`expr $argc + 1` eval argv$argc='"$i"' esac done # double single and double quotes q=\" SED1="s/['$q]/&&/g" # restore quotes and backslashes SED2=" s/''/'/g s/$q$q/$q/g s/\\\\\\\\/\\\\/g " for i in define undef ifdef ifndef if elif else endif do # mark the relevant cpp control lines # due to a bug in some sed versions, the `p' mustn't # be appended to the previous substitute command SED1=" $SED1 /^[ $tab]*#[ $tab]*\\($i\\).*/{ h s//\\\\#\\1/ p g b } " # remove a marked line and the (empty) next line SED2=" $SED2 /^\\\\#$i$/{ N d } " done # set the file arguments set ' ' i=0 while i=`expr $i + 1` test $i -le $argc do eval set '${1+"$@"}' '"$argv'$i'"' done shift esac # canonicalize the `#include' line # double backslashes # protect leading whitespace against stripping by the shell (`read line') SED3=" s/^[ $tab]*#[ $tab]*include/#include/ s/\\\\/&&/g s/^[ $tab]/\\\\&/ " # get include file name SED4=' /[^<"]*.\([^>"]*\).*/{ s//\1/ s/\\\\/\\/g p } ' sed "$SED3" ${1+"$@"} | ( while read line do case $line in \#include*\<*) # don't search dot default dot= ;; \#include*\"*) dot=. ;; *) echo "$line" continue esac name=`echo "$line" | sed -n "$SED4"` file= case $name in /*) file=$name ;; *) for dir in $dot $dirs do if test -f "$dir/$name" then file=$dir/$name break fi done esac case $file in '') echo "$0: include file '$name' not found" >&2 continue esac # process included file $0 -level2 "$file" done ) | ( case $level in 2) cat ;; *) # set cpp options set ' ' i=0 while i=`expr $i + 1` test $i -le $optc do eval set '${1+"$@"}' '"$optv'$i'"' done shift sed "$SED1" | /lib/cpp -P ${1+"$@"} | sed "$SED2" esac ) ----------8<----------8<----------8<----------8<----------8<---------- -- `I AM NEW HEAR AMD I WANT TO INKRIMENT A |Maarten Litmaath @ VU Amsterdam: VURIABLE BY 1 (OONE) IN "c"' (Tom Neff) |maart@cs.vu.nl, mcvax!botter!maart