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 }