Don't use .Xo/.Xc. Fix date format.
[netbsd-mini2440.git] / gnu / usr.bin / groff / etc / soelim.c
blob3e7dfd1cfb9251049db6c08102a50c2680bc175f
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.uucp)
5 This file is part of groff.
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.
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.
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. */
21 #include <stdio.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <stdlib.h>
26 #include "lib.h"
27 #include "errarg.h"
28 #include "error.h"
29 #include "stringclass.h"
31 int compatible_flag = 0;
33 extern int interpret_lf_args(const char *);
35 int do_file(const char *filename);
37 void usage()
39 fprintf(stderr, "usage: %s [ -vC ] [ files ]\n", program_name);
40 exit(1);
43 int main(int argc, char **argv)
45 program_name = argv[0];
46 int opt;
47 while ((opt = getopt(argc, argv, "vC")) != EOF)
48 switch (opt) {
49 case 'v':
51 extern const char *version_string;
52 fprintf(stderr, "GNU soelim version %s\n", version_string);
53 fflush(stderr);
54 break;
56 case 'C':
57 compatible_flag = 1;
58 break;
59 case '?':
60 usage();
61 break;
62 default:
63 assert(0);
65 int nbad = 0;
66 if (optind >= argc)
67 nbad += !do_file("-");
68 else
69 for (int i = optind; i < argc; i++)
70 nbad += !do_file(argv[i]);
71 if (ferror(stdout) || fflush(stdout) < 0)
72 fatal("output error");
73 exit(nbad != 0);
76 void set_location()
78 printf(".lf %d %s\n", current_lineno, current_filename);
81 void do_so(const char *line)
83 const char *p = line;
84 while (*p == ' ')
85 p++;
86 string filename;
87 int success = 1;
88 for (const char *q = p;
89 success && *q != '\0' && *q != '\n' && *q != ' ';
90 q++)
91 if (*q == '\\') {
92 switch (*++q) {
93 case 'e':
94 case '\\':
95 filename += '\\';
96 break;
97 case ' ':
98 filename += ' ';
99 break;
100 default:
101 success = 0;
102 break;
105 else
106 filename += char(*q);
107 if (success && filename.length() > 0) {
108 filename += '\0';
109 const char *fn = current_filename;
110 int ln = current_lineno;
111 current_lineno--;
112 if (do_file(filename.contents())) {
113 current_filename = fn;
114 current_lineno = ln;
115 set_location();
116 return;
118 current_lineno++;
120 fputs(".so", stdout);
121 fputs(line, stdout);
124 int do_file(const char *filename)
126 FILE *fp;
127 if (strcmp(filename, "-") == 0)
128 fp = stdin;
129 else {
130 errno = 0;
131 fp = fopen(filename, "r");
132 if (fp == 0) {
133 error("can't open `%1': %2", filename, strerror(errno));
134 return 0;
137 current_filename = filename;
138 current_lineno = 1;
139 set_location();
140 enum { START, MIDDLE, HAD_DOT, HAD_s, HAD_so, HAD_l, HAD_lf } state = START;
141 for (;;) {
142 int c = getc(fp);
143 if (c == EOF)
144 break;
145 switch (state) {
146 case START:
147 if (c == '.')
148 state = HAD_DOT;
149 else {
150 putchar(c);
151 if (c == '\n') {
152 current_lineno++;
153 state = START;
155 else
156 state = MIDDLE;
158 break;
159 case MIDDLE:
160 putchar(c);
161 if (c == '\n') {
162 current_lineno++;
163 state = START;
165 break;
166 case HAD_DOT:
167 if (c == 's')
168 state = HAD_s;
169 else if (c == 'l')
170 state = HAD_l;
171 else {
172 putchar('.');
173 putchar(c);
174 if (c == '\n') {
175 current_lineno++;
176 state = START;
178 else
179 state = MIDDLE;
181 break;
182 case HAD_s:
183 if (c == 'o')
184 state = HAD_so;
185 else {
186 putchar('.');
187 putchar('s');
188 putchar(c);
189 if (c == '\n') {
190 current_lineno++;
191 state = START;
193 else
194 state = MIDDLE;
196 break;
197 case HAD_so:
198 if (c == ' ' || c == '\n' || compatible_flag) {
199 string line;
200 for (; c != EOF && c != '\n'; c = getc(fp))
201 line += c;
202 current_lineno++;
203 line += '\n';
204 line += '\0';
205 do_so(line.contents());
206 state = START;
208 else {
209 fputs(".so", stdout);
210 putchar(c);
211 state = MIDDLE;
213 break;
214 case HAD_l:
215 if (c == 'f')
216 state = HAD_lf;
217 else {
218 putchar('.');
219 putchar('l');
220 putchar(c);
221 if (c == '\n') {
222 current_lineno++;
223 state = START;
225 else
226 state = MIDDLE;
228 break;
229 case HAD_lf:
230 if (c == ' ' || c == '\n' || compatible_flag) {
231 string line;
232 for (; c != EOF && c != '\n'; c = getc(fp))
233 line += c;
234 current_lineno++;
235 line += '\n';
236 line += '\0';
237 interpret_lf_args(line.contents());
238 printf(".lf%s", line.contents());
239 state = START;
241 else {
242 fputs(".lf", stdout);
243 putchar(c);
244 state = MIDDLE;
246 break;
247 default:
248 assert(0);
251 switch (state) {
252 case HAD_DOT:
253 fputs(".\n", stdout);
254 break;
255 case HAD_l:
256 fputs(".l\n", stdout);
257 break;
258 case HAD_s:
259 fputs(".s\n", stdout);
260 break;
261 case HAD_lf:
262 fputs(".lf\n", stdout);
263 break;
264 case HAD_so:
265 fputs(".so\n", stdout);
266 break;
267 case MIDDLE:
268 putc('\n', stdout);
269 break;
270 case START:
271 break;
273 if (fp != stdin)
274 fclose(fp);
275 current_filename = 0;
276 return 1;