home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / groff-1.09-src.lha / src / amiga / groff-1.09 / libdriver / input.cc next >
C/C++ Source or Header  |  1993-06-10  |  10KB  |  475 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, 675 Mass Ave, Cambridge, MA 02139, 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.     for (int np = 0; possibly_get_integer(&n); np++) {
  273.       if (np >= szp) {
  274.         if (szp == 0) {
  275.           szp = 16;
  276.           p = new int[szp];
  277.         }
  278.         else {
  279.           int *oldp = p;
  280.           p = new int[szp*2];
  281.           memcpy(p, oldp, szp*sizeof(int));
  282.           szp *= 2;
  283.           a_delete oldp;
  284.         }
  285.       }
  286.       p[np] = n;
  287.     }
  288.     pr->draw(c, p, np, &env);
  289.     if (c == 'e') {
  290.       if (np > 0)
  291.         env.hpos += p[0];
  292.     }
  293.     else { 
  294.       for (int i = 0; i < np/2; i++) {
  295.         env.hpos += p[i*2];
  296.         env.vpos += p[i*2 + 1];
  297.       }
  298.       // there might be an odd number of characters
  299.       if (i*2 < np)
  300.         env.hpos += p[i*2];
  301.     }
  302.     a_delete p;
  303.     skip_line();
  304.       }
  305.       break;
  306.     case 'x':
  307.       {
  308.     char *s = get_string();
  309.     int suppress_skip = 0;
  310.     switch (s[0]) {
  311.     case 'i':
  312.       error("duplicate `x init' command");
  313.       break;
  314.     case 'T':
  315.       error("duplicate `x T' command");
  316.       break;
  317.     case 'r':
  318.       error("duplicate `x res' command");
  319.       break;
  320.     case 'p':
  321.       break;
  322.     case 's':
  323.       break;
  324.     case 't':
  325.       break;
  326.     case 'f':
  327.       {
  328.         int n = get_integer();
  329.         char *name = get_string();
  330.         pr->load_font(n, name);
  331.       }
  332.       break;
  333.     case 'H':
  334.       env.height = get_integer();
  335.       if (env.height == env.size)
  336.         env.height = 0;
  337.       break;
  338.     case 'S':
  339.       env.slant = get_integer();
  340.       break;
  341.     case 'X':
  342.       if (npages == 0)
  343.         fatal("`x X' command illegal before first `p' command");
  344.       pr->special(get_string(1), &env);
  345.       suppress_skip = 1;
  346.       break;
  347.     default:
  348.       error("unrecognised x command `%1'", s);
  349.     }
  350.     if (!suppress_skip)
  351.       skip_line();
  352.       }
  353.       break;
  354.     default:
  355.       error("unrecognised command code %1", int(command));
  356.       skip_line();
  357.       break;
  358.     }
  359.   }
  360.   if (npages)
  361.     pr->end_page(env.vpos);
  362. }
  363.  
  364. int get_integer()
  365. {
  366.   int c = get_char();
  367.   while (c == ' ')
  368.     c = get_char();
  369.   int neg = 0;
  370.   if (c == '-') {
  371.     neg = 1;
  372.     c = get_char();
  373.   }
  374.   if (!csdigit(c))
  375.     fatal("integer expected");
  376.   int total = 0;
  377.   do {
  378.     total = total*10;
  379.     if (neg)
  380.       total -= c - '0';
  381.     else
  382.       total += c - '0';
  383.     c = get_char();
  384.   }  while (csdigit(c));
  385.   if (c != EOF)
  386.     ungetc(c, current_file);
  387.   return total;
  388. }
  389.  
  390. int possibly_get_integer(int *res)
  391. {
  392.   int c = get_char();
  393.   while (c == ' ')
  394.     c = get_char();
  395.   int neg = 0;
  396.   if (c == '-') {
  397.     neg = 1;
  398.     c = get_char();
  399.   }
  400.   if (!csdigit(c)) {
  401.     if (c != EOF)
  402.       ungetc(c, current_file);
  403.     return 0;
  404.   }
  405.   int total = 0;
  406.   do {
  407.     total = total*10;
  408.     if (neg)
  409.       total -= c - '0';
  410.     else
  411.       total += c - '0';
  412.     c = get_char();
  413.   }  while (csdigit(c));
  414.   if (c != EOF)
  415.     ungetc(c, current_file);
  416.   *res = total;
  417.   return 1;
  418. }
  419.  
  420.  
  421. char *get_string(int is_long)
  422. {
  423.   static char *buf;
  424.   static int buf_size;
  425.   int c = get_char();
  426.   while (c == ' ')
  427.     c = get_char();
  428.   for (int i = 0;; i++) {
  429.     if (i >= buf_size) {
  430.       if (buf_size == 0) {
  431.     buf_size = 16;
  432.     buf = new char[buf_size];
  433.       }
  434.       else {
  435.     char *old_buf = buf;
  436.     int old_size = buf_size;
  437.     buf_size *= 2;
  438.     buf = new char[buf_size];
  439.     memcpy(buf, old_buf, old_size);
  440.     a_delete old_buf;
  441.       }
  442.     }
  443.     if ((!is_long && (c == ' ' || c == '\n')) || c == EOF) {
  444.       buf[i] = '\0';
  445.       break;
  446.     }
  447.     if (is_long && c == '\n') {
  448.       current_lineno++;
  449.       c = get_char();
  450.       if (c == '+')
  451.     c = '\n';
  452.       else {
  453.     buf[i] = '\0';
  454.     break;
  455.       }
  456.     }  
  457.     buf[i] = c;
  458.     c = get_char();
  459.   }
  460.   if (c != EOF)
  461.     ungetc(c, current_file);
  462.   return buf;
  463. }
  464.  
  465. void skip_line()
  466. {
  467.   int c;
  468.   while ((c = get_char()) != EOF)
  469.     if (c == '\n') {
  470.       current_lineno++;
  471.       break;
  472.     }
  473. }
  474.  
  475.