]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/groff/soelim/soelim.cc
Virgin import of FSF groff v1.10
[FreeBSD/FreeBSD.git] / contrib / groff / soelim / soelim.cc
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 }