#!/usr/bin/awk -f
#
# Copyright (c) 2003-2004, Boris Popov
# Copyright (c) 2004, The Tendra Project <http://www.ten15.org/>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice unmodified, this list of conditions, and the following
# disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $TenDRA: tendra/src/utilities/mkerr/mkerr.awk,v 1.5 2004/07/14 12:19:53 stefanf Exp $
#
function usage()
{
print "usage: " script_name " [-d defnfile] [-l declfile] [-n numfile]";
print " [-u usagefile] [-c compfile] [-hv] srcfile [srcfile...]";
print "where compfile compound .c file";
print " defnfile errors definition file name";
print " declfile errors declaration file name";
print " numfile errors numbers file name";
print " usagefile errors usage file name";
print " -h this help screen";
print " -v increase debug level";
exit 1;
}
function chr(c)
{
return sprintf("%c", c + 0)
}
function warn(msg)
{
print "Warning: ", msg > "/dev/stderr";
}
function err(msg)
{
print "Error: ", msg > "/dev/stderr";
exit(1);
}
function errsrc(msg)
{
err(srcfile ":" lineno ":" linepos ": " msg);
}
function debug(level, msg)
{
if (verbose >= level)
print "Debug: ", msg > "/dev/stderr";
}
function err_syntax()
{
errsrc("Syntax error.");
}
function err_unexpected_eof()
{
errsrc("Unexpected end of file.");
}
function printc(str)
{
print str > outfilename;
}
function lex_reset()
{
lex_eof = 0;
lineno = 0;
linepos = 0;
linelen = 0;
ch = " ";
ttUnknown = 0;
ttIdent = 1;
ttString = 2;
ttOr = 3;
ttColon = 4;
ttComma = 5;
ttKW_DBNAME = 6;
ttOpenRound = 7;
ttCloseRound = 8;
ttOpenBrace = 9;
ttCloseBrace = 10;
ttEqual = 11;
ttArrow = 12;
ttKW_RIG = 13;
ttKW_PREFIX = 14;
ttKW_TYPES = 15;
ttKW_PROPERTIES = 16;
ttKW_KEYS = 17;
ttKW_KEY = 18;
ttKW_USAGE = 19;
ttKW_ENTRIES = 20;
ttKW_COMP_OUT = 21;
ttKW_FROM_COMP = 22;
ttKW_FROM_DB = 23;
ttKW_GLOBALS = 24;
lex_keywords["DATABASE_NAME"] = ttKW_DBNAME;
lex_keywords["RIG"] = ttKW_RIG;
lex_keywords["PREFIX"] = ttKW_PREFIX;
lex_keywords["TYPES"] = ttKW_TYPES;
lex_keywords["PROPERTIES"] = ttKW_PROPERTIES;
lex_keywords["KEYS"] = ttKW_KEYS;
lex_keywords["KEY"] = ttKW_KEY;
lex_keywords["USAGE"] = ttKW_USAGE;
lex_keywords["ENTRIES"] = ttKW_ENTRIES;
lex_keywords["GLOBALS"] = ttKW_GLOBALS;
lex_keywords["compiler_output"] = ttKW_COMP_OUT;
lex_keywords["from_compiler"] = ttKW_FROM_COMP;
lex_keywords["from_database"] = ttKW_FROM_DB;
lex_tt = ttUnknown;
lex_token = "";
lex_unget = 0;
}
function lex_get_token(expected)
{
if (lex_unget) {
lex_unget = 0;
if (expected != "" && expected != lex_tt)
errsrc("Unexpected token (" lex_tt " != " expected ")."); # todo: elaborate more
return 1;
}
lex_tt = ttUnkown;
lex_token = "";
lex_state = 0; # 0 - whitespace, 1 - string
texttoken = 1;
incomment = 0;
while (1) {
if (++linepos > linelen) {
if ((getline < srcfile) <= 0) {
if (expected != "")
err_unexpected_eof();
if (incomment)
errsrc("End of file in comment");
if (lex_state == 1)
errsrc("End of file in string");
lex_eof = 1;
return 0;
}
lineno++;
linepos = 0;
sub(/[ ]+$/, ""); # remove trailing whitespace
if (incomment) {
linelen = length();
comment = comment "\n";
continue;
}
sub(/^[ ]+/, ""); # remove leading whitespace
linelen = length();
ch = " ";
ch2 = " ";
} else {
ch = substr($0, linepos, 1);
ch2 = substr($0, linepos, 2);
}
if (lex_state == 0) { # skipping through whitespaces
if (incomment) {
therest = substr($0, linepos);
tok_end = match(therest, /\*\//);
if (tok_end == 0) {
if (match(therest, /\/\*/))
errsrc("Nested comments not allowed.");
comment = comment therest;
linepos = linelen;
continue;
}
linepos += tok_end;
incomment = 0;
if (!have1st_comment) {
comment = comment substr(therest, 1, tok_end - 1);
comment = comment "*/\n";
first_comment = comment;
have1st_comment = 1;
}
} else if (ch2 == "/*") {
comment = "/*";
incomment = 1;
linepos++;
} else if (ch == "\"") {
lex_state = 1;
continue;
} else if (ch ~ /[A-Za-z_]/) {
therest = substr($0, linepos);
tok_end = match(therest, /[^A-Za-z0-9_]/);
if (tok_end == 0) {
lex_token = therest;
linepos = linelen;
} else {
lex_token = substr(therest, 1, tok_end - 1);
linepos += tok_end - 2;
}
break;
} else if (ch !~ /[ ]/) {
texttoken = 0; # single symbol token
break;
}
continue;
}
# collect string
if (ch == "\"") {
lex_tt = ttString;
break;
}
lex_token = lex_token ch;
} # while (1)
if (lex_tt != ttUnknown) {
} else if (texttoken) {
if (lex_token in lex_keywords) {
lex_tt = lex_keywords[lex_token];
} else
lex_tt = ttIdent;
} else if (ch == "|") {
lex_tt = ttOr;
} else if (ch == ":") {
lex_tt = ttColon;
} else if (ch == ",") {
lex_tt = ttComma;
} else if (ch == "{") {
lex_tt = ttOpenBrace;
} else if (ch == "}") {
lex_tt = ttCloseBrace;
} else if (ch == "(") {
lex_tt = ttOpenRound;
} else if (ch == ")") {
lex_tt = ttCloseRound;
} else if (ch == "=") {
lex_tt = ttEqual;
} else if (ch == "-") {
if (ch2 != "->")
errsrc("'>' expected, but '" ch "' found.");
linepos++;
lex_tt = ttArrow;
lex_token = "->";
} else
errsrc("Unexpected symbol '" ch "'");
if (expected != "" && expected != lex_tt)
errsrc("Unexpected token (" lex_tt " != " expected ")."); # todo: elaborate more
return 1;
}
function lex_unget_token()
{
lex_unget = 1;
}
#
# Syntax: DATABASE_NAME: dbname [| altdbname]
#
function process_database()
{
if (db_defined)
errsrc("Database name can be defined only once.");
lex_get_token(ttIdent);
db_name = lex_token;
lex_get_token();
if (lex_tt == ttOr) {
lex_get_token(ttIdent);
db_name_alt = lex_token;
} else {
lex_unget_token();
db_name_alt = db_name;
}
db_defined = 1;
debug(1, "Database name: " db_name " | " db_name_alt);
}
#
# Syntax: RIG: rig_name
#
# Although we accept the "RIG" keyword, its value never used.
#
function process_rig()
{
lex_get_token(ttIdent);
rig_name = lex_token;
debug(1, "Rig name: " rig_name);
}
#
# Syntax:
# PREFIX: compiler_output -> PX1 from_compiler -> PX2 from_database -> PX3
#
function process_prefix()
{
if (prefix_defined)
errsrc("Prefixes can be defined only once.");
for (;;) {
lex_get_token();
pxdst = lex_tt;
if (pxdst != ttKW_COMP_OUT && pxdst != ttKW_FROM_COMP && pxdst != ttKW_FROM_DB) {
lex_unget_token();
return;
}
px_dest = lex_token;
lex_get_token(ttArrow);
lex_get_token(ttIdent);
px_val = lex_token;
debug(1, "Prefix: " px_dest " -> " px_val);
if (pxdst == ttKW_COMP_OUT) {
rig_comp_output = px_val;
} else if (pxdst == ttKW_FROM_COMP) {
rig_from_comp = px_val;
} else
rig_from_db = px_val;
}
}
#
# Syntax: TYPES: type1 [, typeN]
#
function process_types()
{
for (;;) {
lex_get_token(ttIdent);
types[type_count] = lex_token;
types_hash[lex_token] = type_count++;
debug(1, "Collect type: " lex_token);
lex_get_token();
if (lex_tt != ttComma) {
lex_unget_token();
break;
}
}
}
function lookup_type(atype, i)
{
i = types_hash[atype];
if (i != "")
return i;
return -1;
}
#
# Syntax: GLOBALS: type1: var1 [, typeN: varN]
#
function process_globals()
{
for (;;) {
lex_get_token(ttIdent);
ptype = lex_token;
lex_get_token(ttColon);
lex_get_token(ttIdent);
pname = lex_token;
typeno = lookup_type(ptype);
if (i < 0)
errsrc("Undeclared type '" ptype "' .");
globals_type[global_count] = ptype;
globals_name[global_count] = pname;
global_count++;
debug(1, "Collect global: " pname);
lex_get_token();
if (lex_tt != ttComma) {
lex_unget_token();
break;
}
}
}
function lookup_global(aname, i)
{
for (i = 0; i < global_count; i++) {
if (aname == globals_name[i])
return i;
}
return -1;
}
#
# Syntax: PROPERTIES: prop1 [, propN]
#
function process_properties()
{
prop_count = 0;
for (;;) {
lex_get_token(ttIdent);
props_val[lex_token] = 2 ^ prop_count;
props[prop_count++] = lex_token;
debug(1, "Property: " lex_token);
lex_get_token();
if (lex_tt != ttComma) {
lex_unget_token();
break;
}
}
}
function lookup_key(akey, i)
{
i = keys_hash[akey];
if (i != "")
return i;
errsrc("Unknown key '" akey "'");
}
#
# Syntax: KEYS: key1 [, keyN]
#
function process_keys()
{
for (;;) {
lex_get_token(ttIdent);
keys[key_count] = lex_token;
keys_hash[lex_token] = key_count++;
debug(1, "Key: " lex_token);
lex_get_token();
if (lex_tt != ttComma) {
lex_unget_token();
break;
}
}
}
function lookup_usage(usage, i)
{
i = usages_hash[usage];
if (i != "")
return i;
i = usages_alt_hash[usage];
if (i != "")
return i;
return -1;
}
#
# Syntax: USAGES: usage1 [, usageN] where usage: name [= auxname [| altname]]
#
function process_usages()
{
for (;;) {
lex_get_token(ttIdent);
usages[usage_count] = lex_token;
usages_hash[lex_token] = usage_count;
usages_aux[usage_count] = lex_token;
lex_get_token();
if (lex_tt == ttEqual) {
lex_get_token(ttIdent);
usages_aux[usage_count] = lex_token;
lex_get_token();
if (lex_tt == ttOr) {
lex_get_token(ttIdent);
usages_alt[usage_count] = lex_token;
usages_alt_hash[lex_token] = usage_count;
lex_get_token(); # lookup next
}
}
usage_count++;
if (lex_tt != ttComma) {
lex_unget_token();
break;
}
}
}
function entry_lookup_param(entry, pname, i)
{
i = entry_param_hash[entry, pname];
if (i != "")
return i;
i = lookup_global(pname);
if (i >= 0)
return chr(i + 97); # 'a'
errsrc("Unknown parameter '" pname "'.");
}
function process_entry_body(entry)
{
lex_get_token(ttOpenBrace);
while (1) { # entry body
lex_get_token();
kw = lex_tt;
if (kw == ttCloseBrace)
break;
kwname = lex_token;
lex_get_token();
if (lex_tt == ttColon) {
if (kw == ttKW_USAGE) {
alt = 0;
for (;;alt++) {
lex_get_token(ttIdent);
usageid = lookup_usage(lex_token);
if (usageid < 0)
errsrc("Unknown usage '" lex_token "' .");
if (alt)
entry_usage_alt[entry] = lex_token;
else {
entry_usage[entry] = lex_token;
entry_usage_alt[entry] = lex_token;
}
lex_get_token();
if (lex_tt != ttOr) {
lex_unget_token();
break;
}
}
} else if (kw == ttKW_PROPERTIES) {
prcount = 0;
for (;;) {
lex_get_token(ttIdent);
entry_props[entry, prcount++] = lex_token;
lex_get_token();
if (lex_tt != ttComma) {
lex_unget_token();
break;
}
}
entry_prcount[entry] = prcount;
} else
errsrc("Unexpected keyword " kwname ".");
} else if (lex_tt == ttOpenRound) {
if (kw != ttKW_KEY)
errsrc("'KEY' expected");
lex_get_token(ttIdent);
keyid = lookup_key(lex_token);
entry_key[entry, lex_token] = 1;
lex_get_token(ttCloseRound);
lex_get_token();
if (lex_tt != ttIdent && lex_tt != ttString) {
entry_key_msg[entry, keyid] = "";
lex_unget_token();
continue; # empty key
}
msg = "";
altmsg = "";
alt = 0;
for (;;) {
if (lex_tt == ttString) {
if (alt == 0)
msg = msg lex_token;
else
altmsg = altmsg lex_token;
} else if (lex_tt == ttIdent) {
pn = entry_lookup_param(entry, lex_token);
if (alt == 0)
msg = msg "%" pn;
else
altmsg = altmsg "%" pn;
} else if (lex_tt == ttOr) {
alt = 1;
} else {
lex_unget_token();
break;
}
lex_get_token();
}
entry_key_msg[entry, keyid] = msg;
if (altmsg != "")
entry_key_altmsg[entry, keyid] = altmsg;
} # key()
} # entry body loop
}
function process_entries()
{
for (;;) {
lex_get_token();
if (lex_eof)
break;
if (lex_tt == ttKW_ENTRIES)
break;
if (lex_tt != ttIdent)
errsrc("Entry name or keyword expected.");
entry = lex_token;
if (entries_hash[entry] != "")
errsrc("Duplicate entry");
entries[entry_count] = entry;
entries_hash[entry] = entry_count;
entry_count++;
debug(1, "Entry: " entry);
lex_get_token(ttOpenRound);
lex_get_token();
pcount = 0;
if (lex_tt == ttIdent) {
for (;;) { # parameters loop
ptype = lex_token;
lex_get_token(ttColon);
lex_get_token(ttIdent);
pname = lex_token;
typeno = lookup_type(ptype);
if (typeno < 0)
errsrc("Undeclared type '" ptype "' .");
entry_param_types[entry, pcount] = typeno;
entry_param_names[entry, pcount] = pname;
entry_param_hash[entry, pname] = pcount;
pcount++;
lex_get_token();
if (lex_tt == ttCloseRound) {
break; # EOP
} else if (lex_tt != ttComma)
errsrc("Comma expected but " lex_token " found.");
lex_get_token(ttIdent);
} # parameters loop
} else if (lex_tt != ttCloseRound)
errsrc("'(' expected, but " lex_token " found.");
entry_param_count[entry] = pcount;
process_entry_body(entry);
} # entries loop
}
function process_catalog()
{
lex_reset();
while (!lex_eof) {
if (!lex_get_token())
break;
tt = lex_tt;
kw = lex_token;
lex_get_token(ttColon);
if (tt == ttKW_DBNAME) {
process_database();
} else if (tt == ttKW_RIG) {
process_rig();
} else if (tt == ttKW_PREFIX) {
process_prefix();
} else if (tt == ttKW_TYPES) {
process_types();
} else if (tt == ttKW_PROPERTIES) {
process_properties();
} else if (tt == ttKW_KEYS) {
process_keys();
} else if (tt == ttKW_USAGE) {
process_usages();
} else if (tt == ttKW_ENTRIES) {
process_entries();
} else if (tt == ttKW_GLOBALS) {
process_globals();
} else {
errsrc("Unknown keyword '" kw "'");
}
}
}
function code_letter(n)
{
if (n < 10)
return "0" + n;
if (n < 36)
return chr(n + 65 - 10);
if (n < 72)
return chr(n + 97 - 36);
return chr(n + 128);
}
function out_decl()
{
pre = rig_comp_output;
pre_comp = rig_from_comp;
# Print main types definition
printc("#ifndef " pre "INCLUDED");
printc("#define\t" pre "INCLUDED\n\n");
printc("/* Error data structure */\n");
printc("#ifndef " pre "CONST");
printc("#define\t" pre "CONST");
printc("#endif\n");
if (props_count < 16) {
printc("typedef unsigned " pre "PROPS;\n");
} else {
printc("typedef unsigned long " pre "PROPS;\n");
}
printc("typedef struct {");
printc(" " pre "CONST char *name;");
printc(" " pre "CONST char *signature;");
printc(" int usage;");
printc(" " pre "PROPS props;");
for (i = 0; i < key_count; i++) {
printc(" " pre "CONST char *key_" keys[i] ";");
}
printc("} " pre "DATA;\n");
printc("extern " pre "DATA " pre "CATALOG [];");
printc("extern " pre "CONST char *" pre "NAME;\n\n");
# Print type keys
printc("/* Error type keys */\n");
for (i = 0; i < type_count; i++) {
n = code_letter(i);
printc("#define\t" pre "KEY_" types[i] "\t'" n "'");
}
printc("\n");
# Print usage keys
printc("/* Error usage keys */\n");
printc("#ifndef " pre "USE");
for (i = 0; i < usage_count; i++) {
printc("#define\t" pre_comp usages[i] "\t" i);
}
printc("#endif\n\n");
# Print property keys
printc("/* Error property keys */\n");
printc("#ifndef " pre "PROP");
for (i = 0; i < prop_count; i++) {
u = 2 ^ i;
printc(sprintf("#define\t%sPROP_%s\t((%sPROPS)0x%x)",
pre, props[i], pre, u));
}
printc("#endif\n\n");
if (global_count > 0) {
# Print global variables
printc("/* Global variables */\n");
for (i = 0; i < global_count; i++) {
n = chr(i + 97);
printc("#define\t" pre "GLOB_" globals_name[i] "\t'" n "'");
}
printc("\n");
}
# Print type checking macros */
printc("/* Error type checking */\n");
printc("#if defined(" pre "CHECK)");
for (i = 0; i < type_count; i++) {
n = code_letter(i);
tn = types[i];
printc(sprintf("extern %s chk_%s(%s);", tn, n, tn ));
}
printc("#else");
for (i = 0; i < type_count; i++) {
n = code_letter(i);
printc("#define\tchk_" n "(A)\t(A)");
}
printc("#endif\n\n");
# Print error macros
printc("/* Error message macros */\n");
printc("#ifdef " pre "GEN\n");
for (i = 0; i < entry_count; i++) {
entry = entries[i];
endef = "#define\t"pre entry "(";
pcount = entry_param_count[entry];
# Print parameter list
if (pcount) {
for (arg = 0; arg < pcount; arg++) {
if (arg)
endef = endef ", ";
endef = endef chr(65 + arg);
}
}
endef = endef ")\\\n";
endef = endef sprintf("\t%sGEN (%d", pre, i);
for (arg = 0; arg < pcount; arg++) {
an = code_letter(entry_param_types[entry, arg]);
endef = endef ", chk_" an " (" chr(65 + arg) ")";
}
endef = endef ")\n";
printc(endef);
}
printc("\n#endif\n#endif");
}
#
# Output error definitions
#
function out_defn()
{
d1 = db_name;
d2 = db_name_alt;
pre = rig_comp_output;
pre_comp = rig_from_comp;
# Print each catalogue entry
printc("/* Error catalogue */\n");
if (d1 == d2) {
printc(pre "CONST char *" pre "NAME = \"" d1 "\";");
} else {
printc("#ifndef " pre "ALTERNATE");
printc(pre "CONST char *" pre "NAME = \"" d1 "\";");
printc("#else");
printc(pre "CONST char *" pre "NAME = \"" d2 "\";");
printc("#endif");
}
printc("\n" pre "DATA " pre "CATALOG [] = {");
for (eid = 0; eid < entry_count; eid++) {
entry = entries[eid];
# Print error name
printc(" {\n\t\"" entry "\",");
# Print error signature
pcount = entry_param_count[entry];
if (pcount == 0) {
printc("\tNULL,");
} else {
tstr = "\t\"";
for (arg = 0; arg < pcount; arg++) {
tstr = tstr code_letter(entry_param_types[entry, arg]);
}
tstr = tstr "\",";
printc(tstr);
}
# Print error usage
eu = entry_usage[entry];
ev = entry_usage_alt[entry];
if (eu != ev) {
printc("#ifndef " pre "ALTERNATE");
}
if (eu == "") {
printc("\t0,");
} else {
printc("\t" pre_comp eu",");
}
if (eu != ev) {
printc("#else");
if (ev == "") {
printc("\t0,");
} else {
printc("\t" pre_comp ev",");
}
printc("#endif");
}
# Print error properties
suff = ",";
if (key_count == 0)
suff = "";
prcount = entry_prcount[entry];
u = 0;
for (i = 0; i < prcount; i++) {
u += props_val[entry_props[entry, i]];
}
printc("\t" u suff);
# Print error keys
for (kid = 0; kid < key_count; kid++) {
suff = kid == (key_count - 1) ? "" : ",";
if (!((entry, kid) in entry_key_msg)) {
printc("\tNULL" suff);
} else {
msg = entry_key_msg[entry, kid];
havealt = (entry, kid) in entry_key_altmsg;
altmsg = entry_key_altmsg[entry, kid];
if (havealt) {
printc("#ifndef " pre "ALTERNATE");
}
tmsg = "\t\"" msg "\"" suff;
printc(tmsg);
if (havealt) {
printc("#else");
tmsg = "\t\"" altmsg "\"" suff;
printc(tmsg);
printc("#endif");
}
}
}
printc(" },");
} #entry loop
# Print dummy end marker
printc(" {");
printc("\tNULL,");
printc("\tNULL,");
printc("\t0,");
tmsg = "\t0";
for (kid = 0; kid < key_count; kid++) {
tmsg = tmsg ",\n\tNULL";
}
printc(tmsg);
printc(" }");
printc("};");
return;
}
#
# Output error numbers
#
function out_number()
{
pre = rig_comp_output;
pre_db = rig_from_db;
printc("#ifndef " pre "NO_INCLUDED");
printc("#define\t" pre "NO_INCLUDED\n\n");
printc("/* Error message macros */\n" );
for (eid = 0; eid < entry_count; eid++) {
entry = entries[eid];
printc("#define\t" pre_db entry "\t" eid);
}
printc("\n#endif");
}
#
# Output usages
#
function out_usage( pre, pre_comp, uid, us, aux, alt, havealt)
{
pre = rig_comp_output;
pre_comp = rig_from_comp;
for (uid = 0; uid < usage_count; uid++) {
us = usages[uid];
aux = usages_aux[uid];
alt = usages_alt[uid];
havealt = alt != "";
if (havealt) {
printc("#ifndef " pre "ALTERNATE");
}
printc("{ \"" us "\", " pre_comp "VALUE_" aux " },");
if (havealt) {
printc("#else" );
printc("{ \"" us "\", " pre_comp "VALUE_" alt " },");
printc("#endif");
}
}
}
#
# An attempt to emulate getopt()
#
function getopt(argc, argv, options,
arg, i, opt, opta)
{
arg = argv[optind];
if (arg == "--") {
optind++;
opt_argpos = 0;
return 0;
} else if (arg !~ /^-[^: \t]/) {
opt_argpos = 0;
return 0;
}
if (opt_argpos == 0)
opt_argpos = 2;
opt = substr(arg, opt_argpos, 1);
i = index(options, opt);
if (i == 0) {
err("Unknown option " opt);
}
optopt = opt;
if (substr(options, i + 1, 1) == ":") {
optarg = substr(arg, opt_argpos + 1);
if (optarg == "")
optarg = argv[++optind];
opt_argpos = 0;
} else
optarg = "";
if (opt_argpos == 0 || opt_argpos >= length(argv[optind])) {
optind++;
opt_argpos = 0;
} else
opt_argpos++;
return 1;
}
#
# Begin of the main program.
#
BEGIN {
script_name = "mkerr.awk";
optind = 1;
gerror = 0;
files_count = 0;
while (getopt(ARGC, ARGV, "c:d:hl:n:u:v")) {
if (optopt == "c") {
comp_file = optarg;
} else if (optopt == "d") {
defn_file = optarg;
} else if (optopt == "l") {
decl_file = optarg;
} else if (optopt == "n") {
num_file = optarg;
} else if (optopt == "u") {
usage_file = optarg;
} else if (optopt == "h") {
usage();
} else if (optopt == "v") {
verbose++;
}
}
if (optind >= ARGC)
err("No input file specified");
if (defn_file == "" && decl_file == "" &&
num_file == "" && usage_file == "" && comp_file == "") {
warn("No output files specified. Will perform only syntax check.");
} else
debug(1, "Output: " defn_file ", " decl_file ", " num_file ", " usage_file);
entry_count = 0;
type_count = 0;
key_count = 0;
usage_count = 0;
global_count = 0;
db_name = "ERRORS";
db_name_alt = "ERRORS";
rig_name = "ERR_";
rig_comp_output = "ERR_";
rig_from_comp = "ERR_USE_";
rig_from_db = "ERR_NO_";
autoheader = "/*\n";
for (; optind < ARGC; optind++) {
srcfile = ARGV[optind];
debug(1, "Source file: " srcfile " " ARGC " " optind);
autoheader = autoheader \
" * AUTOMATICALLY GENERATED BY " script_name " FROM " srcfile "\n";
process_catalog();
close(srcfile);
}
autoheader = autoheader " */\n";
first_comment = first_comment "\n" autoheader;
if (decl_file != "") {
outfilename = decl_file;
printc(first_comment);
out_decl();
close(outfilename);
}
if (defn_file != "") {
outfilename = defn_file;
printc(first_comment);
out_defn();
close(outfilename);
}
if (num_file != "") {
outfilename = num_file;
printc(first_comment);
out_number();
close(outfilename);
}
if (usage_file != "") {
outfilename = usage_file;
printc(first_comment);
out_usage();
close(outfilename);
}
if (comp_file != "") {
outfilename = comp_file;
printc(first_comment);
printc("#include <stddef.h>");
printc("#include \"catstd.h\"");
out_defn();
}
exit 0;
}
syntax highlighted by Code2HTML, v. 0.9.1