434 lines
10 KiB
Bash
Executable File
434 lines
10 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# gconf - generate config table for ARCS standalone libsk programs.
|
|
#
|
|
# usage: gconf [filename] [targetdir]
|
|
#
|
|
# Gconf generates a configuration table for built-in devices, filesystems,
|
|
# networks, and tuneable variables. The major use is to convey the
|
|
# inventory topology by listing device install routines, and their parent.
|
|
#
|
|
# Gconf will output filename.c (special case for file.cf -> file.c which
|
|
# should be the norm for co-existance with make). With no parameter it
|
|
# operates on file 'conf'.
|
|
#
|
|
# Note that all gconf directives (X[:!]) must be grouped together. Tables
|
|
# are now generated during parsing in order to allow cpp directives to work
|
|
# as expected.
|
|
#
|
|
# Gconf handles the following syntax (all commands start in column 0):
|
|
#
|
|
# *[...]
|
|
#
|
|
# This line is a comment.
|
|
#
|
|
# #[...]
|
|
#
|
|
# This line copied to the output file (to implement cpp directives).
|
|
#
|
|
# node: name [parent=nameofparent] [install=installname] \
|
|
# [gfxprobe=gfxprobename] [drvrinfo=drvriinfoname]
|
|
#
|
|
# This includes driver "name". Parent specifies the parent of
|
|
# this node. With no install routine will be called, but will
|
|
# cause the driver to be linked in. Gconf also takes the
|
|
# special parent of "root" to be a child of the system class.
|
|
# Install overides the default install routine of name_install().
|
|
# Gfxprobe is for graphics drivers who wish to interface with the
|
|
# textport. Drvrinfo is for drivers that let the system probe
|
|
# for their existance.
|
|
#
|
|
# node! name [rest of line is ignored]
|
|
#
|
|
# This excludes driver "name". It can be used as an alternative
|
|
# in some cases to commenting the line out with a '*'. However
|
|
# this has the additional effect of defining NO_name and including
|
|
# <sys/skpick.h>. This will allow drivers that export more than
|
|
# their install routine to be excluded.
|
|
#
|
|
# fs: name [install=installname]
|
|
#
|
|
# This includes filesystem "name". Install overides the default
|
|
# install routine name_install().
|
|
#
|
|
# fs! name [rest of line is ignored]
|
|
#
|
|
# This excludes filesystem "name" in the same manner as node!.
|
|
#
|
|
# if: nameprefix type description
|
|
#
|
|
# This includes if driver by using the probe, init, open and close
|
|
# routines with nameprefix appended to them. Type is usually IF_SGI
|
|
# (other values in stand/include/if.h). Description is the interface
|
|
# description string: SGI Integral IP1000 Enet Controller.
|
|
#
|
|
# if! [rest of line is ignored]
|
|
#
|
|
# Generate the necessary definitions such that linking can be done
|
|
# successfully even without an ethernet driver. This line will be
|
|
# ignored if there is a 'if:' somewhere else in the file.
|
|
#
|
|
# tune: [name value]
|
|
#
|
|
# This produces a #define name value, which should correspond
|
|
# to an entry in <tune.h>. The value given in the tune: statement
|
|
# will override the default value in <tune.h>. The special case
|
|
# of tune: with no arguements will cause <tune.h> to be included
|
|
# in the generated .c file to get all the default values.
|
|
#
|
|
# "$Revision: 1.17 $"
|
|
|
|
FILENAME=${1-conf}
|
|
TARGETDIR=${2-.}"/"
|
|
|
|
nawk -v TARGETDIR="$TARGETDIR" '
|
|
BEGIN {
|
|
# initialize flags and counters
|
|
tune = exclude = node = nodetouched = fstouched = iftouched = 0;
|
|
|
|
# Variables set when new context is done.
|
|
nodedone = 1; fsdone = 2; ifdone = 3
|
|
finished[nodedone] = finished[fsdone] = finished[ifdone] = 0
|
|
donei = 0
|
|
|
|
# Do not need any trailers yet.
|
|
finish=""
|
|
|
|
# Have at least one 'if:' entry
|
|
if_entry = 0
|
|
|
|
# Figure out filename for .c file. If the input filename ends in
|
|
# .cf, produce a .c file. Otherwise, just append .c to the end
|
|
# of the filename. Note .h file uses the same method.
|
|
cfile=TARGETDIR FILENAME
|
|
if (sub(".cf", ".c", cfile) != 1)
|
|
cfile = FILENAME ".c"
|
|
hfile=cfile
|
|
sub(".c$", ".h", hfile)
|
|
|
|
# Print header comment, and generate files
|
|
print "/* automatically generated config table */" > cfile
|
|
print "/* from " FILENAME " */" >>cfile
|
|
print "#include \"" hfile "\"" >>cfile
|
|
print "/* automatically generated config table header */" > hfile
|
|
print "/* from " FILENAME " */\n" >>hfile
|
|
}
|
|
|
|
/^\*.*$/ {
|
|
# skip comments (a comment must start in column 0).
|
|
continue
|
|
}
|
|
|
|
/^\#.*$/ {
|
|
# output lines starting with hash directly for cpp
|
|
print $0 >>cfile
|
|
continue
|
|
}
|
|
|
|
/^[ \t]*$/ {
|
|
# skip blank lines
|
|
continue
|
|
}
|
|
|
|
/^node:/ {
|
|
# matched a node: save nodename
|
|
nodes[node] = $2
|
|
|
|
# check if commands are grouped properly
|
|
if (finished[nodedone] == 1) {
|
|
print "error line " NR " -> node command " $2 " not grouped."
|
|
err = 1
|
|
continue
|
|
}
|
|
|
|
# look at rest of args to look for modifiers
|
|
gfx=drvr=parent=install=0
|
|
for (i=3; i <= NF; i++) {
|
|
if (match($i,"parent=") == 1)
|
|
parent = substr($i,RLENGTH+1,length($i)-RLENGTH)
|
|
else if (match($i,"install=") == 1)
|
|
install = substr($i,RLENGTH+1,length($i)-RLENGTH)
|
|
else if (match($i,"gfxprobe=") == 1)
|
|
gfx = substr($i,RLENGTH+1,length($i)-RLENGTH)
|
|
else if (match($i,"drvrinfo=") == 1)
|
|
drvr = substr($i,RLENGTH+1,length($i)-RLENGTH)
|
|
else {
|
|
print "error line " NR " -> " $i
|
|
err=1
|
|
continue
|
|
}
|
|
}
|
|
|
|
# If this is the first node, output the header.
|
|
if (nodetouched == 0) {
|
|
print finish >>cfile
|
|
finished[donei] = 1
|
|
print "#include <sys/types.h>" >>cfile
|
|
print "#include <standcfg.h>\n" >>cfile
|
|
print "struct standcfg standcfg[] = {" >>cfile
|
|
|
|
nodetouched=1
|
|
donei=nodedone
|
|
finish="\t0,0,0\n};\n"
|
|
}
|
|
|
|
if (install == 0)
|
|
routine = nodes[node] "_install"
|
|
else
|
|
routine = install
|
|
|
|
# output extern definition
|
|
print "extern int " routine "();" >>hfile
|
|
|
|
# output table entry
|
|
printf "\t%s,\t",routine >>cfile
|
|
if (parent == "root")
|
|
printf "(struct standcfg *)(__psunsigned_t)1" >>cfile
|
|
else if (parent == 0)
|
|
printf "(struct standcfg *)0" >>cfile
|
|
else {
|
|
for (i=0; i < node ; i++) {
|
|
if (nodes[i] == parent) {
|
|
printf "\t&standcfg[%d]",i >>cfile
|
|
break
|
|
}
|
|
}
|
|
if (i == node) {
|
|
print "parent " parent " not found."
|
|
err=1
|
|
continue
|
|
}
|
|
}
|
|
printf ",\t" >>cfile
|
|
if (gfx != 0) {
|
|
printf "%s", gfx >>cfile
|
|
print "extern void *" gfx "();" >>hfile
|
|
}
|
|
else
|
|
printf "\t0" >>cfile
|
|
printf ",\n#ifdef SLOTCONFIG\n\t" >>cfile
|
|
if (drvr != 0) {
|
|
printf "&%s", drvr >>cfile
|
|
print "extern struct drvrinfo_s " drvr ";" >>hfile
|
|
}
|
|
else
|
|
printf "0" >>cfile
|
|
printf ",\n#endif" >>cfile
|
|
print "\t\t\t/* " nodes[node] " */" >>cfile
|
|
|
|
node+=1
|
|
|
|
continue
|
|
}
|
|
|
|
/^node\!/ {
|
|
# check if commands are grouped properly
|
|
if (finished[nodedone] == 1) {
|
|
print "error line " NR " -> node command " $2 " not grouped."
|
|
err = 1
|
|
continue
|
|
}
|
|
|
|
# Node exclusion. Output #define, and note exclusion is used.
|
|
print "#define NO_" $2 >>cfile
|
|
|
|
# If this is the first node, output the header.
|
|
if (nodetouched == 0) {
|
|
print finish >>cfile
|
|
finished[donei] = 1
|
|
print "#include <standcfg.h>\n" >>cfile
|
|
print "struct standcfg standcfg[] = {" >>cfile
|
|
|
|
nodetouched=1
|
|
donei = nodedone
|
|
finish="\t0,0,0\n};\n"
|
|
} exclude=1
|
|
|
|
continue
|
|
}
|
|
|
|
/^fs:/ {
|
|
if (finished[fsdone] == 1) {
|
|
print "error line " NR " -> fs command " $2 " not grouped."
|
|
err = 1
|
|
continue
|
|
}
|
|
|
|
# Include a filesystem. Save Filesystem install
|
|
fs = $2 "_install"
|
|
|
|
# Look for modifiers (override install name)
|
|
for (i=3 ; i <= NF; i++) {
|
|
if (match($i,"install=") == 1)
|
|
fs = substr($i,RLENGTH+1,length($i)-RLENGTH)
|
|
else {
|
|
print "error line " NR " -> " $i
|
|
err=1
|
|
continue
|
|
}
|
|
}
|
|
|
|
# If this is the first fs, output the header.
|
|
if (fstouched == 0) {
|
|
print finish >>cfile
|
|
finished[donei] = 1
|
|
print "int (*_fs_table[])() = {" >>cfile
|
|
|
|
donei = fsdone;
|
|
fstouched=1
|
|
finish="\t0\n};\n"
|
|
}
|
|
|
|
# print the extern and then the filesystem entry
|
|
print "extern int " fs "();" >>hfile
|
|
print "\t" fs "," >>cfile
|
|
|
|
continue
|
|
}
|
|
|
|
/^fs\!/ {
|
|
# check if commands are grouped properly
|
|
if (finished[fsdone] == 1) {
|
|
print "error line " NR " -> fs command " $2 " not grouped."
|
|
err = 1
|
|
continue
|
|
}
|
|
|
|
# Exclude filesystem. Output #define, and not exclusion is used.
|
|
print "#define NO_" $2 >>cfile
|
|
|
|
# If this is the first fs, output the header.
|
|
if (fstouched == 0) {
|
|
print finish >>cfile
|
|
finished[donei] = 1
|
|
print "int (*_fs_table[])() = {" >>cfile
|
|
|
|
donei = fsdone
|
|
fstouched=1
|
|
finish="\t0\n};\n"
|
|
} exclude=1
|
|
|
|
continue
|
|
}
|
|
|
|
/^if:/ {
|
|
# check if commands are grouped properly
|
|
if (finished[ifdone] == 1) {
|
|
print "error line " NR " -> if command " $2 " not grouped."
|
|
err = 1
|
|
continue
|
|
}
|
|
|
|
# Network configuration. Parse it, and save it.
|
|
ifprefix = $2
|
|
iftype = $3
|
|
if (iftype == 0)
|
|
iftype = "IF_SGI"
|
|
ifdesc = $4
|
|
for (i = 5; i < NF ; i++)
|
|
ifdesc = ifdesc " " $i
|
|
if (ifdesc == 0)
|
|
ifdesc == ""
|
|
|
|
# output if header
|
|
if (iftouched == 0) {
|
|
print finish >>cfile
|
|
finished[donei] = 1
|
|
|
|
iftouched = 1;
|
|
donei = ifdone
|
|
}
|
|
|
|
if (if_entry == 0) {
|
|
print "#include <if.h>\n" >>cfile
|
|
print "struct if_func _if_func[] = {" >>cfile
|
|
|
|
finish = "};\n" \
|
|
"int _nifcs = " \
|
|
"(sizeof(_if_func)/sizeof(_if_func[0]));\n"
|
|
if_entry += 1;
|
|
}
|
|
|
|
# output extern definitions
|
|
print "extern void " ifprefix "init();\n"\
|
|
"extern int " ifprefix "probe();\n"\
|
|
"extern int " ifprefix "open();\n"\
|
|
"extern int " ifprefix "close();\n" >>hfile
|
|
|
|
# output current if
|
|
printf "\t{\n\t\t" >>cfile
|
|
print ifprefix "init, " ifprefix "probe, " ifprefix "open, " \
|
|
ifprefix "close," >>cfile
|
|
printf "\t\t%s,\t\"%s\"\n\t},\n", iftype, ifdesc >>cfile
|
|
|
|
continue
|
|
}
|
|
|
|
/^if\!/ {
|
|
# check if commands are grouped properly
|
|
if (finished[ifdone] == 1) {
|
|
print "error line " NR " -> if command " $2 " not grouped."
|
|
err = 1
|
|
continue
|
|
}
|
|
|
|
# output if header
|
|
if (iftouched == 0) {
|
|
print finish >>cfile
|
|
finished[donei] = 1
|
|
|
|
finish = "#include <if.h>\n" \
|
|
"struct if_func _if_func[1];\n" \
|
|
"int _nifcs = 0;\n"
|
|
|
|
iftouched = 1;
|
|
donei = ifdone
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
/^tune:/ {
|
|
# tuning -- note that we are tuning.
|
|
tune = 1
|
|
|
|
# if no parameters just continue, since we already set the flag
|
|
if (NF == 1)
|
|
continue
|
|
|
|
# substitute tune: with #define.
|
|
sub("^tune:","#define",$0)
|
|
|
|
print $0 >>cfile
|
|
continue
|
|
}
|
|
|
|
|
|
{
|
|
# No match above -> error. Print message, set error
|
|
# flag to prevent .c generation at END, and let awk
|
|
# continue to look for more errors.
|
|
print "error line " NR " -> " $0
|
|
err=1
|
|
}
|
|
|
|
END {
|
|
# If there was a error exit with correct error code.
|
|
if (err == 1) {
|
|
system("rm -f " cfile " " hfile)
|
|
exit 1
|
|
}
|
|
|
|
# print last finish string
|
|
print finish >>cfile
|
|
|
|
# if exclusion is used, output #include
|
|
if (exclude != 0)
|
|
print "#include <sys/skpick.h>" >>cfile
|
|
|
|
# if tune is used, output #include
|
|
if (tune != 0)
|
|
print "#include <tune.h>" >>cfile
|
|
}
|
|
' $FILENAME
|