1#!/bin/sh - 2# $NetBSD: genassym.sh,v 1.8 2014/01/06 22:43:15 christos 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="$(basename "${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 40set -e 41 42while getopts cf i 43do 44 case "$i" in 45 c) 46 ccode=1 47 ;; 48 f) 49 fcode=1 50 ;; 51 esac 52done 53shift "$(($OPTIND - 1))" 54if [ $# -eq 0 ]; then 55 usage 56 exit 1 57fi 58 59# Deal with any leading environment settings.. 60 61while [ -n "$1" ] 62do 63 case "$1" in 64 *=*) 65 eval export "$1" 66 shift 67 ;; 68 *) 69 break 70 ;; 71 esac 72done 73 74genassym_temp="$(mktemp -d "${TMPDIR-/tmp}/genassym.XXXXXX")" 75 76 77if [ ! -d $genassym_temp ]; then 78 echo "${progname}: unable to create temporary directory" >&2 79 exit 1 80fi 81trap "rm -rf $genassym_temp" 0 1 2 3 15 82 83$AWK ' 84BEGIN { 85 printf("#if __GNUC__ >= 4\n"); 86 printf("#define offsetof(type, member) __builtin_offsetof(type, member)\n"); 87 printf("#else\n"); 88 printf("#define offsetof(type, member) ((size_t)(&((type *)0)->member))\n"); 89 printf("#endif\n"); 90 defining = 0; 91 type = "long"; 92 asmtype = "n"; 93 asmprint = ""; 94} 95 96{ 97 doing_member = 0; 98} 99 100$0 ~ /^[ \t]*#.*/ || $0 ~ /^[ \t]*$/ { 101 # Just ignore comments and empty lines 102 next; 103} 104 105$0 ~ /^config[ \t]/ { 106 type = $2; 107 asmtype = $3; 108 asmprint = $4; 109 next; 110} 111 112/^include[ \t]/ { 113 if (defining != 0) { 114 defining = 0; 115 printf("}\n"); 116 } 117 printf("#%s\n", $0); 118 next; 119} 120 121$0 ~ /^if[ \t]/ || 122$0 ~ /^ifdef[ \t]/ || 123$0 ~ /^ifndef[ \t]/ || 124$0 ~ /^else/ || 125$0 ~ /^elif[ \t]/ || 126$0 ~ /^endif/ { 127 printf("#%s\n", $0); 128 next; 129} 130 131/^struct[ \t]/ { 132 structname = $2; 133 $0 = "define " structname "_SIZEOF sizeof(struct " structname ")"; 134 # fall through 135} 136 137/^member[ \t]/ { 138 if (NF > 2) 139 $0 = "define " $2 " offsetof(struct " structname ", " $3 ")"; 140 else 141 $0 = "define " $2 " offsetof(struct " structname ", " $2 ")"; 142 doing_member = 1; 143 # fall through 144} 145 146/^export[ \t]/ { 147 $0 = "define " $2 " " $2; 148 # fall through 149} 150 151/^define[ \t]/ { 152 if (defining == 0) { 153 defining = 1; 154 printf("void f" FNR "(void);\n"); 155 printf("void f" FNR "(void) {\n"); 156 if (ccode) 157 call[FNR] = "f" FNR; 158 defining = 1; 159 } 160 value = $0 161 gsub("^define[ \t]+[A-Za-z_][A-Za-z_0-9]*[ \t]+", "", value) 162 if (ccode) 163 printf("printf(\"#define " $2 " %%ld\\n\", (%s)" value ");\n", type); 164 else if (fcode) { 165 if (doing_member) 166 printf("__asm(\"XYZZY : %s d# %%%s0 + ;\" : : \"%s\" (%s));\n", $2, asmprint, asmtype, value); 167 else 168 printf("__asm(\"XYZZY d# %%%s0 constant %s\" : : \"%s\" (%s));\n", asmprint, $2, asmtype, value); 169 } else 170 printf("__asm(\"XYZZY %s %%%s0\" : : \"%s\" (%s));\n", $2, asmprint, asmtype, value); 171 next; 172} 173 174/^quote[ \t]/ { 175 gsub("^quote[ \t]+", ""); 176 print; 177 next; 178} 179 180{ 181 printf("syntax error in line %d\n", FNR) >"/dev/stderr"; 182 exit(1); 183} 184 185END { 186 if (defining != 0) { 187 defining = 0; 188 printf("}\n"); 189 } 190 if (ccode) { 191 printf("int main(int argc, char **argv) {"); 192 for (i in call) 193 printf(call[i] "();"); 194 printf("return(0); }\n"); 195 } 196} 197' ccode="$ccode" fcode="$fcode" > "${genassym_temp}/assym.c" || exit 1 198 199if [ "$ccode" = 1 ]; then 200 "$@" "${genassym_temp}/assym.c" -o "${genassym_temp}/genassym" && \ 201 "${genassym_temp}/genassym" 202elif [ "$fcode" = 1 ]; then 203 # Kill all of the "#" and "$" modifiers; locore.s already 204 # prepends the correct "constant" modifier. 205 "$@" -S "${genassym_temp}/assym.c" -o - | sed -e 's/\$//g' | \ 206 sed -n 's/.*XYZZY//gp' 207else 208 # Kill all of the "#" and "$" modifiers; locore.s already 209 # prepends the correct "constant" modifier. 210 "$@" -S "${genassym_temp}/assym.c" -o - > \ 211 "${genassym_temp}/genassym.out" && \ 212 sed -e 's/#//g' -e 's/\$//g' < "${genassym_temp}/genassym.out" | \ 213 sed -n 's/.*XYZZY/#define/gp' 214fi 215