diff options
Diffstat (limited to 'fref.lex')
-rw-r--r-- | fref.lex | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/fref.lex b/fref.lex new file mode 100644 index 0000000..645a2aa --- /dev/null +++ b/fref.lex @@ -0,0 +1,180 @@ + #include <err.h> + #include <stdarg.h> + + #define MAX 255 + + #define AND "och" + #define AVAIL "Tillgänglig: " + #define ED "red." + #define PP "ss." + #define TR "Övers." + #define VOL "vol." + + void field(char *); + void entry(void); + int pf(char *, ...); + + char *name; + + struct entry { + int a; /* Number of authors. */ + char au[MAX][MAX]; /* author */ + char ad[MAX]; /* internet address */ + char al[MAX]; /* TODO: alternative author name */ + char bo[MAX]; /* book */ + char ci[MAX]; /* city */ + char da[MAX]; /* date (year) */ + char ed[MAX]; /* editor */ + char jo[MAX]; /* journal */ + char no[MAX]; /* TODO: issue number */ + char pp[MAX]; /* pages */ + char pu[MAX]; /* publisher */ + char se[MAX]; /* TODO: series */ + char ti[MAX]; /* title */ + char tr[MAX]; /* translator */ + char vo[MAX]; /* volume */ + char xx[MAX]; /* extra information */ + } e; + +%s ENTRY +%% +^%.*\n field(yytext); BEGIN(ENTRY); +<ENTRY>^[^%] entry(); ECHO; BEGIN(0); +<ENTRY><<EOF>> entry(); yyterminate(); +%% + +void +main(int argc, char *argv[0]) +{ + name = argv[0]; + e.a = 0; + yylex(); +} + +/* Save entry field. */ +void +field(char *t) +{ + +#define AS(a,b) if(strncmp(t, a, 2) == 0 && (t += 3)){ strcpy(b, t); return; } + + t++; + t[strcspn(t, "\n")] = 0; + + AS("au",e.au[e.a++]); + AS("ad",e.ad); + AS("al",e.al); + AS("bo",e.bo); + AS("ci",e.ci); + AS("da",e.da); + AS("ed",e.ed); + AS("jo",e.jo); + AS("no",e.no); + AS("pp",e.pp); + AS("pu",e.pu); + AS("se",e.se); + AS("ti",e.ti); + AS("tr",e.tr); + AS("vo",e.vo); + AS("xx",e.xx); + + fprintf(stderr, "%s: unrecognized field %%%.2s\n", name, t); + exit(1); +} + +/* Print formatted entry. */ +void +entry() +{ + int i; + +#define EI(a, b) a ? a : b + + /* Print authors. */ + for(i = 0; i < e.a-2; i++) + printf("%s, ", e.au[i]); + if(i == e.a-2) + printf("%s "AND" ", e.au[i++]); + if(i == e.a-1) + printf("%s", e.au[i]); + + /* Print date. */ + (pf(" (%).\n", e.da) || (e.a ? pf(".\n") : 0)); + + /* Print title, book/journal. */ + if(*e.bo || *e.jo){ + pf("%.\n", e.ti); + pf("\\fI%\\fP", EI(e.bo, e.jo)); + pf(" ("ED" %)", e.ed); + }else + pf("\\fI%\\fP", e.ti); + + /* Print volume, pages. */ + pf(", "VOL" %", e.vo); + pf(", "PP" %", e.pp); + pf(".\n"); + + /* Print translator. */ + pf(TR" %.\n", e.tr); + + /* Print city, publisher. */ + (pf("%: %.\n", e.ci, e.pu) || pf("%.\n", e.pu)); + + /* Print other information. */ + pf("%.\n", e.xx); + + /* Print internet address. */ + pf(AVAIL"%\n", e.ad); + +#define CL(a) *a = 0 + + e.a = 0; + CL(e.ad); + CL(e.al); + CL(e.bo); + CL(e.ci); + CL(e.da); + CL(e.ed); + CL(e.jo); + CL(e.no); + CL(e.pp); + CL(e.pu); + CL(e.se); + CL(e.ti); + CL(e.tr); + CL(e.vo); + CL(e.xx); +} + +/* Print formatted text if given strings are non-empty. */ +int +pf(char *fmt, ...) +{ + char *buf, *p; + int n; + va_list ap; + + n = 0; + for(p = fmt; *p; p++) + if(*p == '%') + n++; + + if(!(buf = malloc(strlen(fmt)+n*MAX+1))) + err(1, "malloc"); + + va_start(ap, fmt); + for(; *fmt; fmt++) + switch(*fmt){ + case '%': + p = va_arg(ap, char *); + if(!p || !*p) + return 0; + strcat(buf, p); + break; + default: + strncat(buf, fmt, 1); + } + printf("%s", buf); + va_end(ap); + return 1; +} |