Skip to content

Commit

Permalink
[WIP]add files to generate mkfiles on Plan 9
Browse files Browse the repository at this point in the history
  • Loading branch information
lufia committed May 22, 2019
1 parent a1e979f commit cd79456
Show file tree
Hide file tree
Showing 2 changed files with 327 additions and 0 deletions.
313 changes: 313 additions & 0 deletions gen-mkfile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
#!/bin/sh
# usage: gen-mkfiles.sh {lib|bin|include} Makefile.am
set -e

if [ $# -ne 3 -a $# -ne 2 ]; then
echo "usage: $0 {lib|bin|include} Makefile.am" >&2
exit 2
fi

target=$1
wdir=`dirname $2`
recipe=`basename $2`

cd $wdir
d=`git rev-parse --show-cdup`.
top_srcdir=`echo $d | sed 's!/\.$!!'`

# Plan 9 isn't having /dev/stderr, instead it has /fd/2.
stderr=/dev/stderr
if [ -w /fd/2 ]; then
stderr=/fd/2
fi

# filename: current filename
# lineno: current line number of filename
# vars: variables defined in Makefile.am
# defs: variables defined in plan9/defs; these will appear in -D flag too
# ifblock: booleans of nested if-statement; will reverse an value when enter to else
# ifpos: index of last ifblock
awk <$recipe '
BEGIN {
stderr = "'"$stderr"'"
target = "'"$target"'"
vars["top_srcdir"] = "'"$top_srcdir"'"
loaddefs(getvar("top_srcdir") "/plan9/defs")
}
function loaddefs(file) {
while((getline s <file) > 0)
defs[s] = 1
close(file)
}
function fatal(msg) {
printf "%s:%d %s\n", filename, lineno, msg >stderr
exit(1)
}
function assign(name, op, value) {
if(op != "=" && op != "+=")
fatal(sprintf("unknown operator: %s %s %s", name, op, value))
if(op == "=")
delete vars[name]
if(value == "")
return
if(vars[name] == "")
vars[name] = value
else
vars[name] = vars[name] SUBSEP value
}
function expand(s, v) {
while(match(s, /\$\([a-zA-Z0-9_]+\)/)){
v = substr(s, RSTART+2, RLENGTH-3)
s = substr(s, 1, RSTART-1) vars[v] substr(s, RSTART+RLENGTH)
}
return s
}
function getvar(name) {
return expand(vars[name])
}
function getarray(name, a,n,i,u) {
n = split(getvar(name), a, SUBSEP)
for(i = 1; i <= n; i++)
if(a[i] != "")
a[++u] = a[i]
return u
}
function iftrue( i,r) {
r = 1
for(i = 1; i <= ifpos; i++)
r = r && ifblock[i]
return r
}
function eval(tokens, n, v,i) {
if(n == 2 && tokens[1] == "if"){
ifpos++
v = tokens[2]
if(v ~ /^!/){
v = substr(v, 2)
ifblock[ifpos] = !(v in defs)
}else
ifblock[ifpos] = v in defs
}else if(n == 1 && tokens[1] == "else"){
ifblock[ifpos] = !ifblock[ifpos]
}else if(n == 1 && tokens[1] == "endif"){
ifpos--
}
if(!iftrue())
return
if(n >= 2 && tokens[2] == "=" || tokens[2] == "+="){
for(i = 3; i <= n; i++)
assign(tokens[1], tokens[2], tokens[i])
return
}
if(n == 2 && tokens[1] == "include")
evalfile(expand(tokens[2]))
}
# evalfile cannot handle nested include directive referenced with relative path.
function evalfile(file, s,a,i,n) {
while((getline s <file) > 0){
n = split(s, a)
filename = file
lineno = ++i
eval(a, n)
}
close(file)
}
{ for(i = 1; i <= NF; i++)
a[i] = $i
filename = FILENAME
lineno = FNR
eval(a, NF)
next
}
function aname(file, n,a) {
n = split(file, a, "/")
sub(/\.la$/, ".a", a[n])
return a[n]
}
function varname(file, name) {
gsub(/\./, "_", file)
return file "_" name
}
function getarrayof(file, name, a, v) {
v = varname(file, name)
return getarray(v, a)
}
function merge(a, a1, n1, a2, n2, x,n,i) {
for(i = 1; i <= n1; i++)
x[a1[i]] = 1
for(i = 1; i <= n2; i++)
x[a2[i]] = 1
for(i in x)
a[++n] = i
return n
}
function append(a, n, name, a1,n1) {
n1 = getarray(name, a1)
return merge(a, a, n, a1, n1)
}
function join(a, bp, ep, i,s) {
for(i = bp; i <= ep; i++){
if(s != "")
s = s " "
s = s a[i]
}
return s
}
function dirname(path, a,n) {
n = split(path, a, "/")
return join(a, 1, n-1)
}
function dirnames(a, n, r, i,x,s) {
for(i = 1; i <= n; i++){
s = dirname(a[i])
x[s] = 1
}
n = 0
for(s in x)
r[++n] = s
return n
}
function filter(a, n, path, r, i,u,s) {
gsub(/\/+$/, "", path)
for(i = 1; i <= n; i++){
s = dirname(a[i])
if(s != path)
continue
if(path == "")
r[++u] = a[i]
else
r[++u] = substr(a[i], length(s)+2)
}
return u
}
function objfile(s) {
sub(/\.c$/, ".$O", s)
return s
}
function collect(m, name, a, n,i,l,x) {
n = getarrayof(m, name, a)
l = getarrayof(m, "LIBADD", x)
for(i = 1; i <= l; i++)
n = append(a, n, varname(x[i], name))
return n
}
# staticlibs is called if target is "bin" only.
function staticlibs(a, m,x,n,i,v,u,c) {
m = getvar("bin_PROGRAMS")
n = getarrayof(m, "LDADD", x)
for(i = 1; i <= n; i++){
u = getarrayof(x[i], "SOURCES", v)
if(u == 0)
a[++c] = x[i]
}
return c
}
END {
if(target == "include"){
# TODO(lufia)
key = "include_HEADERS"
exit(0)
}
if(target == "lib")
key = "lib_LTLIBRARIES"
else if(target == "bin")
key = "bin_PROGRAMS"
else
fatal(sprintf("invalid target: %s", target))
m = getvar(key)
nc = collect(m, "SOURCES", cfiles)
nh = getarray("noinst_HEADERS", hfiles)
ndir = dirnames(cfiles, nc, dirs)
root = vars["top_srcdir"]
for(i = 1; i <= ndir; i++){
wfile = combine(dirs[i], "mkfile")
mkfilehdr(wfile)
s = relative(dirs[i])
vars["top_srcdir"] = combine(s, root)
n = filter(cfiles, nc, dirs[i], a)
qsort(a, 1, n)
print "OFILES=\\" >>wfile
for(j = 1; j <= n; j++)
printf "\t%s\\\n", objfile(a[j]) >>wfile
print "" >>wfile
n = filter(hfiles, nh, dirs[i], a)
if(n > 0){
qsort(a, 1, n)
print "HFILES=\\" >>wfile
for(j = 1; j <= n; j++)
printf "\t%s\\\n", a[j] >>wfile
print "" >>wfile
}
if(target == "lib"){
printf "LIB=/$objtype/lib/ape/%s\n", aname(m) >>wfile
print "" >>wfile
print "</sys/src/cmd/mklib" >>wfile
}else if(target == "bin"){
n = staticlibs(a)
if(n > 0){
print "LIB=\\" >>wfile
for(i = 1; i <= n; i++)
printf "\t/$objtype/lib/ape/%s\\\n", aname(a[i]) >>wfile
print "" >>wfile
}
print "BIN=/$objtype/bin" >>wfile
print "TARG=" m >>wfile
print "" >>wfile
print "</sys/src/cmd/mkone" >>wfile
}
close(wfile)
}
}
function mkfilehdr(wfile, a,n,i,name) {
print "</sys/src/ape/config" >wfile
#printf "<%s/mkfile.proto\n", getvar("top_srcdir")
print "" >>wfile
print "CFLAGS=$CFLAGS -c\\" >>wfile
for(name in defs)
a[++n] = "-D" name
n = append(a, n, "AM_CFLAGS")
n = append(a, n, "AM_CPPFLAGS")
qsort(a, 1, n)
for(i = 1; i <= n; i++)
printf "\t%s\\\n", a[i] >>wfile
print "" >>wfile
}
function relative(path) {
gsub(/[^\/]+/, "..", path)
return path
}
function combine(p, q) {
if(p == "" || p == ".")
return q
return sprintf("%s/%s", p, q)
}
function swap(a, i, j, v) {
v = a[i]
a[i] = a[j]
a[j] = v
}
function qsort(a, l, r, last,i) {
if(l >= r)
return
swap(a, l, int((l+r)/2))
last = l
for(i = l+1; i <= r; i++)
if(a[i] < a[l])
swap(a, ++last, i)
swap(a, l, last)
qsort(a, l, last-1)
qsort(a, last+1, r)
}
'
14 changes: 14 additions & 0 deletions plan9/defs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
HOST_PLAN9
Plan9
_POSIX_SOURCE
_PLAN9_SOURCE
_BSD_EXTENSION
_SUSV2_SOURCE
_RESEARCH_SOURCE
_REENTRANT_SOURCE
HAVE_ARC4RANDOM_BUF
HAVE_GETENTROPY
HAVE_SOCK_OPTS
HAVE_STRCASECMP
HAVE_GETPAGESIZE
HAVE_GETPROGNAME

0 comments on commit cd79456

Please sign in to comment.