process.c - enscript - GNU Enscript
(HTM) git clone git://thinkerwim.org/enscript.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
process.c (7374B)
---
1 /*
2 * Process input according to the specified rules.
3 * Copyright (c) 1997-1999 Markku Rossi.
4 *
5 * Author: Markku Rossi <mtr@iki.fi>
6 */
7
8 /*
9 * This file is part of GNU Enscript.
10 *
11 * Enscript is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * Enscript is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Enscript. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "defs.h"
26
27 /*
28 * Prototypes for static functions.
29 */
30
31 /*
32 * Evaluate the begin rules of state <state>. The begin rules are
33 * evaluated from parent to child.
34 */
35 static Node *eval_begin_rules ___P ((State *state, int *return_seen));
36
37 /*
38 * Evaluate the end rules of state <state>. The end rules are
39 * evaluated from child to parent.
40 */
41 static Node *eval_end_rules ___P ((State *state, int *found_return));
42
43 /*
44 * Global functions.
45 */
46
47 void
48 process_file (fname)
49 char *fname;
50 {
51 Node *result;
52 int return_seen = 0;
53
54 start_state = NULL;
55 current_fname = fname;
56 current_linenum = 1;
57
58 /* Init buffer variables. */
59 data_in_buffer = 0;
60 bufpos = 0;
61 eof_seen = 0;
62
63 /* Enter build-in variables. */
64 enter_system_variable ("filename", fname);
65
66 /* Read in the first block of data. */
67 data_in_buffer = fread (inbuf, 1, INBUFSIZE, ifp);
68 if (data_in_buffer < INBUFSIZE)
69 eof_seen = 1;
70
71 if (start_state_arg)
72 start_state = start_state_arg;
73
74 /* Execute start block. */
75 result = eval_statement_list (start_stmts, NULL, &return_seen);
76 node_free (result);
77
78 if (start_state == NULL)
79 {
80 /* No start state found, copy our input to output. */
81 while (data_in_buffer)
82 {
83 fwrite (inbuf, 1, data_in_buffer, ofp);
84 data_in_buffer = fread (inbuf, 1, INBUFSIZE, ifp);
85 }
86 }
87 else
88 {
89 result = execute_state (start_state);
90 node_free (result);
91 }
92 }
93
94
95 Node *
96 execute_state (name)
97 char *name;
98 {
99 State *state;
100 State *s;
101 int to_read, got;
102 ListItem *rule, *first_rule;
103 unsigned int first_idx;
104 unsigned int match_len;
105 Node *result = nvoid;
106 Cons *r;
107 Node *exp;
108 int return_seen = 0;
109 int idx;
110
111 /* Lookup state. */
112 state = lookup_state (name);
113 if (state == NULL)
114 {
115 fprintf (stderr, _("%s: undefined state `%s'\n"), program, name);
116 exit (1);
117 }
118
119 /* Begin rules. */
120 result = eval_begin_rules (state, &return_seen);
121 if (return_seen)
122 goto out;
123
124 /* Execute this state. */
125 while (1)
126 {
127 int eol;
128
129 /* Do we have enough data? */
130 if (bufpos >= data_in_buffer)
131 {
132 if (eof_seen)
133 /* All done. */
134 break;
135
136 /* Read more data. */
137 data_in_buffer = fread (inbuf, 1, INBUFSIZE, ifp);
138 if (data_in_buffer < INBUFSIZE)
139 eof_seen = 1;
140
141 bufpos = 0;
142 continue;
143 }
144
145 /* Check line number. */
146 if (bufpos > 0 && inbuf[bufpos - 1] == '\n')
147 current_linenum++;
148
149 /* Find the end of the input line. */
150 for (eol = bufpos; eol < data_in_buffer && inbuf[eol] != '\n'; eol++)
151 ;
152 if (eol < data_in_buffer && inbuf[eol] == '\n')
153 eol++;
154 if (eol >= data_in_buffer && !eof_seen && bufpos > 0)
155 {
156 /* Must read more data to the buffer. */
157 memmove (inbuf, inbuf + bufpos, eol - bufpos);
158 data_in_buffer = eol - bufpos;
159 bufpos = 0;
160
161 to_read = INBUFSIZE - data_in_buffer;
162 got = fread (inbuf + data_in_buffer, 1, to_read, ifp);
163 if (got < to_read)
164 eof_seen = 1;
165
166 data_in_buffer += got;
167 continue;
168 }
169
170 /* Evaluate state expressions. */
171 first_idx = eol;
172 match_len = 0;
173 first_rule = NULL;
174 current_match = NULL;
175
176 for (s = state; s; s = s->super)
177 {
178 for (rule = s->rules->head; rule; rule = rule->next)
179 {
180 int err;
181
182 r = (Cons *) rule->data;
183 exp = (Node *) r->car;
184 if (exp == RULE_BEGIN || exp == RULE_END)
185 continue;
186
187 if (exp->type == nSYMBOL)
188 {
189 Node *n;
190
191 /* Lookup this variable by hand from global variables. */
192 if (!strhash_get (ns_vars, exp->u.sym, strlen (exp->u.sym),
193 (void **) &n))
194 {
195 fprintf (stderr,
196 _("%s: error: undefined variable `%s'\n"),
197 program, exp->u.sym);
198 exit (1);
199 }
200 if (n->type != nREGEXP)
201 /* Skip this rule */
202 continue;
203
204 exp = n;
205 }
206
207 err = re_search (REGEXP (exp), inbuf, eol, bufpos,
208 eol - bufpos, &exp->u.re.matches);
209 if (err < 0)
210 /* No mach. */
211 continue;
212
213 idx = exp->u.re.matches.start[0];
214 if (idx >= 0
215 && (idx < first_idx
216 || (idx == first_idx
217 && (exp->u.re.matches.end[0]
218 - exp->u.re.matches.start[0]
219 > match_len))))
220 {
221 first_idx = idx;
222 first_rule = rule;
223 match_len = (exp->u.re.matches.end[0]
224 - exp->u.re.matches.start[0]);
225 current_match = &exp->u.re.matches;
226 current_match_buf = inbuf;
227 }
228 }
229 }
230
231 /* Print all data before the first rule. */
232 fwrite (inbuf + bufpos, 1, first_idx - bufpos, ofp);
233
234 if (first_rule)
235 {
236 /* Execute statements. */
237 bufpos = current_match->end[0];
238
239 node_free (result);
240 result = eval_statement_list ((List *)
241 ((Cons *) first_rule->data)->cdr,
242 NULL, &return_seen);
243 if (return_seen)
244 goto out;
245 }
246 else
247 bufpos = first_idx;
248 }
249
250 out:
251
252 /* End rules. */
253 {
254 int found = 0;
255 Node *result2;
256
257 result2 = eval_end_rules (state, &found);
258 if (found)
259 {
260 node_free (result);
261 result = result2;
262 }
263 }
264
265 return result;
266 }
267
268
269 /*
270 * Static functions.
271 */
272
273 static Node *
274 eval_begin_rules (state, return_seen)
275 State *state;
276 int *return_seen;
277 {
278 Node *result = nvoid;
279 Cons *r;
280 ListItem *rule;
281
282 /* The begin rules are evaluated from the parent to child. */
283
284 /* Autoload the super if needed. */
285 if (state->super_name && state->super == NULL)
286 {
287 state->super = lookup_state (state->super_name);
288 if (state->super == NULL)
289 {
290 fprintf (stderr, _("%s: undefined super state `%s'\n"),
291 program, state->super_name);
292 exit (1);
293 }
294 }
295
296 if (state->super)
297 {
298 result = eval_begin_rules (state->super, return_seen);
299 if (*return_seen)
300 return result;
301 }
302
303 /* Eval our begin rule. */
304 for (rule = state->rules->head; rule; rule = rule->next)
305 {
306 r = (Cons *) rule->data;
307 if (r->car == RULE_BEGIN)
308 {
309 node_free (result);
310 result = eval_statement_list ((List *) r->cdr, NULL, return_seen);
311 if (*return_seen)
312 break;
313 }
314 }
315
316 return result;
317 }
318
319
320 static Node *
321 eval_end_rules (state, found_return)
322 State *state;
323 int *found_return;
324 {
325 ListItem *rule;
326 Cons *r;
327 Node *result = nvoid;
328 int return_seen;
329
330 /* The end rules are evaluated from child to parent. */
331
332 for (; state; state = state->super)
333 for (rule = state->rules->head; rule; rule = rule->next)
334 {
335 r = (Cons *) rule->data;
336 if (r->car == RULE_END)
337 {
338 *found_return = 1;
339 node_free (result);
340 result = eval_statement_list ((List *) r->cdr, NULL, &return_seen);
341 }
342 }
343
344 return result;
345 }