2 * Process input according to the specified rules.
3 * Copyright (c) 1997-1999 Markku Rossi.
5 * Author: Markku Rossi <mtr@iki.fi>
9 * This file is part of GNU Enscript.
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.
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.
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/>.
28 * Prototypes for static functions.
32 * Evaluate the begin rules of state <state>. The begin rules are
33 * evaluated from parent to child.
35 static Node *eval_begin_rules ___P ((State *state, int *return_seen));
38 * Evaluate the end rules of state <state>. The end rules are
39 * evaluated from child to parent.
41 static Node *eval_end_rules ___P ((State *state, int *found_return));
55 current_fname = fname;
58 /* Init buffer variables. */
63 /* Enter build-in variables. */
64 enter_system_variable ("filename", fname);
66 /* Read in the first block of data. */
67 data_in_buffer = fread (inbuf, 1, INBUFSIZE, ifp);
68 if (data_in_buffer < INBUFSIZE)
72 start_state = start_state_arg;
74 /* Execute start block. */
75 result = eval_statement_list (start_stmts, NULL, &return_seen);
78 if (start_state == NULL)
80 /* No start state found, copy our input to output. */
81 while (data_in_buffer)
83 fwrite (inbuf, 1, data_in_buffer, ofp);
84 data_in_buffer = fread (inbuf, 1, INBUFSIZE, ifp);
89 result = execute_state (start_state);
102 ListItem *rule, *first_rule;
103 unsigned int first_idx;
104 unsigned int match_len;
105 Node *result = nvoid;
112 state = lookup_state (name);
115 fprintf (stderr, _("%s: undefined state `%s'\n"), program, name);
120 result = eval_begin_rules (state, &return_seen);
124 /* Execute this state. */
129 /* Do we have enough data? */
130 if (bufpos >= data_in_buffer)
136 /* Read more data. */
137 data_in_buffer = fread (inbuf, 1, INBUFSIZE, ifp);
138 if (data_in_buffer < INBUFSIZE)
145 /* Check line number. */
146 if (bufpos > 0 && inbuf[bufpos - 1] == '\n')
149 /* Find the end of the input line. */
150 for (eol = bufpos; eol < data_in_buffer && inbuf[eol] != '\n'; eol++)
152 if (eol < data_in_buffer && inbuf[eol] == '\n')
154 if (eol >= data_in_buffer && !eof_seen && bufpos > 0)
156 /* Must read more data to the buffer. */
157 memmove (inbuf, inbuf + bufpos, eol - bufpos);
158 data_in_buffer = eol - bufpos;
161 to_read = INBUFSIZE - data_in_buffer;
162 got = fread (inbuf + data_in_buffer, 1, to_read, ifp);
166 data_in_buffer += got;
170 /* Evaluate state expressions. */
174 current_match = NULL;
176 for (s = state; s; s = s->super)
178 for (rule = s->rules->head; rule; rule = rule->next)
182 r = (Cons *) rule->data;
183 exp = (Node *) r->car;
184 if (exp == RULE_BEGIN || exp == RULE_END)
187 if (exp->type == nSYMBOL)
191 /* Lookup this variable by hand from global variables. */
192 if (!strhash_get (ns_vars, exp->u.sym, strlen (exp->u.sym),
196 _("%s: error: undefined variable `%s'\n"),
197 program, exp->u.sym);
200 if (n->type != nREGEXP)
207 err = re_search (REGEXP (exp), inbuf, eol, bufpos,
208 eol - bufpos, &exp->u.re.matches);
213 idx = exp->u.re.matches.start[0];
217 && (exp->u.re.matches.end[0]
218 - exp->u.re.matches.start[0]
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;
231 /* Print all data before the first rule. */
232 fwrite (inbuf + bufpos, 1, first_idx - bufpos, ofp);
236 /* Execute statements. */
237 bufpos = current_match->end[0];
240 result = eval_statement_list ((List *)
241 ((Cons *) first_rule->data)->cdr,
257 result2 = eval_end_rules (state, &found);
274 eval_begin_rules (state, return_seen)
278 Node *result = nvoid;
282 /* The begin rules are evaluated from the parent to child. */
284 /* Autoload the super if needed. */
285 if (state->super_name && state->super == NULL)
287 state->super = lookup_state (state->super_name);
288 if (state->super == NULL)
290 fprintf (stderr, _("%s: undefined super state `%s'\n"),
291 program, state->super_name);
298 result = eval_begin_rules (state->super, return_seen);
303 /* Eval our begin rule. */
304 for (rule = state->rules->head; rule; rule = rule->next)
306 r = (Cons *) rule->data;
307 if (r->car == RULE_BEGIN)
310 result = eval_statement_list ((List *) r->cdr, NULL, return_seen);
321 eval_end_rules (state, found_return)
327 Node *result = nvoid;
330 /* The end rules are evaluated from child to parent. */
332 for (; state; state = state->super)
333 for (rule = state->rules->head; rule; rule = rule->next)
335 r = (Cons *) rule->data;
336 if (r->car == RULE_END)
340 result = eval_statement_list ((List *) r->cdr, NULL, &return_seen);