# basename is set on the command line
# The regexp below is replaced by an expression to do case insensitive
# searching on the name of a GL function before running this program.
#
# Runs on 'gl.h' ('glu.h', 'glx.h') and locates the lines for the specified
# GL (glu, glx) function, then generates M4 definitions for man page
#
BEGIN {
found = 0
numargs = 0
newargs[0] = ""
stderr = "cat 1>&2"
vee = 0
getnames(basename)
for (j=0; j<numNames; j++)
{
rexpNames[j] = names[j] regExps[j]
head[j] = ""
numFound[j] = 0
nargs[0] = 0
}
}
/extern/ {
cmdfield = 0;
# search for the command string
for (i = 3; i <= NF; i++)
{
name = $i;
if (index(name,"gl") == 1)
{
cmdfield = i;
# strip the gl, glu, or glX prefix
# note that the X of glX is not stripped!
if (index(name,"glu") == 1)
name = substr(name,4);
else
name = substr(name,3);
truename = name;
break;
}
}
if (cmdfield != 0) {
for (i=0; i<numNames; i++)
{
if (name ~ rexpNames[i])
{ # Found one - $cmdfield is the name, $2 through $(cmdfield-1) is
# the return type. The rest is the argument list.
match(name,names[i])
if ((RLENGTH != length(names[i])) || (match(name,rexpNames[i]) != 1))
continue
if (RLENGTH != length(name))
continue
cname = name
names[i,numFound[i]] = truename
p = index($0,"(")
addargs(substr($0,p,length($0)-p-1),i) # Strips trailing semicolon
typestr = $2
for (j = 3; j < cmdfield; j++)
{
typestr = typestr " " $j
}
head[i] = head[i] makeHead(truename,typestr,i)
numFound[i]++
found++
}
}
}
}
END {
if (found == 0) {
if (basename == "xintro") {
numNames = 1;
numFound[0] = 1;
names[0,0] = "XIntro";
}
else if (basename == "intro") {
numNames = 1;
numFound[0] = 1;
names[0,0] = "Intro";
}
else {
printf "No GL call found that matches '%s'.\n", basename | stderr
printf "Edit macros/mkhead.awk to add a special name.\n" | stderr
}
}
printf "_define(_samething,@<.PP\n"
printf "The above subroutines are functionally equivalent;\n"
printf "they differ only in the specification of their parameters.\n"
printf ">@)dnl\n"
printf "_define(_header,@<dnl\n"
printf "_setup()dnl\n"
printf "_define(_cname,$1)dnl\n"
printf ".TH %s$1 3G\n", prefix
printf ".SH NAME\n"
printf ".B \""
for (i=0; i<numNames; i++)
for (j=0; j<numFound[i]; j++)
if ((i == (numNames-1)) && (j == (numFound[i]-1)))
printf "%s%s\n", prefix, names[i,j]
else
printf "%s%s, ", prefix, names[i,j]
printf "\\- $2\n"
printf ">@)dnl\n"
printf "_define(_names,@<dnl\n"
printf "_ifelse($3,@<>@,.SH C SPECIFICATION\n)"
printf "_ifelse("
for (i=0; i<numNames; i++)
{
printf "_namenum,@<%d>@,@<%s>@,dnl\n",i,head[i]
}
printf "ERROR)dnl\n"
printf "_define(@<_namenum>@,_incr(_namenum))>@)dnl\n"
# if (found > 1)
# {
# printf "_samething()\n"
# }
maxArgs = 0
for (i=0; i<numNames; i++)
if (maxArgs < nargs[i])
maxArgs = nargs[i]
long = ""
for (j=1; j<=maxArgs; j++)
{
printf "_define(_param%d,@<",j
printf "_define(@<_tmpnum>@,_ifelse($#,0,_namenum,$1))dnl\n"
printf "_ifelse("
for (i=0; i<numNames; i++)
{
printf "_tmpnum,@<%d>@,\\f2%s\\fP,dnl\n",i+1,args[j,i]
if (length(args[j,i]) > length(long))
long = args[j,i]
}
printf "???)>@)dnl\n"
}
# next loop same as above, except does not italicize
# resulting definitions can be used in equations
for (j=1; j<=maxArgs; j++)
{
printf "_define(_eqnparam%d,@<",j
printf "_define(@<_tmpnum>@,_ifelse($#,0,_namenum,$1))dnl\n"
printf "_ifelse("
for (i=0; i<numNames; i++)
{
printf "_tmpnum,@<%d>@,\"%s\",dnl\n",i+1,args[j,i]
if (length(args[j,i]) > length(long))
long = args[j,i]
}
printf "???)>@)dnl\n"
}
# The following stuff is designed to find the longest argument so that
# the '.TP' indentation can be set in the first instaciation of _phead
# (thus the use of the '_first' macro as a flag). Things are complicated
# by the possibility of multiple arguments in the call to _phead.
# This is what _makelist is for: to turn a space separted multiple
# argument list into a comma separated one (commas can't be used in
# the original list because they have special meaning to m4).
# Unfortunately, this means that (currently) if the longest string is
# a multiple argument, the indentation will only be right if it occurs
# in the first _phead. This is because only the API file is scanned
# for arguments, and not the man page file, so this script can't know
# which instance of phead has the longest (multiple) argument.
long = "\\fI" long "\\fP"
printf "_define(_phead,@<dnl\n"
printf "_ifdef(@<_first>@,@<.TP>@,@<.TP \\w'"
printf "_ifelse(_eval(_len(%s)>_len(_makelist($1))),1,",long
printf "%s,translit(_makelist($1),@<+>@,@<\\>@))\\ \\ 'u dnl\n", long
printf "_define(_first,first)>@)\n"
printf "translit(_makelist($1),@<+>@,@<,>@)>@)dnl\n"
printf "_define(_cmnd,@<\\%%_ifelse($1,@<>@,\\f3" prefix "@<>@_cname\\fP,dnl\n"
printf "\\f3" prefix "$1\\fP)>@)dnl\n"
printf "_define(_glcmnd,@<_ifelse($1,@<>@,\\f3gl@<>@_cname\\fP,dnl\n"
printf "\\f3gl$1\\fP)>@)dnl\n"
printf "_define(_glucmnd,@<_ifelse($1,@<>@,\\f3glu@<>@_cname\\fP,dnl\n"
printf "\\f3glu$1\\fP)>@)dnl\n"
printf "_define(_xcmnd,@<_ifelse($1,@<>@,\\f3X@<>@_cname\\fP,dnl\n"
printf "\\f3X$1\\fP)>@)dnl\n"
# printf "syscmd(@<${maCdIr}/mkname.awk>@ ${maCdIr}/pglspec >_tmpnam)dnl\n"
# printf "_include(_tmpnam)syscmd(rm -f _tmpnam)>@))dnl\n"
}
#
# function to make the troff to typeset the function header
#
function makeHead(fname,type,i)
{
fname = prefix fname
headString = sprintf("%s \\f3%s\\fP(",type,fname)
if (numargs > 0)
{
headString = headString "\n"
if (numargs > 1)
{
headString = headString sprintf("%s,\n",targs[1,i])
headString = headString ".nf\n"
headString = headString sprintf(".ta \\w'\\f3%s \\fP%s( 'u\n",type,fname)
for (j=2; j<=numargs-1; j++)
headString = headString sprintf("\t%s,\n",targs[j,i])
headString = headString sprintf("\t%s )\n",targs[numargs,i])
headString = headString ".fi\n"
}
else
headString = headString sprintf("%s )\n.nf\n.fi\n",targs[numargs,i])
}
else
headString = headString " void )\n.nf\n.fi\n"
return headString
}
# Generates 'args' of untyped argument names
# Also generates 'targs' of typed argument names and 'nargs', the number
# of arguments.
function addargs(arglist,i)
{
#
# First strip leading '(' and trailing ')'
#
if (substr(arglist,1,1) == "(")
arglist = substr(arglist,2,length(arglist))
while (substr(arglist,1,1) == " ")
arglist = substr(arglist,2,length(arglist))
if (substr(arglist,length(arglist),1) == ")")
arglist = substr(arglist,1,length(arglist)-1)
while (substr(arglist,length(arglist),1) == " ")
arglist = substr(arglist,1,length(arglist)-1)
numargs = split(arglist,newargs, ",[ \t]")
if (newargs[1] == "void")
{
numargs = 0;
targs[1,i] = newargs[1];
args[1,i] = newargs[1];
}
if (nargs[i] < numargs)
nargs[i] = numargs;
for (j=1; j<=numargs; j++)
{
# targs[j,i] italicizes the argument but not the type
targs[j,i] = newargs[j]
numWords = split(targs[j,i],words,"[ \t]")
args[j,i] = words[numWords]
targs[j,i] = words[1]
for (k=2; k<=numWords-1; k++)
targs[j,i] = targs[j,i] " " words[k]
targs[j,i] = targs[j,i] " \\fI" words[numWords] "\\fP"
sub(/\[.*\]/,"",args[j,i])
gsub("[*()]","",args[j,i])
}
}
#
# Parse and save away the _names(name,regexp) declarations in the file
# for later use in matching the entries in the API file.
#
function getnames(file)
{
numNames = 0
fname = file ".gl"
while (getline < fname)
{
if (index($0,"_names(") != 0)
{
start = index($0,"_names(") + 7
stuff = substr($0,start,length($0)-start)
split(stuff,things,",")
names[numNames] = things[1]
regExps[numNames] = things[2]
numNames++
}
}
close(fname)
if (numNames == 0)
{
names[0] = file
regExps[0] = "[1-9]*u*[lbsifd]*v*"
numNames++
}
}