1 #! /bin/sh 2 3 # $NetBSD: mkoptions.sh,v 1.9 2024/10/11 08:53:09 kre Exp $ 4 5 # 6 # It would be more sensible to generate 2 .h files, one which 7 # is for everyone to use, defines the "variables" and (perhaps) generates 8 # the externs (though they could just be explicit in options.h) 9 # and one just for options.c which generates the initialisation. 10 # 11 # But then I'd have to deal with making the Makefile handle that properly... 12 # (this is simpler there, and it just means a bit more sh compile time.) 13 14 set -f 15 IFS=' ' # blank, tab (no newline) 16 export LC_ALL=C # for sort consistency 17 18 IF="$1" 19 OF="${3+$3/}$2" 20 21 case $- in 22 *x*) 23 E_FILE=$(${MKTEMP:-mktemp} "${TMPDIR:-/tmp}/MKO.E.$$.XXXXXX") || exit 1 24 O_FILE=$(${MKTEMP:-mktemp} "${TMPDIR:-/tmp}/MKO.O.$$.XXXXXX") || { 25 rm -f "${E_FILE}" 26 exit 1 27 } 28 ;; 29 *) 30 E_FILE=$(${MKTEMP:-mktemp}) || exit 1 31 O_FILE=$(${MKTEMP:-mktemp}) || { rm -f "${E_FILE}"; exit 1; } 32 trap 'rm -f "${E_FILE}" "${O_FILE}"' EXIT 33 ;; 34 esac 35 36 exec 5> "${E_FILE}" 37 exec 6> "${O_FILE}" 38 39 { 40 printf '/*\n * File automatically generated by %s.\n' "$0" 41 printf ' * Do not edit, do not add to cvs.\n' 42 printf ' */\n\n' 43 44 printf '#ifdef DEFINE_OPTIONS\n' 45 printf 'struct optent optlist[] = {\n' 46 } >"${OF}" 47 48 FIRST=true 49 50 ${SED:-sed} <"${IF}" \ 51 -e '/^$/d' \ 52 -e '/^#/d' \ 53 -e '/^[ ]*\//d' \ 54 -e '/^[ ]*\*/d' \ 55 -e '/^[ ]*;/d' | 56 sort -k2b,2f -k2b,2 | 57 while read line 58 do 59 # Look for comments in various styles, and ignore them 60 # (these should generally be already removed by sed above) 61 62 case "${line}" in 63 '') continue;; 64 /*) continue;; 65 \**) continue;; 66 \;*) continue;; 67 \#*) continue;; 68 esac 69 70 case "${line}" in 71 *'#if'*) 72 COND="${line#*#}" 73 COND="#${COND%%#*}" 74 ;; 75 *) 76 COND= 77 ;; 78 esac 79 set -- ${line%%[ ]#*} 80 81 var="$1" name="$2" 82 83 case "${var}" in 84 ('' | [!A-Za-z_]* | *[!A-Za-z0-9_]*) 85 printf >&2 "Bad var name: '%s'\\n" "${var}" 86 # exit 1 87 continue # just ignore it for now 88 esac 89 90 case "${name}" in 91 ?) set -- ${var} '' $name $3 $4; name= ;; 92 esac 93 94 chr="$3" set="$4" dflt="$5" 95 96 case "${chr}" in 97 -) chr= set= dflt="$4";; 98 +) chr= ;; 99 ''|?) ;; 100 *) printf >&2 'flag "%s": Not a character\n' "${chr}"; continue;; 101 esac 102 103 # options must have some kind of name, or they are useless... 104 test -z "${name}${chr}" && continue 105 106 case "${set}" in 107 -) set= ;; 108 [01] | [Oo][Nn] | [Oo][Ff][Ff]) dflt="${set}"; set= ;; 109 ''|?) ;; 110 *) printf >&2 'set "%s": Not a character\n' "${set}"; continue;; 111 esac 112 113 case "${dflt}" in 114 '') ;; 115 [Oo][Nn]) dflt=1;; 116 [Oo][Ff][Ff]) dflt=0;; 117 [01]) ;; 118 *) printf >&2 'default "%s" invalid, use 0 off 1 on\n'; continue;; 119 esac 120 121 # validation complete, now to generate output 122 123 if [ -n "${COND}" ] 124 then 125 printf '%s\n' "${COND}" >&4 126 printf '%s\n' "${COND}" >&5 127 printf '%s\n' "${COND}" >&6 128 fi 129 130 printf '\t_SH_OPT_%s,\n' "${var}" >&5 131 132 if [ -n "${name}" ] 133 then 134 printf ' { "%s", ' "${name}" >&4 135 else 136 printf ' { 0, ' >&4 137 fi 138 139 if [ -n "${chr}" ] 140 then 141 printf "'%s', " "${chr}" >&4 142 else 143 chr= 144 printf '0, ' >&4 145 fi 146 147 if [ -n "${set}" ] 148 then 149 printf "'%s', 0, " "${set}" >&4 150 else 151 printf '0, 0, ' >&4 152 fi 153 154 if [ -n "${dflt}" ] 155 then 156 printf '%s },\n' "${dflt}" >&4 157 else 158 printf '0 },\n' >&4 159 fi 160 161 printf '#define %s\toptlist[_SH_OPT_%s].val\n' "${var}" "${var}" >&6 162 163 if [ -n "${COND}" ] 164 then 165 printf '#endif\n' >&4 166 printf '#endif\n' >&5 167 printf '#endif\n' >&6 168 fi 169 170 test -z "${chr}" && continue 171 172 printf '%s _SH_OPT_%s %s\n' "${chr}" "${var}" "${COND}" 173 174 done 4>>"${OF}" | sort -t' ' -k1,1f -k1,1 | while read chr index COND 175 do 176 if $FIRST 177 then 178 printf ' { 0, 0, 0, 0, 0 }\n};\n' 179 printf '#endif\n\n' 180 181 printf 'enum shell_opt_names {\n' 182 cat "${E_FILE}" 183 printf '};\n\n' 184 185 printf '#ifdef DEFINE_OPTIONS\n' 186 printf 'const unsigned char optorder[] = {\n' 187 FIRST=false 188 fi 189 [ -n "${COND}" ] && printf '%s\n' "${COND}" 190 printf '\t%s,\n' "${index}" 191 [ -n "${COND}" ] && printf '#endif\n' 192 193 done >>"${OF}" 194 195 { 196 printf '};\n\n' 197 printf '#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)\n' 198 printf 'int sizeof_optlist = sizeof optlist;\n\n' 199 printf \ 200 'const int option_flags = (sizeof optorder / sizeof optorder[0]);\n' 201 printf '\n#else\n\n' 202 printf 'extern struct optent optlist[];\n' 203 printf 'extern int sizeof_optlist;\n' 204 printf 'extern const unsigned char optorder[];\n' 205 printf 'extern const int option_flags;\n' 206 printf '\n#endif\n\n' 207 208 cat "${O_FILE}" 209 } >> "${OF}" 210 211 exit 0 212