/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ /* texi2ps -- convert texinfo format files into Postscript files. Copyright (C) 1995 DJ Delorie (dj@delorie.com) texi2ps is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU General Public License for full details. Everyone is granted permission to copy, modify and redistribute texi2ps, but only under the conditions described in the GNU General Public License. A copy of this license is supposed to have been given to you along with texi2ps so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ #include #include #include #include #include #include "fileio.h" #include "screenio.h" #include "word.h" #include "ps.h" #include "ifset.h" int suspend_output = 0; int bye = 0; static char buf[1000]; static int bufp; static int capify=0; static int eat_skips = 0; static int fill_mode; static int show_menus = 0; typedef void FUNCTION (); /* So I can say FUNCTION *foo; */ /* The list of commands that we hack in texinfo. Each one has an associated function. When the command is encountered in the text, the associated function is called with START as the argument. If the function expects arguments in braces, it remembers itself on the stack. When the corresponding close brace is encountered, the function is called with END as the argument. */ #define START 0 #define END 1 typedef struct brace_element { struct brace_element *prev; FUNCTION *proc; char *name; int flags; int index; } BRACE_ELEMENT; #define TABLE_LINE_BREAK 1 #define ENUM_LETTER 2 #define FILL_MODE 2 BRACE_ELEMENT *brace_stack = 0; BRACE_ELEMENT *table_stack = 0; void remember_brace_args(FUNCTION func, char *name) { BRACE_ELEMENT *be = (BRACE_ELEMENT *)malloc(sizeof(BRACE_ELEMENT)); be->proc = func; be->name = name ? strdup(name) : 0; be->prev = brace_stack; brace_stack = be; } void forget_brace_args() { if (brace_stack) { BRACE_ELEMENT *be = brace_stack; /* printf("\033[31m[---@%s(END)---]\033[37m", be->name); */ if (brace_stack->proc) brace_stack->proc(END); brace_stack = brace_stack->prev; if (be->name) free(be->name); free(be); } } void remember_table_cmd(FUNCTION func, char *name) { BRACE_ELEMENT *be = (BRACE_ELEMENT *)malloc(sizeof(BRACE_ELEMENT)); be->proc = func; be->name = name ? strdup(name) : 0; be->prev = table_stack; be->flags = 0; table_stack = be; para_set_prevailing_indent(ps_fontsize*3); para_set_indent(0); } void forget_table_cmd() { if (table_stack) { BRACE_ELEMENT *be = table_stack; table_stack = table_stack->prev; if (be->name) free(be->name); free(be); para_set_prevailing_indent(-ps_fontsize*3); } } typedef struct { char *name; FUNCTION *proc; int argument_in_braces; } COMMAND; static COMMAND CommandTable[]; static FUNCTION *lookup_command(char *name) { int cmd; for (cmd=0; name[cmd]; cmd++) if (name[cmd] == '{') { name[cmd] = 0; break; } for (cmd=0; CommandTable[cmd].name; cmd++) if (strcmp(CommandTable[cmd].name, name) == 0) { return CommandTable[cmd].proc; } return 0; } #define NO_BRACE_ARGS 0 #define BRACE_ARGS 1 #define LINE_ARGS 2 #define WORD_ARGS 3 #define BRACE_WORD_ARGS 4 #define SELF_ARGS 5 void cm_example(); void cm_samp(); void big_font(int se, char *arg, int szup) { if (se == START) { word_emit(); fileio_queue("}"); fileio_queue(arg); remember_brace_args(big_font, "font_change"); psf_pushscale(ps_fontsize+szup); line_break(); } else { line_break(); psf_pop(); eat_skips = 1; } } void cm_TeX(int se) { if (se == START && !suspend_output) { word_emit(); psf_pushfont(PSF_symbol); word_add_char(0124); word_emit(); word_adjust_baseline(-ps_fontsize/4); word_add_char(0105); word_emit(); word_adjust_baseline(ps_fontsize/4); word_add_char(0103); word_emit(); psf_pop(); } } void cm_appendix(int se, char *arg) { if (se == START) page_flush(); big_font(se, arg, 8); } void cm_appendixsec(int se, char *arg) { big_font(se, arg, 6); } void cm_appendixsubsec(int se, char *arg) { big_font(se, arg, 4); } void cm_appendixsubsubsec(int se, char *arg) { big_font(se, arg, 2); } void cm_asis(){} void cm_asterisk() { line_break(); } void cm_author(int se, char *args) { if (suspend_output) return; line_skip(); line_skip(); line_skip(); if (se == START) { word_emit(); psf_pushset(PSF_italic); word_add_string(args); word_emit(); psf_pop(); } } void cm_bold(int se) { if (se == START) psf_pushset(PSF_bold); else psf_pop(); } void cm_br(int se) { if (se == START) para_close(); } void cm_bullet(int se) { if (se == START) { if (!suspend_output) word_add_char(0267); } } void cm_bye() { page_flush_final(); bye = 1; } void cm_cartouche(int se, char *arg) { cm_example(se, arg); } void cm_center(){} void cm_chapheading(int se, char *arg) { big_font(se, arg, 8); } void cm_chapter(int se, char *arg) { if (se == START) page_flush(); big_font(se, arg, 8); } void cm_cindex(){} void cm_cite(){} void cm_clear(int se, char *arg) { char *p; if (se == END) fprintf(stderr, "\ncm_clear(END, %s) at %s", arg, fileio_where()); else if (suspend_output) return; /* The first word is the flag name. */ p = take_name(arg); if (p == arg) { fprintf(stderr, "\n@clear with an empty name at %s", fileio_where()); return; } *p = '\0'; clear_flag(arg); } void cm_code(int se) { if (se == START) psf_pushfont(PSF_courier); else psf_pop(); } void cm_copyright(int se) { if (suspend_output) return; if (se == START) word_symbol(0323); } void cm_ctrl(int se, char *args) { if (suspend_output) return; if (se == START) { word_emit(); psf_pushfont(PSF_courier); word_add_char('^'); word_add_string(args); word_emit(); psf_pop(); } } void cm_defcodeindex(){} void cm_defindex(){} void cm_defun(){} void cm_dfn(){} void cm_display(){} void cm_do_cond(int se) { } void cm_dots(int se) { if (suspend_output) return; if (se == START) word_symbol(0274); } void cm_emph(int se, char *args) { if (se == START) { psf_pushset(PSF_italic); } else { psf_pop(); } } void cm_end(int se, char *w) { FUNCTION *cmd = lookup_command(w); if (cmd) cmd(END); } void helper_enumerate(int se) { if (suspend_output) return; if (se == START) { char buf[10]; if (table_stack->flags & ENUM_LETTER) sprintf(buf, "%c", table_stack->index); else sprintf(buf, "%d.", table_stack->index); table_stack->index ++; word_add_string(buf); word_emit(); word_ws(); } } void cm_enumerate(int se, char *arg) { if (se == START) { remember_table_cmd(helper_enumerate, "enumerate"); if (arg && arg[0]) { if (isdigit(arg[0])) table_stack->index = atoi(arg); else { table_stack->index = arg[0]; table_stack->flags |= ENUM_LETTER; } } else table_stack->index = 1; } else { line_break(); forget_table_cmd(); } } void cm_equiv(int se) { if (suspend_output) return; if (se == START) word_symbol(0272); } void cm_error(int se) { if (suspend_output) return; if (se == START) { word_add_string("error"); word_symbol(0256); } } void cm_example(int se) { if (se == START) { remember_table_cmd(0,0); if (fill_mode) table_stack->flags |= FILL_MODE; fill_mode = 0; psf_pushfont(PSF_courier); } else { psf_pop(); fill_mode = (table_stack->flags & FILL_MODE) ? 1 : 0; forget_table_cmd(); } } void cm_exdent(int se) { if (se == START) para_set_indent(-prevailing_indent); } void cm_expansion(int se) { if (suspend_output) return; if (se == START) word_symbol(0336); } void cm_file(int se, char *args) { cm_samp(se, args); } void cm_findex(){} void cm_flushleft(){} void cm_flushright(){} void cm_italic(); void cm_footnote(int se) { cm_italic(se); } void cm_footnotestyle(){} void cm_force_abbreviated_whitespace(){} void cm_format(int se, char *args) { if (se == 0) { remember_table_cmd(cm_format, "format"); if (fill_mode) table_stack->flags |= FILL_MODE; } else { fill_mode = (table_stack->flags & FILL_MODE) ? 1 : 0; forget_table_cmd(); } } void cm_table(); void cm_ftable(int se, char *arg) { cm_table(se, arg); } void cm_group(){} void cm_heading(int se, char *arg) { big_font(se, arg, 6); } static int set_level, clear_level; void cm_ifclear(int se, char *arg) { if (se == START) { clear_level++; suspend_output += ifset(arg); } else if (clear_level > 0) { clear_level--; if (suspend_output > 0) suspend_output--; } else { fprintf(stderr, "\nunmatched @end ifclear at %s", fileio_where()); clear_level = 0; } } void cm_ifset(int se, char *arg) { if (se == START) { set_level++; suspend_output += !ifset(arg); } else if (set_level > 0) { set_level--; if (suspend_output > 0) suspend_output--; } else { fprintf(stderr, "\nunmatched @end ifset at %s", fileio_where()); set_level = 0; } } void cm_ignore_cond(int se) { if (se == START) suspend_output ++; else if (suspend_output) suspend_output --; else fprintf(stderr, "\nunmatched @end XXX at %s", fileio_where()); } void cm_ignore_line(){} void cm_ignore_sentence_ender(int se, char *arg) { if (suspend_output) return; if (se == START) word_add_quoted(arg[0]); } void cm_include(int se, char *args) { fileio_include(args); } void cm_infoinclude(int se, char *args) { fileio_include(args); } void cm_inforef(){} void cm_italic(int se) { if (se == START) psf_pushset(PSF_italic); else psf_pop(); } void cm_item(int se, char *s) { static int nesting=0; if (nesting) return; nesting++; if (table_stack) { line_break(); para_set_indent(-ps_fontsize*2); if (table_stack->flags & TABLE_LINE_BREAK) fileio_queue("@*"); fileio_queue("}"); fileio_queue(s); remember_brace_args(table_stack->proc, table_stack->name); if (table_stack->proc) table_stack->proc(START, ""); word_emit(); if (!(table_stack->flags & TABLE_LINE_BREAK)) para_set_indent(0); } else fprintf(stderr, "@item without table_stack at %s\n", fileio_where()); nesting--; } void cm_itemize(int se, char *arg) { if (se == START) { arg++; remember_table_cmd(lookup_command(arg), arg); } else { line_break(); forget_table_cmd(); } } void cm_itemx(int se, char *arg) { cm_item(se, arg); } void cm_kbd(int se) { if (se == START) psf_pushfont(PSF_helvetica); else psf_pop(); } void cm_key(int se) { cm_kbd(se); } void cm_kindex(){} void cm_lisp(){} void cm_lowersections(){} void cm_macro(){} void cm_majorheading(int se, char *arg) { big_font(se, arg, 8); } void cm_math(){} void cm_menu(int se) { if (se == START) { if (!show_menus) suspend_output ++; remember_table_cmd(0,0); if (fill_mode) table_stack->flags |= FILL_MODE; fill_mode = 0; } else { fill_mode = (table_stack->flags & FILL_MODE) ? 1 : 0; forget_table_cmd(); if (!show_menus) suspend_output --; } } void cm_minus(int se) { if (suspend_output) return; if (se == START) word_symbol(0055); } void cm_node(int se, char *args) { sscanf(args, "%[^,\n]", args); screenio_note("%3d %s", current_page, args); } void cm_noindent(){} void cm_page(int se) { if (se == START) page_flush(); } void cm_paragraphindent(){} void cm_pindex(){} void cm_point(){} void cm_print(){} void cm_printindex(){} void cm_xref(); void cm_pxref(int se, char *a) { cm_xref(se, a); } void cm_quotation(){} void cm_raisesections(){} void cm_refill(){} void cm_result(int se) { if (suspend_output) return; if (se == START) word_symbol(0336); } void cm_roman(int se, char *arg) { if (se == START) psf_pushfont(PSF_times); else psf_pop(); } void cm_samp(int se) { cm_code(se); } void cm_sc(int se) { if (se == START) { psf_pushscale(ps_fontsize * 7 / 8); capify++; } else { capify--; psf_pop(); } } void cm_section(int se, char *arg) { big_font(se, arg, 6); } void cm_set(int se, char *arg) { char *p; if (se == END) fprintf(stderr, "\ncm_set(END, %s) at %s", arg, fileio_where()); else if (suspend_output) return; /* The first word is the flag name, the rest, if any, its value. */ p = take_name(arg); if (p == arg) { fprintf(stderr, "\n@set with an empty name at %s", fileio_where()); return; } if (*p) { /* Possible value after name. It is the remainder of the line sans the whitespace. */ char *v = p; *v++ = '\0'; while (*v == ' ' || *v == '\t') v++; p = v; } set_flag(arg, p); } void cm_setfilename(){} void cm_smallexample(int se) { cm_example(se); } void cm_smalllisp(){} void cm_sp(int se, char *a) { if (se == START) { int l = atoi(a); word_emit(); line_break(); while (l--) line_skip(); } } void cm_strong(int se) { if (se == START) psf_pushset(PSF_bold); else psf_pop(); } void cm_subheading(int se, char *arg) { big_font(se, arg, 4); } void cm_subsection(int se, char *arg) { big_font(se, arg, 4); } void cm_subsubheading(int se, char *arg) { big_font(se, arg, 2); } void cm_subsubsection(int se, char *arg) { big_font(se, arg, 2); } void cm_subtitle(int se, char *a) { big_font(se, a, 10); } void cm_synindex(){} void cm_table(int se, char *arg) { if (se == START) { arg++; remember_table_cmd(lookup_command(arg), arg); table_stack->flags = TABLE_LINE_BREAK; } else { line_break(); forget_table_cmd(); } } void cm_tindex(){} void cm_title(int se, char *arg) { if (se == START) { word_emit(); fileio_queue("}"); fileio_queue(arg); remember_brace_args(cm_title, "title"); psf_pushscale(ps_fontsize+18); line_skip(); line_skip(); line_skip(); line_skip(); } else { line_break(); psf_pop(); eat_skips = 1; line_skip(); line_skip(); line_skip(); line_skip(); } } void cm_titlefont(int se) { if (se == START) psf_pushscale(ps_fontsize * 2 + 18); else { para_close(); psf_pop(); } } void cm_titlepage(int se) { if (se == START) remember_brace_args(cm_titlepage, "titlepage"); else page_flush(); } void cm_today(int se) { if (suspend_output) return; if (se == START) { time_t now; struct tm *tmnow; char buf[100]; time(&now); tmnow = localtime(&now); strftime(buf, 100, "%e %h %Y", tmnow); word_add_string(buf); } } void cm_top(){} void cm_unmacro(){} void cm_unnumbered(int se, char *arg) { if (se == START) page_flush(); big_font(se, arg, 8); } void cm_unnumberedsec(int se, char *arg) { big_font(se, arg, 6); } void cm_unnumberedsubsec(int se, char *arg) { big_font(se, arg, 4); } void cm_unnumberedsubsubsec(int se, char *arg) { big_font(se, arg, 2); } void cm_value(int se, char *flag) { if (suspend_output) return; if (se == START) { char *value = flag_value(flag); if (value) { word_add_string(value); free(value); } else { fprintf(stderr, "\nError: memory exhausted at %s", fileio_where()); exit(1); } } else fprintf(stderr, "\ncm_value(END, %s) at %s", flag, fileio_where()); } void cm_var(){} void cm_vindex(){} void cm_vskip() { vskip_enabled = 1; } void cm_vtable(int se, char *arg) { cm_table(se, arg); } void cm_w(){} void cm_xref(int se, char *a) { if (suspend_output) return; if (se == START) { word_add_string("See"); word_emit(); word_ws(); word_add_string(a); } } void command_name_condition(){} void do_nothing(){} void insert_self(int se, char *a) { if (suspend_output) return; if (se == START) word_add_quoted(a[0]); } static COMMAND CommandTable[] = { { "!", cm_ignore_sentence_ender, NO_BRACE_ARGS }, { "'", insert_self, SELF_ARGS }, { "*", cm_asterisk, NO_BRACE_ARGS }, { ".", cm_ignore_sentence_ender, NO_BRACE_ARGS }, { ":", cm_force_abbreviated_whitespace, NO_BRACE_ARGS }, { "?", cm_ignore_sentence_ender, NO_BRACE_ARGS }, { "|", do_nothing, NO_BRACE_ARGS }, { "@", insert_self, SELF_ARGS }, { " ", insert_self, SELF_ARGS }, { "\n", insert_self, SELF_ARGS }, { "TeX", cm_TeX, BRACE_ARGS }, { "`", insert_self, SELF_ARGS }, { "appendix", cm_appendix, LINE_ARGS }, { "appendixsection", cm_appendixsec, LINE_ARGS }, { "appendixsec", cm_appendixsec, LINE_ARGS }, { "appendixsubsec", cm_appendixsubsec, LINE_ARGS }, { "appendixsubsubsec", cm_appendixsubsubsec, LINE_ARGS }, { "asis", cm_asis, BRACE_ARGS }, { "author", cm_author, LINE_ARGS }, { "b", cm_bold, BRACE_ARGS }, { "bold", cm_bold, BRACE_ARGS }, { "br", cm_br, BRACE_ARGS }, { "bullet", cm_bullet, BRACE_ARGS }, { "bye", cm_bye, NO_BRACE_ARGS }, { "c", cm_ignore_line, LINE_ARGS }, { "cartouche", cm_cartouche, NO_BRACE_ARGS }, { "center", cm_center, NO_BRACE_ARGS }, { "chapheading", cm_chapheading, NO_BRACE_ARGS }, { "chapter", cm_chapter, LINE_ARGS }, { "cindex", cm_cindex, LINE_ARGS }, { "cite", cm_cite, BRACE_ARGS }, { "clear", cm_clear, LINE_ARGS }, { "code", cm_code, BRACE_ARGS }, { "comment", cm_ignore_line, LINE_ARGS }, { "contents", do_nothing, NO_BRACE_ARGS }, { "copyright", cm_copyright, BRACE_ARGS }, { "ctrl", cm_ctrl, BRACE_ARGS }, { "defcodeindex", cm_defcodeindex, NO_BRACE_ARGS }, { "defindex", cm_defindex, NO_BRACE_ARGS }, { "dfn", cm_dfn, BRACE_ARGS }, /* The `def' commands. */ { "deffn", cm_defun, LINE_ARGS }, { "deffnx", cm_defun, LINE_ARGS }, { "defun", cm_defun, LINE_ARGS }, { "defunx", cm_defun, LINE_ARGS }, { "defmac", cm_defun, LINE_ARGS }, { "defmacx", cm_defun, LINE_ARGS }, { "defspec", cm_defun, LINE_ARGS }, { "defspecx", cm_defun, LINE_ARGS }, { "defvr", cm_defun, LINE_ARGS }, { "defvrx", cm_defun, LINE_ARGS }, { "defvar", cm_defun, LINE_ARGS }, { "defvarx", cm_defun, LINE_ARGS }, { "defopt", cm_defun, LINE_ARGS }, { "defoptx", cm_defun, LINE_ARGS }, { "deftypefn", cm_defun, LINE_ARGS }, { "deftypefnx", cm_defun, LINE_ARGS }, { "deftypefun", cm_defun, LINE_ARGS }, { "deftypefunx", cm_defun, LINE_ARGS }, { "deftypevr", cm_defun, LINE_ARGS }, { "deftypevrx", cm_defun, LINE_ARGS }, { "deftypevar", cm_defun, LINE_ARGS }, { "deftypevarx", cm_defun, LINE_ARGS }, { "defcv", cm_defun, LINE_ARGS }, { "defcvx", cm_defun, LINE_ARGS }, { "defivar", cm_defun, LINE_ARGS }, { "defivarx", cm_defun, LINE_ARGS }, { "defop", cm_defun, LINE_ARGS }, { "defopx", cm_defun, LINE_ARGS }, { "defmethod", cm_defun, LINE_ARGS }, { "defmethodx", cm_defun, LINE_ARGS }, { "deftypemethod", cm_defun, LINE_ARGS }, { "deftypemethodx", cm_defun, LINE_ARGS }, { "deftp", cm_defun, LINE_ARGS }, { "deftpx", cm_defun, LINE_ARGS }, /* The end of the `def' commands. */ { "display", cm_display, NO_BRACE_ARGS }, { "dots", cm_dots, BRACE_ARGS }, { "dmn", do_nothing, BRACE_ARGS }, { "emph", cm_emph, BRACE_ARGS }, { "end", cm_end, WORD_ARGS }, { "enumerate", cm_enumerate, LINE_ARGS }, { "equiv", cm_equiv, BRACE_ARGS }, { "error", cm_error, BRACE_ARGS }, { "example", cm_example, LINE_ARGS }, { "exdent", cm_exdent, NO_BRACE_ARGS }, { "expansion", cm_expansion, BRACE_ARGS }, { "file", cm_file, BRACE_ARGS }, { "findex", cm_findex, LINE_ARGS }, { "finalout", do_nothing, NO_BRACE_ARGS }, { "flushleft", cm_flushleft, NO_BRACE_ARGS }, { "flushright", cm_flushright, NO_BRACE_ARGS }, { "format", cm_format, NO_BRACE_ARGS }, { "ftable", cm_ftable, WORD_ARGS }, { "group", cm_group, NO_BRACE_ARGS }, { "heading", cm_heading, LINE_ARGS }, { "headings", cm_ignore_line, LINE_ARGS }, { "i", cm_italic, BRACE_ARGS }, { "iappendix", cm_appendix, LINE_ARGS }, { "iappendixsection", cm_appendixsec, LINE_ARGS }, { "iappendixsec", cm_appendixsec, LINE_ARGS }, { "iappendixsubsec", cm_appendixsubsec, LINE_ARGS }, { "iappendixsubsubsec", cm_appendixsubsubsec, LINE_ARGS }, { "ichapter", cm_chapter, LINE_ARGS }, { "ifclear", cm_ifclear, LINE_ARGS }, { "ifinfo", cm_ignore_cond, NO_BRACE_ARGS }, { "ifset", cm_ifset, LINE_ARGS }, { "iftex", cm_ignore_cond, NO_BRACE_ARGS }, { "ignore", cm_ignore_cond, NO_BRACE_ARGS }, { "include", cm_include, WORD_ARGS }, { "inforef", cm_inforef, BRACE_ARGS }, { "input", cm_include, NO_BRACE_ARGS }, { "isection", cm_section, LINE_ARGS }, { "isubsection", cm_subsection, LINE_ARGS }, { "isubsubsection", cm_subsubsection, LINE_ARGS }, { "italic", cm_italic, BRACE_ARGS }, { "item", cm_item, LINE_ARGS }, { "itemize", cm_itemize, WORD_ARGS }, { "itemx", cm_itemx, LINE_ARGS }, { "iunnumbered", cm_unnumbered, LINE_ARGS }, { "iunnumberedsec", cm_unnumberedsec, LINE_ARGS }, { "iunnumberedsubsec", cm_unnumberedsubsec, LINE_ARGS }, { "iunnumberedsubsubsec", cm_unnumberedsubsubsec, LINE_ARGS }, { "kbd", cm_kbd, BRACE_ARGS }, { "key", cm_key, BRACE_ARGS }, { "kindex", cm_kindex, LINE_ARGS }, { "lowersections", cm_lowersections, NO_BRACE_ARGS }, { "lisp", cm_lisp, NO_BRACE_ARGS }, { "macro", cm_macro, NO_BRACE_ARGS }, { "majorheading", cm_majorheading, LINE_ARGS }, { "math", cm_math, BRACE_ARGS }, { "menu", cm_menu, LINE_ARGS }, { "minus", cm_minus, BRACE_ARGS }, { "need", cm_ignore_line, WORD_ARGS }, { "node", cm_node, LINE_ARGS }, { "noindent", cm_noindent, NO_BRACE_ARGS }, { "nwnode", cm_node, NO_BRACE_ARGS }, { "overfullrule", cm_ignore_line, LINE_ARGS }, { "page", cm_page, NO_BRACE_ARGS }, { "pindex", cm_pindex, LINE_ARGS }, { "point", cm_point, BRACE_ARGS }, { "print", cm_print, BRACE_ARGS }, { "printindex", cm_printindex, LINE_ARGS }, { "pxref", cm_pxref, BRACE_ARGS }, { "quotation", cm_quotation, NO_BRACE_ARGS }, { "r", cm_roman, BRACE_ARGS }, { "raisesections", cm_raisesections, NO_BRACE_ARGS }, { "ref", cm_xref, BRACE_ARGS }, { "refill", cm_refill, NO_BRACE_ARGS }, { "result", cm_result, BRACE_ARGS }, { "samp", cm_samp, BRACE_ARGS }, { "sc", cm_sc, BRACE_ARGS }, { "section", cm_section, LINE_ARGS }, { "set", cm_set, LINE_ARGS }, { "setchapternewpage", cm_ignore_line, WORD_ARGS }, { "setchapterstyle", cm_ignore_line, WORD_ARGS }, { "setfilename", cm_setfilename, WORD_ARGS }, { "settitle", cm_ignore_line, LINE_ARGS }, { "shortcontents", do_nothing, LINE_ARGS }, { "shorttitlepage", command_name_condition, LINE_ARGS }, { "smallbook", cm_ignore_line, LINE_ARGS }, { "smallexample", cm_smallexample, NO_BRACE_ARGS }, { "smalllisp", cm_smalllisp, NO_BRACE_ARGS }, { "sp", cm_sp, WORD_ARGS }, { "strong", cm_strong, BRACE_ARGS }, { "subheading", cm_subheading, LINE_ARGS }, { "subsection", cm_subsection, LINE_ARGS }, { "subsubheading", cm_subsubheading, LINE_ARGS }, { "subsubsection", cm_subsubsection, LINE_ARGS }, { "subtitle", cm_subtitle, LINE_ARGS }, { "summarycontents", do_nothing, NO_BRACE_ARGS }, { "syncodeindex", cm_synindex, LINE_ARGS }, { "synindex", cm_synindex, LINE_ARGS }, { "t", cm_title, LINE_ARGS }, { "table", cm_table, WORD_ARGS }, { "tex", cm_ignore_cond, NO_BRACE_ARGS }, { "tindex", cm_tindex, LINE_ARGS }, { "title", cm_title, LINE_ARGS }, { "titlefont", cm_titlefont, BRACE_ARGS }, { "titlepage", cm_titlepage, NO_BRACE_ARGS }, { "titlespec", command_name_condition, NO_BRACE_ARGS }, { "today", cm_today, BRACE_ARGS }, { "top", cm_top, NO_BRACE_ARGS }, { "unmacro", cm_unmacro, NO_BRACE_ARGS }, { "unnumbered", cm_unnumbered, LINE_ARGS }, { "unnumberedsec", cm_unnumberedsec, LINE_ARGS }, { "unnumberedsubsec", cm_unnumberedsubsec, LINE_ARGS }, { "unnumberedsubsubsec", cm_unnumberedsubsubsec, LINE_ARGS }, { "value", cm_value, BRACE_WORD_ARGS }, { "var", cm_var, BRACE_ARGS }, { "vindex", cm_vindex, LINE_ARGS }, { "vskip", cm_vskip, LINE_ARGS }, { "vtable", cm_vtable, WORD_ARGS }, { "w", cm_w, BRACE_ARGS }, { "xref", cm_xref, BRACE_ARGS }, { "{", insert_self, SELF_ARGS }, { "}", insert_self, SELF_ARGS }, /* Now @include does what this was supposed to. */ { "infoinclude", cm_infoinclude, WORD_ARGS }, { "footnote", cm_footnote, BRACE_ARGS}, { "footnotestyle", cm_footnotestyle, WORD_ARGS }, { "paragraphindent", cm_paragraphindent, WORD_ARGS }, {(char *) NULL, (FUNCTION *) NULL, NO_BRACE_ARGS} }; void skip_until_setfilename() { static const char str[] = "@setfilename"; int match = 0; while (1) { int ch = fileio_get(); if (ch == EOF) break; if (ch == str[match]) match++; else match = 0; if (str[match] == 0) { while (match) fileio_unget(str[--match]); return; } } fprintf(stderr, "error: no @setfilename\n"); exit(1); } void do_file(char *file_name) { int ch, last_ch=-1; fill_mode = 1; fileio_include(file_name); skip_until_setfilename(); bye = 0; while ((ch = fileio_get()) != EOF && !bye) { if (ch == '\n') { if (suspend_output) continue; word_emit(); if (fill_mode) { if (last_ch == '\n') { if (fill_mode && !eat_skips) para_close(); } else word_ws(); } else { if (last_ch == '\n') line_skip(); else line_break(); } } else if (ch == ' ' || ch == '\t') { if (suspend_output) continue; word_emit(); word_ws(); } else if (ch == '}') { if (!suspend_output) word_emit(); forget_brace_args(); } else if (ch == '@') { char *cmd_name; int cmd, argt, a; word_emit(); eat_skips = 0; bufp = 0; ch = fileio_get(); buf[bufp++] = ch; if (isalnum(ch)) { do { ch = fileio_get(); buf[bufp++] = ch; } while (ch != '{' && ch > ' '); buf[--bufp] = 0; } else buf[bufp] = 0; cmd_name = strdup(buf); for (cmd=0; CommandTable[cmd].name; cmd++) if (strcmp(CommandTable[cmd].name, cmd_name) == 0) break; argt = CommandTable[cmd].argument_in_braces; if (argt == SELF_ARGS) { if (!suspend_output) word_add_string(cmd_name); continue; } if (ch == '{' && argt != BRACE_WORD_ARGS) argt = BRACE_ARGS; bufp = 0; switch (argt) { case NO_BRACE_ARGS: a = 'N'; break; case BRACE_ARGS: a = 'B'; remember_brace_args(CommandTable[cmd].proc, cmd_name); break; case BRACE_WORD_ARGS: a = 'R'; ch = fileio_get(); while (ch != '}') { buf[bufp++] = ch; ch = fileio_get(); } break; case LINE_ARGS: a = 'L'; while (ch == ' ' || ch == '\t') ch = fileio_get(); while (ch != '\n') { buf[bufp++] = ch; ch = fileio_get(); } break; case WORD_ARGS: a = 'W'; while (ch <= ' ') ch = fileio_get(); while (ch > ' ') { buf[bufp++] = ch; ch = fileio_get(); } break; } buf[bufp] = 0; /* printf("\033[36m[---@%s(%c,\033[0m%s\033[1;36m)---]\033[0;1m", cmd_name, a, buf); */ if (CommandTable[cmd].proc) CommandTable[cmd].proc(START, buf); free(cmd_name); } else { eat_skips = 0; if (!suspend_output) { if (capify) word_add_char(toupper(ch)); else word_add_char(ch); } } last_ch = ch; } } static void usage(void) { printf("usage: texi2ps [-f size] [-I dir] [-Idir] [-v] [-m pts] [-Dname[=val]] [-Uname] [file...]\n"); printf(" -f = fontsize (default = 10)\n"); printf(" -I = include path\n"); printf(" -v = verbose progress messages\n"); printf(" -m = set margins (default 54 pts, 3/4\")\n"); printf(" -D = set flag called `name\' to `val\' (default: empty value)\n"); printf(" -U = clear (unset) flags called `name\'\n"); printf(" -2 = print two columns per page\n"); printf(" -menu = print menus\n"); exit(0); } int main(int argc, char **argv) { int arg, margin=54; if (argc < 2) usage(); for (arg=1; arg 0) ps_fontsize = fsize; else { fprintf(stderr, "illegal value for \"-f\" (ignored)\n"); --arg; } } else if (strcmp(argv[arg], "-m") == 0) { int new_margin = atoi(argv[++arg]); if (new_margin > 0) margin = new_margin; else { fprintf(stderr, "illegal value for \"-m\" (ignored)\n"); --arg; } } else if (strncmp(argv[arg], "-I", 2) == 0) { if (argv[arg][2]) fileio_add_path(argv[arg]+2); else fileio_add_path(argv[++arg]); } else if (strcmp(argv[arg], "-v") == 0) screenio_enabled = 1; else if (strcmp(argv[arg], "-2") == 0) two_columns = 1; else if (strcmp(argv[arg], "-menu") == 0) show_menus = 1; else if (strncmp(argv[arg], "-D", 2) == 0 || strncmp(argv[arg], "-U", 2) == 0) { int set = argv[arg][1] == 'D' ? 1 : 0; char *name = argv[arg][2] ? argv[arg] + 2 : argv[++arg]; char *value = strchr(name, '='); if (value) *value++ = '\0'; else value = ""; if (set) set_flag(name, value); else clear_flag(name); } } word_set_margins(margin); word_init(); for (; arg < argc; arg++) { set_level = clear_level = 0; do_file(argv[arg]); } psdone(); screenio_print("\n%d pages generated", current_page); return 0; }