# dbTeX.awk - a simple preprocessor for generating TeX output from
# database files
# Version 1.1.beta (1991-02-12) dr. w. kraml, KPMG Alpen-Treuhand Wien
# see dbTeX.tex for documentation!
BEGIN { console_msg("This is dbTeX Version 1.1.beta (1991-02-12)")
printf("%% dbTeX (1.1.beta) Output generated " ctime() "\n")
# ^ PolyAwk specific!
printf("%% dbTeX Input file: %s\n", ARGV[1])
# a number of initialisations and defs follow here:
FieldS = FS
RecordS = RS
NRincluded = 0
example_flag = 0
buffer = ""
STANDARD = 0
STRING = 1
TEMPLATE = 2
ID = 3
USER = 1
}
# main loop - do this for each line in script
{ if ($0 ~ /^%!/) { # embedded dbTeX-command
in_template = 0
buffer = substr($0,3)
print $0 # output for reference
dbTeX_command()
}
else if ($0 ~ /^%_/) { # template contin. line
print $0
if (in_template) { # start cont. with newlines
nl = length(template[t_name]) ? "\n" : ""
template[t_name] = template[t_name] nl substr($0,3)
}
else error_msg("INVALID CONTINUATION")
}
else if (example_flag) { # embedded examples
in_template = 0
print "%" $0
}
else {
in_template = 0
print $0 # original TeX line
}
}
END { s = NR " line(s) input, " NRincluded " record(s) included, "
s = s (errors+0) " error(s)"
info_msg(s)
}
# functions performing helpful tasks with various messages
function console_msg(s) { # output to console
print s > "/dev/tty"
}
function error_msg(msg, s) { # print error on console
s = "% (dbTeX) Error: " msg "!" # and in output file
++errors
print s
console_msg(s " -> line " NR ":")
console_msg($0)
}
function info_msg(msg, s) { # print info on console
s = "% (dbTeX) Info: " msg "." # and in output file
print s
console_msg(s)
}
# dbTeX functions
function dbTeX_command() { # the dbTeX main function
advance(ID)
example_flag = 0
if (tok == "examples") example_flag = 1 # %! examples
else if (tok == "record") { # %! record <id> <FS> [<RS>]
if (advance(ID)) {
if (tok ~ /^%[0-9]+%$/) { # data-named template
templ_typ = 1
templ_field = substr(tok,2,length(tok)-2)
}
else { # script-named template
templ_typ = 0
templ_name = tok
}
}
FieldS = advance(STRING) ? tok : FS
RecordS = advance(STRING) ? tok : RS
}
else if (tok=="template") { # %! template <id> <template>
in_template = 1
if (advance(ID)) # get name
t_name = tok
if (advance(TEMPLATE))
template[t_name] = tok
}
else if (tok=="break") { # %! break %f% <id>
if (advance(ID)) {
if (tok ~ /^%[0-9]+%$/)
breakfield = substr(tok,2,length(tok)-2)
else
breakfield = tok
}
if (advance(ID))
breaktemplate[breakfield] = tok
if (advance(ID))
breakmode[breakfield] = 1
else breakmode[breakfield] = 0
}
else if (tok=="clearbreaks") { # %! clearbreaks
for (i in oldvalue)
delete oldvalue[i]
for (i in breaktemplate)
delete breaktemplate[i]
for (i in breakmode)
delete breakmode[i]
}
else if (tok=="translate") { # %! translate <id>
if (advance(ID))
set_translation(tok)
}
else if (tok=="change") { # %! change <s1> <s2>
add_trtbl(USER)
}
else if (tok=="include") { # %! include <filename>
if (advance(ID))
do_include(tok)
}
else error_msg("UNKNOWN COMMAND")
}
function advance(type, sep,pos) { # get next token of type
sub(/^[ \t]+/, "", buffer) # remove white space
if (type == ID) {
match(buffer, /^[^ \t]+/) # all up to white space
tok = tolower(substr(buffer, 1, RLENGTH)) # tolower(): PolyAwk & GNU only!
buffer = substr(buffer, RLENGTH+1)
return RLENGTH
}
else if (type == TEMPLATE) { # rest of line
tok = buffer
buffer = ""
return length(tok)
}
else if (type == STRING) { # string delimited by
sep = substr(buffer,1,1) # unique character
buffer = substr(buffer,2)
pos = index(buffer, sep)
if (pos) {
tok = substr(buffer,1,pos-1)
buffer = substr(buffer, pos+1)
return pos
}
else {
tok = ""
return 0
}
}
else return 0
}
function add_trtbl(tbl) { # add an entry to tr table
if (advance(STRING)) {
tmp = tok
if (advance(STRING))
tbl==USER ? (usr_tbl[tmp] = tok) : (std_tbl[tmp] = tok)
else
tbl==USER ? (usr_tbl[tmp] = "") : (std_tbl[tmp] = "")
}
}
function set_translation(id) { # install translation table
if (toupper(id) == "OFF") {
for (i in std_tbl)
delete std_tbl[i]
for (i in usr_tbl)
delete usr_tbl[i]
}
else { # read translation table
while ((status = getline line < id) > 0) {
buffer = line
if (buffer !~ /^#/)
add_trtbl(STANDARD)
}
if (status == -1)
error_msg("TRANSLATION TABLE " id " NOT FOUND")
}
}
function do_include(file) { # include records of <file>
old_FS = FS; old_RS = RS
FS = FieldS; RS = RecordS
inc = 0
while (getline < file > 0) {
for (i in breaktemplate) # check for breaks
if (oldvalue[i] != $i) {
oldvalue[i] = $i
if (inc || breakmode[i]) # no break before 1st rec.,
incl_(template[breaktemplate[i]])
} # if not explicitly wanted!
if (templ_typ)
incl_(template[$templ_field])
else incl_(template[templ_name])
++NRincluded; ++inc
}
FS = old_FS; RS = old_RS
close(file)
if (!inc) error_msg("FILE " file " NOT FOUND OR NOT ACCESSIBLE!")
info_msg(inc " record(s) included from " file)
}
function incl_(t) { # include record with template t
s = ""
while (match(t, /%[0-9]+%/)) {
l = RSTART-1
s = s substr(t,1,l) txlate($(substr(t,RSTART+1,RLENGTH-2)))
# translated data field
t = substr(t,l+RLENGTH+1)
}
print s t
}
function txlate(s) { # perform translations on string s
for (target in std_tbl)
gsub(target, std_tbl[target], s)
for (target in usr_tbl)
gsub(target, usr_tbl[target], s)
return s
}