Annotation of texi2mdoc/main.c, Revision 1.32
1.32 ! kristaps 1: /* $Id: main.c,v 1.31 2015/02/23 11:56:39 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2015 Kristaps Dzonsons <kristaps@bsd.lv>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #include <sys/mman.h>
18: #include <sys/stat.h>
19:
20: #include <assert.h>
21: #include <ctype.h>
22: #include <fcntl.h>
23: #include <getopt.h>
1.2 kristaps 24: #include <libgen.h>
25: #include <limits.h>
1.1 kristaps 26: #include <stdarg.h>
27: #include <stdio.h>
28: #include <stdlib.h>
29: #include <string.h>
1.10 kristaps 30: #include <time.h>
1.6 kristaps 31: #include <unistd.h>
1.1 kristaps 32:
1.24 kristaps 33: #include "extern.h"
1.1 kristaps 34:
1.23 kristaps 35: #define SECTSZ 4
36: static const char *const sects[SECTSZ] = {
37: "Sh",
38: "Ss",
39: "Em",
40: "No",
41: };
42:
1.16 kristaps 43: static void doaccent(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.3 kristaps 44: static void doblock(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.1 kristaps 45: static void dobracket(struct texi *, enum texicmd, const char *, size_t, size_t *);
46: static void dobye(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.27 kristaps 47: static void dodefindex(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.15 kristaps 48: static void dodefn(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.3 kristaps 49: static void dodisplay(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.2 kristaps 50: static void doenumerate(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.1 kristaps 51: static void doexample(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.8 kristaps 52: static void doignargn(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.1 kristaps 53: static void doignblock(struct texi *, enum texicmd, const char *, size_t, size_t *);
54: static void doignbracket(struct texi *, enum texicmd, const char *, size_t, size_t *);
55: static void doignline(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.12 kristaps 56: static void doinline(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.2 kristaps 57: static void doinclude(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.1 kristaps 58: static void doitem(struct texi *, enum texicmd, const char *, size_t, size_t *);
59: static void doitemize(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.8 kristaps 60: static void dolink(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.30 kristaps 61: static void domacro(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.3 kristaps 62: static void domath(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.18 kristaps 63: static void domultitable(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.1 kristaps 64: static void doquotation(struct texi *, enum texicmd, const char *, size_t, size_t *);
65: static void dotable(struct texi *, enum texicmd, const char *, size_t, size_t *);
66: static void dotop(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.23 kristaps 67: static void dosecoffs(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.1 kristaps 68: static void dosection(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.3 kristaps 69: static void dosp(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.1 kristaps 70: static void dosubsection(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.23 kristaps 71: static void dosubsubsection(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.1 kristaps 72: static void dosymbol(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.18 kristaps 73: static void dotab(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.10 kristaps 74: static void dotitle(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.24 kristaps 75: static void dovalue(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.25 kristaps 76: static void doverb(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.16 kristaps 77: static void doverbinclude(struct texi *, enum texicmd, const char *, size_t, size_t *);
1.1 kristaps 78:
1.24 kristaps 79: static const struct texitok __texitoks[TEXICMD__MAX] = {
1.20 kristaps 80: /* TEXICMD__BEGIN */
1.8 kristaps 81: { doignargn, "acronym", 7 }, /* TEXICMD_ACRONYM */
1.16 kristaps 82: { doaccent, "'", 1 }, /* TEXICMD_ACUTE */
1.1 kristaps 83: { doignline, "afourpaper", 10 }, /* TEXICMD_A4PAPER */
84: { doignbracket, "anchor", 6 }, /* TEXICMD_ANCHOR */
1.12 kristaps 85: { dosection, "appendix", 8 }, /* TEXICMD_APPENDIX */
86: { dosection, "appendixsec", 11 }, /* TEXICMD_APPENDIXSEC */
1.20 kristaps 87: { dosubsection, "appendixsubsec", 14 }, /* TEXICMD_APPENDIXSUBSEC */
1.23 kristaps 88: { dosubsubsection, "appendixsubsubsec", 17 }, /* TEXICMD_APPENDIXSUBSUBSEC */
1.25 kristaps 89: { doinline, "asis", 4 }, /* TEXICMD_ASIS */
1.3 kristaps 90: { dosymbol, "*", 1 }, /* TEXICMD_ASTERISK */
1.1 kristaps 91: { dosymbol, "@", 1 }, /* TEXICMD_AT */
1.3 kristaps 92: { doignline, "author", 6 }, /* TEXICMD_AUTHOR */
1.21 kristaps 93: { doinline, "b", 1 }, /* TEXICMD_BOLD */
1.3 kristaps 94: { dosymbol, "!", 1 }, /* TEXICMD_BANG */
1.7 kristaps 95: { dosymbol, "bullet", 6 }, /* TEXICMD_BULLET */
1.1 kristaps 96: { dobye, "bye", 3 }, /* TEXICMD_BYE */
1.12 kristaps 97: { doignline, "center", 6 }, /* TEXICMD_CENTER */
98: { dosection, "chapter", 7 }, /* TEXICMD_CHAPTER */
1.1 kristaps 99: { doignline, "cindex", 6 }, /* TEXICMD_CINDEX */
1.16 kristaps 100: { doaccent, "^", 1 }, /* TEXICMD_CIRCUMFLEX */
1.24 kristaps 101: { doinline, "cite", 4 }, /* TEXICMD_CITE */
102: { dovalue, "clear", 5 }, /* TEXICMD_CLEAR */
1.21 kristaps 103: { doinline, "code", 4 }, /* TEXICMD_CODE */
1.3 kristaps 104: { dosymbol, ":", 1 }, /* TEXICMD_COLON */
1.18 kristaps 105: { NULL, "columnfractions", 15 }, /* TEXICMD_COLUMNFRACTIONS */
1.12 kristaps 106: { doinline, "command", 7 }, /* TEXICMD_COMMAND */
1.1 kristaps 107: { doignline, "c", 1 }, /* TEXICMD_COMMENT */
1.2 kristaps 108: { doignline, "comment", 7 }, /* TEXICMD_COMMENT_LONG */
1.1 kristaps 109: { doignline, "contents", 8 }, /* TEXICMD_CONTENTS */
110: { doignblock, "copying", 7 }, /* TEXICMD_COPYING */
111: { dosymbol, "copyright", 9 }, /* TEXICMD_COPYRIGHT */
1.27 kristaps 112: { dodefindex, "defcodeindex", 12 }, /* TEXICMD_DEFCODEINDEX */
1.15 kristaps 113: { dodefn, "deffn", 5 }, /* TEXICMD_DEFFN */
114: { dodefn, "deffnx", 6 }, /* TEXICMD_DEFFNX */
1.27 kristaps 115: { dodefindex, "defindex", 8 }, /* TEXICMD_DEFINDEX */
1.15 kristaps 116: { dodefn, "defmac", 6 }, /* TEXICMD_DEFMAC */
117: { dodefn, "defmacx", 7 }, /* TEXICMD_DEFMACX */
118: { dodefn, "deftp", 5 }, /* TEXICMD_DEFTP */
119: { dodefn, "deftpx", 6 }, /* TEXICMD_DEFTPX */
120: { dodefn, "deftypefn", 9 }, /* TEXICMD_DEFTYPEFN */
121: { dodefn, "deftypefnx", 10 }, /* TEXICMD_DEFTYPEFNX */
122: { dodefn, "deftypefun", 10 }, /* TEXICMD_DEFTYPEFUN */
123: { dodefn, "deftypefunx", 11 }, /* TEXICMD_DEFTYPEFUNX */
124: { dodefn, "deftypevar", 10 }, /* TEXICMD_DEFTYPEVAR */
125: { dodefn, "deftypevarx", 11 }, /* TEXICMD_DEFTYPEVARX */
126: { dodefn, "deftypevr", 9 }, /* TEXICMD_DEFTYPEVR */
127: { dodefn, "deftypevrx", 10 }, /* TEXICMD_DEFTYPEVRX */
128: { dodefn, "defun", 5 }, /* TEXICMD_DEFUN */
129: { dodefn, "defunx", 6 }, /* TEXICMD_DEFUNX */
130: { dodefn, "defvar", 6 }, /* TEXICMD_DEFVAR */
131: { dodefn, "defvarx", 7 }, /* TEXICMD_DEFVARX */
132: { dodefn, "defvr", 5 }, /* TEXICMD_DEFVR */
133: { dodefn, "defvrx", 6 }, /* TEXICMD_DEFVRX */
1.1 kristaps 134: { doignblock, "detailmenu", 10 }, /* TEXICMD_DETAILMENU */
1.21 kristaps 135: { doinline, "dfn", 3 }, /* TEXICMD_DFN */
1.1 kristaps 136: { doignline, "dircategory", 11 }, /* TEXICMD_DIRCATEGORY */
137: { doignblock, "direntry", 8 }, /* TEXICMD_DIRENTRY */
1.3 kristaps 138: { dodisplay, "display", 7 }, /* TEXICMD_DISPLAY */
1.28 kristaps 139: { doignbracket, "dmn", 3 }, /* TEXICMD_DMN */
1.2 kristaps 140: { dosymbol, "dots", 4 }, /* TEXICMD_DOTS */
1.8 kristaps 141: { dolink, "email", 5 }, /* TEXICMD_EMAIL */
1.21 kristaps 142: { doinline, "emph", 4 }, /* TEXICMD_EMPH */
1.1 kristaps 143: { NULL, "end", 3 }, /* TEXICMD_END */
1.2 kristaps 144: { doenumerate, "enumerate", 9 }, /* TEXICMD_ENUMERATE */
1.12 kristaps 145: { doinline, "env", 3 }, /* TEXICMD_ENV */
1.28 kristaps 146: { dosymbol, "equiv", 5 }, /* TEXICMD_EQUIV */
1.15 kristaps 147: { dosymbol, "error", 5 }, /* TEXICMD_ERROR */
1.1 kristaps 148: { doexample, "example", 7 }, /* TEXICMD_EXAMPLE */
1.25 kristaps 149: { doignline, "exdent", 6 }, /* TEXICMD_EXDENT */
1.17 kristaps 150: { dosymbol, "expansion", 9 }, /* TEXICMD_EXPANSION */
1.12 kristaps 151: { doinline, "file", 4 }, /* TEXICMD_FILE */
1.17 kristaps 152: { doignline, "finalout", 8 }, /* TEXICMD_FINALOUT */
1.20 kristaps 153: { doignline, "findex", 6 }, /* TEXICMD_FINDEX */
1.32 ! kristaps 154: { doignbracket, "footnote", 8 }, /* TEXICMD_FOOTNOTE */
1.20 kristaps 155: { dotable, "ftable", 6 }, /* TEXICMD_FTABLE */
156: { dodisplay, "format", 6 }, /* TEXICMD_FORMAT */
1.16 kristaps 157: { doaccent, "`", 1 }, /* TEXICMD_GRAVE */
1.3 kristaps 158: { doblock, "group", 5 }, /* TEXICMD_GROUP */
1.2 kristaps 159: { dosection, "heading", 7 }, /* TEXICMD_HEADING */
1.3 kristaps 160: { doignline, "headings", 8 }, /* TEXICMD_HEADINGS */
1.18 kristaps 161: { doitem, "headitem", 8 }, /* TEXICMD_HEADITEM */
1.25 kristaps 162: { doignblock, "html", 4 }, /* TEXICMD_HTML */
1.3 kristaps 163: { dosymbol, "-", 1 }, /* TEXICMD_HYPHEN */
1.21 kristaps 164: { doinline, "i", 1 }, /* TEXICMD_I */
1.24 kristaps 165: { dovalue, "ifclear", 7 }, /* TEXICMD_IFCLEAR */
1.14 kristaps 166: { doignblock, "ifdocbook", 9 }, /* TEXICMD_IFDOCBOOK */
1.1 kristaps 167: { doignblock, "ifhtml", 6 }, /* TEXICMD_IFHTML */
1.26 kristaps 168: { doblock, "ifinfo", 6 }, /* TEXICMD_IFINFO */
1.14 kristaps 169: { doblock, "ifnotdocbook", 12 }, /* TEXICMD_IFNOTDOCBOOK */
170: { doblock, "ifnothtml", 9 }, /* TEXICMD_IFNOTHTML */
171: { doblock, "ifnotinfo", 9 }, /* TEXICMD_IFNOTINFO */
172: { doignblock, "ifnotplaintext", 14 }, /* TEXICMD_IFNOTPLAINTEXT */
1.3 kristaps 173: { doblock, "ifnottex", 8 }, /* TEXICMD_IFNOTTEX */
1.14 kristaps 174: { doblock, "ifnotxml", 8 }, /* TEXICMD_IFNOTXML */
175: { doblock, "ifplaintext", 11 }, /* TEXICMD_IFPLAINTEXT */
1.1 kristaps 176: { doignblock, "iftex", 5 }, /* TEXICMD_IFTEX */
1.30 kristaps 177: { dovalue, "ifset", 5 }, /* TEXICMD_IFSET */
1.14 kristaps 178: { doignblock, "ifxml", 5 }, /* TEXICMD_IFXML */
1.17 kristaps 179: { doignblock, "ignore", 6 }, /* TEXICMD_IGNORE */
1.1 kristaps 180: { doignbracket, "image", 5 }, /* TEXICMD_IMAGE */
1.2 kristaps 181: { doinclude, "include", 7 }, /* TEXICMD_INCLUDE */
1.13 kristaps 182: { dodisplay, "indentblock", 11 }, /* TEXICMD_INDENTBLOCK */
1.30 kristaps 183: { doignline, "", 0 }, /* TEXICMD_USER_INDEX */
1.5 kristaps 184: { doignline, "insertcopying", 13 }, /* TEXICMD_INSERTCOPYING */
1.1 kristaps 185: { doitem, "item", 4 }, /* TEXICMD_ITEM */
186: { doitemize, "itemize", 7 }, /* TEXICMD_ITEMIZE */
1.20 kristaps 187: { doitem, "itemx", 5 }, /* TEXICMD_ITEMX */
1.21 kristaps 188: { doinline, "kbd", 3 }, /* TEXICMD_KBD */
1.18 kristaps 189: { dobracket, "key", 3 }, /* TEXICMD_KEY */
1.20 kristaps 190: { doignline, "kindex", 6 }, /* TEXICMD_KINDEX */
1.1 kristaps 191: { dosymbol, "LaTeX", 5 }, /* TEXICMD_LATEX */
1.23 kristaps 192: { dosecoffs, "lowersections", 13 }, /* TEXICMD_LOWERSECTIONS */
1.30 kristaps 193: { domacro, "macro", 5 }, /* TEXICMD_MACRO */
1.3 kristaps 194: { domath, "math", 4 }, /* TEXICMD_MATH */
1.1 kristaps 195: { doignblock, "menu", 4 }, /* TEXICMD_MENU */
1.25 kristaps 196: { dosymbol, "minus", 5 }, /* TEXICMD_MINUS */
1.18 kristaps 197: { domultitable, "multitable", 10 }, /* TEXICMD_MULTITABLE */
1.15 kristaps 198: { doignline, "need", 4 }, /* TEXICMD_NEED */
1.3 kristaps 199: { dosymbol, "\n", 1 }, /* TEXICMD_NEWLINE */
1.1 kristaps 200: { doignline, "node", 4 }, /* TEXICMD_NODE */
1.3 kristaps 201: { doignline, "noindent", 8 }, /* TEXICMD_NOINDENT */
1.16 kristaps 202: { doinline, "option", 6 }, /* TEXICMD_OPTION */
1.8 kristaps 203: { dolink, "pxref", 5 }, /* TEXICMD_PXREF */
1.3 kristaps 204: { dosymbol, "?", 1 }, /* TEXICMD_QUESTIONMARK */
1.1 kristaps 205: { doquotation, "quotation", 9 }, /* TEXICMD_QUOTATION */
1.3 kristaps 206: { doignline, "page", 4 }, /* TEXICMD_PAGE */
1.25 kristaps 207: { doignline, "paragraphindent", 15 }, /* TEXICMD_PARINDENT */
208: { dosymbol, ".", 1 }, /* TEXICMD_PERIOD */
1.28 kristaps 209: { doignline, "pindex", 6 }, /* TEXICMD_PINDEX */
1.2 kristaps 210: { doignline, "printindex", 10 }, /* TEXICMD_PRINTINDEX */
1.21 kristaps 211: { doinline, "r", 1 }, /* TEXICMD_R */
1.23 kristaps 212: { dosecoffs, "raisesections", 13 }, /* TEXICMD_RAISESECTIONS */
1.1 kristaps 213: { dobracket, "ref", 3 }, /* TEXICMD_REF */
1.28 kristaps 214: { doignline, "refill", 6 }, /* TEXICMD_REFILL */
1.15 kristaps 215: { dosymbol, "result", 6 }, /* TEXICMD_RESULT */
1.21 kristaps 216: { doinline, "samp", 4 }, /* TEXICMD_SAMP */
217: { doinline, "sansserif", 9 }, /* TEXICMD_SANSSERIF */
1.7 kristaps 218: { dobracket, "sc", 2 }, /* TEXICMD_SC */
1.1 kristaps 219: { dosection, "section", 7 }, /* TEXICMD_SECTION */
1.24 kristaps 220: { dovalue, "set", 3 }, /* TEXICMD_SET */
1.1 kristaps 221: { doignline, "setchapternewpage", 17 }, /* TEXICMD_SETCHAPNEWPAGE */
222: { doignline, "setfilename", 11 }, /* TEXICMD_SETFILENAME */
1.10 kristaps 223: { dotitle, "settitle", 8 }, /* TEXICMD_SETTITLE */
1.25 kristaps 224: { doignline, "shortcontents", 13 }, /* TEXICMD_SHORTCONTENTS */
1.21 kristaps 225: { doinline, "slanted", 7 }, /* TEXICMD_SLANTED */
1.3 kristaps 226: { dosp, "sp", 2 }, /* TEXICMD_SP */
227: { dosymbol, " ", 1 }, /* TEXICMD_SPACE */
1.17 kristaps 228: { doignline, "smallbook", 9 }, /* TEXICMD_SMALLBOOK */
1.12 kristaps 229: { dodisplay, "smalldisplay", 12 }, /* TEXICMD_SMALLDISPLAY */
1.3 kristaps 230: { doexample, "smallexample", 12 }, /* TEXICMD_SMALLEXAMPLE */
1.20 kristaps 231: { dodisplay, "smallformat", 11 }, /* TEXICMD_SMALLFORMAT */
1.13 kristaps 232: { dodisplay, "smallindentblock", 16 }, /* TEXICMD_SMALLINDENTBLOCK */
1.3 kristaps 233: { dosymbol, "{", 1 }, /* TEXICMD_SQUIGGLE_LEFT */
234: { dosymbol, "}", 1 }, /* TEXICMD_SQUIGGLE_RIGHT */
1.21 kristaps 235: { doinline, "strong", 6 }, /* TEXICMD_STRONG */
1.20 kristaps 236: { dosubsection, "subheading", 10 }, /* TEXICMD_SUBHEADING */
1.1 kristaps 237: { dosubsection, "subsection", 10 }, /* TEXICMD_SUBSECTION */
1.28 kristaps 238: { dosubsubsection, "subsubheading", 13 }, /* TEXICMD_SUBSUBHEADING */
1.23 kristaps 239: { dosubsubsection, "subsubsection", 13 }, /* TEXICMD_SUBSUBSECTION */
1.3 kristaps 240: { doignline, "subtitle", 8 }, /* TEXICMD_SUBTITLE */
1.25 kristaps 241: { doignline, "summarycontents", 15 }, /* TEXICMD_SUMMARYCONTENTS */
1.27 kristaps 242: { doignline, "synindex", 8 }, /* TEXICMD_SYNINDEX */
1.20 kristaps 243: { doignline, "syncodeindex", 12 }, /* TEXICMD_SYNCODEINDEX */
1.21 kristaps 244: { doinline, "t", 1 }, /* TEXICMD_T */
1.18 kristaps 245: { dotab, "tab", 3 }, /* TEXICMD_TAB */
246: { dosymbol, "\t", 1 }, /* TEXICMD_TABSYM */
1.1 kristaps 247: { dotable, "table", 5 }, /* TEXICMD_TABLE */
248: { doignblock, "tex", 3 }, /* TEXICMD_TEX */
249: { dosymbol, "TeX", 3 }, /* TEXICMD_TEXSYM */
1.16 kristaps 250: { doaccent, "~", 1 }, /* TEXICMD_TILDE */
1.25 kristaps 251: { doignline, "tindex", 6 }, /* TEXICMD_TINDEX */
1.3 kristaps 252: { doignline, "title", 5 }, /* TEXICMD_TITLE */
1.1 kristaps 253: { dobracket, "titlefont", 9 }, /* TEXICMD_TITLEFONT */
254: { doignblock, "titlepage", 9 }, /* TEXICMD_TITLEPAGE */
255: { dotop, "top", 3 }, /* TEXICMD_TOP */
1.16 kristaps 256: { doaccent, "\"", 1 }, /* TEXICMD_UMLAUT */
1.12 kristaps 257: { dosection, "unnumbered", 10 }, /* TEXICMD_UNNUMBERED */
1.2 kristaps 258: { dosection, "unnumberedsec", 13 }, /* TEXICMD_UNNUMBEREDSEC */
1.20 kristaps 259: { dosubsection, "unnumberedsubsec", 16 }, /* TEXICMD_UNNUMBEREDSUBSEC */
1.23 kristaps 260: { dosubsubsection, "unnumberedsubsubsec", 19 }, /* TEXICMD_UNNUMBEREDSUBSUBSEC */
1.8 kristaps 261: { dolink, "uref", 4 }, /* TEXICMD_UREF */
262: { dolink, "url", 3 }, /* TEXICMD_URL */
1.24 kristaps 263: { dovalue, "value", 5 }, /* TEXICMD_VALUE */
1.12 kristaps 264: { doinline, "var", 3 }, /* TEXICMD_VAR */
1.25 kristaps 265: { doverb, "verbatim", 8 }, /* TEXICMD_VERBATIM */
1.16 kristaps 266: { doverbinclude, "verbatiminclude", 15 }, /* TEXICMD_VERBATIMINCLUDE */
1.18 kristaps 267: { doignline, "vindex", 6 }, /* TEXICMD_VINDEX */
1.9 kristaps 268: { dosp, "vskip", 5 }, /* TEXICMD_VSKIP */
1.20 kristaps 269: { dotable, "vtable", 6 }, /* TEXICMD_VTABLE */
1.3 kristaps 270: { dobracket, "w", 1 }, /* TEXICMD_W */
1.8 kristaps 271: { dolink, "xref", 4 }, /* TEXICMD_XREF */
1.20 kristaps 272: /* TEXICMD__END */
1.1 kristaps 273: };
274:
1.24 kristaps 275: const struct texitok *const texitoks = __texitoks;
1.18 kristaps 276:
1.2 kristaps 277: static void
1.27 kristaps 278: dodefindex(struct texi *p, enum texicmd cmd,
279: const char *buf, size_t sz, size_t *pos)
280: {
281: size_t start, end;
282: char *cp;
283:
284: while (*pos < sz && isws(buf[*pos]))
285: advance(p, buf, pos);
286:
287: start = end = *pos;
288: while (end < sz && ! ismspace(buf[end]))
289: end++;
290:
291: if (start == end) {
292: advanceeoln(p, buf, sz, pos, 1);
293: return;
294: } else if (NULL == (cp = malloc(end - start + 1)))
295: texiabort(p, NULL);
296:
297: memcpy(cp, &buf[start], end - start);
298: cp[end - start] = '\0';
299:
300: p->indexs = realloc(p->indexs,
301: sizeof(char *) * (p->indexsz + 1));
302:
303: if (NULL == p->indexs)
304: texiabort(p, NULL);
305: p->indexs[p->indexsz++] = cp;
306: }
307:
308: static void
1.15 kristaps 309: dodefn(struct texi *p, enum texicmd cmd,
1.3 kristaps 310: const char *buf, size_t sz, size_t *pos)
311: {
312: const char *blk;
313:
1.5 kristaps 314: blk = NULL;
1.3 kristaps 315: switch (cmd) {
1.15 kristaps 316: case (TEXICMD_DEFFN):
317: case (TEXICMD_DEFTP):
1.3 kristaps 318: case (TEXICMD_DEFTYPEFN):
319: case (TEXICMD_DEFTYPEFUN):
1.15 kristaps 320: case (TEXICMD_DEFTYPEVAR):
321: case (TEXICMD_DEFTYPEVR):
322: case (TEXICMD_DEFUN):
323: case (TEXICMD_DEFVAR):
324: case (TEXICMD_DEFVR):
1.5 kristaps 325: blk = texitoks[cmd].tok;
1.3 kristaps 326: break;
1.5 kristaps 327: default:
1.3 kristaps 328: break;
329: }
330:
331: if (p->ign) {
1.15 kristaps 332: NULL != blk ?
333: parseto(p, buf, sz, pos, blk) :
334: parseeoln(p, buf, sz, pos);
1.3 kristaps 335: return;
336: }
337:
1.15 kristaps 338: if (NULL != blk)
339: texivspace(p);
340:
1.3 kristaps 341: switch (cmd) {
1.15 kristaps 342: case (TEXICMD_DEFMAC):
343: case (TEXICMD_DEFMACX):
344: texiputchars(p, "Macro");
345: break;
346: case (TEXICMD_DEFTYPEVAR):
347: case (TEXICMD_DEFTYPEVARX):
348: case (TEXICMD_DEFVAR):
349: case (TEXICMD_DEFVARX):
350: texiputchars(p, "Variable");
351: break;
1.3 kristaps 352: case (TEXICMD_DEFTYPEFUN):
1.15 kristaps 353: case (TEXICMD_DEFTYPEFUNX):
354: case (TEXICMD_DEFUN):
355: case (TEXICMD_DEFUNX):
356: texiputchars(p, "Function");
1.3 kristaps 357: break;
358: default:
1.15 kristaps 359: parselinearg(p, buf, sz, pos);
1.3 kristaps 360: break;
361: }
1.15 kristaps 362:
363: texiputchars(p, ":\n");
364:
365: switch (cmd) {
366: case (TEXICMD_DEFMAC):
367: case (TEXICMD_DEFMACX):
368: teximacroopen(p, "Dv");
369: while (parselinearg(p, buf, sz, pos))
370: /* Spin. */ ;
371: teximacroclose(p);
372: break;
373: case (TEXICMD_DEFFN):
374: case (TEXICMD_DEFFNX):
375: case (TEXICMD_DEFUN):
376: case (TEXICMD_DEFUNX):
377: teximacroopen(p, "Fo");
378: parselinearg(p, buf, sz, pos);
379: teximacroclose(p);
380: teximacroopen(p, "Fa");
381: while (parselinearg(p, buf, sz, pos))
382: /* Spin. */ ;
383: teximacroclose(p);
384: teximacro(p, "Fc");
385: break;
386: case (TEXICMD_DEFTYPEFUN):
387: case (TEXICMD_DEFTYPEFUNX):
388: case (TEXICMD_DEFTYPEFN):
389: case (TEXICMD_DEFTYPEFNX):
390: teximacroopen(p, "Ft");
391: parselinearg(p, buf, sz, pos);
392: teximacroclose(p);
393: teximacroopen(p, "Fo");
394: parselinearg(p, buf, sz, pos);
395: teximacroclose(p);
396: teximacroopen(p, "Fa");
397: while (parselinearg(p, buf, sz, pos))
398: /* Spin. */ ;
399: teximacroclose(p);
400: teximacro(p, "Fc");
401: break;
402: case (TEXICMD_DEFTP):
403: case (TEXICMD_DEFTPX):
404: case (TEXICMD_DEFTYPEVAR):
405: case (TEXICMD_DEFTYPEVARX):
406: case (TEXICMD_DEFTYPEVR):
407: case (TEXICMD_DEFTYPEVRX):
408: teximacroopen(p, "Vt");
409: while (parselinearg(p, buf, sz, pos))
410: /* Spin. */ ;
411: teximacroclose(p);
412: break;
413: case (TEXICMD_DEFVAR):
414: case (TEXICMD_DEFVARX):
415: case (TEXICMD_DEFVR):
416: case (TEXICMD_DEFVRX):
417: teximacroopen(p, "Va");
418: while (parselinearg(p, buf, sz, pos))
419: /* Spin. */ ;
420: teximacroclose(p);
421: break;
422: default:
423: abort();
1.3 kristaps 424: }
1.15 kristaps 425:
1.11 kristaps 426: texivspace(p);
1.3 kristaps 427: if (NULL != blk)
428: parseto(p, buf, sz, pos, blk);
429: }
430:
431: static void
1.30 kristaps 432: domacro(struct texi *p, enum texicmd cmd,
433: const char *buf, size_t sz, size_t *pos)
434: {
435: size_t start, end, endtoksz, len;
436: struct teximacro m;
437: const char *endtok, *blk;
438:
439: memset(&m, 0, sizeof(struct teximacro));
440:
441: while (*pos < sz && isws(buf[*pos]))
442: advance(p, buf, pos);
443:
444: for (start = end = *pos; end < sz; end++)
445: if (ismspace(buf[end]) || '{' == buf[end])
446: break;
447:
448: if (start == end)
449: texierr(p, "zero-length macro name");
450:
451: advanceto(p, buf, pos, end);
452:
453: m.key = malloc(end - start + 1);
454: if (NULL == m.key)
455: texiabort(p, NULL);
456: memcpy(m.key, &buf[start], end - start);
457: m.key[end - start] = '\0';
458:
1.31 kristaps 459: m.args = argparse(p, buf, sz, pos, &m.argsz, 0);
1.30 kristaps 460: advanceeoln(p, buf, sz, pos, 0);
461:
462: start = *pos;
463: endtok = "\n@end macro\n";
464: endtoksz = strlen(endtok);
465: blk = memmem(&buf[start], sz, endtok, endtoksz);
466: if (NULL == blk)
467: texierr(p, "unterminated macro body");
468: while (&buf[*pos] != blk)
469: advance(p, buf, pos);
470: assert('\n' == buf[*pos]);
471: advance(p, buf, pos);
472: len = blk - &buf[start];
473: m.value = malloc(len + 1);
474: if (NULL == m.value)
475: texiabort(p, NULL);
476: memcpy(m.value, &buf[start], len);
477: m.value[len] = '\0';
478:
479: p->macros = realloc
480: (p->macros,
481: (p->macrosz + 1) *
482: sizeof(struct teximacro));
483: if (NULL == p->macros)
484: texiabort(p, NULL);
485:
486: p->macros[p->macrosz++] = m;
487: advanceeoln(p, buf, sz, pos, 1);
488: }
489:
490: static void
1.1 kristaps 491: doignblock(struct texi *p, enum texicmd cmd,
492: const char *buf, size_t sz, size_t *pos)
493: {
1.26 kristaps 494: char end[32];
495: const char *term;
496: size_t endsz, endpos;
497:
498: /*
499: * We want to completely ignore everything in these blocks, so
500: * simply jump to the @end block.
501: */
502: endsz = snprintf(end, sizeof(end),
503: "\n@end %s\n", texitoks[cmd].tok);
504: assert(endsz < sizeof(end));
505:
506: /*
507: * Look up where our end token occurs.
508: * Set our end position based on the relative offset of that
509: * from our current position, or the EOF if we don't have a
510: * proper ending point.
511: */
512: term = memmem(&buf[*pos], sz, end, endsz);
513: endpos = NULL == term ? sz :
514: *pos + term - &buf[*pos];
515: assert(endpos <= sz);
516: while (*pos < endpos)
517: advance(p, buf, pos);
518:
519: /* Only do this if we're not already at the end. */
520: if (endpos < sz)
521: advanceto(p, buf, pos, endpos + endsz);
1.1 kristaps 522: }
523:
524: static void
1.3 kristaps 525: doblock(struct texi *p, enum texicmd cmd,
1.1 kristaps 526: const char *buf, size_t sz, size_t *pos)
527: {
528:
1.5 kristaps 529: parseto(p, buf, sz, pos, texitoks[cmd].tok);
1.1 kristaps 530: }
531:
532: static void
1.12 kristaps 533: doinline(struct texi *p, enum texicmd cmd,
534: const char *buf, size_t sz, size_t *pos)
1.1 kristaps 535: {
1.21 kristaps 536: const char *macro = NULL;
1.12 kristaps 537:
538: switch (cmd) {
1.21 kristaps 539: case (TEXICMD_CODE):
540: case (TEXICMD_KBD):
541: case (TEXICMD_SAMP):
542: case (TEXICMD_T):
543: macro = "Li";
544: break;
545: case (TEXICMD_CITE):
546: case (TEXICMD_DFN):
547: case (TEXICMD_EMPH):
548: case (TEXICMD_I):
549: case (TEXICMD_SLANTED):
550: macro = "Em";
551: break;
552: case (TEXICMD_B):
553: case (TEXICMD_STRONG):
554: macro = "Sy";
555: break;
1.12 kristaps 556: case (TEXICMD_COMMAND):
557: macro = "Xr";
558: break;
559: case (TEXICMD_ENV):
560: macro = "Ev";
561: break;
562: case (TEXICMD_FILE):
563: macro = "Pa";
564: break;
1.16 kristaps 565: case (TEXICMD_OPTION):
566: macro = "Op";
567: break;
1.12 kristaps 568: case (TEXICMD_VAR):
569: macro = "Va";
570: break;
571: default:
1.22 kristaps 572: break;
1.12 kristaps 573: }
574:
1.25 kristaps 575: if (NULL == macro || p->literal || TEXILIST_TABLE == p->list) {
1.12 kristaps 576: parsebracket(p, buf, sz, pos);
577: return;
578: }
1.1 kristaps 579:
1.5 kristaps 580: teximacroopen(p, macro);
1.1 kristaps 581: p->seenws = 0;
582: parsebracket(p, buf, sz, pos);
1.11 kristaps 583: texipunctuate(p, buf, sz, pos);
1.5 kristaps 584: teximacroclose(p);
1.1 kristaps 585: }
586:
587: static void
1.25 kristaps 588: doverb(struct texi *p, enum texicmd cmd,
589: const char *buf, size_t sz, size_t *pos)
590: {
591: const char *end, *term;
592: size_t endsz, endpos;
593:
1.26 kristaps 594: advanceeoln(p, buf, sz, pos, 1);
595:
1.25 kristaps 596: /* We end at exactly this token. */
597: end = "\n@end verbatim\n";
598: endsz = strlen(end);
599:
600: /*
601: * Look up where our end token occurs.
602: * Set our end position based on the relative offset of that
603: * from our current position.
604: */
605: term = memmem(&buf[*pos], sz, end, endsz);
606: endpos = NULL == term ? sz :
607: *pos + term - &buf[*pos];
608:
609: teximacro(p, "Bd -literal -offset indent");
610: assert(endpos <= sz);
1.26 kristaps 611: while (*pos < endpos) {
612: if (buf[*pos] == '\n')
613: p->outcol = 0;
614: else
615: p->outcol++;
1.25 kristaps 616: if (*pos > 0 && '.' == buf[*pos])
617: if ('\n' == buf[*pos - 1])
618: fputs("\\&", stdout);
619: putchar(buf[*pos]);
620: if ('\\' == buf[*pos])
621: putchar('e');
622: advance(p, buf, pos);
623: }
624: teximacro(p, "Ed");
1.26 kristaps 625: advanceto(p, buf, pos, endpos + endsz);
1.25 kristaps 626: }
627:
628: static void
1.16 kristaps 629: doverbinclude(struct texi *p, enum texicmd cmd,
630: const char *buf, size_t sz, size_t *pos)
631: {
1.25 kristaps 632: char fname[PATH_MAX], path[PATH_MAX];
633: int rc;
634: size_t i, end;
635: const char *v;
636: enum texicmd type;
1.16 kristaps 637:
638: while (*pos < sz && ' ' == buf[*pos])
639: advance(p, buf, pos);
640:
1.25 kristaps 641: for (i = 0; *pos < sz && '\n' != buf[*pos]; ) {
1.16 kristaps 642: if (i == sizeof(fname) - 1)
643: break;
1.25 kristaps 644: if ('@' != buf[*pos]) {
645: fname[i++] = buf[*pos];
646: advance(p, buf, pos);
647: continue;
648: }
1.30 kristaps 649: type = texicmd(p, buf, *pos, sz, &end, NULL);
1.25 kristaps 650: advanceto(p, buf, pos, end);
651: if (TEXICMD_VALUE != type)
652: texierr(p, "unknown verbatiminclude command");
653: v = valueblookup(p, buf, sz, pos);
654: if (NULL == v)
655: continue;
656: while ('\0' != *v) {
657: if (i == sizeof(fname) - 1)
658: break;
659: fname[i++] = *v++;
660: }
661: if ('\0' != *v)
662: break;
1.16 kristaps 663: }
664:
665: if (i == 0)
666: texierr(p, "path too short");
667: else if ('\n' != buf[*pos])
668: texierr(p, "path too long");
669: else if ('/' == fname[0])
670: texierr(p, "no absolute paths");
671: fname[i] = '\0';
672:
673: if (strstr(fname, "../") || strstr(fname, "/.."))
674: texierr(p, "insecure path");
675:
676: rc = snprintf(path, sizeof(path),
677: "%s/%s", p->dirs[0], fname);
678: if (rc < 0)
679: texierr(p, "couldn't format path");
680: else if ((size_t)rc >= sizeof(path))
681: texierr(p, "path too long");
682:
683: parsefile(p, path, 0);
684: }
685:
686: static void
1.2 kristaps 687: doinclude(struct texi *p, enum texicmd cmd,
688: const char *buf, size_t sz, size_t *pos)
689: {
1.25 kristaps 690: char fname[PATH_MAX], path[PATH_MAX];
691: size_t i, end;
692: int rc;
693: const char *v;
694: enum texicmd type;
1.2 kristaps 695:
696: while (*pos < sz && ' ' == buf[*pos])
697: advance(p, buf, pos);
698:
699: /* Read in the filename. */
1.25 kristaps 700: for (i = 0; *pos < sz && '\n' != buf[*pos]; ) {
1.2 kristaps 701: if (i == sizeof(fname) - 1)
702: break;
1.25 kristaps 703: if ('@' != buf[*pos]) {
704: fname[i++] = buf[*pos];
705: advance(p, buf, pos);
706: continue;
707: }
1.30 kristaps 708: type = texicmd(p, buf, *pos, sz, &end, NULL);
1.25 kristaps 709: advanceto(p, buf, pos, end);
710: if (TEXICMD_VALUE != type)
711: texierr(p, "unknown include command");
712: v = valueblookup(p, buf, sz, pos);
713: if (NULL == v)
714: continue;
715: while ('\0' != *v) {
716: if (i == sizeof(fname) - 1)
717: break;
718: fname[i++] = *v++;
719: }
720: if ('\0' != *v)
721: break;
1.2 kristaps 722: }
723:
724: if (i == 0)
725: texierr(p, "path too short");
726: else if ('\n' != buf[*pos])
727: texierr(p, "path too long");
728: else if ('/' == fname[0])
729: texierr(p, "no absolute paths");
730: fname[i] = '\0';
731:
732: if (strstr(fname, "../") || strstr(fname, "/.."))
733: texierr(p, "insecure path");
734:
1.5 kristaps 735: for (i = 0; i < p->dirsz; i++) {
736: rc = snprintf(path, sizeof(path),
737: "%s/%s", p->dirs[i], fname);
738: if (rc < 0)
739: texierr(p, "couldn't format path");
740: else if ((size_t)rc >= sizeof(path))
741: texierr(p, "path too long");
742: else if (-1 == access(path, R_OK))
743: continue;
744:
1.16 kristaps 745: parsefile(p, path, 1);
1.5 kristaps 746: return;
747: }
1.2 kristaps 748:
1.5 kristaps 749: texierr(p, "couldn't find %s in includes", fname);
1.2 kristaps 750: }
751:
752: static void
1.1 kristaps 753: dobracket(struct texi *p, enum texicmd cmd,
754: const char *buf, size_t sz, size_t *pos)
755: {
756:
757: parsebracket(p, buf, sz, pos);
758: }
759:
760: static void
1.3 kristaps 761: dodisplay(struct texi *p, enum texicmd cmd,
762: const char *buf, size_t sz, size_t *pos)
763: {
764:
1.20 kristaps 765: switch (cmd) {
766: case (TEXICMD_FORMAT):
767: case (TEXICMD_SMALLFORMAT):
768: teximacro(p, "Bd -filled");
769: break;
770: default:
771: teximacro(p, "Bd -filled -offset indent");
772: break;
773: }
774:
1.11 kristaps 775: p->seenvs = 1;
1.12 kristaps 776: /* FIXME: ignore and parseeoln. */
1.3 kristaps 777: advanceeoln(p, buf, sz, pos, 1);
1.13 kristaps 778: parseto(p, buf, sz, pos, texitoks[cmd].tok);
1.5 kristaps 779: teximacro(p, "Ed");
1.3 kristaps 780: }
781:
782: static void
1.1 kristaps 783: doexample(struct texi *p, enum texicmd cmd,
784: const char *buf, size_t sz, size_t *pos)
785: {
786:
1.5 kristaps 787: teximacro(p, "Bd -literal -offset indent");
1.12 kristaps 788: /* FIXME: ignore and parseeoln. */
1.3 kristaps 789: advanceeoln(p, buf, sz, pos, 1);
790: p->literal++;
1.13 kristaps 791: parseto(p, buf, sz, pos, texitoks[cmd].tok);
1.3 kristaps 792: p->literal--;
1.5 kristaps 793: teximacro(p, "Ed");
1.1 kristaps 794: }
795:
796: static void
797: dobye(struct texi *p, enum texicmd cmd,
798: const char *buf, size_t sz, size_t *pos)
799: {
800:
801: texiexit(p);
802: exit(EXIT_SUCCESS);
803: }
804:
805: static void
1.10 kristaps 806: dotitle(struct texi *p, enum texicmd cmd,
807: const char *buf, size_t sz, size_t *pos)
808: {
809: size_t start, end;
810:
811: while (*pos < sz && isws(buf[*pos]))
812: advance(p, buf, pos);
813: start = end = *pos;
814: while (end < sz && '\n' != buf[end])
815: end++;
1.26 kristaps 816: advanceeoln(p, buf, sz, pos, 1);
1.10 kristaps 817: free(p->subtitle);
818: p->subtitle = malloc(end - start + 1);
1.27 kristaps 819: if (NULL == p->subtitle)
820: texiabort(p, NULL);
1.10 kristaps 821: memcpy(p->subtitle, &buf[start], end - start);
822: p->subtitle[end - start] = '\0';
823: }
824:
825: static void
1.16 kristaps 826: doaccent(struct texi *p, enum texicmd cmd,
827: const char *buf, size_t sz, size_t *pos)
828: {
829:
830: if (*pos == sz)
831: return;
832: advance(p, buf, pos);
833: switch (cmd) {
834: case (TEXICMD_ACUTE):
835: switch (buf[*pos]) {
836: case ('a'): case ('A'):
837: case ('e'): case ('E'):
838: case ('i'): case ('I'):
839: case ('o'): case ('O'):
840: case ('u'): case ('U'):
841: texiputchars(p, "\\(\'");
842: texiputchar(p, buf[*pos]);
843: break;
844: default:
845: texiputchar(p, buf[*pos]);
846: }
847: break;
848: case (TEXICMD_CIRCUMFLEX):
849: switch (buf[*pos]) {
850: case ('a'): case ('A'):
851: case ('e'): case ('E'):
852: case ('i'): case ('I'):
853: case ('o'): case ('O'):
854: case ('u'): case ('U'):
855: texiputchars(p, "\\(^");
856: texiputchar(p, buf[*pos]);
857: break;
858: default:
859: texiputchar(p, buf[*pos]);
860: }
861: break;
862: case (TEXICMD_GRAVE):
863: switch (buf[*pos]) {
864: case ('a'): case ('A'):
865: case ('e'): case ('E'):
866: case ('i'): case ('I'):
867: case ('o'): case ('O'):
868: case ('u'): case ('U'):
869: texiputchars(p, "\\(`");
870: texiputchar(p, buf[*pos]);
871: break;
872: default:
873: texiputchar(p, buf[*pos]);
874: }
875: break;
876: case (TEXICMD_TILDE):
877: switch (buf[*pos]) {
878: case ('a'): case ('A'):
879: case ('n'): case ('N'):
880: case ('o'): case ('O'):
881: texiputchars(p, "\\(~");
882: texiputchar(p, buf[*pos]);
883: break;
884: default:
885: texiputchar(p, buf[*pos]);
886: }
887: break;
888: case (TEXICMD_UMLAUT):
889: switch (buf[*pos]) {
890: case ('a'): case ('A'):
891: case ('e'): case ('E'):
892: case ('i'): case ('I'):
893: case ('o'): case ('O'):
894: case ('u'): case ('U'):
895: case ('y'):
896: texiputchars(p, "\\(:");
897: texiputchar(p, buf[*pos]);
898: break;
899: default:
900: texiputchar(p, buf[*pos]);
901: }
902: break;
903: default:
904: abort();
905: }
906: }
907:
908: static void
1.1 kristaps 909: dosymbol(struct texi *p, enum texicmd cmd,
910: const char *buf, size_t sz, size_t *pos)
911: {
912:
1.3 kristaps 913: if (p->seenws && p->outcol && 0 == p->literal) {
914: texiputchar(p, ' ');
915: p->seenws = 0;
916: }
917:
1.1 kristaps 918: switch (cmd) {
1.3 kristaps 919: case (TEXICMD_ASTERISK):
920: case (TEXICMD_NEWLINE):
921: case (TEXICMD_SPACE):
1.18 kristaps 922: case (TEXICMD_TABSYM):
1.3 kristaps 923: texiputchar(p, ' ');
924: break;
1.1 kristaps 925: case (TEXICMD_AT):
1.3 kristaps 926: texiputchar(p, '@');
927: break;
928: case (TEXICMD_BANG):
929: texiputchar(p, '!');
1.7 kristaps 930: break;
931: case (TEXICMD_BULLET):
932: texiputchars(p, "\\(bu");
1.1 kristaps 933: break;
934: case (TEXICMD_COPYRIGHT):
935: texiputchars(p, "\\(co");
936: break;
1.2 kristaps 937: case (TEXICMD_DOTS):
938: texiputchars(p, "...");
939: break;
1.28 kristaps 940: case (TEXICMD_EQUIV):
941: texiputchars(p, "\\(==");
942: break;
1.15 kristaps 943: case (TEXICMD_ERROR):
944: texiputchars(p, "error\\(->");
1.17 kristaps 945: break;
946: case (TEXICMD_EXPANSION):
947: texiputchars(p, "\\(->");
1.15 kristaps 948: break;
1.1 kristaps 949: case (TEXICMD_LATEX):
950: texiputchars(p, "LaTeX");
951: break;
1.25 kristaps 952: case (TEXICMD_MINUS):
953: texiputchars(p, "\\-");
954: break;
955: case (TEXICMD_PERIOD):
956: texiputchar(p, '.');
957: break;
1.3 kristaps 958: case (TEXICMD_QUESTIONMARK):
959: texiputchar(p, '?');
1.15 kristaps 960: break;
961: case (TEXICMD_RESULT):
962: texiputchars(p, "\\(rA");
1.3 kristaps 963: break;
964: case (TEXICMD_SQUIGGLE_LEFT):
965: texiputchars(p, "{");
966: break;
967: case (TEXICMD_SQUIGGLE_RIGHT):
968: texiputchars(p, "}");
969: break;
1.1 kristaps 970: case (TEXICMD_TEXSYM):
971: texiputchars(p, "TeX");
972: break;
1.3 kristaps 973: case (TEXICMD_COLON):
974: case (TEXICMD_HYPHEN):
975: break;
1.1 kristaps 976: default:
977: abort();
978: }
979:
1.5 kristaps 980: if (texitoks[cmd].len > 1)
981: doignbracket(p, cmd, buf, sz, pos);
1.1 kristaps 982: }
983:
984: static void
985: doquotation(struct texi *p, enum texicmd cmd,
986: const char *buf, size_t sz, size_t *pos)
987: {
988:
1.5 kristaps 989: teximacro(p, "Qo");
1.1 kristaps 990: parseto(p, buf, sz, pos, "quotation");
1.5 kristaps 991: teximacro(p, "Qc");
1.1 kristaps 992: }
993:
1.3 kristaps 994: static void
995: domath(struct texi *p, enum texicmd cmd,
996: const char *buf, size_t sz, size_t *pos)
997: {
998: size_t nest;
999:
1000: /*
1001: * Math handling is different from everything else.
1002: * We don't allow any subcomponents, and we ignore the rules in
1003: * terms of @-commands.
1004: * This departs from GNU's rules, but whatever.
1005: */
1006: while (*pos < sz && isws(buf[*pos]))
1007: advance(p, buf, pos);
1008: if (*pos == sz || '{' != buf[*pos])
1009: return;
1010: advance(p, buf, pos);
1011: if (p->seenws && p->outcol && 0 == p->literal)
1012: texiputchar(p, ' ');
1013: p->seenws = 0;
1014: for (nest = 1; *pos < sz && nest > 0; ) {
1015: if ('{' == buf[*pos])
1016: nest++;
1017: else if ('}' == buf[*pos])
1018: if (0 == --nest)
1019: continue;
1020: texiputchar(p, buf[*pos]);
1021: advance(p, buf, pos);
1022: }
1023: if (*pos == sz)
1024: return;
1025: assert('}' == buf[*pos]);
1026: advance(p, buf, pos);
1.24 kristaps 1027: }
1028:
1029: static void
1030: dovalue(struct texi *p, enum texicmd cmd,
1031: const char *buf, size_t sz, size_t *pos)
1032: {
1.28 kristaps 1033: size_t start, end, i;
1.25 kristaps 1034: char *key, *val;
1035: const char *cp;
1.24 kristaps 1036:
1037: if (TEXICMD_SET == cmd) {
1038: while (*pos < sz && isws(buf[*pos]))
1039: advance(p, buf, pos);
1040: for (start = end = *pos; end < sz; end++)
1041: if (ismspace(buf[end]))
1042: break;
1.25 kristaps 1043: /* We don't allow empty keys. */
1.24 kristaps 1044: if (start == end)
1045: return;
1.25 kristaps 1046: advanceto(p, buf, pos, end);
1.24 kristaps 1047:
1048: key = malloc(end - start + 1);
1.27 kristaps 1049: if (NULL == key)
1050: texiabort(p, NULL);
1.24 kristaps 1051: memcpy(key, &buf[start], end - start);
1052: key[end - start] = '\0';
1053:
1054: while (*pos < sz && isws(buf[*pos]))
1055: advance(p, buf, pos);
1056: for (start = end = *pos; end < sz; end++)
1057: if ('\n' == buf[end])
1058: break;
1.25 kristaps 1059: /* We do allow empty values. */
1060: advanceeoln(p, buf, sz, pos, 1);
1.24 kristaps 1061:
1062: val = malloc(end - start + 1);
1.27 kristaps 1063: if (NULL == val)
1064: texiabort(p, NULL);
1.24 kristaps 1065: memcpy(val, &buf[start], end - start);
1066: val[end - start] = '\0';
1.25 kristaps 1067: valueadd(p, key, val);
1.24 kristaps 1068: } else if (TEXICMD_VALUE == cmd) {
1069: if (p->seenws)
1070: texiputchar(p, ' ');
1071: p->seenws = 0;
1.28 kristaps 1072: if (NULL != (cp = valueblookup(p, buf, sz, pos))) {
1073: for (i = 0; i < p->valstackpos; i++)
1074: if (cp == p->valstack[i])
1075: break;
1076: if (i < p->valstackpos)
1077: texierr(p, "recursive value");
1.29 kristaps 1078: if (64 == p->valstackpos)
1079: texierr(p, "too many nested values");
1.28 kristaps 1080: p->valstack[p->valstackpos++] = cp;
1.31 kristaps 1081: parsemembuf(p, cp, strlen(cp));
1.28 kristaps 1082: p->valstackpos--;
1083: } else
1.25 kristaps 1084: texiputchars(p, "{No value}");
1.24 kristaps 1085: } else if (TEXICMD_IFCLEAR == cmd) {
1.26 kristaps 1086: if (NULL != valuellookup(p, buf, sz, pos))
1087: doignblock(p, cmd, buf, sz, pos);
1088: else
1089: parseto(p, buf, sz, pos, texitoks[cmd].tok);
1.30 kristaps 1090: } else if (TEXICMD_IFSET == cmd) {
1091: if (NULL == valuellookup(p, buf, sz, pos))
1092: doignblock(p, cmd, buf, sz, pos);
1093: else
1094: parseto(p, buf, sz, pos, texitoks[cmd].tok);
1.25 kristaps 1095: } else if (TEXICMD_CLEAR == cmd)
1096: valuelclear(p, buf, sz, pos);
1.3 kristaps 1097: }
1098:
1.1 kristaps 1099: static void
1.8 kristaps 1100: dolink(struct texi *p, enum texicmd cmd,
1.1 kristaps 1101: const char *buf, size_t sz, size_t *pos)
1102: {
1.8 kristaps 1103: int c;
1.1 kristaps 1104:
1105: switch (cmd) {
1106: case (TEXICMD_EMAIL):
1.5 kristaps 1107: teximacroopen(p, "Mt");
1.1 kristaps 1108: break;
1.3 kristaps 1109: case (TEXICMD_UREF):
1.1 kristaps 1110: case (TEXICMD_URL):
1.5 kristaps 1111: teximacroopen(p, "Lk");
1.1 kristaps 1112: break;
1.8 kristaps 1113: case (TEXICMD_XREF):
1114: texiputchars(p, "See Section");
1115: teximacroopen(p, "Qq");
1116: break;
1117: case (TEXICMD_PXREF):
1118: texiputchars(p, "see Section");
1119: teximacroopen(p, "Qq");
1120: break;
1.1 kristaps 1121: default:
1.8 kristaps 1122: abort();
1.1 kristaps 1123: }
1.8 kristaps 1124:
1125: c = parsearg(p, buf, sz, pos, 0);
1126: p->ign++;
1127: while (c > 0)
1128: c = parsearg(p, buf, sz, pos, 1);
1129: p->ign--;
1130:
1.11 kristaps 1131: texipunctuate(p, buf, sz, pos);
1.8 kristaps 1132: teximacroclose(p);
1133: }
1134:
1135: static void
1136: doignargn(struct texi *p, enum texicmd cmd,
1137: const char *buf, size_t sz, size_t *pos)
1138: {
1139: int c;
1140:
1141: c = parsearg(p, buf, sz, pos, 0);
1142: p->ign++;
1143: while (c > 0)
1144: c = parsearg(p, buf, sz, pos, 1);
1145: p->ign--;
1.1 kristaps 1146: }
1147:
1.23 kristaps 1148: /*
1149: * Sections can be made subsections and so on by way of the
1150: * @raiseections and @lowersections commands.
1151: * Perform this check here and return the actual section number adjusted
1152: * to the raise level.
1153: */
1154: static int
1155: sectioner(struct texi *p, int sec)
1156: {
1157:
1158: if ((sec -= p->secoffs) < 0) {
1159: texiwarn(p, "section below minimum, clamping");
1160: return(0);
1161: } else if (sec >= SECTSZ) {
1162: texiwarn(p, "section above maximum, clamping");
1163: return(SECTSZ - 1);
1164: }
1165: return(sec);
1166: }
1167:
1168: static void
1169: dosubsubsection(struct texi *p, enum texicmd cmd,
1170: const char *buf, size_t sz, size_t *pos)
1171: {
1172: int sec;
1173:
1174: sec = sectioner(p, 3);
1175:
1176: /* We don't have a subsubsubsection, so make one up. */
1177: texivspace(p);
1178: teximacroopen(p, sects[sec]);
1179: parseeoln(p, buf, sz, pos);
1180: teximacroclose(p);
1181: texivspace(p);
1182: }
1183:
1.1 kristaps 1184: static void
1185: dosubsection(struct texi *p, enum texicmd cmd,
1186: const char *buf, size_t sz, size_t *pos)
1187: {
1.23 kristaps 1188: int sec;
1189:
1190: sec = sectioner(p, 2);
1.13 kristaps 1191:
1192: if (p->outmacro)
1.23 kristaps 1193: texierr(p, "\"%s\" in open line scope!?", sects[sec]);
1.13 kristaps 1194: else if (p->literal)
1.23 kristaps 1195: texierr(p, "\"%s\" in a literal scope!?", sects[sec]);
1.1 kristaps 1196:
1.21 kristaps 1197: /* We don't have a subsubsection, so make one up. */
1.11 kristaps 1198: texivspace(p);
1.23 kristaps 1199: teximacroopen(p, sects[sec]);
1.3 kristaps 1200: parseeoln(p, buf, sz, pos);
1.5 kristaps 1201: teximacroclose(p);
1.11 kristaps 1202: texivspace(p);
1.1 kristaps 1203: }
1204:
1205: static void
1.23 kristaps 1206: dosecoffs(struct texi *p, enum texicmd cmd,
1207: const char *buf, size_t sz, size_t *pos)
1208: {
1209:
1210: if (TEXICMD_RAISESECTIONS == cmd)
1211: p->secoffs++;
1212: else
1213: p->secoffs--;
1214: }
1215:
1216: static void
1.1 kristaps 1217: dosection(struct texi *p, enum texicmd cmd,
1.23 kristaps 1218: const char *buf, size_t sz, size_t *pos)
1.1 kristaps 1219: {
1.23 kristaps 1220: int sec;
1.12 kristaps 1221:
1222: switch (cmd) {
1223: case (TEXICMD_APPENDIX):
1224: case (TEXICMD_CHAPTER):
1225: case (TEXICMD_TOP):
1226: case (TEXICMD_UNNUMBERED):
1.23 kristaps 1227: sec = sectioner(p, 0);
1.12 kristaps 1228: break;
1229: case (TEXICMD_APPENDIXSEC):
1230: case (TEXICMD_HEADING):
1231: case (TEXICMD_SECTION):
1232: case (TEXICMD_UNNUMBEREDSEC):
1.23 kristaps 1233: sec = sectioner(p, 1);
1.12 kristaps 1234: break;
1235: default:
1236: abort();
1237: }
1.1 kristaps 1238:
1.3 kristaps 1239: if (p->outmacro)
1.23 kristaps 1240: texierr(p, "\"%s\" in open line scope!?", sects[sec]);
1.3 kristaps 1241: else if (p->literal)
1.23 kristaps 1242: texierr(p, "\"%s\" in a literal scope!?", sects[sec]);
1.3 kristaps 1243:
1.23 kristaps 1244: teximacroopen(p, sects[sec]);
1.3 kristaps 1245: parseeoln(p, buf, sz, pos);
1246: teximacroclose(p);
1.11 kristaps 1247: p->seenvs = 1;
1.3 kristaps 1248: }
1249:
1250: static void
1251: dosp(struct texi *p, enum texicmd cmd,
1252: const char *buf, size_t sz, size_t *pos)
1253: {
1254:
1.11 kristaps 1255: texivspace(p);
1.12 kristaps 1256: /* FIXME: ignore and parseeoln. */
1.3 kristaps 1257: advanceeoln(p, buf, sz, pos, 1);
1.1 kristaps 1258: }
1259:
1260: static void
1261: dotop(struct texi *p, enum texicmd cmd,
1262: const char *buf, size_t sz, size_t *pos)
1263: {
1.10 kristaps 1264: const char *cp;
1265: time_t t;
1266: char date[32];
1267:
1.26 kristaps 1268: if (--p->ign)
1269: texierr(p, "@top command while ignoring (%d)", p->ign);
1270:
1.18 kristaps 1271: /*
1272: * Here we print our standard mdoc(7) prologue.
1273: * We use the title set with @settitle for the `Nd' description
1274: * and the source document filename (the first one as invoked on
1275: * the command line) for the title.
1276: * The date is set to the current date.
1277: */
1.10 kristaps 1278: t = time(NULL);
1279: strftime(date, sizeof(date), "%F", localtime(&t));
1.1 kristaps 1280:
1.10 kristaps 1281: teximacroopen(p, "Dd");
1282: texiputchars(p, date);
1283: teximacroclose(p);
1284: teximacroopen(p, "Dt");
1285: for (cp = p->title; '\0' != *cp; cp++)
1286: texiputchar(p, toupper(*cp));
1.11 kristaps 1287: texiputchars(p, " 7");
1.10 kristaps 1288: teximacroclose(p);
1.5 kristaps 1289: teximacro(p, "Os");
1290: teximacro(p, "Sh NAME");
1.10 kristaps 1291: teximacroopen(p, "Nm");
1292: texiputchars(p, p->title);
1293: teximacroclose(p);
1294: teximacroopen(p, "Nd");
1295: texiputchars(p, NULL != p->subtitle ?
1296: p->subtitle : "Unknown description");
1297: teximacroclose(p);
1.11 kristaps 1298: p->seenvs = 1;
1.12 kristaps 1299: dosection(p, cmd, buf, sz, pos);
1.1 kristaps 1300: }
1301:
1302: static void
1303: doitem(struct texi *p, enum texicmd cmd,
1304: const char *buf, size_t sz, size_t *pos)
1305: {
1306:
1.18 kristaps 1307: /* Multitable is using raw tbl(7). */
1308: if (TEXILIST_TABLE == p->list) {
1309: texiputchar(p, '\n');
1310: return;
1311: }
1312:
1.3 kristaps 1313: if (p->outmacro)
1314: texierr(p, "item in open line scope!?");
1315: else if (p->literal)
1316: texierr(p, "item in a literal scope!?");
1317:
1318: switch (p->list) {
1319: case (TEXILIST_ITEM):
1.5 kristaps 1320: teximacroopen(p, "It");
1.3 kristaps 1321: break;
1322: case (TEXILIST_NOITEM):
1.5 kristaps 1323: teximacro(p, "It");
1.3 kristaps 1324: break;
1325: default:
1.11 kristaps 1326: texivspace(p);
1.3 kristaps 1327: break;
1328: }
1.18 kristaps 1329:
1330: /* Trick so we don't start with Pp. */
1.11 kristaps 1331: p->seenvs = 1;
1.3 kristaps 1332: parseeoln(p, buf, sz, pos);
1.1 kristaps 1333:
1.3 kristaps 1334: if (TEXILIST_ITEM == p->list)
1335: teximacroclose(p);
1.9 kristaps 1336: else if (p->outcol > 0)
1.1 kristaps 1337: texiputchar(p, '\n');
1.18 kristaps 1338: }
1339:
1340: static void
1341: dotab(struct texi *p, enum texicmd cmd,
1342: const char *buf, size_t sz, size_t *pos)
1343: {
1344:
1345: /* This command is only useful in @multitable. */
1346: if (TEXILIST_TABLE == p->list)
1347: texiputchar(p, '\t');
1348: }
1349:
1350: static void
1351: domultitable(struct texi *p, enum texicmd cmd,
1352: const char *buf, size_t sz, size_t *pos)
1353: {
1354: enum texilist sv = p->list;
1.32 ! kristaps 1355: int svliteral = p->literal;
1.18 kristaps 1356: enum texicmd type;
1357: size_t i, end, columns;
1358:
1359: p->list = TEXILIST_TABLE;
1.32 ! kristaps 1360: /*
! 1361: * TS/TE blocks aren't "in mdoc(7)", so we can disregard the
! 1362: * fact that we're in literal mode right now.
! 1363: */
! 1364: p->literal = 0;
1.18 kristaps 1365: teximacro(p, "TS");
1366: columns = 0;
1367:
1368: /* Advance to the first argument... */
1369: while (*pos < sz && isws(buf[*pos]))
1370: advance(p, buf, pos);
1371:
1372: /* Make sure we don't print anything when scanning. */
1373: p->ign++;
1374: if ('@' == buf[*pos]) {
1375: /*
1376: * Look for @columnfractions.
1377: * We ignore these, but we do use the number of
1378: * arguments to set the number of columns that we'll
1379: * have.
1380: */
1.30 kristaps 1381: type = texicmd(p, buf, *pos, sz, &end, NULL);
1.18 kristaps 1382: advanceto(p, buf, pos, end);
1383: if (TEXICMD_COLUMNFRACTIONS != type)
1.25 kristaps 1384: texierr(p, "unknown multitable command");
1.18 kristaps 1385: while (*pos < sz && '\n' != buf[*pos]) {
1386: while (*pos < sz && isws(buf[*pos]))
1387: advance(p, buf, pos);
1388: while (*pos < sz && ! isws(buf[*pos])) {
1389: if ('\n' == buf[*pos])
1390: break;
1391: advance(p, buf, pos);
1392: }
1393: columns++;
1394: }
1395: } else
1396: /*
1397: * We have arguments.
1398: * We could parse these, but it's easier to just let
1399: * tbl(7) figure it out.
1400: * So use this only to count arguments.
1401: */
1402: while (parselinearg(p, buf, sz, pos) > 0)
1403: columns++;
1404: p->ign--;
1405:
1406: /* Left-justify each table entry. */
1407: for (i = 0; i < columns; i++) {
1408: if (i > 0)
1409: texiputchar(p, ' ');
1410: texiputchar(p, 'l');
1411: }
1412: texiputchars(p, ".\n");
1413: p->outmacro++;
1414: parseto(p, buf, sz, pos, texitoks[cmd].tok);
1415: p->outmacro--;
1416: teximacro(p, "TE");
1.32 ! kristaps 1417: p->literal = svliteral;
1.18 kristaps 1418: p->list = sv;
1.1 kristaps 1419: }
1420:
1421: static void
1422: dotable(struct texi *p, enum texicmd cmd,
1423: const char *buf, size_t sz, size_t *pos)
1424: {
1.3 kristaps 1425: enum texilist sv = p->list;
1426:
1427: p->list = TEXILIST_ITEM;
1.5 kristaps 1428: teximacro(p, "Bl -tag -width Ds");
1.12 kristaps 1429: /* FIXME: ignore and parseeoln. */
1430: advanceeoln(p, buf, sz, pos, 1);
1.11 kristaps 1431: p->seenvs = 1;
1.20 kristaps 1432: parseto(p, buf, sz, pos, texitoks[cmd].tok);
1.5 kristaps 1433: teximacro(p, "El");
1.3 kristaps 1434: p->list = sv;
1.1 kristaps 1435: }
1436:
1437: static void
1.2 kristaps 1438: doenumerate(struct texi *p, enum texicmd cmd,
1439: const char *buf, size_t sz, size_t *pos)
1440: {
1.3 kristaps 1441: enum texilist sv = p->list;
1.2 kristaps 1442:
1.3 kristaps 1443: p->list = TEXILIST_NOITEM;
1.5 kristaps 1444: teximacro(p, "Bl -enum");
1.11 kristaps 1445: p->seenvs = 1;
1.12 kristaps 1446: /* FIXME: ignore and parseeoln. */
1447: advanceeoln(p, buf, sz, pos, 1);
1.2 kristaps 1448: parseto(p, buf, sz, pos, "enumerate");
1.5 kristaps 1449: teximacro(p, "El");
1.3 kristaps 1450: p->list = sv;
1.2 kristaps 1451: }
1452:
1453: static void
1.1 kristaps 1454: doitemize(struct texi *p, enum texicmd cmd,
1455: const char *buf, size_t sz, size_t *pos)
1456: {
1.3 kristaps 1457: enum texilist sv = p->list;
1.1 kristaps 1458:
1.21 kristaps 1459: p->list = TEXILIST_NOITEM;
1.5 kristaps 1460: teximacro(p, "Bl -bullet");
1.11 kristaps 1461: p->seenvs = 1;
1.12 kristaps 1462: /* FIXME: ignore and parseeoln. */
1463: advanceeoln(p, buf, sz, pos, 1);
1.1 kristaps 1464: parseto(p, buf, sz, pos, "itemize");
1.5 kristaps 1465: teximacro(p, "El");
1.3 kristaps 1466: p->list = sv;
1.1 kristaps 1467: }
1468:
1469: static void
1470: doignbracket(struct texi *p, enum texicmd cmd,
1471: const char *buf, size_t sz, size_t *pos)
1472: {
1473:
1.3 kristaps 1474: p->ign++;
1.1 kristaps 1475: parsebracket(p, buf, sz, pos);
1.3 kristaps 1476: p->ign--;
1.1 kristaps 1477: }
1478:
1479: static void
1480: doignline(struct texi *p, enum texicmd cmd,
1481: const char *buf, size_t sz, size_t *pos)
1482: {
1483:
1.12 kristaps 1484: /* FIXME: ignore and parseeoln. */
1.3 kristaps 1485: advanceeoln(p, buf, sz, pos, 1);
1.1 kristaps 1486: }
1487:
1.8 kristaps 1488: /*
1489: * Parse colon-separated directories from "cp" (if not NULL) and returns
1490: * the array of pointers.
1491: * Prepends "base" to the array.
1492: * This does NOT sanitise the directories!
1493: */
1.5 kristaps 1494: static char **
1.27 kristaps 1495: parsedirs(struct texi *p, const char *base, const char *cp, size_t *sz)
1.5 kristaps 1496: {
1497: char *tok, *str, *tofree;
1498: const char *cpp;
1499: size_t i;
1500: char **dirs;
1501:
1502: *sz = NULL != (cpp = cp) ? 2 : 1;
1503: if (*sz > 1)
1504: for ( ; NULL != (cpp = strchr(cpp, ':')); (*sz)++)
1505: cpp++;
1506:
1.27 kristaps 1507: if (NULL == (dirs = calloc(*sz, sizeof(char *))))
1508: texiabort(p, NULL);
1509: else if (NULL == (dirs[0] = strdup(base)))
1510: texiabort(p, NULL);
1.5 kristaps 1511:
1512: if (NULL == cp)
1513: return(dirs);
1514:
1.27 kristaps 1515: if (NULL == (tofree = tok = str = strdup(cp)))
1516: texiabort(p, NULL);
1.5 kristaps 1517:
1518: for (i = 1; NULL != (tok = strsep(&str, ":")); i++)
1.27 kristaps 1519: if (NULL == (dirs[i] = strdup(tok)))
1520: texiabort(p, NULL);
1.5 kristaps 1521:
1522: free(tofree);
1523: return(dirs);
1524: }
1525:
1.1 kristaps 1526: int
1527: main(int argc, char *argv[])
1528: {
1529: struct texi texi;
1.2 kristaps 1530: int c;
1531: char *path, *dir;
1.10 kristaps 1532: const char *progname, *Idir, *cp;
1.1 kristaps 1533:
1534: progname = strrchr(argv[0], '/');
1535: if (progname == NULL)
1536: progname = argv[0];
1537: else
1538: ++progname;
1539:
1.10 kristaps 1540: memset(&texi, 0, sizeof(struct texi));
1.5 kristaps 1541: Idir = NULL;
1.10 kristaps 1542:
1.5 kristaps 1543: while (-1 != (c = getopt(argc, argv, "I:")))
1.1 kristaps 1544: switch (c) {
1.5 kristaps 1545: case ('I'):
1546: Idir = optarg;
1547: break;
1.1 kristaps 1548: default:
1549: goto usage;
1550: }
1551:
1552: argv += optind;
1553: if (0 == (argc -= optind))
1554: goto usage;
1555:
1.27 kristaps 1556: if (NULL == (path = strdup(argv[0])))
1557: texiabort(&texi, NULL);
1558: else if (NULL == (dir = dirname(path)))
1559: texiabort(&texi, NULL);
1560:
1.2 kristaps 1561: free(path);
1562:
1.10 kristaps 1563: if (NULL != (cp = strrchr(argv[0], '/')))
1564: texi.title = strdup(cp + 1);
1565: else
1566: texi.title = strdup(argv[0]);
1567:
1.27 kristaps 1568: if (NULL == texi.title)
1569: texiabort(&texi, NULL);
1570: else if (NULL != (path = strchr(texi.title, '.')))
1.10 kristaps 1571: *path = '\0';
1572:
1.3 kristaps 1573: texi.ign = 1;
1.27 kristaps 1574: texi.dirs = parsedirs(&texi, dir, Idir, &texi.dirsz);
1.16 kristaps 1575: parsefile(&texi, argv[0], 1);
1.5 kristaps 1576: /* We shouldn't get here. */
1.2 kristaps 1577: texiexit(&texi);
1578: return(EXIT_FAILURE);
1.1 kristaps 1579: usage:
1.8 kristaps 1580: fprintf(stderr, "usage: %s [-Idirs] file\n", progname);
1.1 kristaps 1581: return(EXIT_FAILURE);
1582: }
CVSweb