home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / util / gnu / groff_src.lha / groff-1.10src / eqn / main.cc < prev    next >
C/C++ Source or Header  |  1995-06-22  |  8KB  |  353 lines

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
  3.      Written by James Clark (jjc@jclark.com)
  4.  
  5. This file is part of groff.
  6.  
  7. groff is free software; you can redistribute it and/or modify it under
  8. the terms of the GNU General Public License as published by the Free
  9. Software Foundation; either version 2, or (at your option) any later
  10. version.
  11.  
  12. groff is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with groff; see the file COPYING.  If not, write to the Free Software
  19. Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  20.  
  21. #include "eqn.h"
  22. #include "stringclass.h"
  23. #include "device.h"
  24. #include "searchpath.h"
  25. #include "macropath.h"
  26.  
  27. #define STARTUP_FILE "eqnrc"
  28.  
  29. extern int yyparse();
  30.  
  31. static char *delim_search(char *, int);
  32. static int inline_equation(FILE *, string &, string &);
  33.  
  34. char start_delim = '\0';
  35. char end_delim = '\0';
  36. int non_empty_flag;
  37. int inline_flag;
  38. int draw_flag = 0;
  39. int one_size_reduction_flag = 0;
  40. int compatible_flag = 0;
  41. int no_newline_in_delim_flag = 0;
  42.  
  43. int read_line(FILE *fp, string *p)
  44. {
  45.   p->clear();
  46.   int c = -1;
  47.   while ((c = getc(fp)) != EOF) {
  48.     if (!illegal_input_char(c))
  49.       *p += char(c);
  50.     else
  51.       error("illegal input character code `%1'", c);
  52.     if (c == '\n')
  53.       break;
  54.   }
  55.   current_lineno++;
  56.   return p->length() > 0;
  57. }
  58.  
  59. void do_file(FILE *fp, const char *filename)
  60. {
  61.   string linebuf;
  62.   string str;
  63.   printf(".lf 1 %s\n", filename);
  64.   current_filename = filename;
  65.   current_lineno = 0;
  66.   while (read_line(fp, &linebuf)) {
  67.     if (linebuf.length() >= 4
  68.     && linebuf[0] == '.' && linebuf[1] == 'l' && linebuf[2] == 'f'
  69.     && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) {
  70.       put_string(linebuf, stdout);
  71.       linebuf += '\0';
  72.       if (interpret_lf_args(linebuf.contents() + 3))
  73.     current_lineno--;
  74.     }
  75.     else if (linebuf.length() >= 4
  76.          && linebuf[0] == '.'
  77.          && linebuf[1] == 'E'
  78.          && linebuf[2] == 'Q'
  79.          && (linebuf[3] == ' ' || linebuf[3] == '\n' || compatible_flag)) {
  80.       put_string(linebuf, stdout);
  81.       int start_lineno = current_lineno + 1;
  82.       str.clear();
  83.       for (;;) {
  84.     if (!read_line(fp, &linebuf))
  85.       fatal("end of file before .EN");
  86.     if (linebuf.length() >= 3 && linebuf[0] == '.' && linebuf[1] == 'E') {
  87.       if (linebuf[2] == 'N'
  88.           && (linebuf.length() == 3 || linebuf[3] == ' '
  89.           || linebuf[3] == '\n' || compatible_flag))
  90.         break;
  91.       else if (linebuf[2] == 'Q' && linebuf.length() > 3
  92.            && (linebuf[3] == ' ' || linebuf[3] == '\n'
  93.                || compatible_flag))
  94.         fatal("nested .EQ");
  95.     }
  96.     str += linebuf;
  97.       }
  98.       str += '\0';
  99.       start_string();
  100.       init_lex(str.contents(), current_filename, start_lineno);
  101.       non_empty_flag = 0;
  102.       inline_flag = 0;
  103.       yyparse();
  104.       if (non_empty_flag) {
  105.     printf(".lf %d\n", current_lineno - 1);
  106.     output_string();
  107.       }
  108.       restore_compatibility();
  109.       printf(".lf %d\n", current_lineno);
  110.       put_string(linebuf, stdout);
  111.     }
  112.     else if (start_delim != '\0' && linebuf.search(start_delim) >= 0
  113.          && inline_equation(fp, linebuf, str))
  114.       ;
  115.     else
  116.       put_string(linebuf, stdout);
  117.   }
  118.   current_filename = 0;
  119.   current_lineno = 0;
  120. }
  121.  
  122. /* Handle an inline equation.  Return 1 if it was an inline equation,
  123. 0 otherwise. */
  124.  
  125. static int inline_equation(FILE *fp, string &linebuf, string &str)
  126. {
  127.   linebuf += '\0';
  128.   char *ptr = &linebuf[0];
  129.   char *start = delim_search(ptr, start_delim);
  130.   if (!start) {
  131.     // It wasn't a delimiter after all.
  132.     linebuf.set_length(linebuf.length() - 1); // strip the '\0'
  133.     return 0;
  134.   }
  135.   start_string();
  136.   inline_flag = 1;
  137.   for (;;) {
  138.     if (no_newline_in_delim_flag && strchr(start + 1, end_delim) == 0) {
  139.       error("missing `%1'", end_delim);
  140.       char *nl = strchr(start + 1, '\n');
  141.       if (nl != 0)
  142.     *nl = '\0';
  143.       do_text(ptr);
  144.       break;
  145.     }
  146.     int start_lineno = current_lineno;
  147.     *start = '\0';
  148.     do_text(ptr);
  149.     ptr = start + 1;
  150.     str.clear();
  151.     for (;;) {
  152.       char *end = strchr(ptr, end_delim);
  153.       if (end != 0) {
  154.     *end = '\0';
  155.     str += ptr;
  156.     ptr = end + 1;
  157.     break;
  158.       }
  159.       str += ptr;
  160.       if (!read_line(fp, &linebuf))
  161.     fatal("end of file before `%1'", end_delim);
  162.       linebuf += '\0';
  163.       ptr = &linebuf[0];
  164.     }
  165.     str += '\0';
  166.     init_lex(str.contents(), current_filename, start_lineno);
  167.     yyparse();
  168.     start = delim_search(ptr, start_delim);
  169.     if (start == 0) {
  170.       char *nl = strchr(ptr, '\n');
  171.       if (nl != 0)
  172.     *nl = '\0';
  173.       do_text(ptr);
  174.       break;
  175.     }
  176.   }
  177.   printf(".lf %d\n", current_lineno);
  178.   output_string();
  179.   restore_compatibility();
  180.   printf(".lf %d\n", current_lineno + 1);
  181.   return 1;
  182. }
  183.  
  184. /* Search for delim.  Skip over number register and string names etc. */
  185.  
  186. static char *delim_search(char *ptr, int delim)
  187. {
  188.   while (*ptr) {
  189.     if (*ptr == delim)
  190.       return ptr;
  191.     if (*ptr++ == '\\') {
  192.       switch (*ptr) {
  193.       case 'n':
  194.       case '*':
  195.       case 'f':
  196.       case 'g':
  197.       case 'k':
  198.     switch (*++ptr) {
  199.     case '\0':
  200.     case '\\':
  201.       break;
  202.     case '(':
  203.       if (*++ptr != '\\' && *ptr != '\0' && *++ptr != '\\' && *ptr != '\0')
  204.           ptr++;
  205.       break;
  206.     case '[':
  207.       while (*++ptr != '\0')
  208.         if (*ptr == ']') {
  209.           ptr++;
  210.           break;
  211.         }
  212.       break;
  213.     default:
  214.       ptr++;
  215.       break;
  216.     }
  217.     break;
  218.       case '\\':
  219.       case '\0':
  220.     break;
  221.       default:
  222.     ptr++;
  223.     break;
  224.       }
  225.     }
  226.   }
  227.   return 0;
  228. }
  229.  
  230. void usage()
  231. {
  232.   fprintf(stderr,
  233.         "usage: %s [ -rvDCNR ] -dxx -fn -sn -pn -mn -Mdir -Ts [ files ... ]\n",
  234.     program_name);
  235.   exit(1);
  236. }
  237.  
  238. int main(int argc, char **argv)
  239. {
  240.   program_name = argv[0];
  241.   static char stderr_buf[BUFSIZ];
  242.   setbuf(stderr, stderr_buf);
  243.   int opt;
  244.   int load_startup_file = 1;
  245.   while ((opt = getopt(argc, argv, "DCRvd:f:p:s:m:T:M:rN")) != EOF)
  246.     switch (opt) {
  247.     case 'C':
  248.       compatible_flag = 1;
  249.       break;
  250.     case 'R':            // don't load eqnchar
  251.       load_startup_file = 0;
  252.       break;
  253.     case 'M':
  254.       macro_path.command_line_dir(optarg);
  255.       break;
  256.     case 'v':
  257.       {
  258.     extern const char *version_string;
  259.     fprintf(stderr, "GNU eqn version %s\n", version_string);
  260.     fflush(stderr);
  261.     break;
  262.       }
  263.     case 'd':
  264.       if (optarg[0] == '\0' || optarg[1] == '\0')
  265.     error("-d requires two character argument");
  266.       else if (illegal_input_char(optarg[0]))
  267.     error("bad delimiter `%1'", optarg[0]);
  268.       else if (illegal_input_char(optarg[1]))
  269.     error("bad delimiter `%1'", optarg[1]);
  270.       else {
  271.     start_delim = optarg[0];
  272.     end_delim = optarg[1];
  273.       }
  274.       break;
  275.     case 'f':
  276.       set_gfont(optarg);
  277.       break;
  278.     case 'T':
  279.       device = optarg;
  280.       break;
  281.     case 's':
  282.       if (!set_gsize(optarg))
  283.     error("invalid size `%1'", optarg);
  284.       break;
  285.     case 'p':
  286.       {
  287.     int n;
  288.     if (sscanf(optarg, "%d", &n) == 1)
  289.       set_script_reduction(n);
  290.     else
  291.       error("bad size `%1'", optarg);
  292.       }
  293.       break;
  294.     case 'm':
  295.       {
  296.     int n;
  297.     if (sscanf(optarg, "%d", &n) == 1)
  298.       set_minimum_size(n);
  299.     else
  300.       error("bad size `%1'", optarg);
  301.       }
  302.       break;
  303.     case 'r':
  304.       one_size_reduction_flag = 1;
  305.       break;
  306.     case 'D':
  307.       warning("-D option is obsolete: use `set draw_lines 1' instead");
  308.       draw_flag = 1;
  309.       break;
  310.     case 'N':
  311.       no_newline_in_delim_flag = 1;
  312.       break;
  313.     case '?':
  314.       usage();
  315.       break;
  316.     default:
  317.       assert(0);
  318.     }
  319.   init_table(device);
  320.   init_char_table();
  321.   printf(".if !'\\*(.T'%s' "
  322.      ".tm warning: %s should have been given a `-T\\*(.T' option\n",
  323.      device, program_name);
  324.   if (load_startup_file) {
  325.     char *path;
  326.     FILE *fp = macro_path.open_file(STARTUP_FILE, &path);
  327.     if (fp) {
  328.       do_file(fp, path);
  329.       fclose(fp);
  330.       a_delete path;
  331.     }
  332.   }
  333.   if (optind >= argc)
  334.     do_file(stdin, "-");
  335.   else
  336.     for (int i = optind; i < argc; i++)
  337.       if (strcmp(argv[i], "-") == 0)
  338.     do_file(stdin, "-");
  339.       else {
  340.     errno = 0;
  341.     FILE *fp = fopen(argv[i], "r");
  342.     if (!fp)
  343.       fatal("can't open `%1': %2", argv[i], strerror(errno));
  344.     else {
  345.       do_file(fp, argv[i]);
  346.       fclose(fp);
  347.     }
  348.       }
  349.   if (ferror(stdout) || fflush(stdout) < 0)
  350.     fatal("output error");
  351.   return 0;
  352. }
  353.