Back to index

tetex-bin  3.0
routines.c
Go to the documentation of this file.
00001 /* routines.c: Generating the finite state automaton.
00002 
00003 This file is part of Omega,
00004 which is based on the web2c distribution of TeX,
00005 
00006 Copyright (c) 1994--2001 John Plaice and Yannis Haralambous
00007 
00008 Omega is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 Omega is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Omega; if not, write to the Free Software Foundation, Inc.,
00020 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00021 
00022 */
00023 
00024 #include <kpathsea/config.h>
00025 #include <kpathsea/types.h>
00026 #include <kpathsea/c-proto.h>
00027 #include <kpathsea/c-std.h>
00028 #include "routines.h"
00029 #include "otp.h"
00030 
00031 #define out_ptr (states[cur_state].length)
00032 #define out_array (states[cur_state].instrs)
00033 
00034 list left_false_holes;
00035 
00036 int left_state;
00037 int right_offset;
00038 int input_bytes;
00039 int output_bytes;
00040 
00041 int no_states = 0;
00042 int cur_state = 0;
00043 int room_for_states = 0;
00044 state_type states[100];
00045 
00046 int no_tables = 0;
00047 int cur_table = 0;
00048 int room_for_tables = 0;
00049 table_type tables[100];
00050 
00051 int no_aliases = 0;
00052 alias_pair aliases[1000];
00053 
00054 list
00055 cons P2C(int, x, list, L)
00056 {
00057 list temp;
00058 temp = (list) malloc(sizeof(cell));
00059 temp->val = x;
00060 temp->ptr = L;
00061 return temp;
00062 }
00063 
00064 list
00065 list1 P1C(int, x)
00066 {
00067 list temp;
00068 temp = (list) malloc(sizeof(cell));
00069 temp->val = x;
00070 temp->ptr = nil;
00071 return temp;
00072 }
00073 
00074 list
00075 list2 P2C(int, x, int, y)
00076 {
00077 list temp, temp1;
00078 temp = (list) malloc(sizeof(cell));
00079 temp1 = (list) malloc(sizeof(cell));
00080 temp->val = x;
00081 temp->ptr = temp1;
00082 temp1->val = y;
00083 temp1->ptr = nil;
00084 return temp;
00085 }
00086 
00087 list
00088 append P2C(list, K, list, L)
00089 {
00090 if (K==nil) return L;
00091 return cons(K->val, append(K->ptr, L));
00092 }
00093 
00094 list
00095 append1 P2C(list, L, int, x)
00096 {
00097 return (append(L,list1(x)));
00098 }
00099 
00100 llist
00101 lcons P2C(left, x, llist, L)
00102 {
00103 llist temp;
00104 temp = (llist) malloc(sizeof(lcell));
00105 temp->val = x;
00106 temp->ptr = L;
00107 return temp;
00108 }
00109 
00110 llist
00111 llist1 P1C(left, x)
00112 {
00113 llist temp;
00114 temp = (llist) malloc(sizeof(lcell));
00115 temp->val = x;
00116 temp->ptr = nil;
00117 return temp;
00118 }
00119 
00120 llist
00121 llist2 P2C(left, x, left, y)
00122 {
00123 llist temp, temp1;
00124 temp = (llist) malloc(sizeof(lcell));
00125 temp1 = (llist) malloc(sizeof(lcell));
00126 temp->val = x;
00127 temp->ptr = temp1;
00128 temp1->val = y;
00129 temp1->ptr = nil;
00130 return temp;
00131 }
00132 
00133 llist
00134 lappend P2C(llist, K, llist, L)
00135 {
00136 if (K==nil) return L;
00137 return lcons(K->val, lappend(K->ptr, L));
00138 }
00139 
00140 llist
00141 lappend1 P2C(llist, L, left, x)
00142 {
00143 return (lappend(L,llist1(x)));
00144 }
00145 
00146 left
00147 WildCard P1H(void)
00148 {
00149 left temp;
00150 temp = (left) malloc(sizeof(lft_cell));
00151 temp->kind=WILDCARD;
00152 return temp;
00153 }
00154 
00155 left
00156 StringLeft P1C(char *, x)
00157 {
00158 left temp;
00159 temp = (left) malloc(sizeof(lft_cell));
00160 temp->kind=STRINGLEFT;
00161 temp->valstr=x;
00162 return temp;
00163 }
00164 
00165 left
00166 SingleLeft P1C(int, x)
00167 {
00168 left temp;
00169 temp = (left) malloc(sizeof(lft_cell));
00170 temp->kind=SINGLELEFT;
00171 temp->val1=x;
00172 return temp;
00173 }
00174 
00175 left
00176 DoubleLeft P2C(int, x, int, y)
00177 {
00178 left temp;
00179 temp = (left) malloc(sizeof(lft_cell));
00180 temp->kind=DOUBLELEFT;
00181 temp->val1=x;
00182 temp->val2=y;
00183 return temp;
00184 }
00185 
00186 left
00187 ChoiceLeft P1C(llist, L)
00188 {
00189 left temp;
00190 temp = (left) malloc(sizeof(lft_cell));
00191 temp->kind=CHOICELEFT;
00192 temp->more_lefts=L;
00193 return temp;
00194 }
00195 
00196 left
00197 NotChoiceLeft P1C(llist, L)
00198 {
00199 left temp;
00200 temp = (left) malloc(sizeof(lft_cell));
00201 temp->kind=NOTCHOICELEFT;
00202 temp->more_lefts=L;
00203 return temp;
00204 }
00205 
00206 left
00207 PlusLeft P2C(left, l, int, n)
00208 {
00209 left temp;
00210 temp = (left) malloc(sizeof(lft_cell));
00211 temp->kind=PLUSLEFT;
00212 temp->one_left=l;
00213 temp->val1=n;
00214 return temp;
00215 }
00216 
00217 left
00218 CompleteLeft P3C(left, l, int, n, int, m)
00219 {
00220 left temp;
00221 temp = (left) malloc(sizeof(lft_cell));
00222 temp->kind=COMPLETELEFT;
00223 temp->one_left=l;
00224 temp->val1=n;
00225 temp->val2=m;
00226 return temp;
00227 }
00228 
00229 left
00230 BeginningLeft P1H(void)
00231 {
00232 left temp;
00233 temp = (left) malloc(sizeof(lft_cell));
00234 temp->kind=BEGINNINGLEFT;
00235 return temp;
00236 }
00237 
00238 left
00239 EndLeft P1H(void)
00240 {
00241 left temp;
00242 temp = (left) malloc(sizeof(lft_cell));
00243 temp->kind=ENDLEFT;
00244 return temp;
00245 }
00246 
00247 list
00248 gen_left P1C(left, arg)
00249 {
00250 int save_ptr, k;
00251 list holes, false_holes, true_holes, backup_holes;
00252 char *runner;
00253 llist p;
00254 
00255 switch(arg->kind) {
00256 case WILDCARD:
00257        return nil;
00258 case STRINGLEFT:
00259         runner=arg->valstr;
00260         holes=nil;
00261        while (*runner) {
00262               out_int(OTP_GOTO_NE, *runner);
00263               out_int(0, 0);
00264               holes=cons(out_ptr-1,holes);
00265               runner++;
00266               if (*runner) {
00267                      out_int(OTP_GOTO_NO_ADVANCE, 0);
00268                      holes = cons(out_ptr-1, holes);
00269               }
00270        }
00271        return holes;
00272 case SINGLELEFT:
00273        out_int(OTP_GOTO_NE, arg->val1);
00274        out_int(0, 0);
00275        return list1(out_ptr-1);
00276 case DOUBLELEFT:
00277        out_int(OTP_GOTO_LT, arg->val1);
00278        out_int(0, 0);
00279        save_ptr = out_ptr;
00280        out_int(OTP_GOTO_GT, arg->val2);
00281        out_int(0, 0);
00282        return list2(save_ptr-1, out_ptr-1);
00283 case CHOICELEFT:
00284        true_holes=nil;
00285        false_holes=nil;
00286        p=arg->more_lefts;
00287        while (p!=nil) {
00288               false_holes = gen_left(p->val);
00289               if (p->ptr) {
00290                      out_int(OTP_GOTO, 0);
00291                      true_holes=cons(out_ptr-1, true_holes);
00292                      fill_in(false_holes);
00293               }
00294               p=p->ptr;
00295        }
00296        fill_in(true_holes);
00297        return false_holes;
00298 case NOTCHOICELEFT:
00299        true_holes=nil;
00300        p=arg->more_lefts;
00301        while (p!=nil) {
00302               false_holes = gen_left(p->val);
00303               out_int(OTP_GOTO, 0);
00304               true_holes=cons(out_ptr-1, true_holes);
00305               fill_in(false_holes);
00306               p=p->ptr;
00307        }
00308        return true_holes;
00309 case PLUSLEFT:
00310        false_holes=nil;
00311        true_holes=nil;
00312        backup_holes=nil;
00313        k=1;
00314        while (k<arg->val1) {
00315               holes = gen_left(arg->one_left);
00316               false_holes = append(false_holes, holes);
00317               out_int(OTP_GOTO_NO_ADVANCE, 0);
00318               false_holes = cons(out_ptr-1, false_holes);
00319               k++;
00320        }
00321        holes=gen_left(arg->one_left);
00322        false_holes = append(false_holes, holes);
00323        save_ptr = out_ptr;
00324        out_int(OTP_GOTO_NO_ADVANCE, 0);
00325        true_holes=cons(out_ptr-1, true_holes);
00326        backup_holes=gen_left(arg->one_left);
00327        out_int(OTP_GOTO, save_ptr);
00328        fill_in(backup_holes);
00329        out_int(OTP_LEFT_BACKUP, 0);
00330        fill_in(true_holes);
00331        return false_holes;
00332 case COMPLETELEFT:
00333        false_holes=nil;
00334        true_holes=nil;
00335        backup_holes=nil;
00336        k=1;
00337        if (arg->val1 > arg->val2) {
00338               return nil;
00339        }
00340        while (k<=arg->val1) {
00341               holes = gen_left(arg->one_left);
00342               false_holes = append(false_holes, holes);
00343               out_int(OTP_GOTO_NO_ADVANCE, 0);
00344               false_holes = cons(out_ptr-1, false_holes);
00345               k++;
00346        }
00347        while (k<arg->val2) {
00348               holes = gen_left(arg->one_left);
00349               true_holes = append(true_holes, holes);
00350               out_int(OTP_GOTO_NO_ADVANCE, 0);
00351               backup_holes = cons(out_ptr-1, backup_holes);
00352               k++;
00353        }
00354        holes = gen_left(arg->one_left);
00355        true_holes = append(true_holes, holes);
00356        out_int(OTP_GOTO, out_ptr+2);
00357        fill_in(true_holes);
00358        out_int(OTP_LEFT_BACKUP, 0);
00359        fill_in(backup_holes);
00360        return false_holes;
00361 case BEGINNINGLEFT:
00362        out_int(OTP_GOTO_BEG, 0);
00363        true_holes=list1(out_ptr-1);
00364        out_int(OTP_GOTO, 0);
00365        false_holes=list1(out_ptr-1);
00366        fill_in(true_holes);
00367        return false_holes;
00368 case ENDLEFT:
00369        out_int(OTP_GOTO_END, 0);
00370        true_holes=list1(out_ptr-1);
00371        out_int(OTP_GOTO, 0);
00372        false_holes=list1(out_ptr-1);
00373        fill_in(true_holes);
00374        return false_holes;
00375 default:
00376        fprintf(stderr, "Unrecognized left: %d\n", arg->kind);
00377        exit(EXIT_FAILURE);
00378 }
00379 }
00380 
00381 void
00382 store_alias P2C(string, str, left, l)
00383 {
00384 int i;
00385 for (i=0; i<no_aliases; i++) {
00386     if (!strcmp(str,aliases[i].str)) {
00387         fprintf(stderr, "alias %s already defined\n", str);
00388         exit(1);
00389     }
00390 }
00391 aliases[i].str=xstrdup(str);
00392 aliases[i].left_val=l;
00393 no_aliases++;
00394 }
00395 
00396 left
00397 lookup_alias P1C(string, str)
00398 {
00399 int i;
00400 for (i=0; i<no_aliases; i++) {
00401     if (!strcmp(str,aliases[i].str)) {
00402         return aliases[i].left_val;
00403     }
00404 }
00405 fprintf(stderr, "state %s not defined\n", str);
00406 exit(EXIT_FAILURE);
00407 }
00408 
00409 void
00410 out_left P1C(llist, L)
00411 {
00412 llist p;
00413 list holes;
00414 if ((states[cur_state].no_exprs)==1) {
00415        out_int(OTP_LEFT_START, 0);
00416 } else {
00417        out_int(OTP_LEFT_RETURN, 0);
00418 }
00419 p=L;
00420 left_false_holes=nil;
00421 while (p!=nil) {
00422        holes = gen_left(p->val);
00423        if ((p->ptr != nil) &&
00424             ((p->val)->kind !=BEGINNINGLEFT) &&
00425             (((p->ptr)->val)->kind !=ENDLEFT)) {
00426               out_int(OTP_GOTO_NO_ADVANCE, 0);
00427               left_false_holes = cons(out_ptr-1,left_false_holes);
00428        }
00429        left_false_holes = append(left_false_holes, holes);
00430        p=p->ptr;
00431 }
00432 }
00433 
00434 void
00435 fill_in_left P1H(void)
00436 {
00437        out_int(OTP_STOP, 0);
00438        fill_in(left_false_holes);
00439 }
00440 
00441 void
00442 fill_in P1C(list, L) 
00443 {
00444 list p;
00445 p=L;
00446 while (p!=0) {
00447     out_array[p->val] = out_array[p->val] + out_ptr;
00448     p=p->ptr;
00449 }
00450 }
00451 
00452 void
00453 out_right P2C(int, instr, int, val)
00454 {
00455 out_int(instr+right_offset, val);
00456 }
00457 
00458 void
00459 out_int P2C(int, instr, int, val)
00460 {
00461 if (val>=(1<<24)) {
00462     fprintf(stderr, "Argument (%d) of instruction too big\n", val);
00463     exit(EXIT_FAILURE);
00464 }
00465 add_to_state((instr<<24)+val);
00466 }
00467 
00468 void
00469 store_state P1C(string, str)
00470 {
00471 int i;
00472 for (i=0; i<no_states; i++) {
00473    if (!strcmp(str,states[i].str)) {
00474       fprintf(stderr, "state %s already defined\n", str);
00475        exit(EXIT_FAILURE);
00476    }
00477 }
00478 states[i].str=xstrdup(str);
00479 states[i].length=0;
00480 states[i].no_exprs=0;
00481 cur_state=i;
00482 no_states++;
00483 }
00484 
00485 int
00486 lookup_state P1C(string, str)
00487 {
00488 int i;
00489 for (i=0; i<no_states; i++) {
00490     if (!strcmp(str,states[i].str)) {
00491         return i;
00492     }
00493 }
00494 fprintf(stderr, "state %s not defined\n", str);
00495 exit(EXIT_FAILURE);
00496 }
00497 
00498 void
00499 add_to_state P1C(int, x)
00500 {
00501 int len;
00502 len = states[cur_state].length;
00503 if (len > ARRAY_SIZE) {
00504        char * str = states[cur_state].str;
00505         fprintf(stderr, "%s state has too many instructions\n", str);
00506         exit(EXIT_FAILURE);
00507 }
00508 (states[cur_state].instrs)[len] = x;
00509 states[cur_state].length = len+1;
00510 }
00511 
00512 void
00513 store_table P2C(string, str, int, len)
00514 {
00515 int i;
00516 for (i=0; i<no_tables; i++) {
00517     if (!strcmp(str,tables[i].str)) {
00518         fprintf(stderr, "table %s already defined\n", str);
00519         exit(EXIT_FAILURE);
00520     }
00521 }
00522 tables[i].str=xstrdup(str);
00523 tables[i].length=0;
00524 cur_table=i;
00525 no_tables++;
00526 }
00527 
00528 void
00529 add_to_table P1C(int, x)
00530 {
00531 int len;
00532 len = tables[cur_table].length;
00533 (tables[cur_table].table)[len] = x;
00534 tables[cur_table].length = len+1;
00535 }
00536 
00537 int
00538 lookup_table P1C(string, str)
00539 {
00540 int i;
00541 for (i=0; i<no_tables; i++) {
00542     if (!strcmp(str,tables[i].str)) {
00543         return i;
00544     }
00545 }
00546 fprintf(stderr, "table %s not defined\n", str);
00547 exit(EXIT_FAILURE);
00548 }
00549