/* delatex.l -- Simple Internationalized LaTeX stripper. by Mihai Budiu --- mihaib+@cs.cmu.edu To compile it you need: flex - the lexical analyser (free software) getopt - parsing arguments (free software) Depending on your library you might need to get both getopt.c and getopt.h or only the latter. The GNU C library includes getopt. Compile with: flex delatex.l cc -o delatex lex.yy.c --or-- cc -o delatex lex.yy.c getopt.c rm lex.yy.c This program is licensed under GNU GPL. See http://www.gnu.org/copyleft/gpl.html for details. */ %{ #include #include #include #include #include #include #define version "1.2, October 23, 1997, by mihaib+@cs.cmu.edu" struct lang { int code; char * name; } languages[] = { #define L_ENGLISH 0 L_ENGLISH, "English", #define L_ROMANIAN 1 L_ROMANIAN, "Romanian", #define L_FRENCH 2 L_FRENCH, "French", #define L_GERMAN 3 L_GERMAN, "German", #define L_HUNGARIAN 4 L_HUNGARIAN, "Hungarian" }; #define NLANG (sizeof(languages)/sizeof(struct lang)) char *messages[][NLANG] = { #define M_FIGURE 0 "[ figure: ", "[ figura: ", "[ figure: ", "[ Bild: ", "[ Abra", #define M_NOTE 1 "[Note: ", "[Nota: ", "[Note: ", "[Bemerkung: ", "[Megjegyzes: ", #define M_FOOTNOTE 2 "[Note: see **]", "[Nota: vezi **]", "[Note: voyez **]", "[Bemerkung: siehe ]", "[Lasd: **]", #define M_LABEL 3 "Label: ", "Eticheta: ", "Etiquette: ", "Marke: ", "Cimke: ", #define M_CONTENTS 4 "CONTENTS\n\n", "CUPRINS\n\n", "TABLE DE MATIERES\n\n", "INHALT\n\n", "TARTALOM\n\n", #define M_AUTHOR 5 "Author: ", "Autor: ", "Auteur: ", "Autor: ", "Szerzo: ", #define M_TITLE 6 "Title: ", "Titlu: ", "Titre: ", "Titel: ", "Cim: ", #define M_DATE 7 "Date: ", "Data: ", "Date: ", "Datum: ", "Datum: ", #define M_APPENDIX 8 "APPENDICES\n\n", "ANEXE\n\n", "ANNEXES\n\n", "ANHANGE\n\n", "FUGGELEK\n\n", #define M_PART 9 "Part ", "Partea ", "Part ", "Abschnitt ", "Resz ", #define M_CHAPTER 10 "Chapter ", "Capitolul ", "Chapitre ", "Kapitel ", "Fejezet ", #define M_BIB 11 "BIBLIOGRAPHY\n", "BIBLIOGRAFIE\n", "BIBLIOGRAPHIE\n", "BIBLIOGRAPHIE\n", "ELETRAJZ\n", #define M_ABSTRACT 12 "Abstract\n", "Rezumat\n", "Resume\n", "Zusammenfassung\n", "Kivonat\n" }; #define MAX(a, b) (((a) < (b)) ? (b) : (a)) #define MIN(a, b) (((a) > (b)) ? (b) : (a)) #define NMESSAGES (sizeof(messages)/NLANG) #define ENVDEPTH 20 /* maximum nesting depth of environments */ #define FILEDEPTH 5 /* recursive file inclusion depth */ #define MAXCOLS 50 /* maximum # columns in a table */ #define FILENAMELEN 80 /* max file name length */ #define INLINE inline #define LINE "-------------------------------------------------------\n" #define LINEN "\n-------------------------------------------------------" #define DEBUG() printf(">> %s <<\n", yytext) typedef char (*filter)(char); /* function processing a character */ int part, chapter, section, subsection, subsubsection; /* counters */ YY_BUFFER_STATE inputbuffers[FILEDEPTH]; /* stack of buffers */ extern FILE * yyin; /* main input */ extern FILE * yyout; /* main output */ char * filename = NULL; /* main file we are processing */ int crtfile=0; /* current file stack position */ struct envdata * ce; /* current environment */ char verbchar = 0; /* first char after a \verb */ int prefix = 0; /* current indendation level */ int skipnext = 0; /* skip next environment */ int blanklines = 3; /* consecutive blank lines */ int language = 0; /* default language: English */ int quiet; /* no error messages */ char * crtstring = NULL; /* current string to depozit chars */ int crtstringsize = 0; /* size for crtstring yet allocated */ int stringoutput = 0; /* place output in the crtstring */ char coltype[MAXCOLS]; /* type of each column */ char colsep[MAXCOLS]; /* where column separators are */ int cutdiacriticals = 0; /* cut Romanian diacritical signs (' and ") */ int ROWSIZE = 80; /* some filters */ char identic(char c) /* identic function filter */ { return c;} char up(char c) /* uppercase filter */ { return toupper(c); } char discard(char c) /* discard filter */ { return 0; } void die(char * format, ...) { va_list arg; va_start(arg, format); if (!quiet) vfprintf(stderr, format, arg); va_end(arg); exit(1); } void * xmalloc(size_t s) { void * p = malloc(s); if (!p) die("Out of memory.\n"); return p; } void * xcalloc(int n, size_t s) { void *p = calloc(n, s); if (!p) die("Out of memory.\n"); return p; } void * xrealloc(void * p, size_t s) { if (!p) p = malloc(s); else p = realloc(p, s); if (!p) die("Out of memory.\n"); return p; } /****************************** * Operations on environments * ******************************/ struct envdata { /* an environment */ char *terminator; filter action; int item; /* numbering in itemize */ int condition; int skipafter; int skipthis; int centering; } envstack[ENVDEPTH]; /* a stack of them */ void beginenv(void) /* begin a new environment */ { ce++; if (ce == envstack + ENVDEPTH) die("Env stack overflow.\n"); ce->action = identic; ce->terminator = " "; ce->item = 0; if (skipnext) { ce->skipthis = 1; ce->skipafter = skipnext - 1; skipnext = 0; } else if ((ce >envstack) && (ce-1)->skipthis) ce->skipthis = 1; else ce->skipthis = 0; ce->centering = 0; if (0) printf("\n%d> this %d, next %d, after %d, (%s)\n", ce - envstack, ce->skipthis, skipnext, ce->skipafter, yytext); } INLINE void skipthisenv(void) /* do not generate output for this environment */ { ce->skipthis = 1; } INLINE void skipnextenvs(int n) /* do not generate output for the n env that follow this one */ { ce->skipafter = n; } /********** * tables * **********/ struct table { int cols; int x, y; int width; char *** rows; char * hline; int * colsize; char * colsep; char * coltype; int colskip; /* columns to skip on \multicolumn */ } tables[ENVDEPTH]; int crttable = -1; struct table * ct; void new_table(int cols) { crttable++; if (crttable == ENVDEPTH) die("Table stack overflow.\n"); ct = tables + crttable; ct->cols = cols; ct->x = ct->y = 0; ct->rows = (char ***)xmalloc(sizeof(char **)); ct->rows[0] = (char**)xcalloc(cols, sizeof(char *)); ct->hline = (char *)xcalloc(2, sizeof(char)); ct->colsize = (int *)xcalloc(cols, sizeof(int)); ct->coltype = (char *)xcalloc(cols, sizeof(char)); memcpy(ct->coltype, coltype, cols); ct->colsep = (char *)xcalloc(cols+1, sizeof(char)); memcpy(ct->colsep, colsep, cols+1); } void kill_table(void) { int i, j; if (crttable == -1) die("Table stack underflow.\n"); for (i=0; i <= ct->y; i++) { if (ct->rows[i]) { for (j = 0; j < ct->cols; j++) if (ct->rows[i][j]) free(ct->rows[i][j]); free(ct->rows[i]); } } free(ct->rows); free(ct->hline); free(ct->colsize); free(ct->coltype); free(ct->colsep); ct->rows = NULL; crttable--; ct = tables + crttable; } void new_line(void) { ct->y++; ct->x = 0; ct->rows = (char***)xrealloc(ct->rows, (ct->y+1)*sizeof(char**)); ct->rows[ct->y] = (char**)xcalloc(ct->cols, sizeof(char *)); ct->hline = (char*)xrealloc(ct->hline, ct->y+2*sizeof(char)); ct->hline[ct->y+1] = 0; } void table_elem(char * s) { if (ct->x == ct->cols) new_line(); ct->rows[ct->y][ct->x] = (char *)xmalloc((1+strlen(s)) * sizeof(char)); strcpy(ct->rows[ct->y][ct->x], s); if (ct->colskip) { ct->x += ct->colskip; ct->colskip = 0; } else ct->x++; } int print_string(char * s, int width, char type, int k) { int i, left, right, l, sl; if (!s || ((sl=strlen(s)) < (width * k))) { for (; width-- > 0;) putchar(' '); return 0; } l = MAX(width * (k+1) - sl, 0); switch (type) { case 'c': left = l / 2; break; case 'r': left = l; break; case 'l': default: left = 0; break; } right = l - left; for (; left > 0; left--) putchar(' '); if (s) { for (i=width * k; (i < sl) && (i < width * (k+1)); i++) printf("%c", s[i]); } for (; right > 0; right--) putchar(' '); if (sl > width * (k+1)) return 1; else return 0; } void print_table(void) { int i, j, stop, k; int pcolumns = 0, totsize = 0, passes; /* First figure out dimensions and stuff */ for (j = 0; j < ct->cols; j++) { if (ct->coltype[j] == 'p') pcolumns++; for (i = 0; i < ct->y; i++) if (ct->rows[i][j] && (ct->coltype[j] != 'p')) ct->colsize[j] = MAX(ct->colsize[j], strlen(ct->rows[i][j])); } for (j = 0; j < ct->cols; j++) totsize += ct->colsize[j]; if (pcolumns) { for (j = 0; j < ct->cols; j++) if (ct->coltype[j] == 'p') ct->colsize[j] = MAX(10, (ROWSIZE - totsize) / pcolumns); } ct->width = 0; for (j = 0; j < ct->cols; j++) ct->width += ct->colsize[j]+1; /* Now go and print */ for (i = 0; i <= ct->y; i++) { if (ce->centering) { for (j=0; j < ROWSIZE - ct->width; j+=2) putchar(' '); } if (ct->hline[i]) { for (j=0; j <= ct->width; j++) putchar('-'); putchar('\n'); if (i == ct->y) break; if (ce->centering) { for (j=0; j < ROWSIZE - ct->width; j+=2) putchar(' '); } } if (i == ct->y) break; for (k=0; ;k++) { stop = 0; for (j = 0; j < ct->cols; j++) { if (ct->colsep[j]) putchar('|'); else putchar(' '); stop += print_string(ct->rows[i][j], ct->colsize[j], ct->coltype[j], k); } if (ct->colsep[j]) putchar('|'); else putchar(' '); putchar('\n'); if (!stop) break; } } } /***************** * low-level I/O * *****************/ INLINE void outchar(char c) /* Output a character; some are also printed elsewhere. */ { if (!isspace(c)) blanklines = 0; else if (c == '\n' || c == '\r') { if (blanklines >= 3) return; blanklines++; } if (!ce->skipthis) { if (stringoutput) { int n; if ((n = strlen(crtstring)) >= (crtstringsize-1)) { crtstring = (char*)xrealloc(crtstring, crtstringsize *= 2); } crtstring[n] = c; crtstring[++n] = 0; } else putchar(c); } } INLINE void outstring(char * s) { int i; for (i=0; i < strlen(s); i++) outchar(s[i]); } INLINE void outmessage(int code) { if (code > NMESSAGES) die("Wrong message code"); outstring(messages[code][language]); } void endenv(void) /* end current environment */ { if (ce == envstack) die("Env stack null.\n"); if (ce->terminator[0] != ' ') outstring(ce->terminator); if (ce->skipafter) skipnext = ce->skipafter; else skipnext = 0; if (0) printf("\n%d< this %d, next %d, after %d, (%s)\n", ce - envstack, ce->skipthis, skipnext, ce->skipafter, yytext); ce--; } FILE * openfile(char *s, char *suffix) /* open this file */ { FILE * f; char crtfilename[FILENAMELEN]; /* local buffer */ if (strlen(s) + strlen(suffix) > FILENAMELEN) { if (!quiet) fprintf(stderr, "File name too long `%s'\n", s); return NULL; } strcpy(crtfilename, s); f = fopen(crtfilename, "r"); if (!f) { strcat(crtfilename, suffix); f = fopen(crtfilename, "r"); } if (!f) { if (!quiet) fprintf(stderr, "Can't open file `%s[%s]'\n", s, suffix); return NULL; } return f; } INLINE void action(filter f) { ce->action = f; } INLINE void terminate(char *s) { ce->terminator = s; } #define pushfile(f) \ do { \ if (!f) break; \ if (crtfile >= FILEDEPTH) { \ die("Too many includes\n"); \ } \ inputbuffers[crtfile++] = YY_CURRENT_BUFFER; \ yyin = f; \ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); \ } while (0) %} NB [^a-zA-Z] B ([ \t\n]*) OPTARG ({B}\[[^\]]*\])? BEG (\\begin{B}) END (\\end{B}) SKIPENV ({B}\{[^}]*\}) %x VERBATIM %x VERB %s TABULAR %% {BEG}\{verbatim\} { beginenv(); ce->condition = YY_START; /* current condition */ BEGIN VERBATIM; outstring(LINEN); } {END}\{verbatim\} { BEGIN ce->condition; endenv(); outstring(LINE); } . { outchar(yytext[0]); } \\verb. { beginenv(); ce->condition = YY_START; BEGIN VERB; verbchar = yytext[5]; } . { if (yytext[0] == verbchar) { BEGIN ce->condition; endenv(); } else outchar(yytext[0]); } {BEG}\{(tabular|array)\}{B}\{ {{ int c, b = 1, cols = 0; while (b) { /* eat these environments */ if (cols > MAXCOLS) die("Too many columns.\n"); c = input(); if (b == 1) { switch(c) { case 'l': case 'c': case 'D': case 'r': case 'p': coltype[cols++]=c; break; case '|': colsep[cols] = 1; break; default: break; } } if (c == '{') b++; if (c == '}') b--; } new_table(cols); stringoutput = 1; beginenv(); ce->condition = YY_START; if (!crtstring) { crtstring = (char *)xcalloc(2, 1); crtstringsize = 2; } BEGIN TABULAR; }} {END}\{(tabular|array)\} { BEGIN ce->condition; endenv(); stringoutput = 0; print_table(); kill_table(); } {B}&{B} { /* outchar('\t'); */ table_elem(crtstring); crtstring[0] = 0; } {B}\\hline{B} { ct->hline[ct->y] = 1; } \\multicolumn{B}\{{B}[0-9]+{B}\}{B}\{ {int i = yyleng; while (!isdigit(yytext[i])) i--; while (isspace(yytext[i]) || isdigit(yytext[i])) i--; ct->colskip = atoi(yytext + i + 1); beginenv(); skipthisenv(); } \\multicolumn{B}\{ { beginenv(); skipthisenv(); skipnextenvs(1); } [ \t\n]+ { outchar(' '); } {B}\\\\{B} { /* outchar('\n'); */ table_elem(crtstring); new_line(); crtstring[0] = 0; } {BEG}\{romana\} { beginenv(); } {END}\{romana\} { endenv(); } \\(c|u){B} { outstring((language == L_ROMANIAN) ? cutdiacriticals ? "" : "\'" : yytext); } \\"^"{B}(\\i|\{\\i{B}\}) { outstring((language == L_ROMANIAN) ? cutdiacriticals ? "i" : "\'i" : yytext); } \\"^"{B}(a|\{a\}) { outstring((language == L_ROMANIAN) ? cutdiacriticals ? "a" : "\"a" : yytext); } \\"^"{B}(I|\{I{B}\}) { outstring((language == L_ROMANIAN) ? cutdiacriticals ? "I" : "\'I" : yytext); } \\"^"{B}(A|\{A\}) { outstring((language == L_ROMANIAN) ? cutdiacriticals ? "A" : "\"A" : yytext); } \\[~'`^\"] { outchar(yytext[1]); /* couple of accents */} \\(normmode(false|true))/{NB} { if (language != L_ROMANIAN) outstring(yytext); } \\(setlength|(addto|new)counter){B}\{ { beginenv(); skipthisenv(); skipnextenvs(1); } \\(re)?newcommand{B}\{ {beginenv(); skipthisenv(); skipnextenvs(1); } \\input{B}{SKIPENV} { yytext[yyleng - 1] = 0; /* eat } */ { FILE * f; f = openfile(yytext + strlen("\\input{"), ".tex"); if (f) { pushfile(f); BEGIN INITIAL; }} } \\footnote(text)?{B}\{ { outmessage(M_NOTE); if (yytext[10] == 't') outstring("** "); beginenv(); terminate("]");} \\footnotemark { outmessage(M_FOOTNOTE); } {BEG}\{quot(e|ation)\} { prefix += 4; beginenv(); } {END}\{quot(e|ation)\} { prefix -= 4; endenv(); } {BEG}\{(itemize|description)\} { beginenv(); ce->item = '*'; prefix+=2; } {END}\{(itemize|description|enumerate)\} { endenv(); prefix-=2; } {BEG}\{enumerate\} { beginenv(); ce->item = 0; prefix+=2; } \\document(style|class){OPTARG}\{ {beginenv(); skipthisenv(); } {BEG}\{document\} { beginenv(); } {END}\{document\} { endenv(); action(discard); } \\usepackage{B}\{ { beginenv(); skipthisenv(); } "\n" { {int i; outchar('\n'); for (i=0; i < prefix; i++) outchar(' '); }} \\label{B}\{ { outchar('{'); beginenv(); outmessage(M_LABEL); terminate("}");} \\(ref|cite|pageref){B}\{ { outchar('{'); beginenv(); terminate("}"); } \\index{B}\{ { beginenv(); skipthisenv(); } \\(caption|protect) ; \\\\[*]?{OPTARG} ; /* Handled by "\n" that usu. follows */ \\(newline|newpage) { outchar('\n'); } \\(linebreak|pagebreak){OPTARG} { outchar('\n'); } \\enlargethispage[*]?{B}\{ { beginenv(); skipthisenv(); } \\[&_%$#{}^ ] { outchar(yytext[1]); } \\[/;,] { outchar(' '); } \\"-" ; "{" { beginenv(); } "}" { endenv(); } [$] ; /* Can't do much about mathematics */ [~] { outchar(' '); } \\times/{NB} { outchar('*'); } \\ldots/{NB} { outstring("..."); } \\leq/{NB} { outstring("<="); } \\geq/{NB} { outstring(">="); } \\(long)?leftarrow/{NB} { outstring("<-"); if (yyleng>10) outstring("--"); } \\(long)?rightarrow/{NB} { if (yyleng>10) outstring("--"); outstring("->"); } \\leftrightarrow/{NB} { outstring("<--->"); } \\Rightarrow/{NB} { outstring("==>"); } \\Leftarrow/{NB} { outstring("<=="); } \\Leftrightarrow/{NB} { outstring("<===>"); } \\(vee|lor)/{NB} { outchar('V'); } \\(vedge|land)/{NB} { outchar('&'); } \\uparrow/{NB} { outchar('^'); } \\langle/{NB} { outchar('<'); } \\rangle/{NB} { outchar('>'); } \\((arc)?(sin|cos|tan)(h)?|arg|cot(h)?|deg)/{NB} { outstring(yytext + 1); } \\(det|dim|exp|gcd|lim(inf|sup)?|inf|sup)/{NB} { outstring(yytext + 1); } \\(ln|log|max|min|Pr|sec|hom)/{NB} { outstring(yytext + 1); } \\backslash/{NB} { outchar('\\'); } \\lbrace/{NB} { outchar('{'); } \\rbrace/{NB} { outchar('}'); } \\(left|right)/{NB} ; \\LaTeX/{NB} { outstring("LaTeX"); } \\TeX/{NB} { outstring("TeX"); } \\tableofcontents/{NB} { if (!filename) { if (!quiet) fprintf(stderr, "Don't know which toc to use\n"); } else { FILE * f; f = openfile(filename, ".toc"); if (f) { outmessage(M_CONTENTS); pushfile(f); }}} \\printindex/{NB} ; \\vspace[*]?{B}\{ { outchar('\n'); beginenv(); skipthisenv(); } \\par/{NB} { outstring("\n "); } \\hspace{B}\{ { outstring(" "); beginenv(); skipthisenv(); } \\indent{B} { outstring(" "); } \\indent/{NB} { outstring(" "); } \\noindent{B} ; \\noindent/{NB} ; \\rq{B} { outchar('\''); } \\rq/{NB} { outchar('\''); } \\lq{B} { outchar('`'); } \\lq/{NB} { outchar('`'); } \\h(line|fill)/{NB} ; \\hrule/{NB} { outstring(LINE); } \\maketitle/{NB} ; \\([Ll]arge|[Hh]uge|LARGE) { action(up); } \\((normal|footnote|script)size|small|tiny) {action(identic); } \\em{B} { action(up); terminate(" "); } \\em/{NB} { action(up); terminate(" "); } \\emph{B}\{ { beginenv(); action(up); terminate(" "); } \\it{B} { action(up); terminate(" "); } \\it/{NB} { action(up); terminate(" "); } \\text(it|sl|sc){B}\{ { beginenv(); action(up); terminate(" "); } \\bf{B} { action(identic); terminate(" "); } \\bf/{NB} { action(identic); terminate(" "); } \\textbf{B}\{ { beginenv(); action(identic); terminate(" "); } \\tt{B} { outchar('`'); terminate("\'"); } \\tt/{NB} { outchar('`'); terminate("\'"); } \\texttt{B}\{ { beginenv(); outchar('`'); terminate("\'"); } \\rm{B} { action(identic); terminate(" "); } \\rm/{NB} { action(identic); terminate(" "); } \\text(rm|up){B}\{ { beginenv(); action(identic); terminate(" "); } [%].*"\n" ; /* LaTeX comment; skip to eol */ \\item/{NB} { if (!ce->skipthis) { blanklines = 0; if (ce->item != '*') { ce->item++; printf("[%d]", (int)ce->item); } else printf("[%c]", ce->item); }} \\author{B}\{ { outmessage(M_AUTHOR); beginenv(); } \\title{B}\{ { outmessage(M_TITLE); beginenv(); } \\date{B}\{ { outmessage(M_DATE); beginenv(); } \\appendix/{NB} { outmessage(M_APPENDIX); } \\part(\*)?{OPTARG}{B}\{ { if (!ce->skipthis) { outmessage(M_PART); printf("%d: ", ++part); } beginenv(); } \\chapter(\*)?{OPTARG}{B}\{ { if (!ce->skipthis) { outmessage(M_CHAPTER); printf("%d: ", ++chapter); section = subsection = subsubsection = 0; } beginenv(); } \\section(\*)?{OPTARG}{B}\{ { if (!ce->skipthis) { blanklines = 0; printf("%d. ", ++section); subsection = subsubsection = 0; } beginenv(); action(up); } \\subsection(\*)?{OPTARG}\{ { if (!ce->skipthis) { blanklines = 0; printf("%d.%d. ", section, ++subsubsection); subsubsection = 0; } beginenv(); } \\subsubsection(\*)?{OPTARG}{B}\{ { if (!ce->skipthis) { blanklines = 0; printf("%d.%d.%d. ", section, subsection, ++subsection); } beginenv(); } \\paragraph(\*)?{B}\{ { beginenv(); action(up); } \\contentsline{B}\{paragraph\}{B}\{ { outstring("\t\t"); beginenv(); skipnextenvs(1); } \\contentsline{B}{SKIPENV}{B}\{ { beginenv(); skipnextenvs(1); } \\numberline{B}\{ { beginenv(); terminate(".\t");} \\uppercase{B}\{ { beginenv(); action(up); } ({BEG}|{END})\{samepage\} ; {BEG}\{center\} { beginenv(); ce->centering = 1; } {END}\{center\} { endenv(); } ({BEG}|{END})\{(table|figure)\}{OPTARG} ; \\(m|f|frame)box{B}\{ { beginenv(); } \\(centerline|ragged(left|right)) ; \\centering { ce->centering = 1; } \\relax/{NB} ; {BEG}\{thebibliography\}{B}\{ { outmessage(M_BIB); prefix = 10; beginenv(); skipthisenv(); } {END}\{thebibliography\} { prefix = 0; } \\bibitem{OPTARG}\{ { beginenv(); outstring("\n["); terminate("] "); } {BEG}\{eqnarray[*]?\} { beginenv(); } {END}\{eqnarray[*]?\} { endenv(); } {BEG}\{abstract\} { outmessage(M_ABSTRACT); } {END}\{abstract\} ; ({BEG}|{END})\{(rotate|sideways|turn)\} ; \\[a-zA-Z]+ { outstring(yytext); } <> { if (crtfile == 0) yyterminate(); else { /* revert to previous file */ yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer( inputbuffers[--crtfile]); BEGIN INITIAL; }} . { if (!ce->skipthis) { int c = ce->action(yytext[0]); if (c) outchar(c); }} /* default rule */ %% /**********************************************************************/ int yywrap() { return 1; } void usage(char * name) { int i; if (quiet) return; fprintf(stderr, "Usage: %s [-qrhv] [-w widtg] [-l lang] [input]\n", name); fprintf(stderr, "-v: print version number information\n" "-h: print this help and exit\n" "-l language: use this language for generated output\n" "-r: cut Romanian diacritical signs from output\n" "-q: quiet; do not complain about (non fatal) errors\n" "-w width: line width (orientative)\n" "\nSimulates a very simple LaTeX processing\n"); fprintf(stderr, "Recognized languages:\n"); for (i=0; i < NLANG; i++) { fprintf(stderr, "\t%s\n", languages[i].name); } } char * strip_suffix(char * filename) { char * p = filename, *r; while (*p && *p != '.') p++; r = malloc(p - filename + 1); if (!r) { if (!quiet) fprintf(stderr, "Can't allocate filename\n"); return NULL; } strncpy(r, filename, p - filename); r[p-filename] = 0; return r; } int matchlang(char * s) { int i; for (i = 0; i < NLANG; i++) if (!strcmp(s, languages[i].name)) return languages[i].code; return -1; } int main(int argc, char *argv[]) { int c; quiet = 0; while ((c = getopt(argc, argv, "vhql:rw:")) != -1) { switch(c) { case 'w': ROWSIZE = atoi(optarg); if (ROWSIZE < 20) ROWSIZE = 70; break; case 'r': cutdiacriticals = 1; break; case 'v': fprintf(stderr, "%s: version %s\n", argv[0], version); break; case 'h': usage(argv[0]); exit(0); break; case 'l': language = matchlang(optarg); if (language < 0) { usage(argv[0]); exit(1); } break; case 'q': quiet = 1; break; default: usage(argv[0]); exit(1); } } if (optind < argc) { if (optind < argc - 1) { usage(argv[0]); exit(1); } filename = strip_suffix(argv[optind]); yyin = openfile(filename, ".tex"); if (!yyin) { yyin = openfile(argv[optind], ""); if (!yyin) exit(1); } } ce = envstack - 1; /* to initialize properly */ beginenv(); action(discard); /* before begin{document} */ return yylex(); }