aboutsummaryrefslogtreecommitdiff
path: root/fref.lex
diff options
context:
space:
mode:
Diffstat (limited to 'fref.lex')
-rw-r--r--fref.lex180
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;
+}