X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/blobdiff_plain/7136a6c7f094fa423c48ec319748c4fd7e1fa645..f4551933f1b39e3d017ce964cd3284193fb34cbe:/input.c diff --git a/input.c b/input.c index 6cad0f7..cb6cf9c 100644 --- a/input.c +++ b/input.c @@ -162,6 +162,7 @@ enum { c__invalid, /* invalid command */ c__comment, /* comment command (\#) */ c__escaped, /* escaped character */ + c__nop, /* no-op */ c__nbsp, /* nonbreaking space */ c_A, /* appendix heading */ c_B, /* bibliography entry */ @@ -190,8 +191,9 @@ enum { c_lcont, /* continuation para(s) for list item */ c_n, /* numbered list */ c_nocite, /* bibliography trickery */ - c_preamble, /* document preamble text */ + c_preamble, /* (obsolete) preamble text */ c_q, /* quote marks */ + c_quote, /* block-quoted paragraphs */ c_rule, /* horizontal rule */ c_title, /* document title */ c_u, /* aux field is char code */ @@ -230,6 +232,7 @@ static void match_kw(token *tok) { static const struct { char const *name; int id; } keywords[] = { {"#", c__comment}, /* comment command (\#) */ {"-", c__escaped}, /* nonbreaking hyphen */ + {".", c__nop}, /* no-op */ {"A", c_A}, /* appendix heading */ {"B", c_B}, /* bibliography entry */ {"BR", c_BR}, /* bibliography rewrite */ @@ -258,8 +261,9 @@ static void match_kw(token *tok) { {"lcont", c_lcont}, /* continuation para(s) for list item */ {"n", c_n}, /* numbered list */ {"nocite", c_nocite}, /* bibliography trickery */ - {"preamble", c_preamble}, /* document preamble text */ + {"preamble", c_preamble}, /* (obsolete) preamble text */ {"q", c_q}, /* quote marks */ + {"quote", c_quote}, /* block-quoted paragraphs */ {"rule", c_rule}, /* horizontal rule */ {"title", c_title}, /* document title */ {"versionid", c_versionid}, /* document RCS id */ @@ -358,7 +362,7 @@ token get_token(input *in) { } else if (c == '\\') { /* tok_cmd */ c = get(in, &cpos); if (c == '-' || c == '\\' || c == '_' || - c == '#' || c == '{' || c == '}') { + c == '#' || c == '{' || c == '}' || c == '.') { /* single-char command */ rdadd(&rs, c); } else if (c == 'u') { @@ -524,11 +528,12 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { } type; word **whptr; /* to restore from \u alternatives */ word **idximplicit; /* to restore from \u alternatives */ + filepos fpos; } *sitem; stack parsestk; struct crossparaitem { - int type; /* currently c_lcont or -1 */ - int seen_lcont; + int type; /* currently c_lcont, c_quote or -1 */ + int seen_lcont, seen_quote; }; stack crossparastk; word *indexword, *uword, *iword; @@ -569,11 +574,13 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { * Parse code paragraphs separately. */ if (t.type == tok_cmd && t.cmd == c_c && !isbrace(in)) { + int wtype = word_WeakCode; + par.type = para_Code; par.fpos = t.pos; while (1) { dtor(t), t = get_codepar_token(in); - wd.type = word_WeakCode; + wd.type = wtype; wd.breaks = FALSE; /* shouldn't need this... */ wd.text = ustrdup(t.text); wd.alt = NULL; @@ -586,9 +593,17 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { */ dtor(t), t = get_token(in); } - if (t.type == tok_eop || t.type == tok_eof) + if (t.type == tok_eop || t.type == tok_eof || + t.type == tok_rbrace) { /* might be } terminating \lcont */ + if (t.type == tok_rbrace) + already = TRUE; break; - else if (t.type != tok_cmd || t.cmd != c_c) { + } else if (t.type == tok_cmd && t.cmd == c_c) { + wtype = word_WeakCode; + } else if (t.type == tok_cmd && t.cmd == c_e && + wtype == word_WeakCode) { + wtype = word_Emph; + } else { error(err_brokencodepara, &t.pos); prev_para_type = par.type; addpara(par, ret); @@ -609,8 +624,9 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { * finish them. */ if (t.type == tok_cmd && - t.cmd == c_lcont) { + (t.cmd == c_lcont || t.cmd == c_quote)) { struct crossparaitem *sitem, *stop; + int cmd = t.cmd; /* * Expect, and swallow, an open brace. @@ -622,30 +638,63 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { } /* - * \lcont causes a continuation of a list item into - * multiple paragraphs (which may in turn contain - * nested lists, code paras etc). Hence, the previous - * paragraph must be of a list type. + * Also expect, and swallow, any whitespace after that + * (a newline before a code paragraph wouldn't be + * surprising). */ - sitem = mknew(struct crossparaitem); - stop = (struct crossparaitem *)stk_top(crossparastk); - if (prev_para_type == para_Bullet || - prev_para_type == para_NumberedList || - prev_para_type == para_Description) { - sitem->type = c_lcont; - sitem->seen_lcont = 1; - par.type = para_LcontPush; - prev_para_type = par.type; - addpara(par, ret); + do { + dtor(t), t = get_token(in); + } while (t.type == tok_white); + already = TRUE; + + if (cmd == c_lcont) { + /* + * \lcont causes a continuation of a list item into + * multiple paragraphs (which may in turn contain + * nested lists, code paras etc). Hence, the previous + * paragraph must be of a list type. + */ + sitem = mknew(struct crossparaitem); + stop = (struct crossparaitem *)stk_top(crossparastk); + if (stop) + *sitem = *stop; + else + sitem->seen_quote = sitem->seen_lcont = 0; + + if (prev_para_type == para_Bullet || + prev_para_type == para_NumberedList || + prev_para_type == para_Description) { + sitem->type = c_lcont; + sitem->seen_lcont = 1; + par.type = para_LcontPush; + prev_para_type = par.type; + addpara(par, ret); + } else { + /* + * Push a null item on the cross-para stack so that + * when we see the corresponding closing brace we + * don't give a cascade error. + */ + sitem->type = -1; + error(err_misplacedlcont, &t.pos); + } } else { /* - * Push a null item on the cross-para stack so that - * when we see the corresponding closing brace we - * don't give a cascade error. + * \quote causes a group of paragraphs to be + * block-quoted (typically they will be indented a + * bit). */ - sitem->type = -1; - sitem->seen_lcont = (stop ? stop->seen_lcont : 0); - error(err_misplacedlcont, &t.pos); + sitem = mknew(struct crossparaitem); + stop = (struct crossparaitem *)stk_top(crossparastk); + if (stop) + *sitem = *stop; + else + sitem->seen_quote = sitem->seen_lcont = 0; + sitem->type = c_quote; + sitem->seen_quote = 1; + par.type = para_QuotePush; + prev_para_type = par.type; + addpara(par, ret); } stk_push(crossparastk, sitem); continue; @@ -660,6 +709,11 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { prev_para_type = par.type; addpara(par, ret); break; + case c_quote: + par.type = para_QuotePop; + prev_para_type = par.type; + addpara(par, ret); + break; } sfree(sitem); } @@ -728,7 +782,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { case c_define: is_macro = TRUE; needkw = 1; break; /* For \nocite the keyword is _everything_ */ case c_nocite: needkw = 8; par.type = para_NoCite; break; - case c_preamble: needkw = 32; par.type = para_Preamble; break; + case c_preamble: needkw = 32; par.type = para_Normal; break; case c_rule: needkw = 16; par.type = para_Rule; break; case c_title: needkw = 32; par.type = para_Title; break; case c_versionid: needkw = 32; par.type = para_VersionID; break; @@ -740,8 +794,10 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { par.type == para_Appendix || par.type == para_UnnumberedChapter) { struct crossparaitem *sitem = stk_top(crossparastk); - if (sitem && sitem->seen_lcont) { - error(err_sectmarkerinlcont, &t.pos); + if (sitem && (sitem->seen_lcont || sitem->seen_quote)) { + error(err_sectmarkerinblock, + &t.pos, + (sitem->seen_lcont ? "lcont" : "quote")); } } @@ -865,6 +921,11 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { break; } + if (t.type == tok_cmd && t.cmd == c__nop) { + dtor(t), t = get_token(in); + continue; /* do nothing! */ + } + if (t.type == tok_cmd && t.cmd == c__escaped) { t.type = tok_word; /* nice and simple */ t.aux = 0; /* even if `\-' - nonbreaking! */ @@ -928,6 +989,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { /* Error recovery: push nop */ sitem = mknew(struct stack_item); sitem->type = stack_nop; + sitem->fpos = t.pos; stk_push(parsestk, sitem); break; case tok_rbrace: @@ -952,11 +1014,20 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { } if (sitem->type & stack_idx) { indexword->text = ustrdup(indexstr.text); - if (index_downcase) + if (index_downcase) { + word *w; + ustrlow(indexword->text); + ustrlow(indexstr.text); + + for (w = idxwordlist; w; w = w->next) + if (w->text) + ustrlow(w->text); + } indexing = FALSE; rdadd(&indexstr, L'\0'); - index_merge(idx, FALSE, indexstr.text, idxwordlist); + index_merge(idx, FALSE, indexstr.text, + idxwordlist, &sitem->fpos); sfree(indexstr.text); } if (sitem->type & stack_hyper) { @@ -1042,6 +1113,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { addword(wd, &idximplicit); } sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_quote; stk_push(parsestk, sitem); } @@ -1121,6 +1193,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { * Special cases: \W{}\c, \W{}\e, \W{}\cw */ sitem = mknew(struct stack_item); + sitem->fpos = wd.fpos; sitem->type = stack_hyper; if (t.type == tok_cmd && (t.cmd == c_e || t.cmd == c_c || t.cmd == c_cw)) { @@ -1152,6 +1225,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { /* Error recovery: eat lbrace, push nop. */ dtor(t), t = get_token(in); sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_nop; stk_push(parsestk, sitem); } @@ -1164,6 +1238,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { word_Emph); spcstyle = tospacestyle(style); sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_style; stk_push(parsestk, sitem); } @@ -1177,10 +1252,12 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { /* Error recovery: eat lbrace, push nop. */ dtor(t), t = get_token(in); sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_nop; stk_push(parsestk, sitem); } sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_idx; dtor(t), t = get_token(in); /* @@ -1250,6 +1327,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { * paragraph. */ sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_ualt; sitem->whptr = whptr; sitem->idximplicit = idximplicit;