home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / util / gnu / groff_src.lha / groff-1.10src / soelim / soelim.cc < prev    next >
C/C++ Source or Header  |  1995-06-22  |  5KB  |  279 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 <stdio.h>
  22. #include <ctype.h>
  23. #include <string.h>
  24. #include <assert.h>
  25. #include <stdlib.h>
  26. #include <errno.h>
  27. #include "lib.h"
  28. #include "errarg.h"
  29. #include "error.h"
  30. #include "stringclass.h"
  31.  
  32. int compatible_flag = 0;
  33.  
  34. extern int interpret_lf_args(const char *);
  35.  
  36. int do_file(const char *filename);
  37.  
  38. void usage()
  39. {
  40.   fprintf(stderr, "usage: %s [ -vC ] [ files ]\n", program_name);
  41.   exit(1);
  42. }
  43.  
  44. int main(int argc, char **argv)
  45. {
  46.   program_name = argv[0];
  47.   int opt;
  48.   while ((opt = getopt(argc, argv, "vC")) != EOF)
  49.     switch (opt) {
  50.     case 'v':
  51.       {
  52.     extern const char *version_string;
  53.     fprintf(stderr, "GNU soelim version %s\n", version_string);
  54.     fflush(stderr);
  55.     break;
  56.       }
  57.     case 'C':
  58.       compatible_flag = 1;
  59.       break;
  60.     case '?':
  61.       usage();
  62.       break;
  63.     default:
  64.       assert(0);
  65.     }
  66.   int nbad = 0;
  67.   if (optind >= argc)
  68.     nbad += !do_file("-");
  69.   else
  70.     for (int i = optind; i < argc; i++)
  71.       nbad += !do_file(argv[i]);
  72.   if (ferror(stdout) || fflush(stdout) < 0)
  73.     fatal("output error");
  74.   return nbad != 0;
  75. }
  76.  
  77. void set_location()
  78. {
  79.   printf(".lf %d %s\n", current_lineno, current_filename);
  80. }
  81.  
  82. void do_so(const char *line)
  83. {
  84.   const char *p = line;
  85.   while (*p == ' ')
  86.     p++;
  87.   string filename;
  88.   int success = 1;
  89.   for (const char *q = p;
  90.        success && *q != '\0' && *q != '\n' && *q != ' ';
  91.        q++)
  92.     if (*q == '\\') {
  93.       switch (*++q) {
  94.       case 'e':
  95.       case '\\':
  96.     filename += '\\';
  97.     break;
  98.       case ' ':
  99.     filename += ' ';
  100.     break;
  101.       default:
  102.     success = 0;
  103.     break;
  104.       }
  105.     }
  106.     else
  107.       filename += char(*q);
  108.   if (success && filename.length() > 0) {
  109.     filename += '\0';
  110.     const char *fn = current_filename;
  111.     int ln = current_lineno;
  112.     current_lineno--;
  113.     if (do_file(filename.contents())) {
  114.       current_filename = fn;
  115.       current_lineno = ln;
  116.       set_location();
  117.       return;
  118.     }
  119.     current_lineno++;
  120.   }
  121.   fputs(".so", stdout);
  122.   fputs(line, stdout);
  123. }
  124.  
  125. int do_file(const char *filename)
  126. {
  127.   FILE *fp;
  128.   if (strcmp(filename, "-") == 0)
  129.     fp = stdin;
  130.   else {
  131.     errno = 0;
  132.     fp = fopen(filename, "r");
  133.     if (fp == 0) {
  134.       error("can't open `%1': %2", filename, strerror(errno));
  135.       return 0;
  136.     }
  137.   }
  138.   current_filename = filename;
  139.   current_lineno = 1;
  140.   set_location();
  141.   enum { START, MIDDLE, HAD_DOT, HAD_s, HAD_so, HAD_l, HAD_lf } state = START;
  142.   for (;;) {
  143.     int c = getc(fp);
  144.     if (c == EOF)
  145.       break;
  146.     switch (state) {
  147.     case START:
  148.       if (c == '.')
  149.     state = HAD_DOT;
  150.       else {
  151.     putchar(c);
  152.     if (c == '\n') {
  153.       current_lineno++;
  154.       state = START;
  155.     }
  156.     else
  157.       state = MIDDLE;
  158.       }
  159.       break;
  160.     case MIDDLE:
  161.       putchar(c);
  162.       if (c == '\n') {
  163.     current_lineno++;
  164.     state = START;
  165.       }
  166.       break;
  167.     case HAD_DOT:
  168.       if (c == 's')
  169.     state = HAD_s;
  170.       else if (c == 'l')
  171.     state = HAD_l;
  172.       else {
  173.     putchar('.');
  174.     putchar(c);
  175.     if (c == '\n') {
  176.       current_lineno++;
  177.       state = START;
  178.     }
  179.     else
  180.       state = MIDDLE;
  181.       }
  182.       break;
  183.     case HAD_s:
  184.       if (c == 'o')
  185.     state = HAD_so;
  186.       else  {
  187.     putchar('.');
  188.     putchar('s');
  189.     putchar(c);
  190.     if (c == '\n') {
  191.       current_lineno++;
  192.       state = START;
  193.     }
  194.     else
  195.       state = MIDDLE;
  196.       }
  197.       break;
  198.     case HAD_so:
  199.       if (c == ' ' || c == '\n' || compatible_flag) {
  200.     string line;
  201.     for (; c != EOF && c != '\n'; c = getc(fp))
  202.       line += c;
  203.     current_lineno++;
  204.     line += '\n';
  205.     line += '\0';
  206.     do_so(line.contents());
  207.     state = START;
  208.       }
  209.       else {
  210.     fputs(".so", stdout);
  211.     putchar(c);
  212.     state = MIDDLE;
  213.       }
  214.       break;
  215.     case HAD_l:
  216.       if (c == 'f')
  217.     state = HAD_lf;
  218.       else {
  219.     putchar('.');
  220.     putchar('l');
  221.     putchar(c);
  222.     if (c == '\n') {
  223.       current_lineno++;
  224.       state = START;
  225.     }
  226.     else
  227.       state = MIDDLE;
  228.       }
  229.       break;
  230.     case HAD_lf:
  231.       if (c == ' ' || c == '\n' || compatible_flag) {
  232.     string line;
  233.     for (; c != EOF && c != '\n'; c = getc(fp))
  234.       line += c;
  235.     current_lineno++;
  236.     line += '\n';
  237.     line += '\0';
  238.     interpret_lf_args(line.contents());
  239.     printf(".lf%s", line.contents());
  240.     state = START;
  241.       }
  242.       else {
  243.     fputs(".lf", stdout);
  244.     putchar(c);
  245.     state = MIDDLE;
  246.       }
  247.       break;
  248.     default:
  249.       assert(0);
  250.     }
  251.   }
  252.   switch (state) {
  253.   case HAD_DOT:
  254.     fputs(".\n", stdout);
  255.     break;
  256.   case HAD_l:
  257.     fputs(".l\n", stdout);
  258.     break;
  259.   case HAD_s:
  260.     fputs(".s\n", stdout);
  261.     break;
  262.   case HAD_lf:
  263.     fputs(".lf\n", stdout);
  264.     break;
  265.   case HAD_so:
  266.     fputs(".so\n", stdout);
  267.     break;
  268.   case MIDDLE:
  269.     putc('\n', stdout);
  270.     break;
  271.   case START:
  272.     break;
  273.   }
  274.   if (fp != stdin)
  275.     fclose(fp);
  276.   current_filename = 0;
  277.   return 1;
  278. }
  279.