#! /usr/bin/gawk -f # Last edited on 2004-02-29 07:47:46 by stolfi BEGIN { abort = -1; usage = ( "rugg-generator \\\n" \ " -v grilles='PMS PMS PMS ... PMS' \\\n" \ " -v tokens=NUM \\\n" \ " < INPUT.tbl > OUTPUT.txt " \ ); # Gordon Rugg's table-and-grille generator. The input must be a # table for Gordon Rugg's method, one entry per line with prefix, # medfix, and suffix separated by "_". # # The {grilles} argument specifies the positions of the holes in # each grille, as three digits {P}, {M}, {S}. Each grille is used # for {N} successive words where {N} is the length of the table. The # {grilles} list is reused as often as needed # Check whether arguments were sepcified if (grilles == "") { arg_error("must define \"grilles\""); } if (tokens == "") { arg_error("must define \"tokens\""); } # Check grille syntax: if (grilles !~ /^[0-9][0-9][0-9]([ ][0-9][0-9][0-9])*$/) { arg_error("invalid \"grilles\" argument"); } # Create empty table: split("", pre); split("", mid); split("", suf); nt = 0; } # Watch abort flag: (abort >= 0) { exit abort; } # Ignore comments and blank lines: /^ *([\#]|$)/ { next; } # Table must have three columns separated by (NF == 1) { if (! match($0, /^([^_]*)[_]([^_]*)[_]([^_]*)$/, fld)) { data_error(("bad table entry = [" $0 "]")); } pre[nt] = fld[1]; mid[nt] = fld[2]; suf[nt] = fld[3]; nt++; next; } # Anything else is error: // { data_error(("bad input line [" $0 "]")); } # After loading the table, generate the text: END { # Check for errors in input: if (abort >= 0) { exit abort; } # Table must be non-empty if (nt == 0) { arg_error("empty table?"); } # To force the selection of a new grille (the first one): ng = length(grilles) + 1; used = nt; # Loop on output tokens: for (i = 0; i < tokens; i++) { # Have we exhausted this grille? if (used >= nt) { # Get new grille: ng += 4; if (ng+3 > length(grilles)) { ng = 0; } pk = int(substr(grilles, ng+1, 1) * 13 + 0.5) % nt; mk = int(substr(grilles, ng+2, 1) * 13 + 0.5) % nt; sk = int(substr(grilles, ng+3, 1) * 13 + 0.5) % nt; used = 0; } # Generate next word: print (pre[pk] mid[mk] suf[sk]); # Advance the grille: pk = (pk + 1) % nt; mk = (mk + 1) % nt; sk = (sk + 1) % nt; used++; } } function arg_error(msg) { printf "%s\n", msg > "/dev/stderr"; printf "usage: %s\n", usage > "/dev/stderr"; abort = 1; exit 1; } function data_error(msg) { printf "line %d: %s\n", FNR, msg > "/dev/stderr"; abort = 1; exit 1; }