1#!/bin/sh - 2# $OpenBSD: genassym.sh,v 1.4 2020/04/02 06:06:22 otto Exp $ 3# $NetBSD: genassym.sh,v 1.8 2014/01/06 22:43:15 christos Exp $ 4# 5# Copyright (c) 1997 Matthias Pfaller. 6# All rights reserved. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27# 28 29progname="$(basename "${0}")" 30: ${AWK:=awk} 31 32ccode=0 # generate temporary C file, compile it, execute result 33fcode=0 # generate Forth code 34 35usage() 36{ 37 38 echo "usage: ${progname} [-c | -f] -- compiler command" >&2 39} 40 41set -e 42 43while getopts cf i 44do 45 case "$i" in 46 c) 47 ccode=1 48 ;; 49 f) 50 fcode=1 51 ;; 52 esac 53done 54shift "$(($OPTIND - 1))" 55if [ $# -eq 0 ]; then 56 usage 57 exit 1 58fi 59 60# Deal with any leading environment settings.. 61 62while [ -n "$1" ] 63do 64 case "$1" in 65 *=*) 66 eval export "$1" 67 shift 68 ;; 69 *) 70 break 71 ;; 72 esac 73done 74 75genassym_temp="$(mktemp -d "${TMPDIR-/tmp}/genassym.XXXXXX")" 76 77 78if [ ! -d $genassym_temp ]; then 79 echo "${progname}: unable to create temporary directory" >&2 80 exit 1 81fi 82trap "rm -rf $genassym_temp" 0 1 2 3 15 83 84$AWK ' 85BEGIN { 86 printf("#if __GNUC__ >= 4\n"); 87 printf("#define offsetof(type, member) __builtin_offsetof(type, member)\n"); 88 printf("#else\n"); 89 printf("#define offsetof(type, member) ((size_t)(&((type *)0)->member))\n"); 90 printf("#endif\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