"program" maps can be used for aliases
[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>
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
32int compatible_flag = 0;
33
34extern int interpret_lf_args(const char *);
35
36int do_file(const char *filename);
37
38void usage()
39{
40 fprintf(stderr, "usage: %s [ -vC ] [ files ]\n", program_name);
41 exit(1);
42}
43
44int 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 exit(nbad != 0);
75}
76
77void set_location()
78{
79 printf(".lf %d %s\n", current_lineno, current_filename);
80}
81
82void 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
125int 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}