aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2021-07-20 13:33:35 +0200
committerJohn Ankarström <john@ankarstrom.se>2021-07-21 11:19:55 +0200
commit45a1cc39c6515c6f8462a1d833da1bd58af420b6 (patch)
tree1e3172f4138478ab5cb7eddc8fe959eb582aae0d
parent577a9653d0c22779a64d38e2338ed07ffbe0ecf5 (diff)
downloadfref-45a1cc39c6515c6f8462a1d833da1bd58af420b6.tar.gz
Add -l (language) flag
-rw-r--r--fref.188
-rw-r--r--fref.lex127
2 files changed, 134 insertions, 81 deletions
diff --git a/fref.1 b/fref.1
index 2326c99..74e6c53 100644
--- a/fref.1
+++ b/fref.1
@@ -7,6 +7,7 @@
.
.Sh SYNOPSIS
.Nm
+.Op Fl l Ar lang
.
.Sh DESCRIPTION
.Pp
@@ -24,32 +25,19 @@ They are inserted in the places they are specified in the
.Xr troff 1
source code.
.Pp
-.Pa fref.lex
-contains a number of hardcoded strings
-that should be manually changed
-depending on the desired output language:
-.Bl -tag -width AVAIL -offset indent
-.It AND
-.Dq and :
-Inserted between next to last and last author.
-.It AVAIL
-.Dq available :
-Inserted before a hypertext reference.
-.It ED
-.Dq editor :
-Inserted before the name of the editor.
-.It P
-.Dq page :
-Inserted before a single page.
-.It PP
-.Dq pages :
-Inserted before multiple pages.
-.It TR
-.Dq translator :
-Inserted before the name of the translator.
-.It VOL
-.Dq volume :
-Inserted before the volume number.
+The
+.Fl l
+flag controls the language of certain strings, such as
+.Dq ed. ,
+.Dq pp. ,
+and
+.Dq and .
+The following values are supported:
+.Bl -tag -width xx -offset indent
+.It Em en
+English (default)
+.It Em sv
+Swedish
.El
.
.Sh SYNTAX
@@ -68,38 +56,46 @@ non-field lines.
The following fields are available:
.Bl -tag -width xxx -offset indent
.It Sy %ad
-Access date.
+Access date
.It Sy %bo
-Book.
+Book
.It Sy %ci
-City.
+City
.It Sy %da
-Date (year).
+Date (year)
.It Sy %ed
-Editor.
+Editor
.It Sy %hr
-Hypertext reference.
+Hypertext reference
.It Sy %jo
-Journal.
+Journal
.It Sy %la
-Label.
+Label
.It Sy %no
-TODO: Issue number.
+TODO: Issue number
.It Sy %pp
-Pages.
+Pages
.It Sy %pu
-Publisher.
+Publisher
.It Sy %se
-TODO: Series.
+TODO: Series
.It Sy %ti
-Title.
+Title
.It Sy %tr
-Translator.
+Translator
.It Sy %vo
-Volume.
+Volume
.It Sy %xx
-Extra information.
+Extra information
.El
+.Pp
+Note that
+.Nm
+performs no special formatting of the
+.Sy %au
+field.
+Thus, it should be specified as
+.Dq "last name, first name" .
.
.Sh EXAMPLES
.Pp
@@ -119,6 +115,8 @@ References
%ci Bloomington
%pu Indiana University Press
%xx Extra information
+\&.XP
+\&.\\" ...
.Ed
.Pp
results in the following output:
@@ -128,10 +126,12 @@ References
\&.XP
Baudouin de Courtenay, J. (1972).
The Difference between Phonetics and Psychophonetics.
-\\fIA Baudouin de Courtenay Anthology\\fP (red. T. A. Sebeok et al.).
-Övers. Edward Stankiewicz.
+\\fIA Baudouin de Courtenay Anthology\\fP (ed. T. A. Sebeok et al.).
+Trans. Edward Stankiewicz.
Bloomington: Indiana University Press.
Extra information.
+\&.XP
+\&.\\" ...
.Ed
.
.Sh SEE ALSO
diff --git a/fref.lex b/fref.lex
index d1ee949..dee3658 100644
--- a/fref.lex
+++ b/fref.lex
@@ -16,18 +16,6 @@
#define MAX 255 /* Max field length. */
- /*
- * The following string constants can be redefined to support
- * other languages.
- */
- #define AND "och"
- #define AVAIL "Tillgänglig: "
- #define ED "red."
- #define P "s."
- #define PP "ss."
- #define TR "Övers."
- #define VOL "vol."
-
#define DO_FIELDS \
DO("ad",ad,e.ad) /* Access date. */ \
DO("bo",bo,e.bo) /* Book. */ \
@@ -52,14 +40,14 @@
void harvard(void);
int pf(char *, ...);
+ extern char *optarg;
+ extern int optind;
+
char *name;
int line; /* Line at which entry begins. */
int lines = 0; /* Total number of lines. */
- /*
- * e is a struct holding all fields of the current entry.
- * It is zeroed at the end of each call to entry().
- */
+ /* Fields of current entry. */
struct entry {
#define DO(s,n,m) char n[MAX];
DO_FIELDS
@@ -68,6 +56,17 @@
char au[MAX][MAX]; /* Authors. */
} e;
+ /* Translation strings. */
+ struct translations {
+ char *and;
+ char *avail;
+ char *ed;
+ char *p;
+ char *pp;
+ char *tr;
+ char *vo;
+ } t;
+
%%
\n lines++; ECHO;
^%.*\n line = ++lines; field(yytext); BEGIN(ENTRY);
@@ -77,32 +76,74 @@
%%
void
-main(int argc, char *argv[0])
+main(int argc, char *argv[])
{
+ char *lang;
+ int c;
+
+ /* Save program name. */
name = strrchr(argv[0], '/');
if(name) name++;
else name = argv[0];
+ /* Parse command-line options. */
+ while((c = getopt(argc, argv, "l:")) != -1)
+ switch(c){
+ case 'l':
+ lang = optarg;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-lLANG]\n", argv[0]);
+ exit(1);
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Set translation strings according to -l. */
+ if(strncmp(lang, "sv", 2) == 0){
+ t.and = strdup("och");
+ t.avail = strdup("Tillgänglig: ");
+ t.ed = strdup("red. ");
+ t.p = strdup("s. ");
+ t.pp = strdup("ss. ");
+ t.tr = strdup("Övers. ");
+ t.vo = strdup("vol. ");
+ }else{
+ t.and = strdup("and");
+ t.avail = strdup("Available: ");
+ t.ed = strdup("ed. ");
+ t.p = strdup("p. ");
+ t.pp = strdup("pp. ");
+ t.tr = strdup("Trans. ");
+ t.vo = strdup("vol. ");
+ }
+
+ /* Clear entry struct. */
memset(&e, 0, sizeof(e));
+
yylex();
}
/* Save entry field. */
void
-field(char *t)
+field(char *s)
{
- t++;
- t[strcspn(t, "\n")] = 0;
+ s++;
+ s[strcspn(s, "\n")] = 0;
/* Fill corresponding field. */
-#define AS(a,b) if(strncmp(t, a, 2) == 0 && (t += 3)){ strcpy(b, t); return; }
+#define AS(a,b) if(strncmp(s, a, 2) == 0 && (s += 3)){ strcpy(b, s); return; }
AS("au",e.au[e.a++]);
#define DO(s,n,m) AS(s,m)
DO_FIELDS
#undef DO
+ /*
+ * As no field matched, an error is printed and the program exits
+ * with a positive value.
+ */
fprintf(stderr, "%s: unrecognized field %%%.2s at line %d\n",
- name, t, lines);
+ name, s, lines);
exit(1);
}
@@ -111,8 +152,8 @@ void
entry()
{
/*
- * Presently, fref supports only Harvard-style citations, but
- * allows for future extensions.
+ Presently, fref supports only Harvard-style citations, but
+ this allows for future extensions.
*/
harvard();
}
@@ -130,7 +171,7 @@ harvard()
for(i = 0; i < e.a-2; i++)
printf("%s, ", e.au[i]);
if(i == e.a-2)
- printf("%s "AND" ", e.au[i++]);
+ printf("%s %s ", e.au[i++], t.and);
if(i == e.a-1)
printf("%s", e.au[i]);
@@ -141,16 +182,16 @@ harvard()
if(*e.bo || *e.jo){
pf("%.\n", e.ti);
pf("\\fI%\\fP", e.bo ? e.bo : e.jo);
- pf(" ("ED" %)", e.ed);
+ pf(" (*%)", t.ed, e.ed);
}else
pf("\\fI%\\fP", e.ti);
/* Print volume. */
- pf(", "VOL" %", e.vo);
+ pf(", *%", t.vo, e.vo);
/* Print pages, converting hyphens to en dashes. */
if(*e.pp){
- printf(", %s ", strpbrk(e.pp, ",-") ? PP : P);
+ printf(", %s", strpbrk(e.pp, ",-") ? t.pp : t.p);
for(i = 0; i < strlen(e.pp); i++){
if(e.pp[i] == '-') putchar('\\');
putchar(e.pp[i]);
@@ -160,7 +201,7 @@ harvard()
pf(".\n");
/* Print translator. */
- pf(TR" %.\n", e.tr);
+ pf("*%.\n", t.tr, e.tr);
/* Print city, publisher. */
(pf("%: %.\n", e.ci, e.pu) || pf("%.\n", e.pu));
@@ -169,7 +210,7 @@ harvard()
pf("%.\n", e.xx);
/* Print hypertext reference. */
- pf(AVAIL"%\n", e.hr);
+ pf("*%\n", t.avail, e.hr);
/* Print access date. */
pf("[%]\n", e.ad);
@@ -184,7 +225,12 @@ harvard()
#undef DO
}
-/* Print formatted text if given fields are non-empty. Clear fields. */
+/*
+ * This function interpolates any number of strings into a formatted
+ * string, which is printed only if all interpolated strings are non-empty.
+ * Interpolation points are marked by % or *. If a string is interpolated
+ * using %, the function empties it after printing it.
+ */
int
pf(char *fmt, ...)
{
@@ -192,16 +238,18 @@ pf(char *fmt, ...)
int i, n, sz;
va_list ap;
- /* Count given fields. */
+ /* Count interpolated strings. */
for(n = 0, p = fmt; *p; p++)
- if(*p == '%')
+ if(*p == '%' || *p == '*')
n++;
- /* Allocate memory. */
if(!(fs = malloc(n)))
err(1, "malloc");
- /* Verify that no field is empty. */
+ /*
+ * The strings to be interpolated are saved in fs.
+ * If any string is empty, the function returns false.
+ */
va_start(ap, fmt);
for(i = 0; i < n; i++){
p = va_arg(ap, char *);
@@ -211,12 +259,17 @@ pf(char *fmt, ...)
}
va_end(ap);
- /* Print fields according to format. */
+ /* Print formatted string. */
for(i = 0; *fmt; fmt++)
switch(*fmt){
case '%':
printf("%s", fs[i]);
- fs[i++][0] = 0;
+ fs[i][0] = 0;
+ i++;
+ break;
+ case '*':
+ printf("%s", fs[i]);
+ i++;
break;
default:
putchar(*fmt);