Two of the bugs listed in the man page are out of date: Unicode and
[sgt/halibut] / input.c
diff --git a/input.c b/input.c
index 4eb1d8c..d1b529d 100644 (file)
--- a/input.c
+++ b/input.c
@@ -86,9 +86,7 @@ static void input_configure(input *in, paragraph *cfg) {
     assert(cfg->type == para_Config);
 
     if (!ustricmp(cfg->keyword, L"input-charset")) {
-       char *csname = utoa_dup(uadv(cfg->keyword), CS_ASCII);
-       in->charset = charset_from_localenc(csname);
-       sfree(csname);
+       in->charset = charset_from_ustr(&cfg->fpos, uadv(cfg->keyword));
     }
 }
 
@@ -105,6 +103,8 @@ static int get(input *in, filepos *pos, rdstringc *rsc) {
     }
     else if (in->stack) {
        wchar_t c = in->stack->text[in->stack->ptr];
+        if (pos)
+            *pos = in->stack->pos;
        if (in->stack->text[++in->stack->ptr] == L'\0') {
            macrostack *tmp = in->stack;
            in->stack = tmp->next;
@@ -221,6 +221,7 @@ enum {
     c_c,                              /* code */
     c_cfg,                            /* configuration directive */
     c_copyright,                      /* copyright statement */
+    c_cq,                             /* quoted code (sugar for \q{\cw{x}}) */
     c_cw,                             /* weak code */
     c_date,                           /* document processing date */
     c_dd,                             /* description list: description */
@@ -291,6 +292,7 @@ static void match_kw(token *tok) {
        {"c", c_c},                    /* code */
        {"cfg", c_cfg},                /* configuration directive */
        {"copyright", c_copyright},    /* copyright statement */
+       {"cq", c_cq},                  /* quoted code (sugar for \q{\cw{x}}) */
        {"cw", c_cw},                  /* weak code */
        {"date", c_date},              /* document processing date */
        {"dd", c_dd},                  /* description list: description */
@@ -424,6 +426,7 @@ token get_token(input *in) {
            c == '#' || c == '{' || c == '}' || c == '.') {
            /* single-char command */
            rdadd(&rs, c);
+           prevpos = rsc.pos;
        } else if (c == 'u') {
            int len = 0;
            do {
@@ -589,11 +592,11 @@ static paragraph *addpara(paragraph newpara, paragraph ***hptrptr) {
 /*
  * Reads a single file (ie until get() returns EOF)
  */
-static void read_file(paragraph ***ret, input *in, indexdata *idx) {
+static void read_file(paragraph ***ret, input *in, indexdata *idx,
+                     tree234 *macros) {
     token t;
     paragraph par;
     word wd, **whptr, **idximplicit;
-    tree234 *macros;
     wchar_t utext[2], *wdtext;
     int style, spcstyle;
     int already;
@@ -607,7 +610,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
            stack_style = 2,           /* \e, \c, \cw */
            stack_idx = 4,             /* \I, \i, \ii */
            stack_hyper = 8,           /* \W */
-           stack_quote = 16,          /* \q */
+           stack_quote = 16           /* \q */
        } type;
        word **whptr;                  /* to restore from \u alternatives */
        word **idximplicit;            /* to restore from \u alternatives */
@@ -629,7 +632,6 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
 
     t.text = NULL;
     t.origtext = NULL;
-    macros = newtree234(macrocmp);
     already = FALSE;
 
     crossparastk = stk_new();
@@ -806,6 +808,11 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
            continue;
        }
 
+       while (t.type == tok_cmd &&
+              macrolookup(macros, in, t.text, &t.pos)) {
+           dtor(t), t = get_token(in);
+       }
+
        /*
         * This token begins a paragraph. See if it's one of the
         * special commands that define a paragraph type.
@@ -998,10 +1005,11 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
         * Mid-paragraph commands:
         *
         *  \K \k
-        *  \c \cw
+        *  \c \cw \cq
         *  \e
         *  \i \ii
         *  \I
+         *  \q
         *  \u
         *  \W
         *  \date
@@ -1198,6 +1206,8 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
                    }
                    break;
                  case c_q:
+                  case c_cq:
+                    type = t.cmd;
                    dtor(t), t = get_token(in);
                    if (t.type != tok_lbrace) {
                        error(err_explbr, &t.pos);
@@ -1235,6 +1245,15 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
                        sitem = snew(struct stack_item);
                        sitem->fpos = t.pos;
                        sitem->type = stype;
+                        if (type == c_cq) {
+                            if (style != word_Normal) {
+                                error(err_nestedstyles, &t.pos);
+                            } else {
+                                style = word_WeakCode;
+                                spcstyle = tospacestyle(style);
+                                sitem->type |= stack_style;
+                            }
+                        }
                        stk_push(parsestk, sitem);
                    }
                    break;
@@ -1510,7 +1529,17 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
        }
        stk_free(parsestk);
        prev_para_type = par.type;
-       addpara(par, ret);
+       /*
+        * Before we add the paragraph to the output list, we
+        * should check that there was any text in it at all; there
+        * might not be if (for example) the paragraph contained
+        * nothing but an unrecognised command sequence, and if we
+        * put an empty paragraph on the list it may confuse the
+        * back ends later on.
+        */
+       if (par.words) {
+           addpara(par, ret);
+       }
        if (t.type == tok_eof)
            already = TRUE;
     }
@@ -1528,7 +1557,6 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
      * this cleanup doesn't happen.
      */
     dtor(t);
-    macrocleanup(macros);
 
     stk_free(crossparastk);
 }
@@ -1536,6 +1564,9 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
 paragraph *read_input(input *in, indexdata *idx) {
     paragraph *head = NULL;
     paragraph **hptr = &head;
+    tree234 *macros;
+
+    macros = newtree234(macrocmp);
 
     while (in->currindex < in->nfiles) {
        in->currfp = fopen(in->filenames[in->currindex], "r");
@@ -1545,10 +1576,19 @@ paragraph *read_input(input *in, indexdata *idx) {
            in->csstate = charset_init_state;
            in->wcpos = in->nwc = 0;
            in->pushback_chars = NULL;
-           read_file(&hptr, in, idx);
+           if (strcmp(in->filenames[in->currindex] +
+                      strlen(in->filenames[in->currindex]) - 4, ".afm") == 0)
+               read_afm_file(in);
+           else if (strcmp(in->filenames[in->currindex] +
+                      strlen(in->filenames[in->currindex]) - 4, ".pfa") == 0)
+               read_pfa_file(in);
+           else
+               read_file(&hptr, in, idx, macros);
        }
        in->currindex++;
     }
 
+    macrocleanup(macros);
+
     return head;
 }