1#!/bin/sh - 2# $NetBSD: genassym.sh,v 1.4 2008/10/19 22:10:05 apb Exp $ 3# 4# Copyright (c) 1997 Matthias Pfaller. 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 3. All advertising materials mentioning features or use of this software 16# must display the following acknowledgement: 17# This product includes software developed by Matthias Pfaller. 18# 4. The name of the author may not be used to endorse or promote products 19# derived from this software without specific prior written permission 20# 21# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31# 32 33progname=${0} 34: ${AWK:=awk} 35 36ccode=0 # generate temporary C file, compile it, execute result 37fcode=0 # generate Forth code 38 39usage() 40{ 41 42 echo "usage: ${progname} [-c | -f] -- compiler command" >&2 43} 44 45args=`getopt cf $*` 46if [ $? != 0 ]; then 47 usage; 48 exit 1; 49fi 50set -- $args 51 52for i; do 53 case "$i" in 54 -c) 55 ccode=1 56 shift;; 57 -f) 58 fcode=1 59 shift;; 60 --) 61 shift; break;; 62 esac 63done 64 65# Deal with any leading environment settings.. 66 67while [ "$1" ] 68do 69 case "$1" in 70 *=*) 71 eval export "$1" 72 shift 73 ;; 74 *) 75 break 76 ;; 77 esac 78done 79 80genassym_temp=/tmp/genassym.$$ 81 82if ! mkdir $genassym_temp; then 83 echo "${progname}: unable to create temporary directory" >&2 84 exit 1 85fi 86trap "rm -rf $genassym_temp" 0 1 2 3 15 87 88$AWK ' 89BEGIN { 90 printf("#define offsetof(type, member) ((size_t)(&((type *)0)->member))\n"); 91 defining = 0; 92 type = "long"; 93 asmtype = "n"; 94 asmprint = ""; 95} 96 97{ 98 doing_member = 0; 99} 100 101$0 ~ /^[ \t]*#.*/ || $0 ~ /^[ \t]*$/ { 102 # Just ignore comments and empty lines 103 next; 104} 105 106$0 ~ /^config[ \t]/ { 107 type = $2; 108 asmtype = $3; 109 asmprint = $4; 110 next; 111} 112 113/^include[ \t]/ { 114 if (defining != 0) { 115 defining = 0; 116 printf("}\n"); 117 } 118 printf("#%s\n", $0); 119 next; 120} 121 122$0 ~ /^if[ \t]/ || 123$0 ~ /^ifdef[ \t]/ || 124$0 ~ /^ifndef[ \t]/ || 125$0 ~ /^else/ || 126$0 ~ /^elif[ \t]/ || 127$0 ~ /^endif/ { 128 printf("#%s\n", $0); 129 next; 130} 131 132/^struct[ \t]/ { 133 structname = $2; 134 $0 = "define " structname "_SIZEOF sizeof(struct " structname ")"; 135 # fall through 136} 137 138/^member[ \t]/ { 139 if (NF > 2) 140 $0 = "define " $2 " offsetof(struct " structname ", " $3 ")"; 141 else 142 $0 = "define " $2 " offsetof(struct " structname ", " $2 ")"; 143 doing_member = 1; 144 # fall through 145} 146 147/^export[ \t]/ { 148 $0 = "define " $2 " " $2; 149 # fall through 150} 151 152/^define[ \t]/ { 153 if (defining == 0) { 154 defining = 1; 155 printf("void f" FNR "(void);\n"); 156 printf("void f" FNR "(void) {\n"); 157 if (ccode) 158 call[FNR] = "f" FNR; 159 defining = 1; 160 } 161 value = $0 162 gsub("^define[ \t]+[A-Za-z_][A-Za-z_0-9]*[ \t]+", "", value) 163 if (ccode) 164 printf("printf(\"#define " $2 " %%ld\\n\", (%s)" value ");\n", type); 165 else if (fcode) { 166 if (doing_member) 167 printf("__asm(\"XYZZY : %s d# %%%s0 + ;\" : : \"%s\" (%s));\n", $2, asmprint, asmtype, value); 168 else 169 printf("__asm(\"XYZZY d# %%%s0 constant %s\" : : \"%s\" (%s));\n", asmprint, $2, asmtype, value); 170 } else 171 printf("__asm(\"XYZZY %s %%%s0\" : : \"%s\" (%s));\n", $2, asmprint, asmtype, value); 172 next; 173} 174 175/^quote[ \t]/ { 176 gsub("^quote[ \t]+", ""); 177 print; 178 next; 179} 180 181{ 182 printf("syntax error in line %d\n", FNR) >"/dev/stderr"; 183 exit(1); 184} 185 186END { 187 if (defining != 0) { 188 defining = 0; 189 printf("}\n"); 190 } 191 if (ccode) { 192 printf("int main(int argc, char **argv) {"); 193 for (i in call) 194 printf(call[i] "();"); 195 printf("return(0); }\n"); 196 } 197} 198' ccode=$ccode fcode=$fcode > ${genassym_temp}/assym.c || exit 1 199 200if [ $ccode = 1 ] ; then 201 "$@" ${genassym_temp}/assym.c -o ${genassym_temp}/genassym && \ 202 ${genassym_temp}/genassym 203elif [ $fcode = 1 ]; then 204 # Kill all of the "#" and "$" modifiers; locore.s already 205 # prepends the correct "constant" modifier. 206 "$@" -S ${genassym_temp}/assym.c -o - | sed -e 's/\$//g' | \ 207 sed -n 's/.*XYZZY//gp' 208else 209 # Kill all of the "#" and "$" modifiers; locore.s already 210 # prepends the correct "constant" modifier. 211 "$@" -S ${genassym_temp}/assym.c -o - > \ 212 ${genassym_temp}/genassym.out && \ 213 sed -e 's/#//g' -e 's/\$//g' < ${genassym_temp}/genassym.out | \ 214 sed -n 's/.*XYZZY/#define/gp' 215fi 216