home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / groff / libdriver / input.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-30  |  9.4 KB  |  460 lines

  1. // -*- C++ -*-
  2. /* Copyright (C) 1989, 1990 Free Software Foundation, Inc.
  3.      Written by James Clark (jjc@jclark.uucp)
  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 1, 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 LICENSE.  If not, write to the Free Software
  19. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include "driver.h"
  22.  
  23. const char *current_filename;
  24. int current_lineno;
  25. FILE *current_file;
  26.  
  27. int get_char();
  28. int get_integer();        // don't read the newline
  29. int possibly_get_integer(int *);
  30. char *get_string(int is_long = 0);
  31. void skip_line();
  32.  
  33. struct environment_list {
  34.   environment env;
  35.   environment_list *next;
  36.  
  37.   environment_list(const environment &, environment_list *);
  38. };
  39.  
  40. environment_list::environment_list(const environment &e, environment_list *p)
  41. : env(e), next(p)
  42. {
  43. }
  44.  
  45. void do_file(const char *filename)
  46. {
  47.   int npages = 0;
  48.   if (filename[0] == '-' && filename[1] == '\0') {
  49.     current_filename = "<standard input>";
  50.     current_file = stdin;
  51.   }
  52.   else {
  53.     current_file = fopen(filename, "r");
  54.     if (current_file == 0) {
  55.       error("can't open `%1'", filename);
  56.       return;
  57.     }
  58.     current_filename = filename;
  59.   }
  60.   environment env;
  61.   env.vpos = -1;
  62.   env.hpos = -1;
  63.   env.fontno = -1;
  64.   env.height = 0;
  65.   env.slant = 0;
  66.   environment_list *env_list = 0;
  67.   current_lineno = 1;
  68.   int command;
  69.   char *s;
  70.   command = get_char();
  71.   if (command == EOF)
  72.     return;
  73.   if (command != 'x')
  74.     fatal("the first command must be `x T'");
  75.   s = get_string();
  76.   if (s[0] != 'T')
  77.     fatal("the first command must be `x T'");
  78.   char *dev = get_string();
  79.   if (pr == 0) {
  80.     font::set_device_name(dev);
  81.     if (!font::load_desc())
  82.       fatal("sorry, I can't continue");
  83.   }
  84.   else {
  85.     const char *d = font::get_device_name();
  86.     if (d == 0 || strcmp(d, dev) != 0)
  87.       fatal("all files must use the same device");
  88.   }
  89.   skip_line();
  90.   env.size = 10*font::sizescale;
  91.   command = get_char();
  92.   if (command != 'x')
  93.     fatal("the second command must be `x res'");
  94.   s = get_string();
  95.   if (s[0] != 'r')
  96.     fatal("the second command must be `x res'");
  97.   int n = get_integer();
  98.   if (n != font::res)
  99.     fatal("resolution does not match");
  100.   n = get_integer();
  101.   if (n != font::hor)
  102.     fatal("horizontal resolution does not match");
  103.   n = get_integer();
  104.   if (n != font::vert)
  105.     fatal("vertical resolution does not match");
  106.   skip_line();
  107.   command = get_char();
  108.   if (command != 'x')
  109.     fatal("the third command must be `x init'");
  110.   s = get_string();
  111.   if (s[0] != 'i')
  112.     fatal("the third command must be `x init'");
  113.   skip_line();
  114.   if (pr == 0)
  115.     pr = make_printer();
  116.   while ((command = get_char()) != EOF) {
  117.     switch (command) {
  118.     case 's':
  119.       env.size = get_integer();
  120.       if (env.height == env.size)
  121.     env.height = 0;
  122.       break;
  123.     case 'f':
  124.       env.fontno = get_integer();
  125.       break;
  126.     case 'C':
  127.       {
  128.     if (npages == 0)
  129.       fatal("`C' command illegal before first `p' command");
  130.     char *s = get_string();
  131.     pr->set_special_char(s, &env);
  132.       }
  133.       break;
  134.     case 'N':
  135.       {
  136.     if (npages == 0)
  137.       fatal("`N' command illegal before first `p' command");
  138.     pr->set_numbered_char(get_integer(), &env);
  139.       }
  140.       break;
  141.     case 'H':
  142.       env.hpos = get_integer();
  143.       break;
  144.     case 'h':
  145.       env.hpos += get_integer();
  146.       break;
  147.     case 'V':
  148.       env.vpos = get_integer();
  149.       break;
  150.     case 'v':
  151.       env.vpos += get_integer();
  152.       break;
  153.     case '0':
  154.     case '1':
  155.     case '2':
  156.     case '3':
  157.     case '4':
  158.     case '5':
  159.     case '6':
  160.     case '7':
  161.     case '8':
  162.     case '9':
  163.       {
  164.     int c = get_char();
  165.     if (!isascii(c) || !isdigit(c))
  166.       fatal("digit expected");
  167.     env.hpos += (command - '0')*10 + (c - '0');
  168.       }
  169.       // fall through
  170.     case 'c':
  171.       {
  172.     if (npages == 0)
  173.       fatal("`c' command illegal before first `p' command");
  174.     int c = get_char();
  175.     if (c == EOF)
  176.       fatal("missing argument to `c' command");
  177.     pr->set_ascii_char(c, &env);
  178.       }
  179.       break;
  180.     case 'n':
  181.       if (npages == 0)
  182.     fatal("`n' command illegal before first `p' command");
  183.       pr->end_of_line();
  184.       (void)get_integer();
  185.       (void)get_integer();
  186.       break;
  187.     case 'w':
  188.     case ' ':
  189.     case '\n':
  190.       break;
  191.     case 'p':
  192.       if (npages)
  193.     pr->end_page();
  194.       npages++;
  195.       pr->begin_page(get_integer());
  196.       env.vpos = 0;
  197.       break;
  198.     case '{':
  199.       env_list = new environment_list(env, env_list);
  200.       break;
  201.     case '}':
  202.       if (!env_list) {
  203.     fatal("can't pop");
  204.       }
  205.       else {
  206.     env = env_list->env;
  207.     environment_list *tem = env_list;
  208.     env_list = env_list->next;
  209.     delete tem;
  210.       }
  211.       break;
  212.     case 'u':
  213.       {
  214.     if (npages == 0)
  215.       fatal("`u' command illegal before first `p' command");
  216.     int kern = get_integer();
  217.     int c = get_char();
  218.     while (c == ' ')
  219.       c = get_char();
  220.     while (c != EOF && c != ' ' && c != '\n') {
  221.       int w;
  222.       pr->set_ascii_char(c, &env, &w);
  223.       env.hpos += w + kern;
  224.       c = get_char();
  225.     }
  226.       }
  227.       break;
  228.     case 't':
  229.       {
  230.     if (npages == 0)
  231.       fatal("`t' command illegal before first `p' command");
  232.     int c;
  233.     while ((c = get_char()) != EOF && c != ' ' && c != '\n') {
  234.       int w;
  235.       pr->set_ascii_char(c, &env, &w);
  236.       env.hpos += w;
  237.     }
  238.       }
  239.       break;
  240.     case '#':
  241.       skip_line();
  242.     case 'D':
  243.       {
  244.     if (npages == 0)
  245.       fatal("`D' command illegal before first `p' command");
  246.     int c;
  247.     while ((c = get_char()) == ' ')
  248.       ;
  249.     int n;
  250.     int *p = 0;
  251.     int szp = 0;
  252.     for (int np = 0; possibly_get_integer(&n); np++) {
  253.       if (np >= szp) {
  254.         if (szp == 0) {
  255.           szp = 16;
  256.           p = new int[szp];
  257.         }
  258.         else {
  259.           int *oldp = p;
  260.           p = new int[szp*2];
  261.           memcpy(p, oldp, szp*sizeof(int));
  262.           szp *= 2;
  263.           delete oldp;
  264.         }
  265.       }
  266.       p[np] = n;
  267.     }
  268.     pr->draw(c, p, np, &env);
  269.     if (c == 'e') {
  270.       if (np > 0)
  271.         env.hpos += p[0];
  272.     }
  273.     else { 
  274.       for (int i = 0; i < np/2; i++) {
  275.         env.hpos += p[i*2];
  276.         env.vpos += p[i*2 + 1];
  277.       }
  278.       // there might be an odd number of characters
  279.       if (i*2 < np)
  280.         env.hpos += p[i*2];
  281.     }
  282.     delete p;
  283.     skip_line();
  284.       }
  285.       break;
  286.     case 'x':
  287.       {
  288.     char *s = get_string();
  289.     int suppress_skip = 0;
  290.     switch (s[0]) {
  291.     case 'i':
  292.       error("duplicate `x init' command");
  293.       break;
  294.     case 'T':
  295.       error("duplicate `x T' command");
  296.       break;
  297.     case 'r':
  298.       error("duplicate `x res' command");
  299.       break;
  300.     case 'p':
  301.       break;
  302.     case 's':
  303.       break;
  304.     case 't':
  305.       break;
  306.     case 'f':
  307.       {
  308.         int n = get_integer();
  309.         char *name = get_string();
  310.         pr->load_font(n, name);
  311.       }
  312.       break;
  313.     case 'H':
  314.       env.height = get_integer();
  315.       if (env.height == env.size)
  316.         env.height = 0;
  317.       break;
  318.     case 'S':
  319.       env.slant = get_integer();
  320.       break;
  321.     case 'X':
  322.       if (npages == 0)
  323.         fatal("`x X' command illegal before first `p' command");
  324.       pr->special(get_string(1), &env);
  325.       suppress_skip = 1;
  326.       break;
  327.     default:
  328.       error("unrecognised x command `%1'", s);
  329.     }
  330.     if (!suppress_skip)
  331.       skip_line();
  332.       }
  333.       break;
  334.     default:
  335.       error("unrecognised command code %1", int(command));
  336.       skip_line();
  337.       break;
  338.     }
  339.   }
  340.   if (npages)
  341.     pr->end_page();
  342. }
  343.  
  344. int get_char()
  345. {
  346.   int c = getc(current_file);
  347.   if (c == '\n')
  348.     current_lineno++;
  349.   return c;
  350. }
  351.  
  352. int get_integer()
  353. {
  354.   int c = getc(current_file);
  355.   while (c == ' ')
  356.     c = getc(current_file);
  357.   int neg = 0;
  358.   if (c == '-') {
  359.     neg = 1;
  360.     c = getc(current_file);
  361.   }
  362.   if (!isascii(c) || !isdigit(c))
  363.     fatal("integer expected");
  364.   int total = 0;
  365.   do {
  366.     total = total*10;
  367.     if (neg)
  368.       total -= c - '0';
  369.     else
  370.       total += c - '0';
  371.     c = getc(current_file);
  372.   }  while (isascii(c) && isdigit(c));
  373.   if (c != EOF)
  374.     ungetc(c, current_file);
  375.   return total;
  376. }
  377.  
  378. int possibly_get_integer(int *res)
  379. {
  380.   int c = getc(current_file);
  381.   while (c == ' ')
  382.     c = getc(current_file);
  383.   int neg = 0;
  384.   if (c == '-') {
  385.     neg = 1;
  386.     c = getc(current_file);
  387.   }
  388.   if (!isascii(c) || !isdigit(c)) {
  389.     if (c != EOF)
  390.       ungetc(c, current_file);
  391.     return 0;
  392.   }
  393.   int total = 0;
  394.   do {
  395.     total = total*10;
  396.     if (neg)
  397.       total -= c - '0';
  398.     else
  399.       total += c - '0';
  400.     c = getc(current_file);
  401.   }  while (isascii(c) && isdigit(c));
  402.   if (c != EOF)
  403.     ungetc(c, current_file);
  404.   *res = total;
  405.   return 1;
  406. }
  407.  
  408.  
  409. char *get_string(int is_long)
  410. {
  411.   static char *buf;
  412.   static int buf_size;
  413.   int c = getc(current_file);
  414.   while (c == ' ')
  415.     c = getc(current_file);
  416.   for (int i = 0;; i++) {
  417.     if (i >= buf_size) {
  418.       if (buf_size == 0) {
  419.     buf_size = 16;
  420.     buf = new char[buf_size];
  421.       }
  422.       else {
  423.     char *old_buf = buf;
  424.     int old_size = buf_size;
  425.     buf_size *= 2;
  426.     buf = new char[buf_size];
  427.     memcpy(buf, old_buf, old_size);
  428.     delete old_buf;
  429.       }
  430.     }
  431.     if ((!is_long && (c == ' ' || c == '\n')) || c == EOF) {
  432.       buf[i] = '\0';
  433.       break;
  434.     }
  435.     if (is_long && c == '\n') {
  436.       current_lineno++;
  437.       c = getc(current_file);
  438.       if (c == '+')
  439.     c = '\n';
  440.       else {
  441.     buf[i] = '\0';
  442.     break;
  443.       }
  444.     }  
  445.     buf[i] = c;
  446.     c = getc(current_file);
  447.   }
  448.   if (c != EOF)
  449.     ungetc(c, current_file);
  450.   return buf;
  451. }
  452.  
  453. void skip_line()
  454. {
  455.   int c;
  456.   while ((c = get_char()) != EOF && c != '\n')
  457.     ;
  458. }
  459.  
  460.