Remove crufty CVS $Id$ tags.
[fwd] / scan.c
CommitLineData
e82f7154 1/* -*-c-*-
2 *
e82f7154 3 * Character scanners
4 *
77d0e3dc 5 * (c) 1999 Straylight/Edgeware
e82f7154 6 */
7
8/*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of the `fw' port forwarder.
11 *
12 * `fw' is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * `fw' is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with `fw'; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
e82f7154 27/*----- Header files ------------------------------------------------------*/
28
e82f7154 29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include <mLib/dstr.h>
77d0e3dc 34#include <mLib/sub.h>
e82f7154 35
36#include "scan.h"
37
77d0e3dc 38/*----- File scanner source -----------------------------------------------*/
39
40/* --- File scanner block --- */
41
42typedef struct fscan {
43 scansrc ss;
44 FILE *fp;
45 unsigned f;
46} fscan;
e82f7154 47
77d0e3dc 48/* --- @scan@ --- */
e82f7154 49
77d0e3dc 50static int fscan_scan(scansrc *ss)
e82f7154 51{
77d0e3dc 52 fscan *fs = (fscan *)ss;
53 int ch = getc(fs->fp);
54 if (ch == '\n')
55 fs->ss.line++;
56 return (ch);
e82f7154 57}
58
77d0e3dc 59/* --- @destroy@ --- */
e82f7154 60
77d0e3dc 61static void fscan_destroy(scansrc *ss)
e82f7154 62{
77d0e3dc 63 fscan *fs = (fscan *)ss;
64 if (!(fs->f & SCF_NOCLOSE))
65 fclose(fs->fp);
7bb7c50b 66 xfree(fs->ss.src);
77d0e3dc 67 DESTROY(fs);
68}
e82f7154 69
77d0e3dc 70/* --- File scanner operations --- */
71
72static scansrc_ops fscan_ops = { fscan_scan, fscan_destroy };
73
74/* --- @scan_file@ --- *
75 *
76 * Arguments: @FILE *fp@ = pointer to file descriptor
7bb7c50b 77 * @const char *name@ = pointer to source file name
77d0e3dc 78 * @unsigned f@ = flags
79 *
80 * Returns: A scanner source.
81 *
82 * Use: Creates a new scanner source for reading from a file.
83 */
84
7bb7c50b 85scansrc *scan_file(FILE *fp, const char *name, unsigned f)
77d0e3dc 86{
372a98e2 87 fscan *fs = CREATE(fscan);
77d0e3dc 88 fs->ss.ops = &fscan_ops;
7bb7c50b 89 fs->ss.src = xstrdup(name);
77d0e3dc 90 fs->ss.line = 1;
91 fs->fp = fp;
92 fs->f = f;
93 return (&fs->ss);
94}
95
96/*---- Argv scanner source ------------------------------------------------*/
97
98/* --- Argv scanner block --- */
99
100typedef struct avscan {
101 scansrc ss;
102 char **av;
103 char *p;
104} avscan;
105
106/* --- @scan@ --- */
e82f7154 107
77d0e3dc 108static int avscan_scan(scansrc *ss)
109{
110 avscan *as = (avscan *)ss;
111 int ch;
112 if (!as->p)
113 ch = EOF;
9e1c09df 114 else if ((ch = (unsigned char)*as->p++) == 0) {
77d0e3dc 115 as->ss.line++;
116 as->p = *as->av++;
117 ch = '\n';
118 }
e82f7154 119 return (ch);
120}
121
77d0e3dc 122/* --- @destroy@ --- */
123
124static void avscan_destroy(scansrc *ss)
e82f7154 125{
77d0e3dc 126 avscan *as = (avscan *)ss;
127 DESTROY(as);
e82f7154 128}
129
77d0e3dc 130/* --- Argv scanner operations --- */
131
132static scansrc_ops avscan_ops = { avscan_scan, avscan_destroy };
133
134/* --- @scan_argv@ --- *
135 *
136 * Arguments: @char **av@ = pointer to argument array (null terminated)
137 *
138 * Returns: A scanner source.
139 *
140 * Use: Creates a new scanner source for reading from an @argv@
141 * array.
142 */
143
144scansrc *scan_argv(char **av)
e82f7154 145{
77d0e3dc 146 avscan *as = CREATE(avscan);
147 as->ss.ops = &avscan_ops;
148 as->ss.src = "<argv>";
149 as->ss.line = 1;
150 as->p = *av++;
151 as->av = av;
152 return (&as->ss);
e82f7154 153}
154
77d0e3dc 155/*----- End-of-file sentinel block ----------------------------------------*/
156
157/* --- @scan@ --- */
e82f7154 158
77d0e3dc 159static int eof_scan(scansrc *ss)
e82f7154 160{
77d0e3dc 161 return (EOF);
e82f7154 162}
163
77d0e3dc 164/* --- @destroy@ --- */
165
166static void eof_destroy(scansrc *ss)
e82f7154 167{
77d0e3dc 168 ;
e82f7154 169}
170
77d0e3dc 171/* --- Eof scanner operations --- */
172
173static scansrc_ops eof_ops = { eof_scan, eof_destroy };
174
175/* --- The end of file marker --- */
176
7bb7c50b 177static scansrc scan_eof = { &scan_eof, &eof_ops, "<eof>", 0, DSTR_INIT };
77d0e3dc 178
179/*----- General scanner handling ------------------------------------------*/
180
181/* --- @scan@ --- *
182 *
183 * Arguments: @scanner *sc@ = pointer to main scanner context
184 *
185 * Returns: Character read, or end-of-file.
186 *
187 * Use: Scans a character from a source of characters.
188 */
189
190int scan(scanner *sc)
191{
192 int ch;
7bb7c50b 193 if (sc->head->pushback.len)
194 ch = sc->head->pushback.buf[--sc->head->pushback.len];
195 else {
77d0e3dc 196 scansrc *ss = sc->head;
197 if (ss == &scan_eof)
198 ch = EOF;
199 else if ((ch = ss->ops->scan(ss)) == EOF) {
200 sc->head = ss->next;
201 if (sc->head == &scan_eof)
202 sc->tail = &sc->head;
203 ss->ops->destroy(ss);
204 ch = '\n';
205 }
206 }
207 return (ch);
208}
209
210/* --- @unscan@ --- *
211 *
212 * Arguments: @scanner *sc@ = pointer to main scanner context
213 * @int ch@ = character to unscan
214 *
215 * Returns: ---
216 *
217 * Use: Scans a character from a source of characters.
218 */
219
220void unscan(scanner *sc, int ch)
221{
7bb7c50b 222 DPUTC(&sc->head->pushback, ch);
77d0e3dc 223}
224
225/* --- @scan_push@ --- *
226 *
227 * Arguments: @scanner *sc@ = pointer to main scanner context
228 * @scansrc *ss@ = souorce to push
229 *
230 * Returns: ---
231 *
232 * Use: Pushes a scanner source onto the front of the queue.
233 */
234
235void scan_push(scanner *sc, scansrc *ss)
e82f7154 236{
77d0e3dc 237 ss->next = sc->head;
238 if (sc->head == &scan_eof)
239 sc->tail = &ss->next;
240 sc->head = ss;
7bb7c50b 241 dstr_create(&ss->pushback);
77d0e3dc 242 ss->tok = 0;
243 ss->t = 0;
e82f7154 244}
245
77d0e3dc 246/* --- @scan_add@ --- *
247 *
248 * Arguments: @scanner *sc@ = pointer to main scanner context
249 * @scansrc *ss@ = souorce to push
250 *
251 * Returns: ---
252 *
253 * Use: Adds a scanner source onto the end of the queue.
254 */
255
256void scan_add(scanner *sc, scansrc *ss)
257{
258 ss->next = &scan_eof;
259 *sc->tail = ss;
260 sc->tail = &ss->next;
7bb7c50b 261 dstr_create(&ss->pushback);
77d0e3dc 262 ss->tok = 0;
263 ss->t = 0;
264}
265
266/* --- @scan_create@ --- *
267 *
268 * Arguments: @scanner *sc@ = scanner context to initialize
269 *
270 * Returns: ---
271 *
272 * Use: Initializes a scanner block ready for use.
273 */
274
275void scan_create(scanner *sc)
276{
277 sc->head = &scan_eof;
278 sc->tail = &sc->head;
279 dstr_create(&sc->d);
e91b672f 280 sc->wbegin = sc->wcont = 0;
77d0e3dc 281}
282
283/* --- @scan_destroy@ --- *
284 *
285 * Arguments: @scanner *sc@ = pointer to scanner context
286 *
287 * Returns: ---
288 *
289 * Use: Destroys a scanner and all the sources attached to it.
290 */
e82f7154 291
77d0e3dc 292void scan_destroy(scanner *sc)
e82f7154 293{
77d0e3dc 294 scansrc *ss = sc->head;
295 while (ss != &scan_eof) {
296 scansrc *sss = ss;
297 ss = ss->next;
298 if (sss->tok)
7bb7c50b 299 xfree(sss->tok);
300 dstr_destroy(&sss->pushback);
77d0e3dc 301 sss->ops->destroy(sss);
302 }
e82f7154 303 dstr_destroy(&sc->d);
77d0e3dc 304 if (scan_eof.tok)
7bb7c50b 305 xfree(scan_eof.tok);
77d0e3dc 306 scan_eof.tok = 0;
307 sc->head = &scan_eof;
308 sc->tail = &sc->head;
e82f7154 309}
310
311/*----- That's all, folks -------------------------------------------------*/