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