home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / utils / texi2ps / texi2ps.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-08  |  30.0 KB  |  1,401 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. /* texi2ps -- convert texinfo format files into Postscript files.
  3.  
  4.    Copyright (C) 1995 DJ Delorie (dj@delorie.com)
  5.  
  6.    texi2ps is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY.  No author or distributor accepts
  8.    responsibility to anyone for the consequences of using it or for
  9.    whether it serves any particular purpose or works at all, unless he
  10.    says so in writing.  Refer to the GNU General Public License
  11.    for full details.
  12.  
  13.    Everyone is granted permission to copy, modify and redistribute
  14.    texi2ps, but only under the conditions described in the GNU
  15.    General Public License.   A copy of this license is supposed to
  16.    have been given to you along with texi2ps so you can know your
  17.    rights and responsibilities.  It should be in a file named COPYING.
  18.    Among other things, the copyright notice and this notice must be
  19.    preserved on all copies.  */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25. #include <time.h>
  26.  
  27. #include "fileio.h"
  28. #include "screenio.h"
  29. #include "word.h"
  30. #include "ps.h"
  31. #include "ifset.h"
  32.  
  33. int suspend_output = 0;
  34. int bye = 0;
  35.  
  36. static char buf[1000];
  37. static int bufp;
  38. static int capify=0;
  39. static int eat_skips = 0;
  40. static int fill_mode;
  41.  
  42. typedef int FUNCTION ();    /* So I can say FUNCTION *foo; */
  43.  
  44. /* The list of commands that we hack in texinfo.  Each one
  45.    has an associated function.  When the command is encountered in the
  46.    text, the associated function is called with START as the argument.
  47.    If the function expects arguments in braces, it remembers itself on
  48.    the stack.  When the corresponding close brace is encountered, the
  49.    function is called with END as the argument. */
  50.  
  51. #define START 0
  52. #define END 1
  53.  
  54. typedef struct brace_element
  55. {
  56.   struct brace_element *prev;
  57.   FUNCTION *proc;
  58.   char *name;
  59.   int flags;
  60.   int index;
  61. } BRACE_ELEMENT;
  62.  
  63. #define TABLE_LINE_BREAK    1
  64. #define ENUM_LETTER        2
  65. #define FILL_MODE        2
  66.  
  67. BRACE_ELEMENT *brace_stack = 0;
  68. BRACE_ELEMENT *table_stack = 0;
  69.  
  70. void remember_brace_args(FUNCTION func, char *name)
  71. {
  72.   BRACE_ELEMENT *be = (BRACE_ELEMENT *)malloc(sizeof(BRACE_ELEMENT));
  73.   be->proc = func;
  74.   be->name = name ? strdup(name) : 0;
  75.   be->prev = brace_stack;
  76.   brace_stack = be;
  77. }
  78.  
  79. void forget_brace_args()
  80. {
  81.   if (brace_stack)
  82.   {
  83.     BRACE_ELEMENT *be = brace_stack;
  84. /*    printf("\033[31m[---@%s(END)---]\033[37m", be->name); */
  85.     if (brace_stack->proc)
  86.       brace_stack->proc(END);
  87.     brace_stack = brace_stack->prev;
  88.     if (be->name) free(be->name);
  89.     free(be);
  90.   }
  91. }
  92.  
  93. void remember_table_cmd(FUNCTION func, char *name)
  94. {
  95.   BRACE_ELEMENT *be = (BRACE_ELEMENT *)malloc(sizeof(BRACE_ELEMENT));
  96.   be->proc = func;
  97.   be->name = name ? strdup(name) : 0;
  98.   be->prev = table_stack;
  99.   be->flags = 0;
  100.   table_stack = be;
  101.   para_set_prevailing_indent(+36);
  102.   para_set_indent(0);
  103. }
  104.  
  105. void forget_table_cmd()
  106. {
  107.   if (table_stack)
  108.   {
  109.     BRACE_ELEMENT *be = table_stack;
  110.     table_stack = table_stack->prev;
  111.     if (be->name) free(be->name);
  112.     free(be);
  113.     para_set_prevailing_indent(-36);
  114.   }
  115. }
  116.  
  117. typedef struct
  118. {
  119.   char *name;
  120.   FUNCTION *proc;
  121.   int argument_in_braces;
  122. } COMMAND;
  123.  
  124. static COMMAND CommandTable[];
  125.  
  126.  
  127. static FUNCTION *lookup_command(char *name)
  128. {
  129.   int cmd;
  130.   for (cmd=0; name[cmd]; cmd++)
  131.     if (name[cmd] == '{')
  132.     {
  133.       name[cmd] = 0;
  134.       break;
  135.     }
  136.   for (cmd=0; CommandTable[cmd].name; cmd++)
  137.     if (strcmp(CommandTable[cmd].name, name) == 0)
  138.     {
  139.       return CommandTable[cmd].proc;
  140.     }
  141.   return 0;
  142. }
  143.  
  144. #define NO_BRACE_ARGS 0
  145. #define BRACE_ARGS 1
  146. #define LINE_ARGS 2
  147. #define WORD_ARGS 3
  148. #define BRACE_WORD_ARGS 4
  149. #define SELF_ARGS 5
  150.  
  151. int cm_example();
  152. int cm_samp();
  153.  
  154. big_font(int se, char *arg, int szup)
  155. {
  156.   if (se == START)
  157.   {
  158.     word_emit();
  159.     fileio_queue("}");
  160.     fileio_queue(arg);
  161.     remember_brace_args(big_font, "font_change");
  162.     psf_pushscale(ps_fontsize+szup);
  163.     line_break();
  164.   }
  165.   else
  166.   {
  167.     psf_pop();
  168.     line_break();
  169.     eat_skips = 1;
  170.   }
  171. }
  172.  
  173. cm_TeX(int se)
  174. {
  175.   if (se == START && !suspend_output)
  176.   {
  177.     word_emit();
  178.     psf_pushfont(PSF_symbol);
  179.     word_add_char(0124);
  180.     word_emit();
  181.     word_adjust_baseline(-ps_fontsize/4);
  182.     word_add_char(0105);
  183.     word_emit();
  184.     word_adjust_baseline(ps_fontsize/4);
  185.     word_add_char(0103);
  186.     word_emit();
  187.     psf_pop();
  188.   }
  189. }
  190.  
  191. cm_appendix(int se, char *arg)
  192. {
  193.   if (se == START)
  194.     page_flush();
  195.   big_font(se, arg, 8);
  196. }
  197.  
  198. cm_appendixsec(int se, char *arg) { big_font(se, arg, 6); }
  199. cm_appendixsubsec(int se, char *arg) { big_font(se, arg, 4); }
  200. cm_appendixsubsubsec(int se, char *arg) { big_font(se, arg, 2); }
  201. cm_asis(){}
  202.      
  203. cm_asterisk()
  204. {
  205.   line_break();
  206. }
  207.  
  208. cm_author(int se, char *args)
  209. {
  210.   if (suspend_output)
  211.     return;
  212.   line_skip();
  213.   line_skip();
  214.   line_skip();
  215.   if (se == START)
  216.   {
  217.     word_emit();
  218.     psf_pushset(PSF_italic);
  219.     word_add_string(args);
  220.     word_emit();
  221.     psf_pop();
  222.   }
  223. }
  224.      
  225. cm_bold(int se)
  226. {
  227.   if (se == START)
  228.     psf_pushset(PSF_bold);
  229.   else
  230.     psf_pop();
  231. }
  232.  
  233. cm_br(int se)
  234. {
  235.   if (se == START)
  236.     para_close();
  237. }
  238.  
  239. cm_bullet(int se)
  240. {
  241.   if (se == START)
  242.   {
  243.     if (!suspend_output)
  244.       word_add_char(0267);
  245.   }
  246. }
  247.  
  248. cm_bye()
  249. {
  250.   page_flush();
  251.   bye = 1;
  252. }
  253.  
  254. cm_cartouche(int se, char *arg) { cm_example(se, arg); }
  255. cm_center(){}
  256. cm_chapheading(int se, char *arg)
  257. {
  258.   big_font(se, arg, 8);
  259. }
  260.  
  261. cm_chapter(int se, char *arg)
  262. {
  263.   if (se == START)
  264.     page_flush();
  265.   big_font(se, arg, 8);
  266. }
  267.  
  268. cm_cindex(){}
  269. cm_cite(){}
  270.  
  271. cm_clear(int se, char *arg)
  272. {
  273.   char *p;
  274.  
  275.   if (se == END)
  276.     fprintf(stderr, "\ncm_clear(END, %s) at %s", arg, fileio_where());
  277.   else if (suspend_output)
  278.     return;
  279.  
  280.   /* The first word is the flag name.  */
  281.   p = take_name(arg);
  282.  
  283.   if (p == arg)
  284.     {
  285.       fprintf(stderr, "\n@clear with an empty name at %s", fileio_where());
  286.       return;
  287.     }
  288.  
  289.   *p = '\0';
  290.  
  291.   clear_flag(arg);
  292. }
  293.  
  294. cm_code(int se)
  295. {
  296.   if (se == START)
  297.     psf_pushfont(PSF_courier);
  298.   else
  299.     psf_pop();
  300. }
  301.  
  302. cm_copyright(int se)
  303. {
  304.   if (suspend_output)
  305.     return;
  306.   if (se == START)
  307.     word_symbol(0323);
  308. }
  309.  
  310. cm_ctrl(int se, char *args)
  311. {
  312.   if (suspend_output)
  313.     return;
  314.   if (se == START)
  315.   {
  316.     word_emit();
  317.     psf_pushfont(PSF_courier);
  318.     word_add_char('^');
  319.     word_add_string(args);
  320.     word_emit();
  321.     psf_pop();
  322.   }
  323. }
  324.  
  325. cm_defcodeindex(){}
  326. cm_defindex(){}
  327. cm_defun(){}
  328. cm_dfn(){}
  329. cm_display(){}
  330.  
  331. cm_do_cond(int se)
  332. {
  333. }
  334.  
  335. cm_dots(int se)
  336. {
  337.   if (suspend_output)
  338.     return;
  339.   if (se == START)
  340.     word_symbol(0274);
  341. }
  342.  
  343. cm_emph(int se, char *args)
  344. {
  345.   if (se == START)
  346.   {
  347.     psf_pushset(PSF_italic);
  348.   }
  349.   else
  350.   {
  351.     psf_pop();
  352.   }
  353. }
  354.  
  355. cm_end(int se, char *w)
  356. {
  357.   FUNCTION *cmd = lookup_command(w);
  358.   if (cmd)
  359.     cmd(END);
  360. }
  361.  
  362. helper_enumerate(int se)
  363. {
  364.   if (suspend_output)
  365.     return;
  366.   if (se == START)
  367.   {
  368.     char buf[10];
  369.     if (table_stack->flags & ENUM_LETTER)
  370.       sprintf(buf, "%c", table_stack->index);
  371.     else
  372.       sprintf(buf, "%d.", table_stack->index);
  373.     table_stack->index ++;
  374.     word_add_string(buf);
  375.     word_emit();
  376.     word_ws();
  377.   }
  378. }
  379.  
  380. cm_enumerate(int se, char *arg)
  381. {
  382.   if (se == START)
  383.   {
  384.     remember_table_cmd(helper_enumerate, "enumerate");
  385.     if (arg && arg[0])
  386.     {
  387.       if (isdigit(arg[0]))
  388.         table_stack->index = atoi(arg);
  389.       else
  390.       {
  391.         table_stack->index = arg[0];
  392.     table_stack->flags |= ENUM_LETTER;
  393.       }
  394.     }
  395.     else
  396.       table_stack->index = 1;
  397.   }
  398.   else
  399.   {
  400.     line_break();
  401.     forget_table_cmd();
  402.   }
  403. }
  404.  
  405. cm_equiv(int se)
  406. {
  407.   if (suspend_output)
  408.     return;
  409.   if (se == START)
  410.     word_symbol(0272);
  411. }
  412.  
  413. cm_error(int se)
  414. {
  415.   if (suspend_output)
  416.     return;
  417.   if (se == START)
  418.   {
  419.     word_add_string("error");
  420.     word_symbol(0256);
  421.   }
  422. }
  423.  
  424. cm_example(int se)
  425. {
  426.   if (se == START)
  427.   {
  428.     remember_table_cmd(0,0);
  429.     if (fill_mode)
  430.       table_stack->flags |= FILL_MODE;
  431.     fill_mode = 0;
  432.     psf_pushfont(PSF_courier);
  433.   }
  434.   else
  435.   {
  436.     psf_pop();
  437.     fill_mode = (table_stack->flags & FILL_MODE) ? 1 : 0;
  438.     forget_table_cmd();
  439.   }
  440. }
  441.  
  442. cm_exdent(int se)
  443. {
  444.   if (se == START)
  445.     para_set_indent(-prevailing_indent);
  446. }
  447.      
  448. cm_expansion(int se)
  449. {
  450.   if (suspend_output)
  451.     return;
  452.   if (se == START)
  453.     word_symbol(0336);
  454. }
  455.  
  456. cm_file(int se, char *args)
  457. {
  458.   cm_samp(se, args);
  459. }
  460.  
  461. cm_findex(){}
  462. cm_flushleft(){}
  463. cm_flushright(){}
  464.  
  465. int cm_italic();
  466. cm_footnote(int se)
  467. {
  468.   cm_italic(se);
  469. }
  470.  
  471. cm_footnotestyle(){}
  472. cm_force_abbreviated_whitespace(){}
  473.  
  474. cm_format(int se, char *args)
  475. {
  476.   if (se == 0)
  477.   {
  478.     remember_table_cmd(cm_format, "format");
  479.     if (fill_mode)
  480.       table_stack->flags |= FILL_MODE;
  481.   }
  482.   else
  483.   {
  484.     fill_mode = (table_stack->flags & FILL_MODE) ? 1 : 0;
  485.     forget_table_cmd();
  486.   }
  487. }
  488.  
  489. int cm_table();
  490. cm_ftable(int se, char *arg)
  491. {
  492.   cm_table(se, arg);
  493. }
  494. cm_group(){}
  495. cm_heading(int se, char *arg) { big_font(se, arg, 6); }
  496.  
  497. static int set_level, clear_level;
  498.  
  499. cm_ifclear(int se, char *arg)
  500. {
  501.   if (se == START)
  502.   {
  503.     clear_level++;
  504.     suspend_output += ifset(arg);
  505.   }
  506.   else if (clear_level > 0)
  507.   {
  508.     clear_level--;
  509.     if (suspend_output > 0)
  510.       suspend_output--;
  511.   }
  512.   else
  513.   {
  514.     fprintf(stderr, "\nunmatched @end ifclear at %s", fileio_where());
  515.     clear_level = 0;
  516.   }
  517. }
  518.  
  519. cm_ifset(int se, char *arg)
  520. {
  521.   if (se == START)
  522.   {
  523.     set_level++;
  524.     suspend_output += !ifset(arg);
  525.   }
  526.   else if (set_level > 0)
  527.   {
  528.     set_level--;
  529.     if (suspend_output > 0)
  530.       suspend_output--;
  531.   }
  532.   else
  533.   {
  534.     fprintf(stderr, "\nunmatched @end ifset at %s", fileio_where());
  535.     set_level = 0;
  536.   }
  537. }
  538.  
  539. cm_ignore_cond(int se)
  540. {
  541.   if (se == START)
  542.     suspend_output ++;
  543.   else if (suspend_output)
  544.     suspend_output --;
  545.   else
  546.     fprintf(stderr, "\nunmatched @end XXX at %s", fileio_where());
  547. }
  548.  
  549. cm_ignore_line(){}
  550.  
  551. cm_ignore_sentence_ender(int se, char *arg)
  552. {
  553.   if (suspend_output)
  554.     return;
  555.   if (se == START)
  556.     word_add_quoted(arg[0]);
  557. }
  558.  
  559. cm_include(int se, char *args) { fileio_include(args); }
  560. cm_infoinclude(int se, char *args) { fileio_include(args); }
  561. cm_inforef(){}
  562.  
  563. cm_italic(int se)
  564. {
  565.   if (se == START)
  566.     psf_pushset(PSF_italic);
  567.   else
  568.     psf_pop();
  569. }
  570.  
  571. cm_item(int se, char *s)
  572. {
  573.   if (table_stack)
  574.   {
  575.     line_break();
  576.     para_set_indent(-20);
  577.     if (table_stack->flags & TABLE_LINE_BREAK)
  578.       fileio_queue("@*");
  579.     fileio_queue("}");
  580.     fileio_queue(s);
  581.     remember_brace_args(table_stack->proc, table_stack->name);
  582.     table_stack->proc(START, "");
  583.     word_emit();
  584.     if (!(table_stack->flags & TABLE_LINE_BREAK))
  585.       para_set_indent(0);
  586.   }
  587.   else
  588.     fprintf(stderr, "\n@item without table_stack at %s\n", fileio_where());
  589. }
  590.  
  591. cm_itemize(int se, char *arg)
  592. {
  593.   if (se == START)
  594.   {
  595.     arg++;
  596.     remember_table_cmd(lookup_command(arg), arg);
  597.   }
  598.   else
  599.   {
  600.     line_break();
  601.     forget_table_cmd();
  602.   }
  603. }
  604.  
  605. cm_itemx(int se, char *arg)
  606. {
  607.   cm_item(se, arg);
  608. }
  609.  
  610. cm_kbd(int se)
  611. {
  612.   if (se == START)
  613.     psf_pushfont(PSF_helvetica);
  614.   else
  615.     psf_pop();
  616. }
  617. cm_key(int se) { cm_kbd(se); }
  618. cm_kindex(){}
  619. cm_lisp(){}
  620. cm_lowersections(){}
  621. cm_macro(){}
  622.  
  623. cm_majorheading(int se, char *arg)
  624. {
  625.   big_font(se, arg, 8);
  626. }
  627.  
  628. cm_math(){}
  629.  
  630. cm_menu(int se)
  631. {
  632.   if (se == START)
  633.   {
  634.     remember_table_cmd(0,0);
  635.     if (fill_mode)
  636.       table_stack->flags |= FILL_MODE;
  637.     fill_mode = 0;
  638.   }
  639.   else
  640.   {
  641.     fill_mode = (table_stack->flags & FILL_MODE) ? 1 : 0;
  642.     forget_table_cmd();
  643.   }
  644. }
  645.  
  646. cm_minus(int se)
  647. {
  648.   if (suspend_output)
  649.     return;
  650.   if (se == START)
  651.     word_symbol(0055);
  652. }
  653.  
  654. cm_node(int se, char *args)
  655. {
  656.   sscanf(args, "%[^,\n]", args);
  657.   screenio_note("%3d %s", current_page, args);
  658. }
  659.  
  660. cm_noindent(){}
  661.  
  662. cm_page(int se)
  663. {
  664.   if (se == START)
  665.     page_flush();
  666. }
  667.  
  668. cm_paragraphindent(){}
  669. cm_pindex(){}
  670. cm_point(){}
  671. cm_print(){}
  672. cm_printindex(){}
  673. int cm_xref();
  674. cm_pxref(int se, char *a)
  675. {
  676.   cm_xref(se, a);
  677. }
  678. cm_quotation(){}
  679. cm_raisesections(){}
  680. cm_refill(){}
  681.  
  682. cm_result(int se)
  683. {
  684.   if (suspend_output)
  685.     return;
  686.   if (se == START)
  687.     word_symbol(0336);
  688. }
  689.  
  690. cm_roman(int se, char *arg)
  691. {
  692.   if (se == START)
  693.     psf_pushfont(PSF_times);
  694.   else
  695.     psf_pop();
  696. }
  697.  
  698. cm_samp(int se)
  699. {
  700.   cm_code(se);
  701. }
  702.  
  703. cm_sc(int se)
  704. {
  705.   if (se == START)
  706.   {
  707.     psf_pushscale(ps_fontsize * 7 / 8);
  708.     capify++;
  709.   }
  710.   else
  711.   {
  712.     capify--;
  713.     psf_pop();
  714.   }
  715. }
  716.  
  717. cm_section(int se, char *arg) { big_font(se, arg, 6); }
  718.  
  719. cm_set(int se, char *arg)
  720. {
  721.   char *p;
  722.  
  723.   if (se == END)
  724.     fprintf(stderr, "\ncm_set(END, %s) at %s", arg, fileio_where());
  725.   else if (suspend_output)
  726.     return;
  727.  
  728.   /* The first word is the flag name, the rest, if any, its value.  */
  729.   p = take_name(arg);
  730.  
  731.   if (p == arg)
  732.     {
  733.       fprintf(stderr, "\n@set with an empty name at %s", fileio_where());
  734.       return;
  735.     }
  736.  
  737.   if (*p)
  738.     {
  739.       /* Possible value after name.  It is the remainder of the line
  740.          sans the whitespace.  */
  741.       char *v = p;
  742.  
  743.       *v++ = '\0';
  744.       while (*v == ' ' || *v == '\t')
  745.         v++;
  746.       p = v;
  747.     }
  748.  
  749.   set_flag(arg, p);
  750. }
  751.  
  752. cm_setfilename(){}
  753.  
  754. cm_smallexample(int se)
  755. {
  756.   cm_example(se);
  757. }
  758.  
  759. cm_smalllisp(){}
  760.  
  761. cm_sp(int se, char *a)
  762. {
  763.   if (se == START)
  764.   {
  765.     int l = atoi(a);
  766.     word_emit();
  767.     line_break();
  768.     while (l--)
  769.       line_skip();
  770.   }
  771. }
  772.  
  773. cm_strong(int se)
  774. {
  775.   if (se == START)
  776.     psf_pushset(PSF_bold);
  777.   else
  778.     psf_pop();
  779. }
  780.  
  781. cm_subheading(int se, char *arg) { big_font(se, arg, 4); }
  782. cm_subsection(int se, char *arg) { big_font(se, arg, 4); }
  783. cm_subsubheading(int se, char *arg) { big_font(se, arg, 2); }
  784. cm_subsubsection(int se, char *arg) { big_font(se, arg, 2); }
  785. cm_subtitle(int se, char *a) { big_font(se, a, 10); }
  786. cm_synindex(){}
  787.  
  788. cm_table(int se, char *arg)
  789. {
  790.   if (se == START)
  791.   {
  792.     arg++;
  793.     remember_table_cmd(lookup_command(arg), arg);
  794.     table_stack->flags = TABLE_LINE_BREAK;
  795.   }
  796.   else
  797.   {
  798.     line_break();
  799.     forget_table_cmd();
  800.   }
  801. }
  802.  
  803. cm_tindex(){}
  804.  
  805. cm_title(int se, char *arg)
  806. {
  807.   if (se == START)
  808.   {
  809.     word_emit();
  810.     fileio_queue("}");
  811.     fileio_queue(arg);
  812.     remember_brace_args(cm_title, "title");
  813.     psf_pushscale(ps_fontsize+18);
  814.     line_skip();
  815.     line_skip();
  816.     line_skip();
  817.     line_skip();
  818.   }
  819.   else
  820.   {
  821.     psf_pop();
  822.     line_break();
  823.     eat_skips = 1;
  824.     line_skip();
  825.     line_skip();
  826.     line_skip();
  827.     line_skip();
  828.   }
  829. }
  830.  
  831. cm_titlefont(int se)
  832. {
  833.   if (se == START)
  834.     psf_pushscale(ps_fontsize * 2 + 18);
  835.   else
  836.   {
  837.     para_close();
  838.     psf_pop();
  839.   }
  840. }
  841.  
  842. cm_titlepage(int se)
  843. {
  844.   if (se == START)
  845.     remember_brace_args(cm_titlepage, "titlepage");
  846.   else
  847.     page_flush();
  848. }
  849.  
  850. cm_today(int se)
  851. {
  852.   if (suspend_output)
  853.     return;
  854.   if (se == START)
  855.   {
  856.     time_t now;
  857.     struct tm *tmnow;
  858.     char buf[100];
  859.     time(&now);
  860.     tmnow = localtime(&now);
  861.     strftime(buf, 100, "%e %h %Y", tmnow);
  862.     word_add_string(buf);
  863.   }
  864. }
  865.  
  866. cm_top(){}
  867. cm_unmacro(){}
  868.  
  869. cm_unnumbered(int se, char *arg)
  870. {
  871.   if (se == START)
  872.     page_flush();
  873.   big_font(se, arg, 8);
  874. }
  875.  
  876. cm_unnumberedsec(int se, char *arg) { big_font(se, arg, 6); }
  877. cm_unnumberedsubsec(int se, char *arg) { big_font(se, arg, 4); }
  878. cm_unnumberedsubsubsec(int se, char *arg) { big_font(se, arg, 2); }
  879.  
  880. cm_value(int se, char *flag)
  881. {
  882.   if (suspend_output)
  883.     return;
  884.   if (se == START)
  885.     {
  886.       char *value = flag_value(flag);
  887.  
  888.       if (value)
  889.         {
  890.           word_add_string(value);
  891.           free(value);
  892.         }
  893.       else
  894.         {
  895.           fprintf(stderr, "\nError: memory exhausted at %s", fileio_where());
  896.           exit(1);
  897.         }
  898.     }
  899.   else
  900.     fprintf(stderr, "\ncm_value(END, %s) at %s", flag, fileio_where());
  901. }
  902.  
  903. cm_var(){}
  904. cm_vindex(){}
  905.  
  906. cm_vskip()
  907. {
  908.   vskip_enabled = 1;
  909. }
  910.  
  911. cm_vtable(int se, char *arg)
  912. {
  913.   cm_table(se, arg);
  914. }
  915.  
  916. cm_w(){}
  917.  
  918. cm_xref(int se, char *a)
  919. {
  920.   if (suspend_output)
  921.     return;
  922.   if (se == START)
  923.   {
  924.     word_add_string("See");
  925.     word_emit();
  926.     word_ws();
  927.     word_add_string(a);
  928.   }
  929. }
  930.  
  931. command_name_condition(){}
  932. do_nothing(){}
  933.  
  934. insert_self(int se, char *a)
  935. {
  936.   if (suspend_output)
  937.     return;
  938.   if (se == START)
  939.     word_add_quoted(a[0]);
  940. }
  941.  
  942.  
  943. static COMMAND CommandTable[] = {
  944.   { "!", cm_ignore_sentence_ender, NO_BRACE_ARGS },
  945.   { "'", insert_self, SELF_ARGS },
  946.   { "*", cm_asterisk, NO_BRACE_ARGS },
  947.   { ".", cm_ignore_sentence_ender, NO_BRACE_ARGS },
  948.   { ":", cm_force_abbreviated_whitespace, NO_BRACE_ARGS },
  949.   { "?", cm_ignore_sentence_ender, NO_BRACE_ARGS },
  950.   { "|", do_nothing, NO_BRACE_ARGS },
  951.   { "@", insert_self, SELF_ARGS },
  952.   { " ", insert_self, SELF_ARGS },
  953.   { "\n", insert_self, SELF_ARGS },
  954.   { "TeX", cm_TeX, BRACE_ARGS },
  955.   { "`", insert_self, SELF_ARGS },
  956.   { "appendix", cm_appendix, LINE_ARGS },
  957.   { "appendixsection", cm_appendixsec, LINE_ARGS },
  958.   { "appendixsec", cm_appendixsec, LINE_ARGS },
  959.   { "appendixsubsec", cm_appendixsubsec, LINE_ARGS },
  960.   { "appendixsubsubsec", cm_appendixsubsubsec, LINE_ARGS },
  961.   { "asis", cm_asis, BRACE_ARGS },
  962.   { "author", cm_author, LINE_ARGS },
  963.   { "b", cm_bold, BRACE_ARGS },
  964.   { "bold", cm_bold, BRACE_ARGS },
  965.   { "br", cm_br, BRACE_ARGS },
  966.   { "bullet", cm_bullet, BRACE_ARGS },
  967.   { "bye", cm_bye, NO_BRACE_ARGS },
  968.   { "c", cm_ignore_line, LINE_ARGS },
  969.   { "cartouche", cm_cartouche, NO_BRACE_ARGS },
  970.   { "center", cm_center, NO_BRACE_ARGS },
  971.   { "chapheading", cm_chapheading, NO_BRACE_ARGS },
  972.   { "chapter", cm_chapter, LINE_ARGS },
  973.   { "cindex", cm_cindex, LINE_ARGS },
  974.   { "cite", cm_cite, BRACE_ARGS },
  975.   { "clear", cm_clear, LINE_ARGS },
  976.   { "code", cm_code, BRACE_ARGS },
  977.   { "comment", cm_ignore_line, LINE_ARGS },
  978.   { "contents", do_nothing, NO_BRACE_ARGS },
  979.   { "copyright", cm_copyright, BRACE_ARGS },
  980.   { "ctrl", cm_ctrl, BRACE_ARGS },
  981.   { "defcodeindex", cm_defcodeindex, NO_BRACE_ARGS },
  982.   { "defindex", cm_defindex, NO_BRACE_ARGS },
  983.   { "dfn", cm_dfn, BRACE_ARGS },
  984.  
  985. /* The `def' commands. */
  986.   { "deffn", cm_defun, LINE_ARGS },
  987.   { "deffnx", cm_defun, LINE_ARGS },
  988.   { "defun", cm_defun, LINE_ARGS },
  989.   { "defunx", cm_defun, LINE_ARGS },
  990.   { "defmac", cm_defun, LINE_ARGS },
  991.   { "defmacx", cm_defun, LINE_ARGS },
  992.   { "defspec", cm_defun, LINE_ARGS },
  993.   { "defspecx", cm_defun, LINE_ARGS },
  994.   { "defvr", cm_defun, LINE_ARGS },
  995.   { "defvrx", cm_defun, LINE_ARGS },
  996.   { "defvar", cm_defun, LINE_ARGS },
  997.   { "defvarx", cm_defun, LINE_ARGS },
  998.   { "defopt", cm_defun, LINE_ARGS },
  999.   { "defoptx", cm_defun, LINE_ARGS },
  1000.   { "deftypefn", cm_defun, LINE_ARGS },
  1001.   { "deftypefnx", cm_defun, LINE_ARGS },
  1002.   { "deftypefun", cm_defun, LINE_ARGS },
  1003.   { "deftypefunx", cm_defun, LINE_ARGS },
  1004.   { "deftypevr", cm_defun, LINE_ARGS },
  1005.   { "deftypevrx", cm_defun, LINE_ARGS },
  1006.   { "deftypevar", cm_defun, LINE_ARGS },
  1007.   { "deftypevarx", cm_defun, LINE_ARGS },
  1008.   { "defcv", cm_defun, LINE_ARGS },
  1009.   { "defcvx", cm_defun, LINE_ARGS },
  1010.   { "defivar", cm_defun, LINE_ARGS },
  1011.   { "defivarx", cm_defun, LINE_ARGS },
  1012.   { "defop", cm_defun, LINE_ARGS },
  1013.   { "defopx", cm_defun, LINE_ARGS },
  1014.   { "defmethod", cm_defun, LINE_ARGS },
  1015.   { "defmethodx", cm_defun, LINE_ARGS },
  1016.   { "deftypemethod", cm_defun, LINE_ARGS },
  1017.   { "deftypemethodx", cm_defun, LINE_ARGS },
  1018.   { "deftp", cm_defun, LINE_ARGS },
  1019.   { "deftpx", cm_defun, LINE_ARGS },
  1020. /* The end of the `def' commands. */
  1021.  
  1022.   { "display", cm_display, NO_BRACE_ARGS },
  1023.   { "dots", cm_dots, BRACE_ARGS },
  1024.   { "dmn", do_nothing, BRACE_ARGS },
  1025.   { "emph", cm_emph, BRACE_ARGS },
  1026.   { "end", cm_end, WORD_ARGS },
  1027.   { "enumerate", cm_enumerate, LINE_ARGS },
  1028.   { "equiv", cm_equiv, BRACE_ARGS },
  1029.   { "error", cm_error, BRACE_ARGS },
  1030.   { "example", cm_example, LINE_ARGS },
  1031.   { "exdent", cm_exdent, NO_BRACE_ARGS },
  1032.   { "expansion", cm_expansion, BRACE_ARGS },
  1033.   { "file", cm_file, BRACE_ARGS },
  1034.   { "findex", cm_findex, LINE_ARGS },
  1035.   { "finalout", do_nothing, NO_BRACE_ARGS },
  1036.   { "flushleft", cm_flushleft, NO_BRACE_ARGS },
  1037.   { "flushright", cm_flushright, NO_BRACE_ARGS },
  1038.   { "format", cm_format, NO_BRACE_ARGS },
  1039.   { "ftable", cm_ftable, WORD_ARGS },
  1040.   { "group", cm_group, NO_BRACE_ARGS },
  1041.   { "heading", cm_heading, LINE_ARGS },
  1042.   { "headings", cm_ignore_line, LINE_ARGS },
  1043.   { "i", cm_italic, BRACE_ARGS },
  1044.   { "iappendix", cm_appendix, LINE_ARGS },
  1045.   { "iappendixsection", cm_appendixsec, LINE_ARGS },
  1046.   { "iappendixsec", cm_appendixsec, LINE_ARGS },
  1047.   { "iappendixsubsec", cm_appendixsubsec, LINE_ARGS },
  1048.   { "iappendixsubsubsec", cm_appendixsubsubsec, LINE_ARGS },
  1049.   { "ichapter", cm_chapter, LINE_ARGS },
  1050.   { "ifclear", cm_ifclear, LINE_ARGS },
  1051.   { "ifinfo", cm_ignore_cond, NO_BRACE_ARGS },
  1052.   { "ifset", cm_ifset, LINE_ARGS },
  1053.   { "iftex", cm_ignore_cond, NO_BRACE_ARGS },
  1054.   { "ignore", cm_ignore_cond, NO_BRACE_ARGS },
  1055.   { "include", cm_include, WORD_ARGS },
  1056.   { "inforef", cm_inforef, BRACE_ARGS },
  1057.   { "input", cm_include, NO_BRACE_ARGS },
  1058.   { "isection", cm_section, LINE_ARGS },
  1059.   { "isubsection", cm_subsection, LINE_ARGS },
  1060.   { "isubsubsection", cm_subsubsection, LINE_ARGS },
  1061.   { "italic", cm_italic, BRACE_ARGS },
  1062.   { "item", cm_item, LINE_ARGS },
  1063.   { "itemize", cm_itemize, WORD_ARGS },
  1064.   { "itemx", cm_itemx, LINE_ARGS },
  1065.   { "iunnumbered", cm_unnumbered, LINE_ARGS },
  1066.   { "iunnumberedsec", cm_unnumberedsec, LINE_ARGS },
  1067.   { "iunnumberedsubsec", cm_unnumberedsubsec, LINE_ARGS },
  1068.   { "iunnumberedsubsubsec", cm_unnumberedsubsubsec, LINE_ARGS },
  1069.   { "kbd", cm_kbd, BRACE_ARGS },
  1070.   { "key", cm_key, BRACE_ARGS },
  1071.   { "kindex", cm_kindex, LINE_ARGS },
  1072.   { "lowersections", cm_lowersections, NO_BRACE_ARGS },
  1073.   { "lisp", cm_lisp, NO_BRACE_ARGS },
  1074.   { "macro", cm_macro, NO_BRACE_ARGS },
  1075.   { "majorheading", cm_majorheading, LINE_ARGS },
  1076.   { "math", cm_math, BRACE_ARGS },
  1077.   { "menu", cm_menu, LINE_ARGS },
  1078.   { "minus", cm_minus, BRACE_ARGS },
  1079.   { "need", cm_ignore_line, WORD_ARGS },
  1080.   { "node", cm_node, LINE_ARGS },
  1081.   { "noindent", cm_noindent, NO_BRACE_ARGS },
  1082.   { "nwnode", cm_node, NO_BRACE_ARGS },
  1083.   { "overfullrule", cm_ignore_line, LINE_ARGS },
  1084.   { "page", cm_page, NO_BRACE_ARGS },
  1085.   { "pindex", cm_pindex, LINE_ARGS },
  1086.   { "point", cm_point, BRACE_ARGS },
  1087.   { "print", cm_print, BRACE_ARGS },
  1088.   { "printindex", cm_printindex, LINE_ARGS },
  1089.   { "pxref", cm_pxref, BRACE_ARGS },
  1090.   { "quotation", cm_quotation, NO_BRACE_ARGS },
  1091.   { "r", cm_roman, BRACE_ARGS },
  1092.   { "raisesections", cm_raisesections, NO_BRACE_ARGS },
  1093.   { "ref", cm_xref, BRACE_ARGS },
  1094.   { "refill", cm_refill, NO_BRACE_ARGS },
  1095.   { "result", cm_result, BRACE_ARGS },
  1096.   { "samp", cm_samp, BRACE_ARGS },
  1097.   { "sc", cm_sc, BRACE_ARGS },
  1098.   { "section", cm_section, LINE_ARGS },
  1099.   { "set", cm_set, LINE_ARGS },
  1100.   { "setchapternewpage", cm_ignore_line, WORD_ARGS },
  1101.   { "setchapterstyle", cm_ignore_line, WORD_ARGS },
  1102.   { "setfilename", cm_setfilename, WORD_ARGS },
  1103.   { "settitle", cm_ignore_line, LINE_ARGS },
  1104.   { "shortcontents", do_nothing, LINE_ARGS },
  1105.   { "shorttitlepage", command_name_condition, LINE_ARGS },
  1106.   { "smallbook", cm_ignore_line, LINE_ARGS },
  1107.   { "smallexample", cm_smallexample, NO_BRACE_ARGS },
  1108.   { "smalllisp", cm_smalllisp, NO_BRACE_ARGS },
  1109.   { "sp", cm_sp, WORD_ARGS },
  1110.   { "strong", cm_strong, BRACE_ARGS },
  1111.   { "subheading", cm_subheading, LINE_ARGS },
  1112.   { "subsection", cm_subsection, LINE_ARGS },
  1113.   { "subsubheading", cm_subsubheading, LINE_ARGS },
  1114.   { "subsubsection", cm_subsubsection, LINE_ARGS },
  1115.   { "subtitle", cm_subtitle, LINE_ARGS },
  1116.   { "summarycontents", do_nothing, NO_BRACE_ARGS },
  1117.   { "syncodeindex", cm_synindex, LINE_ARGS },
  1118.   { "synindex", cm_synindex, LINE_ARGS },
  1119.   { "t", cm_title, LINE_ARGS },
  1120.   { "table", cm_table, WORD_ARGS },
  1121.   { "tex", cm_ignore_cond, NO_BRACE_ARGS },
  1122.   { "tindex", cm_tindex, LINE_ARGS },
  1123.   { "title", cm_title, LINE_ARGS },
  1124.   { "titlefont", cm_titlefont, BRACE_ARGS },
  1125.   { "titlepage", cm_titlepage, NO_BRACE_ARGS },
  1126.   { "titlespec", command_name_condition, NO_BRACE_ARGS },
  1127.   { "today", cm_today, BRACE_ARGS },
  1128.   { "top", cm_top, NO_BRACE_ARGS  },
  1129.   { "unmacro", cm_unmacro, NO_BRACE_ARGS },
  1130.   { "unnumbered", cm_unnumbered, LINE_ARGS },
  1131.   { "unnumberedsec", cm_unnumberedsec, LINE_ARGS },
  1132.   { "unnumberedsubsec", cm_unnumberedsubsec, LINE_ARGS },
  1133.   { "unnumberedsubsubsec", cm_unnumberedsubsubsec, LINE_ARGS },
  1134.   { "value", cm_value, BRACE_WORD_ARGS },
  1135.   { "var", cm_var, BRACE_ARGS },
  1136.   { "vindex", cm_vindex, LINE_ARGS },
  1137.   { "vskip", cm_vskip, LINE_ARGS },
  1138.   { "vtable", cm_vtable, WORD_ARGS },
  1139.   { "w", cm_w, BRACE_ARGS },
  1140.   { "xref", cm_xref, BRACE_ARGS },
  1141.   { "{", insert_self, SELF_ARGS },
  1142.   { "}", insert_self, SELF_ARGS },
  1143.  
  1144.   /* Now @include does what this was supposed to. */
  1145.   { "infoinclude", cm_infoinclude, WORD_ARGS },
  1146.   { "footnote", cm_footnote, BRACE_ARGS},
  1147.   { "footnotestyle", cm_footnotestyle, WORD_ARGS },
  1148.   { "paragraphindent", cm_paragraphindent, WORD_ARGS },
  1149.     
  1150.   {(char *) NULL, (FUNCTION *) NULL, NO_BRACE_ARGS}
  1151.   };
  1152.  
  1153. void
  1154. skip_until_setfilename()
  1155. {
  1156.   static const char str[] = "@setfilename";
  1157.   int match = 0;
  1158.   while (1)
  1159.   {
  1160.     int ch = fileio_get();
  1161.     if (ch == str[match])
  1162.       match++;
  1163.     else
  1164.       match = 0;
  1165.     if (str[match] == 0)
  1166.     {
  1167.       while (match)
  1168.     fileio_unget(str[--match]);
  1169.       return;
  1170.     }
  1171.   }
  1172.   fprintf(stderr, "error: no @setfilename\n");
  1173.   exit(1);
  1174. }
  1175.  
  1176. void
  1177. do_file(char *file_name)
  1178. {
  1179.   int ch, last_ch=-1;
  1180.   fill_mode = 1;
  1181.   fileio_include(file_name);
  1182.   skip_until_setfilename();
  1183.   bye = 0;
  1184.   while ((ch = fileio_get()) != EOF && !bye)
  1185.   {
  1186.     if (ch == '\n')
  1187.     {
  1188.       if (suspend_output)
  1189.     continue;
  1190.       word_emit();
  1191.       if (fill_mode)
  1192.       {
  1193.     if (last_ch == '\n')
  1194.     {
  1195.       if (fill_mode && !eat_skips)
  1196.         para_close();
  1197.     }
  1198.     else
  1199.       word_ws();
  1200.       }
  1201.       else
  1202.       {
  1203.     if (last_ch == '\n')
  1204.       line_skip();
  1205.     else
  1206.       line_break();
  1207.       }
  1208.     }
  1209.     else if (ch == ' ' || ch == '\t')
  1210.     {
  1211.       if (suspend_output)
  1212.     continue;
  1213.       word_emit();
  1214.       word_ws();
  1215.     }
  1216.     else if (ch == '}')
  1217.     {
  1218.       if (!suspend_output)
  1219.     word_emit();
  1220.       forget_brace_args();
  1221.     }
  1222.     else if (ch == '@')
  1223.     {
  1224.       char *cmd_name;
  1225.       int cmd, argt, a;
  1226.       word_emit();
  1227.       eat_skips = 0;
  1228.       bufp = 0;
  1229.       ch = fileio_get();
  1230.       buf[bufp++] = ch;
  1231.       if (isalnum(ch))
  1232.       {
  1233.     do {
  1234.       ch = fileio_get();
  1235.       buf[bufp++] = ch;
  1236.     } while (ch != '{' && ch > ' ');
  1237.     buf[--bufp] = 0;
  1238.       }
  1239.       else
  1240.     buf[bufp] = 0;
  1241.       cmd_name = strdup(buf);
  1242.       for (cmd=0; CommandTable[cmd].name; cmd++)
  1243.     if (strcmp(CommandTable[cmd].name, cmd_name) == 0)
  1244.       break;
  1245.       argt = CommandTable[cmd].argument_in_braces;
  1246.       if (argt == SELF_ARGS)
  1247.       {
  1248.     if (!suspend_output)
  1249.       word_add_string(cmd_name);
  1250.     continue;
  1251.       }
  1252.       if (ch == '{' && argt != BRACE_WORD_ARGS)
  1253.     argt = BRACE_ARGS;
  1254.       bufp = 0;
  1255.       switch (argt)
  1256.       {
  1257.       case NO_BRACE_ARGS:
  1258.     a = 'N';
  1259.     break;
  1260.       case BRACE_ARGS:
  1261.     a = 'B';
  1262.     remember_brace_args(CommandTable[cmd].proc, cmd_name);
  1263.     break;
  1264.       case BRACE_WORD_ARGS:
  1265.     a = 'R';
  1266.     ch = fileio_get();
  1267.     while (ch != '}')
  1268.     {
  1269.       buf[bufp++] = ch;
  1270.       ch = fileio_get();
  1271.     }
  1272.     break;
  1273.       case LINE_ARGS:
  1274.     a = 'L';
  1275.     while (ch == ' ' || ch == '\t')
  1276.       ch = fileio_get();
  1277.     while (ch != '\n')
  1278.     {
  1279.       buf[bufp++] = ch;
  1280.       ch = fileio_get();
  1281.     }
  1282.     break;
  1283.       case WORD_ARGS:
  1284.     a = 'W';
  1285.     while (ch <= ' ')
  1286.       ch = fileio_get();
  1287.     while (ch > ' ')
  1288.     {
  1289.       buf[bufp++] = ch;
  1290.       ch = fileio_get();
  1291.     }
  1292.     break;
  1293.       }
  1294.       buf[bufp] = 0;
  1295. /*      printf("\033[36m[---@%s(%c,\033[0m%s\033[1;36m)---]\033[0;1m", cmd_name, a, buf); */
  1296.       if (CommandTable[cmd].proc)
  1297.     CommandTable[cmd].proc(START, buf);
  1298.       free(cmd_name);
  1299.     }
  1300.     else
  1301.     {
  1302.       eat_skips = 0;
  1303.       if (!suspend_output)
  1304.       {
  1305.     if (capify)
  1306.       word_add_char(toupper(ch));
  1307.     else
  1308.       word_add_char(ch);
  1309.       }
  1310.     }
  1311.     last_ch = ch;
  1312.   }
  1313. }
  1314.  
  1315. static int
  1316. usage(void)
  1317. {
  1318.   printf("usage: texi2ps [-f size] [-I dir] [-Idir] [-v] [-m pts] [-Dname[=val]] [-Uname] [file...]\n");
  1319.   printf("  -f = fontsize (default = 10)\n");
  1320.   printf("  -I = include path\n");
  1321.   printf("  -v = verbose progress messages\n");
  1322.   printf("  -m = set margins (default 54 pts, 3/4\")\n");
  1323.   printf("  -D = set flag called `name\' to `val\' (default: empty value)\n");
  1324.   printf("  -U = clear (unset) flags called `name\'\n");
  1325.   exit(0);
  1326. }
  1327.  
  1328. int
  1329. main(int argc, char **argv)
  1330. {
  1331.   int arg;
  1332.   if (argc < 2)
  1333.     usage();
  1334.   for (arg=1; arg<argc && argv[arg][0] == '-'; arg++)
  1335.   {
  1336.     if (strcmp(argv[arg], "-h") == 0)
  1337.     {
  1338.       usage();
  1339.     }
  1340.     else if (strcmp(argv[arg], "-f") == 0)
  1341.     {
  1342.       int fsize = atoi(argv[++arg]);
  1343.  
  1344.       if (fsize > 0)
  1345.         ps_fontsize = fsize;
  1346.       else
  1347.       {
  1348.         fprintf(stderr, "illegal value for \"-f\" (ignored)\n");
  1349.         --arg;
  1350.       }
  1351.     }
  1352.     else if (strcmp(argv[arg], "-m") == 0)
  1353.     {
  1354.       int margin = atoi(argv[++arg]);
  1355.  
  1356.       if (margin > 0)
  1357.         word_set_margins(margin);
  1358.       else
  1359.       {
  1360.         fprintf(stderr, "illegal value for \"-m\" (ignored)\n");
  1361.         --arg;
  1362.       }
  1363.     }
  1364.     else if (strncmp(argv[arg], "-I", 2) == 0)
  1365.     {
  1366.       if (argv[arg][2])
  1367.     fileio_add_path(argv[arg]+2);
  1368.       else
  1369.     fileio_add_path(argv[++arg]);
  1370.     }
  1371.     else if (strcmp(argv[arg], "-v") == 0)
  1372.       screenio_enabled = 1;
  1373.     else if (strncmp(argv[arg], "-D", 2) == 0 ||
  1374.              strncmp(argv[arg], "-U", 2) == 0)
  1375.     {
  1376.       int   set   = argv[arg][1] == 'D' ? 1 : 0;
  1377.       char *name  = argv[arg][2] ? argv[arg] + 2 : argv[++arg];
  1378.       char *value = strchr(name, '=');
  1379.  
  1380.       if (value)
  1381.         *value++ = '\0';
  1382.       else
  1383.         value = "";
  1384.  
  1385.       if (set)
  1386.         set_flag(name, value);
  1387.       else
  1388.         clear_flag(name);
  1389.     }
  1390.   }
  1391.   word_init();
  1392.   for (; arg < argc; arg++)
  1393.   {
  1394.     set_level = clear_level = 0;
  1395.     do_file(argv[arg]);
  1396.   }
  1397.   psdone();
  1398.   screenio_print("\n%d pages generated", current_page);
  1399.   return 0;
  1400. }
  1401.