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("#if __GNUC__ >= 4\n"); 83 printf("#define offsetof(type, member) __builtin_offsetof(type, member)\n"); 84 printf("#else\n"); 85 printf("#define offsetof(type, member) ((size_t)(&((type *)0)->member))\n"); 86 printf("#endif\n"); 87 defining = 0; 88 type = "long"; 89 asmtype = "n"; 90 asmprint = ""; 91} 92 93{ 94 doing_member = 0; 95} 96 97$0 ~ /^[ \t]*#.*/ || $0 ~ /^[ \t]*$/ { 98 # Just ignore comments and empty lines 99 next; 100} 101 102$0 ~ /^config[ \t]/ { 103 type = $2; 104 asmtype = $3; 105 asmprint = $4; 106 next; 107} 108 109/^include[ \t]/ { 110 if (defining != 0) { 111 defining = 0; 112 printf("}\n"); 113 } 114 printf("#%s\n", $0); 115 next; 116} 117 118$0 ~ /^if[ \t]/ || 119$0 ~ /^ifdef[ \t]/ || 120$0 ~ /^ifndef[ \t]/ || 121$0 ~ /^else/ || 122$0 ~ /^elif[ \t]/ || 123$0 ~ /^endif/ { 124 printf("#%s\n", $0); 125 next; 126} 127 128/^struct[ \t]/ { 129 structname = $2; 130 $0 = "define " structname "_SIZEOF sizeof(struct " structname ")"; 131 # fall through 132} 133 134/^member[ \t]/ { 135 if (NF > 2) 136 $0 = "define " $2 " offsetof(struct " structname ", " $3 ")"; 137 else 138 $0 = "define " $2 " offsetof(struct " structname ", " $2 ")"; 139 doing_member = 1; 140 # fall through 141} 142 143/^export[ \t]/ { 144 $0 = "define " $2 " " $2; 145 # fall through 146} 147 148/^define[ \t]/ { 149 if (defining == 0) { 150 defining = 1; 151 printf("void f" FNR "(void);\n"); 152 printf("void f" FNR "(void) {\n"); 153 if (ccode) 154 call[FNR] = "f" FNR; 155 defining = 1; 156 } 157 value = $0 158 gsub("^define[ \t]+[A-Za-z_][A-Za-z_0-9]*[ \t]+", "", value) 159 if (ccode) 160 printf("printf(\"#define " $2 " %%ld\\n\", (%s)" value ");\n", type); 161 else if (fcode) { 162 if (doing_member) 163 printf("__asm(\"XYZZY : %s d# %%%s0 + ;\" : : \"%s\" (%s));\n", $2, asmprint, asmtype, value); 164 else 165 printf("__asm(\"XYZZY d# %%%s0 constant %s\" : : \"%s\" (%s));\n", asmprint, $2, asmtype, value); 166 } else 167 printf("__asm(\"XYZZY %s %%%s0\" : : \"%s\" (%s));\n", $2, asmprint, asmtype, value); 168 next; 169} 170 171/^quote[ \t]/ { 172 gsub("^quote[ \t]+", ""); 173 print; 174 next; 175} 176 177{ 178 printf("syntax error in line %d\n", FNR) >"/dev/stderr"; 179 exit(1); 180} 181 182END { 183 if (defining != 0) { 184 defining = 0; 185 printf("}\n"); 186 } 187 if (ccode) { 188 printf("int main(int argc, char **argv) {"); 189 for (i in call) 190 printf(call[i] "();"); 191 printf("return(0); }\n"); 192 } 193} 194' ccode=$ccode fcode=$fcode > ${genassym_temp}/assym.c || exit 1 195 196if [ $ccode = 1 ] ; then 197 "$@" ${genassym_temp}/assym.c -o ${genassym_temp}/genassym && \ 198 ${genassym_temp}/genassym 199elif [ $fcode = 1 ]; then 200 # Kill all of the "#" and "$" modifiers; locore.s already 201 # prepends the correct "constant" modifier. 202 "$@" -S ${genassym_temp}/assym.c -o - | sed -e 's/\$//g' | \ 203 sed -n 's/.*XYZZY//gp' 204else 205 # Kill all of the "#" and "$" modifiers; locore.s already 206 # prepends the correct "constant" modifier. 207 "$@" -S ${genassym_temp}/assym.c -o - > \ 208 ${genassym_temp}/genassym.out && \ 209 sed -e 's/#//g' -e 's/\$//g' < ${genassym_temp}/genassym.out | \ 210 sed -n 's/.*XYZZY/#define/gp' 211fi 212