#! /bin/sh # $NetBSD: mknodes.sh,v 1.4 2019/01/19 13:08:50 kre Exp $ # Copyright (c) 2003 The NetBSD Foundation, Inc. # All rights reserved. # # This code is derived from software contributed to The NetBSD Foundation # by David Laight. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. nodetypes=$1 nodes_pat=$2 objdir="$3" exec <$nodetypes exec >$objdir/nodes.h.tmp echo "/*" echo " * This file was generated by mknodes.sh" echo " */" echo tagno=0 while IFS=; read -r line; do line="${line%%#*}" IFS=' ' set -- $line IFS= [ -z "$2" ] && continue case "$line" in [" "]* ) IFS=' ' [ $field = 0 ] && struct_list="$struct_list $struct" eval field_${struct}_$field=\"\$*\" eval numfld_$struct=\$field field=$(($field + 1)) ;; * ) define=$1 struct=$2 echo "#define $define $tagno" tagno=$(($tagno + 1)) eval define_$struct=\"\$define_$struct \$define\" struct_define="$struct_define $struct" field=0 ;; esac done echo IFS=' ' for struct in $struct_list; do echo echo echo "struct $struct {" field=0 while eval line=\"\$field_${struct}_$field\" field=$(($field + 1)) [ -n "$line" ] do IFS=' ' set -- $line name=$1 case "$name" in type) if [ -n "$typetype" ] && [ "$typetype" != "$2" ] then echo >&2 "Conflicting type fields: node" \ "$struct has $2, others $typetype" exit 1 fi if [ $field -ne 1 ] then echo >&2 "Node $struct has type as field" \ "$field (should only be first)" exit 1 fi typetype=$2 ;; *) if [ $field -eq 1 ] then echo >&2 "Node $struct does not have" \ "type as first field" exit 1 fi ;; esac case $2 in nodeptr ) type="union node *";; nodelist ) type="struct nodelist *";; string ) type="char *";; int*_t | uint*_t | int ) type="$2 ";; * ) name=; shift 2; type="$*";; esac echo " $type$name;" done echo "};" done echo echo echo "union node {" echo " $typetype type;" for struct in $struct_list; do echo " struct $struct $struct;" done echo "};" echo echo echo "struct nodelist {" echo " struct nodelist *next;" echo " union node *n;" echo "};" echo echo echo 'struct funcdef;' echo 'struct funcdef *copyfunc(union node *);' echo 'union node *getfuncnode(struct funcdef *);' echo 'void reffunc(struct funcdef *);' echo 'void unreffunc(struct funcdef *);' echo 'void freefunc(struct funcdef *);' mv $objdir/nodes.h.tmp $objdir/nodes.h || exit 1 exec <$nodes_pat exec >$objdir/nodes.c.tmp echo "/*" echo " * This file was generated by mknodes.sh" echo " */" echo while IFS=; read -r line; do IFS=' ' set -- $line IFS= case "$1" in '%SIZES' ) echo "static const short nodesize[$tagno] = {" IFS=' ' for struct in $struct_define; do echo " SHELL_ALIGN(sizeof (struct $struct))," done echo "};" ;; '%CALCSIZE' ) echo " if (n == NULL)" echo " return;" echo " res->bsize += nodesize[n->type];" echo " switch (n->type) {" IFS=' ' for struct in $struct_list; do eval defines=\"\$define_$struct\" for define in $defines; do echo " case $define:" done eval field=\$numfld_$struct while [ $field != 0 ] do eval line=\"\$field_${struct}_$field\" field=$(($field - 1)) IFS=' ' set -- $line name=$1 cl=", res)" case $2 in nodeptr ) fn=calcsize;; nodelist ) fn=sizenodelist;; string ) fn="res->ssize += strlen" cl=") + 1";; * ) continue;; esac echo " ${fn}(n->$struct.$name${cl};" done echo " break;" done echo " };" ;; '%COPY' ) echo " if (n == NULL)" echo " return NULL;" echo " new = st->block;" echo " st->block = (char *) st->block + nodesize[n->type];" echo " switch (n->type) {" IFS=' ' for struct in $struct_list; do eval defines=\"\$define_$struct\" for define in $defines; do echo " case $define:" done eval field=\$numfld_$struct while [ $field != 0 ] do eval line=\"\$field_${struct}_$field\" field=$(($field - 1)) IFS=' ' set -- $line name=$1 case $2 in nodeptr ) fn="copynode(";; nodelist ) fn="copynodelist(";; string ) fn="nodesavestr(";; int*_t| uint*_t | int ) fn=;; * ) continue;; esac f="$struct.$name" echo " new->$f = ${fn}n->$f${fn:+, st)};" done echo " break;" done echo " };" echo " new->type = n->type;" ;; * ) echo "$line";; esac done mv $objdir/nodes.c.tmp $objdir/nodes.c || exit 1