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