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
@@ -31,7 +31,7 @@
        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
@@ -39,20 +39,18 @@
 
 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
@@ -0,0 +1,91 @@
+#!/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 $@ | grep '^INCLUDE' | sed -e "s/INCLUDE/#include/"
+
+echo
+echo
+echo
+
+cat $@ | 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 $@
+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 $@
+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 $@
+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 $@
+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
@@ -0,0 +1,227 @@
+#!/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.h
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to