## ## scpp -- Sharing C Pre-Processor ## Copyright (c) 1999-2001 Ralf S. Engelschall ## Originally written for GNU Pth ## ## This file is part of shtool and free software; you can redistribute ## it and/or modify it under the terms of the GNU General Public ## License as published by the Free Software Foundation; either version ## 2 of the License, or (at your option) any later version. ## ## This file is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ## USA, or contact Ralf S. Engelschall . ## str_tool="scpp" str_usage="[-v] [-p] [-f] [-o] [-t] [-M] [-D] [-C] [ ...]" gen_tmpfile=yes arg_spec="1+" opt_spec="v.p.f+o:t:M:D:C:" opt_v=no opt_p=no opt_f="" opt_o="lib.h" opt_t="lib.h.in" opt_M="%%MARK%%" opt_D="cpp" opt_C="intern" . ./sh.common srcs="$*" output="${opt_o}.n" # find a reasonable Awk awk='' paths=`echo $PATH |\ sed -e 's%/*:%:%g' -e 's%/$%%' \ -e 's/^:/.:/' -e 's/::/:.:/g' -e 's/:$/:./' \ -e 's/:/ /g'` for name in gawk nawk awk; do for path in $paths; do if [ -r "$path/$name" ]; then awk="$path/$name" break fi done if [ ".$awk" != . ]; then break fi done if [ ".$awk" = . ]; then echo "$msgprefix:Error: cannot find a reasonable Awk" 1>&2 exit 1 fi # parse source file(s) if [ ".$opt_v" = .yes ]; then echo "Parsing:" | $awk '{ printf("%s", $0); }' 1>&2 fi for src in $srcs; do if [ ".$opt_v" = .yes ]; then echo $src | $awk '{ printf(" %s", $0); }' 1>&2 fi if [ ".$opt_f" = . ]; then inputcmd="cat $src" else inputcmd="sed $opt_f $src" fi $inputcmd |\ $awk ' BEGIN { ln = 0; fln = 0; level = 0; mode = ""; store = ""; } { ln++; } /^#if.*/ { level++; } /^#if [a-zA-Z_][a-zA-Z0-9_]* *$/ { if ($2 == define) { mode = "D"; printf("D:#line %d \"%s\"\n", ln, src); next; } } /^#endif.*/ { level--; if (mode == "D" && level == 0) { mode = ""; next; } } /^[a-zA-Z_][a-zA-Z0-9_].*;.*/ { if ($1 == class) { printf("V:#line %d \"%s\"\n", ln, src); printf("V:%s\n", $0); printf("J:%s\n", $0); next; } } /^[a-zA-Z_][a-zA-Z0-9_].*=.*/ { if ($1 == class) { printf("V:#line %d \"%s\"\n", ln, src); printf("V:%s\n", $0); printf("J:%s\n", $0); next; } } /^[a-zA-Z_][a-zA-Z0-9_]*/ { if ($1 == class) { fln = ln; store = $0; mode = "F"; next; } } /^\{ *$/ { if (mode == "F") { printf("F:#line %d \"%s\"\n", fln, src); printf("F:%s;\n", store); printf("I:%s;\n", store); store = ""; mode = ""; next; } } { if (mode == "D") printf("D:%s\n", $0); else if (mode == "F") store = store " " $0; } ' "src=$src" "define=$opt_D" "class=$opt_C" >>$tmpfile done if [ ".$opt_v" = .yes ]; then echo "" 1>&2 fi # start generating output header echo "/* $opt_o -- autogenerated from $opt_t, DO NOT EDIT! */" >$output echo "#line 1 \"$opt_t\"" >>$output sed <$opt_t -e "1,/^${opt_M} *\$/p" -e 'd' |\ sed -e "/^${opt_M} *\$/d" >>$output # merge in the define blocks grep '^D:' $tmpfile | sed -e 's/^D://' >>$output # generate standard prolog echo "#line 1 \"_ON_THE_FLY_\"" >>$output echo "" >>$output echo "/* make sure the scpp source extensions are skipped */" >>$output echo "#define $opt_D 0" >>$output echo "#define $opt_C /**/" >>$output # generate namespace hiding for variables echo "" >>$output echo "/* move intern variables to hidden namespace */" >>$output grep '^J:' $tmpfile | sed >>$output \ -e 's/^J://' \ -e 's/ */ /g' \ -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\)\[\];.*$/#define \1 __\1/' \ -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\)\[\] =.*$/#define \1 __\1/' \ -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\);.*$/#define \1 __\1/' \ -e 's/^[^=;]*[ *]\([a-zA-Z0-9_]*\) =.*$/#define \1 __\1/' # generate namespace hiding for functions echo "" >>$output echo "/* move intern functions to hidden namespace */" >>$output grep '^I:' $tmpfile | sed >>$output \ -e 's/^I://' \ -e 's/\([ (]\) */\1/g' \ -e 's/ *\([),]\)/\1/g' \ -e 's/^[^(]*[ *]\([a-zA-Z0-9_]*\)(.*$/#define \1 __\1/' # generate prototypes for variables echo "" >>$output echo "/* prototypes for intern variables */" >>$output grep '^V:' $tmpfile | sed >>$output \ -e 's/^V://' \ -e 's/ */ /g' \ -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\[\]\);.*$/\1;/' \ -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\[\]\) =.*$/\1;/' \ -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\);.*$/\1;/' \ -e 's/^\([^=;]*[ *][a-zA-Z0-9_]*\) =.*$/\1;/' \ -e 's/ ;/;/g' \ -e "s/^$opt_C /extern /" # generate prototypes for functions echo "" >>$output echo "/* prototypes for intern functions */" >>$output grep '^F:' $tmpfile | sed >>$output \ -e 's/^F://' \ -e 's/\([ (]\) */\1/g' \ -e 's/ *\([),]\)/\1/g' \ -e 's/\([* ]\)[a-zA-Z0-9_]*,/\1,/g' \ -e 's/\([* ]\)[a-zA-Z0-9_]*);/\1);/g' \ -e 's/(\*[a-zA-Z0-9_]*)(/(*)(/g' \ -e 's/\([ (]\) */\1/g' \ -e 's/ *\([),]\)/\1/g' \ -e "s/^$opt_C /extern /" # finish generating output header n=`(echo ''; sed <$opt_t -e "1,/^${opt_M} *\$/p" -e 'd') |\ wc -l | sed -e 's;^ *\([0-9]*\) *$;\1;'` echo "#line $n \"$opt_t\"" >>$output sed <$opt_t -e "/^${opt_M} *\$/,\$p" -e 'd' |\ sed -e "/^${opt_M} *\$/d" >>$output # create final output file if [ -f $opt_o ]; then if [ ".$opt_p" = .yes ]; then grep -v '^#line' $opt_o >$tmpfile.o grep -v '^#line' $output >$tmpfile.n out_old="$tmpfile.o" out_new="$tmpfile.n" else out_old="$opt_o" out_new="$output" fi if cmp -s $out_old $out_new; then : else cp $output $opt_o fi else cp $output $opt_o fi rm -f $output rm -f $tmpfile $tmpfile.* >/dev/null 2>&1