unistd.h for optarg
[unix-history] / usr / src / contrib / groff-1.08 / soelim / soelim.cc
CommitLineData
72ea2dfc
KB
1// -*- C++ -*-
2/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
4
5This file is part of groff.
6
7groff is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12groff is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License along
18with groff; see the file COPYING. If not, write to the Free Software
19Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21#include <stdio.h>
99c873a3 22#include <unistd.h>
72ea2dfc
KB
23#include <ctype.h>
24#include <string.h>
25#include <assert.h>
26#include <stdlib.h>
27#include <errno.h>
28#include "lib.h"
29#include "errarg.h"
30#include "error.h"
31#include "stringclass.h"
32
33int compatible_flag = 0;
34
35extern int interpret_lf_args(const char *);
36
37int do_file(const char *filename);
38
39void usage()
40{
41 fprintf(stderr, "usage: %s [ -vC ] [ files ]\n", program_name);
42 exit(1);
43}
44
45int main(int argc, char **argv)
46{
47 program_name = argv[0];
48 int opt;
49 while ((opt = getopt(argc, argv, "vC")) != EOF)
50 switch (opt) {
51 case 'v':
52 {
53 extern const char *version_string;
54 fprintf(stderr, "GNU soelim version %s\n", version_string);
55 fflush(stderr);
56 break;
57 }
58 case 'C':
59 compatible_flag = 1;
60 break;
61 case '?':
62 usage();
63 break;
64 default:
65 assert(0);
66 }
67 int nbad = 0;
68 if (optind >= argc)
69 nbad += !do_file("-");
70 else
71 for (int i = optind; i < argc; i++)
72 nbad += !do_file(argv[i]);
73 if (ferror(stdout) || fflush(stdout) < 0)
74 fatal("output error");
75 exit(nbad != 0);
76}
77
78void set_location()
79{
80 printf(".lf %d %s\n", current_lineno, current_filename);
81}
82
83void do_so(const char *line)
84{
85 const char *p = line;
86 while (*p == ' ')
87 p++;
88 string filename;
89 int success = 1;
90 for (const char *q = p;
91 success && *q != '\0' && *q != '\n' && *q != ' ';
92 q++)
93 if (*q == '\\') {
94 switch (*++q) {
95 case 'e':
96 case '\\':
97 filename += '\\';
98 break;
99 case ' ':
100 filename += ' ';
101 break;
102 default:
103 success = 0;
104 break;
105 }
106 }
107 else
108 filename += char(*q);
109 if (success && filename.length() > 0) {
110 filename += '\0';
111 const char *fn = current_filename;
112 int ln = current_lineno;
113 current_lineno--;
114 if (do_file(filename.contents())) {
115 current_filename = fn;
116 current_lineno = ln;
117 set_location();
118 return;
119 }
120 current_lineno++;
121 }
122 fputs(".so", stdout);
123 fputs(line, stdout);
124}
125
126int do_file(const char *filename)
127{
128 FILE *fp;
129 if (strcmp(filename, "-") == 0)
130 fp = stdin;
131 else {
132 errno = 0;
133 fp = fopen(filename, "r");
134 if (fp == 0) {
135 error("can't open `%1': %2", filename, strerror(errno));
136 return 0;
137 }
138 }
139 current_filename = filename;
140 current_lineno = 1;
141 set_location();
142 enum { START, MIDDLE, HAD_DOT, HAD_s, HAD_so, HAD_l, HAD_lf } state = START;
143 for (;;) {
144 int c = getc(fp);
145 if (c == EOF)
146 break;
147 switch (state) {
148 case START:
149 if (c == '.')
150 state = HAD_DOT;
151 else {
152 putchar(c);
153 if (c == '\n') {
154 current_lineno++;
155 state = START;
156 }
157 else
158 state = MIDDLE;
159 }
160 break;
161 case MIDDLE:
162 putchar(c);
163 if (c == '\n') {
164 current_lineno++;
165 state = START;
166 }
167 break;
168 case HAD_DOT:
169 if (c == 's')
170 state = HAD_s;
171 else if (c == 'l')
172 state = HAD_l;
173 else {
174 putchar('.');
175 putchar(c);
176 if (c == '\n') {
177 current_lineno++;
178 state = START;
179 }
180 else
181 state = MIDDLE;
182 }
183 break;
184 case HAD_s:
185 if (c == 'o')
186 state = HAD_so;
187 else {
188 putchar('.');
189 putchar('s');
190 putchar(c);
191 if (c == '\n') {
192 current_lineno++;
193 state = START;
194 }
195 else
196 state = MIDDLE;
197 }
198 break;
199 case HAD_so:
200 if (c == ' ' || c == '\n' || compatible_flag) {
201 string line;
202 for (; c != EOF && c != '\n'; c = getc(fp))
203 line += c;
204 current_lineno++;
205 line += '\n';
206 line += '\0';
207 do_so(line.contents());
208 state = START;
209 }
210 else {
211 fputs(".so", stdout);
212 putchar(c);
213 state = MIDDLE;
214 }
215 break;
216 case HAD_l:
217 if (c == 'f')
218 state = HAD_lf;
219 else {
220 putchar('.');
221 putchar('l');
222 putchar(c);
223 if (c == '\n') {
224 current_lineno++;
225 state = START;
226 }
227 else
228 state = MIDDLE;
229 }
230 break;
231 case HAD_lf:
232 if (c == ' ' || c == '\n' || compatible_flag) {
233 string line;
234 for (; c != EOF && c != '\n'; c = getc(fp))
235 line += c;
236 current_lineno++;
237 line += '\n';
238 line += '\0';
239 interpret_lf_args(line.contents());
240 printf(".lf%s", line.contents());
241 state = START;
242 }
243 else {
244 fputs(".lf", stdout);
245 putchar(c);
246 state = MIDDLE;
247 }
248 break;
249 default:
250 assert(0);
251 }
252 }
253 switch (state) {
254 case HAD_DOT:
255 fputs(".\n", stdout);
256 break;
257 case HAD_l:
258 fputs(".l\n", stdout);
259 break;
260 case HAD_s:
261 fputs(".s\n", stdout);
262 break;
263 case HAD_lf:
264 fputs(".lf\n", stdout);
265 break;
266 case HAD_so:
267 fputs(".so\n", stdout);
268 break;
269 case MIDDLE:
270 putc('\n', stdout);
271 break;
272 case START:
273 break;
274 }
275 if (fp != stdin)
276 fclose(fp);
277 current_filename = 0;
278 return 1;
279}