# 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 }