Sync usage with man page.
[netbsd-mini2440.git] / gnu / dist / groff / src / preproc / soelim / soelim.cpp
blobc507da49fe614fd274b7e4ffb3c4772096fc0c98
1 /* $NetBSD$ */
3 // -*- C++ -*-
4 /* Copyright (C) 1989-1992, 2000, 2001, 2003, 2004, 2005
5 Free Software Foundation, Inc.
6 Written by James Clark (jjc@jclark.com)
8 This file is part of groff.
10 groff is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 2, or (at your option) any later
13 version.
15 groff is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License along
21 with groff; see the file COPYING. If not, write to the Free Software
22 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
24 #include "lib.h"
26 #include <ctype.h>
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include "errarg.h"
31 #include "error.h"
32 #include "stringclass.h"
33 #include "nonposix.h"
34 #include "searchpath.h"
36 // The include search path initially contains only the current directory.
37 static search_path include_search_path(0, 0, 0, 1);
39 int compatible_flag = 0;
40 int raw_flag = 0;
41 int tex_flag = 0;
43 extern "C" const char *Version_string;
45 int do_file(const char *filename);
48 void usage(FILE *stream)
50 fprintf(stream, "usage: %s [ -Crtv ] [ -I file ] [ files ]\n", program_name);
53 int main(int argc, char **argv)
55 program_name = argv[0];
56 int opt;
57 static const struct option long_options[] = {
58 { "help", no_argument, 0, CHAR_MAX + 1 },
59 { "version", no_argument, 0, 'v' },
60 { NULL, 0, 0, 0 }
62 while ((opt = getopt_long(argc, argv, "CI:rtv", long_options, NULL)) != EOF)
63 switch (opt) {
64 case 'v':
66 printf("GNU soelim (groff) version %s\n", Version_string);
67 exit(0);
68 break;
70 case 'C':
71 compatible_flag = 1;
72 break;
73 case 'I':
74 include_search_path.command_line_dir(optarg);
75 break;
76 case 'r':
77 raw_flag = 1;
78 break;
79 case 't':
80 tex_flag = 1;
81 break;
82 case CHAR_MAX + 1: // --help
83 usage(stdout);
84 exit(0);
85 break;
86 case '?':
87 usage(stderr);
88 exit(1);
89 break;
90 default:
91 assert(0);
93 int nbad = 0;
94 if (optind >= argc)
95 nbad += !do_file("-");
96 else
97 for (int i = optind; i < argc; i++)
98 nbad += !do_file(argv[i]);
99 if (ferror(stdout) || fflush(stdout) < 0)
100 fatal("output error");
101 return nbad != 0;
104 void set_location()
106 if(!raw_flag) {
107 if(!tex_flag)
108 printf(".lf %d %s\n", current_lineno, current_filename);
109 else
110 printf("%% file %s, line %d\n", current_filename, current_lineno);
114 void do_so(const char *line)
116 const char *p = line;
117 while (*p == ' ')
118 p++;
119 string filename;
120 int success = 1;
121 for (const char *q = p;
122 success && *q != '\0' && *q != '\n' && *q != ' ';
123 q++)
124 if (*q == '\\') {
125 switch (*++q) {
126 case 'e':
127 case '\\':
128 filename += '\\';
129 break;
130 case ' ':
131 filename += ' ';
132 break;
133 default:
134 success = 0;
135 break;
138 else
139 filename += char(*q);
140 if (success && filename.length() > 0) {
141 filename += '\0';
142 const char *fn = current_filename;
143 int ln = current_lineno;
144 current_lineno--;
145 if (do_file(filename.contents())) {
146 current_filename = fn;
147 current_lineno = ln;
148 set_location();
149 return;
151 current_lineno++;
153 fputs(".so", stdout);
154 fputs(line, stdout);
157 int do_file(const char *filename)
159 char *file_name_in_path = 0;
160 FILE *fp = include_search_path.open_file_cautious(filename,
161 &file_name_in_path);
162 int err = errno;
163 string whole_filename(file_name_in_path ? file_name_in_path : filename);
164 whole_filename += '\0';
165 a_delete file_name_in_path;
166 if (fp == 0) {
167 error("can't open `%1': %2", whole_filename.contents(), strerror(err));
168 return 0;
170 current_filename = whole_filename.contents();
171 current_lineno = 1;
172 set_location();
173 enum { START, MIDDLE, HAD_DOT, HAD_s, HAD_so, HAD_l, HAD_lf } state = START;
174 for (;;) {
175 int c = getc(fp);
176 if (c == EOF)
177 break;
178 switch (state) {
179 case START:
180 if (c == '.')
181 state = HAD_DOT;
182 else {
183 putchar(c);
184 if (c == '\n') {
185 current_lineno++;
186 state = START;
188 else
189 state = MIDDLE;
191 break;
192 case MIDDLE:
193 putchar(c);
194 if (c == '\n') {
195 current_lineno++;
196 state = START;
198 break;
199 case HAD_DOT:
200 if (c == 's')
201 state = HAD_s;
202 else if (c == 'l')
203 state = HAD_l;
204 else {
205 putchar('.');
206 putchar(c);
207 if (c == '\n') {
208 current_lineno++;
209 state = START;
211 else
212 state = MIDDLE;
214 break;
215 case HAD_s:
216 if (c == 'o')
217 state = HAD_so;
218 else {
219 putchar('.');
220 putchar('s');
221 putchar(c);
222 if (c == '\n') {
223 current_lineno++;
224 state = START;
226 else
227 state = MIDDLE;
229 break;
230 case HAD_so:
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 do_so(line.contents());
239 state = START;
241 else {
242 fputs(".so", stdout);
243 putchar(c);
244 state = MIDDLE;
246 break;
247 case HAD_l:
248 if (c == 'f')
249 state = HAD_lf;
250 else {
251 putchar('.');
252 putchar('l');
253 putchar(c);
254 if (c == '\n') {
255 current_lineno++;
256 state = START;
258 else
259 state = MIDDLE;
261 break;
262 case HAD_lf:
263 if (c == ' ' || c == '\n' || compatible_flag) {
264 string line;
265 for (; c != EOF && c != '\n'; c = getc(fp))
266 line += c;
267 current_lineno++;
268 line += '\n';
269 line += '\0';
270 interpret_lf_args(line.contents());
271 printf(".lf%s", line.contents());
272 state = START;
274 else {
275 fputs(".lf", stdout);
276 putchar(c);
277 state = MIDDLE;
279 break;
280 default:
281 assert(0);
284 switch (state) {
285 case HAD_DOT:
286 fputs(".\n", stdout);
287 break;
288 case HAD_l:
289 fputs(".l\n", stdout);
290 break;
291 case HAD_s:
292 fputs(".s\n", stdout);
293 break;
294 case HAD_lf:
295 fputs(".lf\n", stdout);
296 break;
297 case HAD_so:
298 fputs(".so\n", stdout);
299 break;
300 case MIDDLE:
301 putc('\n', stdout);
302 break;
303 case START:
304 break;
306 if (fp != stdin)
307 fclose(fp);
308 current_filename = 0;
309 return 1;