|
| 1 | +#!/bin/sh |
| 2 | +# usage: gen-mkfiles.sh {lib|bin|include} Makefile.am |
| 3 | +set -e |
| 4 | + |
| 5 | +if [ $# -ne 3 -a $# -ne 2 ]; then |
| 6 | + echo "usage: $0 {lib|bin|include} Makefile.am" >&2 |
| 7 | + exit 2 |
| 8 | +fi |
| 9 | + |
| 10 | +target=$1 |
| 11 | +wdir=`dirname $2` |
| 12 | +recipe=`basename $2` |
| 13 | + |
| 14 | +cd $wdir |
| 15 | +d=`git rev-parse --show-cdup`. |
| 16 | +top_srcdir=`echo $d | sed 's!/\.$!!'` |
| 17 | + |
| 18 | +# Plan 9 isn't having /dev/stderr, instead it has /fd/2. |
| 19 | +stderr=/dev/stderr |
| 20 | +if [ -w /fd/2 ]; then |
| 21 | + stderr=/fd/2 |
| 22 | +fi |
| 23 | + |
| 24 | +# filename: current filename |
| 25 | +# lineno: current line number of filename |
| 26 | +# vars: variables defined in Makefile.am |
| 27 | +# defs: variables defined in plan9/defs; these will appear in -D flag too |
| 28 | +# ifblock: booleans of nested if-statement; will reverse an value when enter to else |
| 29 | +# ifpos: index of last ifblock |
| 30 | +awk <$recipe ' |
| 31 | +BEGIN { |
| 32 | + stderr = "'"$stderr"'" |
| 33 | + target = "'"$target"'" |
| 34 | + vars["top_srcdir"] = "'"$top_srcdir"'" |
| 35 | + loaddefs(getvar("top_srcdir") "/plan9/defs") |
| 36 | +} |
| 37 | +
|
| 38 | +function loaddefs(file) { |
| 39 | + while((getline s <file) > 0) |
| 40 | + defs[s] = 1 |
| 41 | + close(file) |
| 42 | +} |
| 43 | +
|
| 44 | +function fatal(msg) { |
| 45 | + printf "%s:%d %s\n", filename, lineno, msg >stderr |
| 46 | + exit(1) |
| 47 | +} |
| 48 | +function assign(name, op, value) { |
| 49 | + if(op != "=" && op != "+=") |
| 50 | + fatal(sprintf("unknown operator: %s %s %s", name, op, value)) |
| 51 | + if(op == "=") |
| 52 | + delete vars[name] |
| 53 | + if(value == "") |
| 54 | + return |
| 55 | +
|
| 56 | + if(vars[name] == "") |
| 57 | + vars[name] = value |
| 58 | + else |
| 59 | + vars[name] = vars[name] SUBSEP value |
| 60 | +} |
| 61 | +function expand(s, v) { |
| 62 | + while(match(s, /\$\([a-zA-Z0-9_]+\)/)){ |
| 63 | + v = substr(s, RSTART+2, RLENGTH-3) |
| 64 | + s = substr(s, 1, RSTART-1) vars[v] substr(s, RSTART+RLENGTH) |
| 65 | + } |
| 66 | + return s |
| 67 | +} |
| 68 | +function getvar(name) { |
| 69 | + return expand(vars[name]) |
| 70 | +} |
| 71 | +function getarray(name, a,n,i,u) { |
| 72 | + n = split(getvar(name), a, SUBSEP) |
| 73 | + for(i = 1; i <= n; i++) |
| 74 | + if(a[i] != "") |
| 75 | + a[++u] = a[i] |
| 76 | + return u |
| 77 | +} |
| 78 | +function iftrue( i,r) { |
| 79 | + r = 1 |
| 80 | + for(i = 1; i <= ifpos; i++) |
| 81 | + r = r && ifblock[i] |
| 82 | + return r |
| 83 | +} |
| 84 | +function eval(tokens, n, v,i) { |
| 85 | + if(n == 2 && tokens[1] == "if"){ |
| 86 | + ifpos++ |
| 87 | + v = tokens[2] |
| 88 | + if(v ~ /^!/){ |
| 89 | + v = substr(v, 2) |
| 90 | + ifblock[ifpos] = !(v in defs) |
| 91 | + }else |
| 92 | + ifblock[ifpos] = v in defs |
| 93 | + }else if(n == 1 && tokens[1] == "else"){ |
| 94 | + ifblock[ifpos] = !ifblock[ifpos] |
| 95 | + }else if(n == 1 && tokens[1] == "endif"){ |
| 96 | + ifpos-- |
| 97 | + } |
| 98 | + if(!iftrue()) |
| 99 | + return |
| 100 | +
|
| 101 | + if(n >= 2 && tokens[2] == "=" || tokens[2] == "+="){ |
| 102 | + for(i = 3; i <= n; i++) |
| 103 | + assign(tokens[1], tokens[2], tokens[i]) |
| 104 | + return |
| 105 | + } |
| 106 | + if(n == 2 && tokens[1] == "include") |
| 107 | + evalfile(expand(tokens[2])) |
| 108 | +} |
| 109 | +
|
| 110 | +# evalfile cannot handle nested include directive referenced with relative path. |
| 111 | +function evalfile(file, s,a,i,n) { |
| 112 | + while((getline s <file) > 0){ |
| 113 | + n = split(s, a) |
| 114 | + filename = file |
| 115 | + lineno = ++i |
| 116 | + eval(a, n) |
| 117 | + } |
| 118 | + close(file) |
| 119 | +} |
| 120 | +{ for(i = 1; i <= NF; i++) |
| 121 | + a[i] = $i |
| 122 | + filename = FILENAME |
| 123 | + lineno = FNR |
| 124 | + eval(a, NF) |
| 125 | + next |
| 126 | +} |
| 127 | +
|
| 128 | +function aname(file, n,a) { |
| 129 | + n = split(file, a, "/") |
| 130 | + sub(/\.la$/, ".a", a[n]) |
| 131 | + return a[n] |
| 132 | +} |
| 133 | +function varname(file, name) { |
| 134 | + gsub(/\./, "_", file) |
| 135 | + return file "_" name |
| 136 | +} |
| 137 | +function getarrayof(file, name, a, v) { |
| 138 | + v = varname(file, name) |
| 139 | + return getarray(v, a) |
| 140 | +} |
| 141 | +function merge(a, a1, n1, a2, n2, x,n,i) { |
| 142 | + for(i = 1; i <= n1; i++) |
| 143 | + x[a1[i]] = 1 |
| 144 | + for(i = 1; i <= n2; i++) |
| 145 | + x[a2[i]] = 1 |
| 146 | + for(i in x) |
| 147 | + a[++n] = i |
| 148 | + return n |
| 149 | +} |
| 150 | +function append(a, n, name, a1,n1) { |
| 151 | + n1 = getarray(name, a1) |
| 152 | + return merge(a, a, n, a1, n1) |
| 153 | +} |
| 154 | +function join(a, bp, ep, i,s) { |
| 155 | + for(i = bp; i <= ep; i++){ |
| 156 | + if(s != "") |
| 157 | + s = s " " |
| 158 | + s = s a[i] |
| 159 | + } |
| 160 | + return s |
| 161 | +} |
| 162 | +function dirname(path, a,n) { |
| 163 | + n = split(path, a, "/") |
| 164 | + return join(a, 1, n-1) |
| 165 | +} |
| 166 | +function dirnames(a, n, r, i,x,s) { |
| 167 | + for(i = 1; i <= n; i++){ |
| 168 | + s = dirname(a[i]) |
| 169 | + x[s] = 1 |
| 170 | + } |
| 171 | + n = 0 |
| 172 | + for(s in x) |
| 173 | + r[++n] = s |
| 174 | + return n |
| 175 | +} |
| 176 | +function filter(a, n, path, r, i,u,s) { |
| 177 | + gsub(/\/+$/, "", path) |
| 178 | + for(i = 1; i <= n; i++){ |
| 179 | + s = dirname(a[i]) |
| 180 | + if(s != path) |
| 181 | + continue |
| 182 | + if(path == "") |
| 183 | + r[++u] = a[i] |
| 184 | + else |
| 185 | + r[++u] = substr(a[i], length(s)+2) |
| 186 | + } |
| 187 | + return u |
| 188 | +} |
| 189 | +function objfile(s) { |
| 190 | + sub(/\.c$/, ".$O", s) |
| 191 | + return s |
| 192 | +} |
| 193 | +
|
| 194 | +function collect(m, name, a, n,i,l,x) { |
| 195 | + n = getarrayof(m, name, a) |
| 196 | + l = getarrayof(m, "LIBADD", x) |
| 197 | + for(i = 1; i <= l; i++) |
| 198 | + n = append(a, n, varname(x[i], name)) |
| 199 | + return n |
| 200 | +} |
| 201 | +
|
| 202 | +# staticlibs is called if target is "bin" only. |
| 203 | +function staticlibs(a, m,x,n,i,v,u,c) { |
| 204 | + m = getvar("bin_PROGRAMS") |
| 205 | + n = getarrayof(m, "LDADD", x) |
| 206 | + for(i = 1; i <= n; i++){ |
| 207 | + u = getarrayof(x[i], "SOURCES", v) |
| 208 | + if(u == 0) |
| 209 | + a[++c] = x[i] |
| 210 | + } |
| 211 | + return c |
| 212 | +} |
| 213 | +
|
| 214 | +END { |
| 215 | + if(target == "include"){ |
| 216 | + # TODO(lufia) |
| 217 | + key = "include_HEADERS" |
| 218 | + exit(0) |
| 219 | + } |
| 220 | + if(target == "lib") |
| 221 | + key = "lib_LTLIBRARIES" |
| 222 | + else if(target == "bin") |
| 223 | + key = "bin_PROGRAMS" |
| 224 | + else |
| 225 | + fatal(sprintf("invalid target: %s", target)) |
| 226 | + m = getvar(key) |
| 227 | + nc = collect(m, "SOURCES", cfiles) |
| 228 | + nh = getarray("noinst_HEADERS", hfiles) |
| 229 | + ndir = dirnames(cfiles, nc, dirs) |
| 230 | + root = vars["top_srcdir"] |
| 231 | + for(i = 1; i <= ndir; i++){ |
| 232 | + wfile = combine(dirs[i], "mkfile") |
| 233 | + mkfilehdr(wfile) |
| 234 | +
|
| 235 | + s = relative(dirs[i]) |
| 236 | + vars["top_srcdir"] = combine(s, root) |
| 237 | + n = filter(cfiles, nc, dirs[i], a) |
| 238 | + qsort(a, 1, n) |
| 239 | + print "OFILES=\\" >>wfile |
| 240 | + for(j = 1; j <= n; j++) |
| 241 | + printf "\t%s\\\n", objfile(a[j]) >>wfile |
| 242 | + print "" >>wfile |
| 243 | + n = filter(hfiles, nh, dirs[i], a) |
| 244 | + if(n > 0){ |
| 245 | + qsort(a, 1, n) |
| 246 | + print "HFILES=\\" >>wfile |
| 247 | + for(j = 1; j <= n; j++) |
| 248 | + printf "\t%s\\\n", a[j] >>wfile |
| 249 | + print "" >>wfile |
| 250 | + } |
| 251 | +
|
| 252 | + if(target == "lib"){ |
| 253 | + printf "LIB=/$objtype/lib/ape/%s\n", aname(m) >>wfile |
| 254 | + print "" >>wfile |
| 255 | + print "</sys/src/cmd/mklib" >>wfile |
| 256 | + }else if(target == "bin"){ |
| 257 | + n = staticlibs(a) |
| 258 | + if(n > 0){ |
| 259 | + print "LIB=\\" >>wfile |
| 260 | + for(i = 1; i <= n; i++) |
| 261 | + printf "\t/$objtype/lib/ape/%s\\\n", aname(a[i]) >>wfile |
| 262 | + print "" >>wfile |
| 263 | + } |
| 264 | + print "BIN=/$objtype/bin" >>wfile |
| 265 | + print "TARG=" m >>wfile |
| 266 | + print "" >>wfile |
| 267 | + print "</sys/src/cmd/mkone" >>wfile |
| 268 | + } |
| 269 | + close(wfile) |
| 270 | + } |
| 271 | +} |
| 272 | +
|
| 273 | +function mkfilehdr(wfile, a,n,i,name) { |
| 274 | + print "</sys/src/ape/config" >wfile |
| 275 | + #printf "<%s/mkfile.proto\n", getvar("top_srcdir") |
| 276 | + print "" >>wfile |
| 277 | + print "CFLAGS=$CFLAGS -c\\" >>wfile |
| 278 | + for(name in defs) |
| 279 | + a[++n] = "-D" name |
| 280 | + n = append(a, n, "AM_CFLAGS") |
| 281 | + n = append(a, n, "AM_CPPFLAGS") |
| 282 | + qsort(a, 1, n) |
| 283 | + for(i = 1; i <= n; i++) |
| 284 | + printf "\t%s\\\n", a[i] >>wfile |
| 285 | + print "" >>wfile |
| 286 | +} |
| 287 | +function relative(path) { |
| 288 | + gsub(/[^\/]+/, "..", path) |
| 289 | + return path |
| 290 | +} |
| 291 | +function combine(p, q) { |
| 292 | + if(p == "" || p == ".") |
| 293 | + return q |
| 294 | + return sprintf("%s/%s", p, q) |
| 295 | +} |
| 296 | +function swap(a, i, j, v) { |
| 297 | + v = a[i] |
| 298 | + a[i] = a[j] |
| 299 | + a[j] = v |
| 300 | +} |
| 301 | +function qsort(a, l, r, last,i) { |
| 302 | + if(l >= r) |
| 303 | + return |
| 304 | + swap(a, l, int((l+r)/2)) |
| 305 | + last = l |
| 306 | + for(i = l+1; i <= r; i++) |
| 307 | + if(a[i] < a[l]) |
| 308 | + swap(a, ++last, i) |
| 309 | + swap(a, l, last) |
| 310 | + qsort(a, l, last-1) |
| 311 | + qsort(a, last+1, r) |
| 312 | +} |
| 313 | +' |
0 commit comments