5 * (c) 1999 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the `fw' port forwarder.
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.
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.
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.
29 /*----- File scanner source -----------------------------------------------*/
31 /* --- File scanner block --- */
33 typedef struct fscan {
41 static int fscan_scan(scansrc *ss)
43 fscan *fs = (fscan *)ss;
44 int ch = getc(fs->fp);
50 /* --- @destroy@ --- */
52 static void fscan_destroy(scansrc *ss)
54 fscan *fs = (fscan *)ss;
55 if (!(fs->f & SCF_NOCLOSE))
61 /* --- File scanner operations --- */
63 static scansrc_ops fscan_ops = { fscan_scan, fscan_destroy };
65 /* --- @scan_file@ --- *
67 * Arguments: @FILE *fp@ = pointer to file descriptor
68 * @const char *name@ = pointer to source file name
69 * @unsigned f@ = flags
71 * Returns: A scanner source.
73 * Use: Creates a new scanner source for reading from a file.
76 scansrc *scan_file(FILE *fp, const char *name, unsigned f)
78 fscan *fs = CREATE(fscan);
79 fs->ss.ops = &fscan_ops;
80 fs->ss.src = xstrdup(name);
87 /*---- Argv scanner source ------------------------------------------------*/
89 /* --- Argv scanner block --- */
91 typedef struct avscan {
99 static int avscan_scan(scansrc *ss)
101 avscan *as = (avscan *)ss;
105 else if ((ch = (unsigned char)*as->p++) == 0) {
113 /* --- @destroy@ --- */
115 static void avscan_destroy(scansrc *ss)
117 avscan *as = (avscan *)ss;
121 /* --- Argv scanner operations --- */
123 static scansrc_ops avscan_ops = { avscan_scan, avscan_destroy };
125 /* --- @scan_argv@ --- *
127 * Arguments: @char **av@ = pointer to argument array (null terminated)
129 * Returns: A scanner source.
131 * Use: Creates a new scanner source for reading from an @argv@
135 scansrc *scan_argv(char **av)
137 avscan *as = CREATE(avscan);
138 as->ss.ops = &avscan_ops;
139 as->ss.src = "<argv>";
146 /*----- End-of-file sentinel block ----------------------------------------*/
150 static int eof_scan(scansrc *ss)
155 /* --- @destroy@ --- */
157 static void eof_destroy(scansrc *ss)
162 /* --- Eof scanner operations --- */
164 static scansrc_ops eof_ops = { eof_scan, eof_destroy };
166 /* --- The end of file marker --- */
168 static scansrc scan_eof = { &scan_eof, &eof_ops, "<eof>", 0, DSTR_INIT };
170 /*----- General scanner handling ------------------------------------------*/
174 * Arguments: @scanner *sc@ = pointer to main scanner context
176 * Returns: Character read, or end-of-file.
178 * Use: Scans a character from a source of characters.
181 int scan(scanner *sc)
184 if (sc->head->pushback.len)
185 ch = sc->head->pushback.buf[--sc->head->pushback.len];
187 scansrc *ss = sc->head;
190 else if ((ch = ss->ops->scan(ss)) == EOF) {
192 if (sc->head == &scan_eof)
193 sc->tail = &sc->head;
194 ss->ops->destroy(ss);
201 /* --- @unscan@ --- *
203 * Arguments: @scanner *sc@ = pointer to main scanner context
204 * @int ch@ = character to unscan
208 * Use: Scans a character from a source of characters.
211 void unscan(scanner *sc, int ch)
213 DPUTC(&sc->head->pushback, ch);
216 /* --- @scan_push@ --- *
218 * Arguments: @scanner *sc@ = pointer to main scanner context
219 * @scansrc *ss@ = souorce to push
223 * Use: Pushes a scanner source onto the front of the queue.
226 void scan_push(scanner *sc, scansrc *ss)
229 if (sc->head == &scan_eof)
230 sc->tail = &ss->next;
232 dstr_create(&ss->pushback);
237 /* --- @scan_add@ --- *
239 * Arguments: @scanner *sc@ = pointer to main scanner context
240 * @scansrc *ss@ = souorce to push
244 * Use: Adds a scanner source onto the end of the queue.
247 void scan_add(scanner *sc, scansrc *ss)
249 ss->next = &scan_eof;
251 sc->tail = &ss->next;
252 dstr_create(&ss->pushback);
257 /* --- @scan_create@ --- *
259 * Arguments: @scanner *sc@ = scanner context to initialize
263 * Use: Initializes a scanner block ready for use.
266 void scan_create(scanner *sc)
268 sc->head = &scan_eof;
269 sc->tail = &sc->head;
271 sc->wbegin = sc->wcont = 0;
274 /* --- @scan_destroy@ --- *
276 * Arguments: @scanner *sc@ = pointer to scanner context
280 * Use: Destroys a scanner and all the sources attached to it.
283 void scan_destroy(scanner *sc)
285 scansrc *ss = sc->head;
286 while (ss != &scan_eof) {
291 dstr_destroy(&sss->pushback);
292 sss->ops->destroy(sss);
294 dstr_destroy(&sc->d);
298 sc->head = &scan_eof;
299 sc->tail = &sc->head;
302 /*----- That's all, folks -------------------------------------------------*/