Marcel Moolenaar wrote: > On Mon, Jun 30, 2003 at 08:10:02PM -0700, Tim Kientzle wrote: > In general I think that the more portable the build tool, the better. > If the shell script is not gross or overly ugly compared to the C > program, then replacing the latter may not be a bad idea. The attached diff replaces two of the build tools for /bin/sh with equivalent shell scripts (using grep/sed/awk). I personally find the awk versions clearer than the C versions. I apologize that these have not been very well tested, but they were written in quite a rush. For the most part, the output of these is exactly the same as that from the C programs. The few differences look functionally equivalent to me, but I've not had time to test it very carefully. The remaining 'mksyntax' also looks pretty easy to replace with a shell script, at which point, /bin/sh will require no build-tools target. Then, /rescue will also not need a buld-tools target (assuming everyone is willing to drop csh from /rescue). Unfortunately, it's late, I haven't had dinner, and I have a lot of paying work piling up. <sigh> Someone else may have to finish this, as I won't be able to get back to it for a few days. Tim Kientzle Index: Makefile =================================================================== RCS file: /usr/cvs/FreeBSD-CVS/src/bin/sh/Makefile,v retrieving revision 1.40 diff -u -r1.40 Makefile --- Makefile 2 May 2003 06:26:32 -0000 1.40 +++ Makefile 1 Jul 2003 05:25:08 -0000 _at__at_ -31,7 +31,7 _at__at_ mksyntax mksyntax.o CLEANFILES+= ${GENSRCS} ${GENHDRS} -build-tools: mkinit mknodes mksyntax +build-tools: mksyntax .ORDER: builtins.c builtins.h builtins.c builtins.h: mkbuiltins builtins.def _at__at_ -39,20 +39,18 _at__at_ init.c: mkinit alias.c eval.c exec.c input.c jobs.c options.c parser.c \ redir.c trap.c var.c - ./mkinit ${.ALLSRC:S/^mkinit$//} + sh ${.CURDIR}/mkinit ${.ALLSRC:S/^mkinit$//} # XXX this is just to stop the default .c rule being used, so that the # intermediate object has a fixed name. # XXX we have a default .c rule, but no default .o rule. .o: ${CC} ${CFLAGS} ${LDFLAGS} ${.IMPSRC} ${LDLIBS} -o ${.TARGET} -mkinit: mkinit.o -mknodes: mknodes.o mksyntax: mksyntax.o .ORDER: nodes.c nodes.h nodes.c nodes.h: mknodes nodetypes nodes.c.pat - ./mknodes ${.CURDIR}/nodetypes ${.CURDIR}/nodes.c.pat + sh ${.CURDIR}/mknodes ${.CURDIR}/nodetypes ${.CURDIR}/nodes.c.pat .ORDER: syntax.c syntax.h syntax.c syntax.h: mksyntax --- /dev/null Mon Jun 30 22:15:03 2003 +++ mkinit Mon Jun 30 22:25:04 2003 _at__at_ -0,0 +1,91 _at__at_ +#!/bin/sh + +( # to send output to init.c + +echo "/*" +echo " * This file was generated by the mkinit program." +echo " */" +echo "" +echo '#include "shell.h"' +echo '#include "mystring.h"' + +cat $_at_ | grep '^INCLUDE' | sed -e "s/INCLUDE/#include/" + +echo +echo +echo + +cat $_at_ | sed -n -e '/^#define/ s/#define //p' | grep -v '\\$' | egrep -v '^[A-Z_]+\(' | awk '{print "#undef ",$1; print "#define",$0; }' + +echo +echo + +for f in $_at_ +do + cat $f | sed -n -e '/^MKINIT$/,/^}/ p' -e '/^MKINIT / s/^MKINIT/extern/p' | grep -v '^MKINIT$' + echo +done + +echo +echo +echo "/*" +echo " * Initialization code." +echo " */" + +echo +echo "void" +echo "init() {" + +for f in $_at_ +do + echo " /* from $f: */" + cat $f | sed -n -e '/^INIT/,/^}/ p' | sed -e 's/INIT //' | \ + awk '{print " ",$0;}' OFS='' + echo +done + +echo "}" + +echo +echo +echo + +echo "/*" +echo " * This routine is called when an error or an interrupt occurs in an" +echo " * interactive shell and control is returned to the main command loop." +echo " */" +echo +echo "void" +echo "reset() {" + +for f in $_at_ +do + echo " /* from $f: */" + cat $f | sed -n -e '/^RESET/,/^}/ p' | sed -e 's/RESET //' | \ + awk '{print " ",$0;}' OFS='' + echo +done +echo "}" + +echo +echo +echo +echo "/*" +echo " * This routine is called to initialize the shell to run a shell procedure." +echo " */" +echo +echo "void" +echo "initshellproc() {" + + +for f in $_at_ +do + echo " /* from $f: */" + cat $f | sed -n -e '/^SHELLPROC/,/^}/ p' | sed -e 's/SHELLPROC //' | \ + awk '{print " ",$0;}' OFS='' + echo +done +echo "}" + + +) > init.c --- /dev/null Mon Jun 30 22:15:03 2003 +++ mknodes Mon Jun 30 22:20:58 2003 _at__at_ -0,0 +1,227 _at__at_ +#!/bin/sh + +NODEFILE=$1 +PATFILE=$2 + +# +# The awk scripts are driven by the 'nodetypes' file format, +# which is basically just a set of C structure definitions. +# +# Here's an example entry from nodetypes: +# NSEMI nbinary +# type int +# ch1 nodeptr +# ch2 nodeptr +# +# This says that an 'NSEMI' node uses the 'nbinary' structure; +# the following lines define the structure. Another example: +# +# NWHILE nbinary +# +# This says that an 'NWHILE' node uses the 'nbinary' structure, +# but doesn't define the structure (since it's defined elsewhere). +# Correlating all of this is much simpler with AWK's associative +# arrays than with the old C version. +# + + +########################################################################### +# +# Create nodes.c +# +########################################################################### +( # Spawn a subshell to direct output to nodes.c + + +echo "/*" +echo " * This file was generated by the mknodes program." +echo " */" +echo + +# Emit first part of pattern file +cat $PATFILE | sed -ne '1,/%SIZES/p' | grep -v '%SIZES' + +# Build nodesize[] array +echo 'static const short nodesize[26] = {' + +cat $NODEFILE | sed -nEe '/^N/ s/^N[A-Z]* (n[a-z]*)[[:>:]].*/ ALIGN(sizeof (struct \1)),/ p' + +echo '};' + +# Next part of pattern file +cat $PATFILE | sed -ne '/%SIZES/,/%CALCSIZE/p' \ + | grep -v '%SIZES' | grep -v '%CALCSIZE' + +# Build calcsize function body +cat $NODEFILE | sed -ne '/^N/,$ p' | sed -e 's/#.*//' | awk ' + BEGIN { newentry=0; + print " if (n == NULL)"; + print "\t return;" + print " funcblocksize += nodesize[n->type];" + print " switch (n->type) {" + } + /^N/ { a=$1; f=$2; + cases[f] = cases[f] " " $1; + newentry=1; + } + !/^N/ { if(NF > 1) { # Ignore short lines + if(newentry) { + types = types " " f; + action[f] = "\t break;"; + newentry = 0; + } + if($2 == "nodeptr") { + action[f] = "\t calcsize(n->" f "." $1 ");\n" action[f]; + } else if($2 == "nodelist") { + action[f] = "\t sizenodelist(n->" f "." $1 ");\n" action[f]; + } else if($2 == "string") { + action[f] = "\t funcstringsize += strlen(n->" f "." $1 ") + 1;\n" action[f]; + } + } + } + END { + ntypes = split(types,typesarr," "); + for(nt = 1; nt <= ntypes; ++nt) { + f = typesarr[nt]; + i = split(cases[f],arr," "); + for(n = 1; n <= i; ++n) + print " case " arr[n] ":"; + print action[f]; + } + } +' + +echo " };" + +# Emit next block of pattern file +cat $PATFILE | sed -ne '/%CALCSIZE/,/%COPY/p' \ + | grep -v '%CALCSIZE' | grep -v '%COPY' + +# Build copynode function body + +cat $NODEFILE | sed -ne '/^N/,$ p' | sed 's/#.*//' | awk ' + BEGIN { newentry=0; + print " if (n == NULL)" + print "\t return NULL;" + print " new = funcblock;" + print " funcblock = (char *)funcblock + nodesize[n->type];" + print " switch (n->type) {" + + } + /^N/ { a=$1; f=$2; + cases[f] = cases[f] " " $1; + newentry=1; + } + !/^N/ { if(NF > 1) { + if(newentry) { + types = types " " f; + action[f] = "\t break;"; + newentry = 0; + } + if($1 == "type") { + } else if($2 == "nodeptr") { + action[f] = "\t new->" f "." $1 " = copynode(n->" f "." $1 ");\n" action[f]; + } else if($2 == "nodelist") { + action[f] = "\t new->" f "." $1 " = copynodelist(n->" f "." $1 ");\n" action[f]; + } else if($2 == "string") { + action[f] = "\t new->" f "." $1 " = nodesavestr(n->" f "." $1 ");\n" action[f]; + } else if($2 == "temp") { + # Nothing + } else { + action[f] = "\t new->" f "." $1 " = n->" f "." $1 ";\n" action[f]; + } + } + } + END { + ntypes = split(types,typesarr," "); + for(nt = 1; nt <= ntypes; ++nt) { + f = typesarr[nt]; + i = split(cases[f],arr," "); + for(n = 1; n <= i; ++n) + print " case " arr[n] ":"; + print action[f]; + } + } +' + +echo " };" +echo " new->type = n->type;" + +# Emit final part of pattern file +cat $PATFILE | sed -ne '/%COPY/,$ p' | grep -v '%COPY' + +# End of subshell; here's the promised redirect +) >nodes.c + + +########################################################################### +# +# Create nodes.h +# +########################################################################### +( # Spawn a subshell to direct output to nodes.h + +echo "/*" +echo " * This file was generated by the mknodes program." +echo " */" +echo + +# Print out enum constants +cat $NODEFILE | awk 'BEGIN{i=0;} /^N/ { print "#define " $1 " " i; ++i }' + +echo +echo +echo + +# Print out structure definitions + +cat $NODEFILE | sed -ne '/^N/,$ p' | sed -e 's/#.*//' | awk ' + BEGIN { closeold=0; } + /^N/ { if(closeold) print "};\n\n" + closeold = 0; + t = $2; + } + !/^N/ { if(NF > 1) { + if(t) { + print "struct " t " {"; + struct = struct " struct " t " " t ";\n"; + closeold = 1; + t = 0; + } + + if($2 == "nodeptr") { + print " union node *" $1 ";"; + } else if($2 == "nodelist") { + print " struct nodelist *" $1 ";"; + } else if($2 == "string") { + print " char *" $1 ";"; + } else if($2 == "temp") { + printf " "; + for(i = 3; i <= NF; i++) printf " " $i; + print ";"; + } else { + print " " $2 " " $1 ";"; + } + } + } + END { + if(closeold) print "};\n\n" + print "union node {"; + print " int type;"; + print struct "};"; + } +' + +echo +echo +echo "struct nodelist {" +echo " struct nodelist *next;" +echo " union node *n;" +echo "};" +echo +echo +echo "union node *copyfunc(union node *);" +echo "void freefunc(union node *);" + +# End of subshell; here's the promised redirect +) > nodes.hReceived on Mon Jun 30 2003 - 20:38:13 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:13 UTC