| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** This file contains all sources (including headers) to the LEMON | 2 ** This file contains all sources (including headers) to the LEMON |
| 3 ** LALR(1) parser generator. The sources have been combined into a | 3 ** LALR(1) parser generator. The sources have been combined into a |
| 4 ** single file to make it easy to include LEMON in the source tree | 4 ** single file to make it easy to include LEMON in the source tree |
| 5 ** and Makefile of another program. | 5 ** and Makefile of another program. |
| 6 ** | 6 ** |
| 7 ** The author of this program disclaims copyright. | 7 ** The author of this program disclaims copyright. |
| 8 */ | 8 */ |
| 9 #include <stdio.h> | 9 #include <stdio.h> |
| 10 #include <stdarg.h> | 10 #include <stdarg.h> |
| 11 #include <string.h> | 11 #include <string.h> |
| 12 #include <ctype.h> | 12 #include <ctype.h> |
| 13 #include <stdlib.h> | 13 #include <stdlib.h> |
| 14 #include <assert.h> | 14 #include <assert.h> |
| 15 | 15 |
| 16 #ifndef __WIN32__ | 16 #ifndef __WIN32__ |
| 17 # if defined(_WIN32) || defined(WIN32) | 17 # if defined(_WIN32) || defined(WIN32) |
| 18 #» define __WIN32__ | 18 # define __WIN32__ |
| 19 # endif | 19 # endif |
| 20 #endif | 20 #endif |
| 21 | 21 |
| 22 #ifdef __WIN32__ | 22 #ifdef __WIN32__ |
| 23 #ifdef __cplusplus | 23 #ifdef __cplusplus |
| 24 extern "C" { | 24 extern "C" { |
| 25 #endif | 25 #endif |
| 26 extern int access(const char *path, int mode); | 26 extern int access(const char *path, int mode); |
| 27 #ifdef __cplusplus | 27 #ifdef __cplusplus |
| 28 } | 28 } |
| 29 #endif | 29 #endif |
| 30 #else | 30 #else |
| 31 #include <unistd.h> | 31 #include <unistd.h> |
| 32 #endif | 32 #endif |
| 33 | 33 |
| 34 /* #define PRIVATE static */ | 34 /* #define PRIVATE static */ |
| 35 #define PRIVATE | 35 #define PRIVATE |
| 36 | 36 |
| 37 #ifdef TEST | 37 #ifdef TEST |
| 38 #define MAXRHS 5 /* Set low to exercise exception code */ | 38 #define MAXRHS 5 /* Set low to exercise exception code */ |
| 39 #else | 39 #else |
| 40 #define MAXRHS 1000 | 40 #define MAXRHS 1000 |
| 41 #endif | 41 #endif |
| 42 | 42 |
| 43 static int showPrecedenceConflict = 0; | 43 static int showPrecedenceConflict = 0; |
| 44 static const char **made_files = NULL; | |
| 45 static int made_files_count = 0; | |
| 46 static int successful_exit = 0; | |
| 47 static void LemonAtExit(void) | |
| 48 { | |
| 49 /* if we failed, delete (most) files we made, to unconfuse build tools. */ | |
| 50 int i; | |
| 51 for (i = 0; i < made_files_count; i++) { | |
| 52 if (!successful_exit) { | |
| 53 remove(made_files[i]); | |
| 54 } | |
| 55 } | |
| 56 free(made_files); | |
| 57 made_files_count = 0; | |
| 58 made_files = NULL; | |
| 59 } | |
| 60 | |
| 61 static char *msort(char*,char**,int(*)(const char*,const char*)); | 44 static char *msort(char*,char**,int(*)(const char*,const char*)); |
| 62 | 45 |
| 63 /* | 46 /* |
| 64 ** Compilers are getting increasingly pedantic about type conversions | 47 ** Compilers are getting increasingly pedantic about type conversions |
| 65 ** as C evolves ever closer to Ada.... To work around the latest problems | 48 ** as C evolves ever closer to Ada.... To work around the latest problems |
| 66 ** we have to define the following variant of strlen(). | 49 ** we have to define the following variant of strlen(). |
| 67 */ | 50 */ |
| 68 #define lemonStrlen(X) ((int)strlen(X)) | 51 #define lemonStrlen(X) ((int)strlen(X)) |
| 69 | 52 |
| 53 /* |
| 54 ** Compilers are starting to complain about the use of sprintf() and strcpy(), |
| 55 ** saying they are unsafe. So we define our own versions of those routines too. |
| 56 ** |
| 57 ** There are three routines here: lemon_sprintf(), lemon_vsprintf(), and |
| 58 ** lemon_addtext(). The first two are replacements for sprintf() and vsprintf()
. |
| 59 ** The third is a helper routine for vsnprintf() that adds texts to the end of a |
| 60 ** buffer, making sure the buffer is always zero-terminated. |
| 61 ** |
| 62 ** The string formatter is a minimal subset of stdlib sprintf() supporting only |
| 63 ** a few simply conversions: |
| 64 ** |
| 65 ** %d |
| 66 ** %s |
| 67 ** %.*s |
| 68 ** |
| 69 */ |
| 70 static void lemon_addtext( |
| 71 char *zBuf, /* The buffer to which text is added */ |
| 72 int *pnUsed, /* Slots of the buffer used so far */ |
| 73 const char *zIn, /* Text to add */ |
| 74 int nIn, /* Bytes of text to add. -1 to use strlen() */ |
| 75 int iWidth /* Field width. Negative to left justify */ |
| 76 ){ |
| 77 if( nIn<0 ) for(nIn=0; zIn[nIn]; nIn++){} |
| 78 while( iWidth>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth--; } |
| 79 if( nIn==0 ) return; |
| 80 memcpy(&zBuf[*pnUsed], zIn, nIn); |
| 81 *pnUsed += nIn; |
| 82 while( (-iWidth)>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth++; } |
| 83 zBuf[*pnUsed] = 0; |
| 84 } |
| 85 static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){ |
| 86 int i, j, k, c; |
| 87 int nUsed = 0; |
| 88 const char *z; |
| 89 char zTemp[50]; |
| 90 str[0] = 0; |
| 91 for(i=j=0; (c = zFormat[i])!=0; i++){ |
| 92 if( c=='%' ){ |
| 93 int iWidth = 0; |
| 94 lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); |
| 95 c = zFormat[++i]; |
| 96 if( isdigit(c) || (c=='-' && isdigit(zFormat[i+1])) ){ |
| 97 if( c=='-' ) i++; |
| 98 while( isdigit(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; |
| 99 if( c=='-' ) iWidth = -iWidth; |
| 100 c = zFormat[i]; |
| 101 } |
| 102 if( c=='d' ){ |
| 103 int v = va_arg(ap, int); |
| 104 if( v<0 ){ |
| 105 lemon_addtext(str, &nUsed, "-", 1, iWidth); |
| 106 v = -v; |
| 107 }else if( v==0 ){ |
| 108 lemon_addtext(str, &nUsed, "0", 1, iWidth); |
| 109 } |
| 110 k = 0; |
| 111 while( v>0 ){ |
| 112 k++; |
| 113 zTemp[sizeof(zTemp)-k] = (v%10) + '0'; |
| 114 v /= 10; |
| 115 } |
| 116 lemon_addtext(str, &nUsed, &zTemp[sizeof(zTemp)-k], k, iWidth); |
| 117 }else if( c=='s' ){ |
| 118 z = va_arg(ap, const char*); |
| 119 lemon_addtext(str, &nUsed, z, -1, iWidth); |
| 120 }else if( c=='.' && memcmp(&zFormat[i], ".*s", 3)==0 ){ |
| 121 i += 2; |
| 122 k = va_arg(ap, int); |
| 123 z = va_arg(ap, const char*); |
| 124 lemon_addtext(str, &nUsed, z, k, iWidth); |
| 125 }else if( c=='%' ){ |
| 126 lemon_addtext(str, &nUsed, "%", 1, 0); |
| 127 }else{ |
| 128 fprintf(stderr, "illegal format\n"); |
| 129 exit(1); |
| 130 } |
| 131 j = i+1; |
| 132 } |
| 133 } |
| 134 lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); |
| 135 return nUsed; |
| 136 } |
| 137 static int lemon_sprintf(char *str, const char *format, ...){ |
| 138 va_list ap; |
| 139 int rc; |
| 140 va_start(ap, format); |
| 141 rc = lemon_vsprintf(str, format, ap); |
| 142 va_end(ap); |
| 143 return rc; |
| 144 } |
| 145 static void lemon_strcpy(char *dest, const char *src){ |
| 146 while( (*(dest++) = *(src++))!=0 ){} |
| 147 } |
| 148 static void lemon_strcat(char *dest, const char *src){ |
| 149 while( *dest ) dest++; |
| 150 lemon_strcpy(dest, src); |
| 151 } |
| 152 |
| 153 |
| 70 /* a few forward declarations... */ | 154 /* a few forward declarations... */ |
| 71 struct rule; | 155 struct rule; |
| 72 struct lemon; | 156 struct lemon; |
| 73 struct action; | 157 struct action; |
| 74 | 158 |
| 75 static struct action *Action_new(void); | 159 static struct action *Action_new(void); |
| 76 static struct action *Action_sort(struct action *); | 160 static struct action *Action_sort(struct action *); |
| 77 | 161 |
| 78 /********** From the file "build.h" ************************************/ | 162 /********** From the file "build.h" ************************************/ |
| 79 void FindRulePrecedences(); | 163 void FindRulePrecedences(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 void ReportOutput(struct lemon *); | 211 void ReportOutput(struct lemon *); |
| 128 void ReportTable(struct lemon *, int); | 212 void ReportTable(struct lemon *, int); |
| 129 void ReportHeader(struct lemon *); | 213 void ReportHeader(struct lemon *); |
| 130 void CompressTables(struct lemon *); | 214 void CompressTables(struct lemon *); |
| 131 void ResortStates(struct lemon *); | 215 void ResortStates(struct lemon *); |
| 132 | 216 |
| 133 /********** From the file "set.h" ****************************************/ | 217 /********** From the file "set.h" ****************************************/ |
| 134 void SetSize(int); /* All sets will be of size N */ | 218 void SetSize(int); /* All sets will be of size N */ |
| 135 char *SetNew(void); /* A new set for element 0..N */ | 219 char *SetNew(void); /* A new set for element 0..N */ |
| 136 void SetFree(char*); /* Deallocate a set */ | 220 void SetFree(char*); /* Deallocate a set */ |
| 137 | |
| 138 char *SetNew(void); /* A new set for element 0..N */ | |
| 139 int SetAdd(char*,int); /* Add element to a set */ | 221 int SetAdd(char*,int); /* Add element to a set */ |
| 140 int SetUnion(char *,char *); /* A <- A U B, thru element N */ | 222 int SetUnion(char *,char *); /* A <- A U B, thru element N */ |
| 141 #define SetFind(X,Y) (X[Y]) /* True if Y is in set X */ | 223 #define SetFind(X,Y) (X[Y]) /* True if Y is in set X */ |
| 142 | 224 |
| 143 /********** From the file "struct.h" *************************************/ | 225 /********** From the file "struct.h" *************************************/ |
| 144 /* | 226 /* |
| 145 ** Principal data structures for the LEMON parser generator. | 227 ** Principal data structures for the LEMON parser generator. |
| 146 */ | 228 */ |
| 147 | 229 |
| 148 typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean; | 230 typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean; |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 struct symbol *sp = rp->rhs[i]; | 747 struct symbol *sp = rp->rhs[i]; |
| 666 if( sp->type==MULTITERMINAL ){ | 748 if( sp->type==MULTITERMINAL ){ |
| 667 for(j=0; j<sp->nsubsym; j++){ | 749 for(j=0; j<sp->nsubsym; j++){ |
| 668 if( sp->subsym[j]->prec>=0 ){ | 750 if( sp->subsym[j]->prec>=0 ){ |
| 669 rp->precsym = sp->subsym[j]; | 751 rp->precsym = sp->subsym[j]; |
| 670 break; | 752 break; |
| 671 } | 753 } |
| 672 } | 754 } |
| 673 }else if( sp->prec>=0 ){ | 755 }else if( sp->prec>=0 ){ |
| 674 rp->precsym = rp->rhs[i]; | 756 rp->precsym = rp->rhs[i]; |
| 675 » } | 757 } |
| 676 } | 758 } |
| 677 } | 759 } |
| 678 } | 760 } |
| 679 return; | 761 return; |
| 680 } | 762 } |
| 681 | 763 |
| 682 /* Find all nonterminals which will generate the empty string. | 764 /* Find all nonterminals which will generate the empty string. |
| 683 ** Then go back and compute the first sets of every nonterminal. | 765 ** Then go back and compute the first sets of every nonterminal. |
| 684 ** The first set is the set of all terminal symbols which can begin | 766 ** The first set is the set of all terminal symbols which can begin |
| 685 ** a string generated by that nonterminal. | 767 ** a string generated by that nonterminal. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 696 for(i=lemp->nterminal; i<lemp->nsymbol; i++){ | 778 for(i=lemp->nterminal; i<lemp->nsymbol; i++){ |
| 697 lemp->symbols[i]->firstset = SetNew(); | 779 lemp->symbols[i]->firstset = SetNew(); |
| 698 } | 780 } |
| 699 | 781 |
| 700 /* First compute all lambdas */ | 782 /* First compute all lambdas */ |
| 701 do{ | 783 do{ |
| 702 progress = 0; | 784 progress = 0; |
| 703 for(rp=lemp->rule; rp; rp=rp->next){ | 785 for(rp=lemp->rule; rp; rp=rp->next){ |
| 704 if( rp->lhs->lambda ) continue; | 786 if( rp->lhs->lambda ) continue; |
| 705 for(i=0; i<rp->nrhs; i++){ | 787 for(i=0; i<rp->nrhs; i++){ |
| 706 struct symbol *sp = rp->rhs[i]; | 788 struct symbol *sp = rp->rhs[i]; |
| 707 if( sp->type!=TERMINAL || sp->lambda==LEMON_FALSE ) break; | 789 assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE ); |
| 790 if( sp->lambda==LEMON_FALSE ) break; |
| 708 } | 791 } |
| 709 if( i==rp->nrhs ){ | 792 if( i==rp->nrhs ){ |
| 710 rp->lhs->lambda = LEMON_TRUE; | 793 rp->lhs->lambda = LEMON_TRUE; |
| 711 progress = 1; | 794 progress = 1; |
| 712 } | 795 } |
| 713 } | 796 } |
| 714 }while( progress ); | 797 }while( progress ); |
| 715 | 798 |
| 716 /* Now compute all first sets */ | 799 /* Now compute all first sets */ |
| 717 do{ | 800 do{ |
| 718 struct symbol *s1, *s2; | 801 struct symbol *s1, *s2; |
| 719 progress = 0; | 802 progress = 0; |
| 720 for(rp=lemp->rule; rp; rp=rp->next){ | 803 for(rp=lemp->rule; rp; rp=rp->next){ |
| 721 s1 = rp->lhs; | 804 s1 = rp->lhs; |
| 722 for(i=0; i<rp->nrhs; i++){ | 805 for(i=0; i<rp->nrhs; i++){ |
| 723 s2 = rp->rhs[i]; | 806 s2 = rp->rhs[i]; |
| 724 if( s2->type==TERMINAL ){ | 807 if( s2->type==TERMINAL ){ |
| 725 progress += SetAdd(s1->firstset,s2->index); | 808 progress += SetAdd(s1->firstset,s2->index); |
| 726 break; | 809 break; |
| 727 }else if( s2->type==MULTITERMINAL ){ | 810 }else if( s2->type==MULTITERMINAL ){ |
| 728 for(j=0; j<s2->nsubsym; j++){ | 811 for(j=0; j<s2->nsubsym; j++){ |
| 729 progress += SetAdd(s1->firstset,s2->subsym[j]->index); | 812 progress += SetAdd(s1->firstset,s2->subsym[j]->index); |
| 730 } | 813 } |
| 731 break; | 814 break; |
| 732 » }else if( s1==s2 ){ | 815 }else if( s1==s2 ){ |
| 733 if( s1->lambda==LEMON_FALSE ) break; | 816 if( s1->lambda==LEMON_FALSE ) break; |
| 734 » }else{ | 817 }else{ |
| 735 progress += SetUnion(s1->firstset,s2->firstset); | 818 progress += SetUnion(s1->firstset,s2->firstset); |
| 736 if( s2->lambda==LEMON_FALSE ) break; | 819 if( s2->lambda==LEMON_FALSE ) break; |
| 737 » } | 820 } |
| 738 } | 821 } |
| 739 } | 822 } |
| 740 }while( progress ); | 823 }while( progress ); |
| 741 return; | 824 return; |
| 742 } | 825 } |
| 743 | 826 |
| 744 /* Compute all LR(0) states for the grammar. Links | 827 /* Compute all LR(0) states for the grammar. Links |
| 745 ** are added to between some states so that the LR(1) follow sets | 828 ** are added to between some states so that the LR(1) follow sets |
| 746 ** can be computed later. | 829 ** can be computed later. |
| 747 */ | 830 */ |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 do{ | 1053 do{ |
| 971 progress = 0; | 1054 progress = 0; |
| 972 for(i=0; i<lemp->nstate; i++){ | 1055 for(i=0; i<lemp->nstate; i++){ |
| 973 for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ | 1056 for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ |
| 974 if( cfp->status==COMPLETE ) continue; | 1057 if( cfp->status==COMPLETE ) continue; |
| 975 for(plp=cfp->fplp; plp; plp=plp->next){ | 1058 for(plp=cfp->fplp; plp; plp=plp->next){ |
| 976 change = SetUnion(plp->cfp->fws,cfp->fws); | 1059 change = SetUnion(plp->cfp->fws,cfp->fws); |
| 977 if( change ){ | 1060 if( change ){ |
| 978 plp->cfp->status = INCOMPLETE; | 1061 plp->cfp->status = INCOMPLETE; |
| 979 progress = 1; | 1062 progress = 1; |
| 980 » } | 1063 } |
| 981 » } | 1064 } |
| 982 cfp->status = COMPLETE; | 1065 cfp->status = COMPLETE; |
| 983 } | 1066 } |
| 984 } | 1067 } |
| 985 }while( progress ); | 1068 }while( progress ); |
| 986 } | 1069 } |
| 987 | 1070 |
| 988 static int resolve_conflict(struct action *,struct action *, struct symbol *); | 1071 static int resolve_conflict(struct action *,struct action *); |
| 989 | 1072 |
| 990 /* Compute the reduce actions, and resolve conflicts. | 1073 /* Compute the reduce actions, and resolve conflicts. |
| 991 */ | 1074 */ |
| 992 void FindActions(struct lemon *lemp) | 1075 void FindActions(struct lemon *lemp) |
| 993 { | 1076 { |
| 994 int i,j; | 1077 int i,j; |
| 995 struct config *cfp; | 1078 struct config *cfp; |
| 996 struct state *stp; | 1079 struct state *stp; |
| 997 struct symbol *sp; | 1080 struct symbol *sp; |
| 998 struct rule *rp; | 1081 struct rule *rp; |
| 999 | 1082 |
| 1000 /* Add all of the reduce actions | 1083 /* Add all of the reduce actions |
| 1001 ** A reduce action is added for each element of the followset of | 1084 ** A reduce action is added for each element of the followset of |
| 1002 ** a configuration which has its dot at the extreme right. | 1085 ** a configuration which has its dot at the extreme right. |
| 1003 */ | 1086 */ |
| 1004 for(i=0; i<lemp->nstate; i++){ /* Loop over all states */ | 1087 for(i=0; i<lemp->nstate; i++){ /* Loop over all states */ |
| 1005 stp = lemp->sorted[i]; | 1088 stp = lemp->sorted[i]; |
| 1006 for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */ | 1089 for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */ |
| 1007 if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */ | 1090 if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */ |
| 1008 for(j=0; j<lemp->nterminal; j++){ | 1091 for(j=0; j<lemp->nterminal; j++){ |
| 1009 if( SetFind(cfp->fws,j) ){ | 1092 if( SetFind(cfp->fws,j) ){ |
| 1010 /* Add a reduce action to the state "stp" which will reduce by the | 1093 /* Add a reduce action to the state "stp" which will reduce by the |
| 1011 ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ | 1094 ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ |
| 1012 Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); | 1095 Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); |
| 1013 } | 1096 } |
| 1014 » } | 1097 } |
| 1015 } | 1098 } |
| 1016 } | 1099 } |
| 1017 } | 1100 } |
| 1018 | 1101 |
| 1019 /* Add the accepting token */ | 1102 /* Add the accepting token */ |
| 1020 if( lemp->start ){ | 1103 if( lemp->start ){ |
| 1021 sp = Symbol_find(lemp->start); | 1104 sp = Symbol_find(lemp->start); |
| 1022 if( sp==0 ) sp = lemp->rule->lhs; | 1105 if( sp==0 ) sp = lemp->rule->lhs; |
| 1023 }else{ | 1106 }else{ |
| 1024 sp = lemp->rule->lhs; | 1107 sp = lemp->rule->lhs; |
| 1025 } | 1108 } |
| 1026 /* Add to the first state (which is always the starting state of the | 1109 /* Add to the first state (which is always the starting state of the |
| 1027 ** finite state machine) an action to ACCEPT if the lookahead is the | 1110 ** finite state machine) an action to ACCEPT if the lookahead is the |
| 1028 ** start nonterminal. */ | 1111 ** start nonterminal. */ |
| 1029 Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); | 1112 Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); |
| 1030 | 1113 |
| 1031 /* Resolve conflicts */ | 1114 /* Resolve conflicts */ |
| 1032 for(i=0; i<lemp->nstate; i++){ | 1115 for(i=0; i<lemp->nstate; i++){ |
| 1033 struct action *ap, *nap; | 1116 struct action *ap, *nap; |
| 1034 struct state *stp; | 1117 struct state *stp; |
| 1035 stp = lemp->sorted[i]; | 1118 stp = lemp->sorted[i]; |
| 1036 /* assert( stp->ap ); */ | 1119 /* assert( stp->ap ); */ |
| 1037 stp->ap = Action_sort(stp->ap); | 1120 stp->ap = Action_sort(stp->ap); |
| 1038 for(ap=stp->ap; ap && ap->next; ap=ap->next){ | 1121 for(ap=stp->ap; ap && ap->next; ap=ap->next){ |
| 1039 for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ | 1122 for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ |
| 1040 /* The two actions "ap" and "nap" have the same lookahead. | 1123 /* The two actions "ap" and "nap" have the same lookahead. |
| 1041 ** Figure out which one should be used */ | 1124 ** Figure out which one should be used */ |
| 1042 lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym); | 1125 lemp->nconflict += resolve_conflict(ap,nap); |
| 1043 } | 1126 } |
| 1044 } | 1127 } |
| 1045 } | 1128 } |
| 1046 | 1129 |
| 1047 /* Report an error for each rule that can never be reduced. */ | 1130 /* Report an error for each rule that can never be reduced. */ |
| 1048 for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE; | 1131 for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE; |
| 1049 for(i=0; i<lemp->nstate; i++){ | 1132 for(i=0; i<lemp->nstate; i++){ |
| 1050 struct action *ap; | 1133 struct action *ap; |
| 1051 for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ | 1134 for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ |
| 1052 if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE; | 1135 if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1067 ** is on an error rule. In that case, take the action which | 1150 ** is on an error rule. In that case, take the action which |
| 1068 ** is not associated with the error rule. If neither or both | 1151 ** is not associated with the error rule. If neither or both |
| 1069 ** actions are associated with an error rule, then try to | 1152 ** actions are associated with an error rule, then try to |
| 1070 ** use precedence to resolve the conflict. | 1153 ** use precedence to resolve the conflict. |
| 1071 ** | 1154 ** |
| 1072 ** If either action is a SHIFT, then it must be apx. This | 1155 ** If either action is a SHIFT, then it must be apx. This |
| 1073 ** function won't work if apx->type==REDUCE and apy->type==SHIFT. | 1156 ** function won't work if apx->type==REDUCE and apy->type==SHIFT. |
| 1074 */ | 1157 */ |
| 1075 static int resolve_conflict( | 1158 static int resolve_conflict( |
| 1076 struct action *apx, | 1159 struct action *apx, |
| 1077 struct action *apy, | 1160 struct action *apy |
| 1078 struct symbol *errsym /* The error symbol (if defined. NULL otherwise) */ | |
| 1079 ){ | 1161 ){ |
| 1080 struct symbol *spx, *spy; | 1162 struct symbol *spx, *spy; |
| 1081 int errcnt = 0; | 1163 int errcnt = 0; |
| 1082 assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */ | 1164 assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */ |
| 1083 if( apx->type==SHIFT && apy->type==SHIFT ){ | 1165 if( apx->type==SHIFT && apy->type==SHIFT ){ |
| 1084 apy->type = SSCONFLICT; | 1166 apy->type = SSCONFLICT; |
| 1085 errcnt++; | 1167 errcnt++; |
| 1086 } | 1168 } |
| 1087 if( apx->type==SHIFT && apy->type==REDUCE ){ | 1169 if( apx->type==SHIFT && apy->type==REDUCE ){ |
| 1088 spx = apx->sp; | 1170 spx = apx->sp; |
| 1089 spy = apy->x.rp->precsym; | 1171 spy = apy->x.rp->precsym; |
| 1090 if( spy==0 || spx->prec<0 || spy->prec<0 ){ | 1172 if( spy==0 || spx->prec<0 || spy->prec<0 ){ |
| 1091 /* Not enough precedence information. */ | 1173 /* Not enough precedence information. */ |
| 1092 apy->type = SRCONFLICT; | 1174 apy->type = SRCONFLICT; |
| 1093 errcnt++; | 1175 errcnt++; |
| 1094 }else if( spx->prec>spy->prec ){ /* higher precedence wins */ | 1176 }else if( spx->prec>spy->prec ){ /* higher precedence wins */ |
| 1095 apy->type = RD_RESOLVED; | 1177 apy->type = RD_RESOLVED; |
| 1096 }else if( spx->prec<spy->prec ){ | 1178 }else if( spx->prec<spy->prec ){ |
| 1097 apx->type = SH_RESOLVED; | 1179 apx->type = SH_RESOLVED; |
| 1098 }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */ | 1180 }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */ |
| 1099 apy->type = RD_RESOLVED; /* associativity */ | 1181 apy->type = RD_RESOLVED; /* associativity */ |
| 1100 }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */ | 1182 }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */ |
| 1101 apx->type = SH_RESOLVED; | 1183 apx->type = SH_RESOLVED; |
| 1102 }else{ | 1184 }else{ |
| 1103 assert( spx->prec==spy->prec && spx->assoc==NONE ); | 1185 assert( spx->prec==spy->prec && spx->assoc==NONE ); |
| 1104 apy->type = SRCONFLICT; | 1186 apx->type = ERROR; |
| 1105 errcnt++; | |
| 1106 } | 1187 } |
| 1107 }else if( apx->type==REDUCE && apy->type==REDUCE ){ | 1188 }else if( apx->type==REDUCE && apy->type==REDUCE ){ |
| 1108 spx = apx->x.rp->precsym; | 1189 spx = apx->x.rp->precsym; |
| 1109 spy = apy->x.rp->precsym; | 1190 spy = apy->x.rp->precsym; |
| 1110 if( spx==0 || spy==0 || spx->prec<0 || | 1191 if( spx==0 || spy==0 || spx->prec<0 || |
| 1111 spy->prec<0 || spx->prec==spy->prec ){ | 1192 spy->prec<0 || spx->prec==spy->prec ){ |
| 1112 apy->type = RRCONFLICT; | 1193 apy->type = RRCONFLICT; |
| 1113 errcnt++; | 1194 errcnt++; |
| 1114 }else if( spx->prec>spy->prec ){ | 1195 }else if( spx->prec>spy->prec ){ |
| 1115 apy->type = RD_RESOLVED; | 1196 apy->type = RD_RESOLVED; |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1274 xsp = rp->rhs[i]; | 1355 xsp = rp->rhs[i]; |
| 1275 if( xsp->type==TERMINAL ){ | 1356 if( xsp->type==TERMINAL ){ |
| 1276 SetAdd(newcfp->fws,xsp->index); | 1357 SetAdd(newcfp->fws,xsp->index); |
| 1277 break; | 1358 break; |
| 1278 }else if( xsp->type==MULTITERMINAL ){ | 1359 }else if( xsp->type==MULTITERMINAL ){ |
| 1279 int k; | 1360 int k; |
| 1280 for(k=0; k<xsp->nsubsym; k++){ | 1361 for(k=0; k<xsp->nsubsym; k++){ |
| 1281 SetAdd(newcfp->fws, xsp->subsym[k]->index); | 1362 SetAdd(newcfp->fws, xsp->subsym[k]->index); |
| 1282 } | 1363 } |
| 1283 break; | 1364 break; |
| 1284 » }else{ | 1365 }else{ |
| 1285 SetUnion(newcfp->fws,xsp->firstset); | 1366 SetUnion(newcfp->fws,xsp->firstset); |
| 1286 if( xsp->lambda==LEMON_FALSE ) break; | 1367 if( xsp->lambda==LEMON_FALSE ) break; |
| 1287 » } | 1368 } |
| 1288 » } | 1369 } |
| 1289 if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); | 1370 if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); |
| 1290 } | 1371 } |
| 1291 } | 1372 } |
| 1292 } | 1373 } |
| 1293 return; | 1374 return; |
| 1294 } | 1375 } |
| 1295 | 1376 |
| 1296 /* Sort the configuration list */ | 1377 /* Sort the configuration list */ |
| 1297 void Configlist_sort(){ | 1378 void Configlist_sort(){ |
| 1298 current = (struct config *)msort((char *)current,(char **)&(current->next),Con
figcmp); | 1379 current = (struct config *)msort((char *)current,(char **)&(current->next),Con
figcmp); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 if( azDefine==0 ){ | 1460 if( azDefine==0 ){ |
| 1380 fprintf(stderr,"out of memory\n"); | 1461 fprintf(stderr,"out of memory\n"); |
| 1381 exit(1); | 1462 exit(1); |
| 1382 } | 1463 } |
| 1383 paz = &azDefine[nDefine-1]; | 1464 paz = &azDefine[nDefine-1]; |
| 1384 *paz = (char *) malloc( lemonStrlen(z)+1 ); | 1465 *paz = (char *) malloc( lemonStrlen(z)+1 ); |
| 1385 if( *paz==0 ){ | 1466 if( *paz==0 ){ |
| 1386 fprintf(stderr,"out of memory\n"); | 1467 fprintf(stderr,"out of memory\n"); |
| 1387 exit(1); | 1468 exit(1); |
| 1388 } | 1469 } |
| 1389 strcpy(*paz, z); | 1470 lemon_strcpy(*paz, z); |
| 1390 for(z=*paz; *z && *z!='='; z++){} | 1471 for(z=*paz; *z && *z!='='; z++){} |
| 1391 *z = 0; | 1472 *z = 0; |
| 1392 } | 1473 } |
| 1393 | 1474 |
| 1394 static char *user_templatename = NULL; | 1475 static char *user_templatename = NULL; |
| 1395 static void handle_T_option(char *z){ | 1476 static void handle_T_option(char *z){ |
| 1396 user_templatename = (char *) malloc( lemonStrlen(z)+1 ); | 1477 user_templatename = (char *) malloc( lemonStrlen(z)+1 ); |
| 1397 if( user_templatename==0 ){ | 1478 if( user_templatename==0 ){ |
| 1398 memory_error(); | 1479 memory_error(); |
| 1399 } | 1480 } |
| 1400 strcpy(user_templatename, z); | 1481 lemon_strcpy(user_templatename, z); |
| 1401 } | 1482 } |
| 1402 | 1483 |
| 1403 /* The main program. Parse the command line and do it... */ | 1484 /* The main program. Parse the command line and do it... */ |
| 1404 int main(int argc, char **argv) | 1485 int main(int argc, char **argv) |
| 1405 { | 1486 { |
| 1406 static int version = 0; | 1487 static int version = 0; |
| 1407 static int rpflag = 0; | 1488 static int rpflag = 0; |
| 1408 static int basisflag = 0; | 1489 static int basisflag = 0; |
| 1409 static int compress = 0; | 1490 static int compress = 0; |
| 1410 static int quiet = 0; | 1491 static int quiet = 0; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1426 {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"}, | 1507 {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"}, |
| 1427 {OPT_FLAG, "s", (char*)&statistics, | 1508 {OPT_FLAG, "s", (char*)&statistics, |
| 1428 "Print parser stats to standard output."}, | 1509 "Print parser stats to standard output."}, |
| 1429 {OPT_FLAG, "x", (char*)&version, "Print the version number."}, | 1510 {OPT_FLAG, "x", (char*)&version, "Print the version number."}, |
| 1430 {OPT_FLAG,0,0,0} | 1511 {OPT_FLAG,0,0,0} |
| 1431 }; | 1512 }; |
| 1432 int i; | 1513 int i; |
| 1433 int exitcode; | 1514 int exitcode; |
| 1434 struct lemon lem; | 1515 struct lemon lem; |
| 1435 | 1516 |
| 1436 atexit(LemonAtExit); | |
| 1437 | |
| 1438 OptInit(argv,options,stderr); | 1517 OptInit(argv,options,stderr); |
| 1439 if( version ){ | 1518 if( version ){ |
| 1440 printf("Lemon version 1.0\n"); | 1519 printf("Lemon version 1.0\n"); |
| 1441 exit(0); | 1520 exit(0); |
| 1442 } | 1521 } |
| 1443 if( OptNArgs()!=1 ){ | 1522 if( OptNArgs()!=1 ){ |
| 1444 fprintf(stderr,"Exactly one filename argument is required.\n"); | 1523 fprintf(stderr,"Exactly one filename argument is required.\n"); |
| 1445 exit(1); | 1524 exit(1); |
| 1446 } | 1525 } |
| 1447 memset(&lem, 0, sizeof(lem)); | 1526 memset(&lem, 0, sizeof(lem)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1461 | 1540 |
| 1462 /* Parse the input file */ | 1541 /* Parse the input file */ |
| 1463 Parse(&lem); | 1542 Parse(&lem); |
| 1464 if( lem.errorcnt ) exit(lem.errorcnt); | 1543 if( lem.errorcnt ) exit(lem.errorcnt); |
| 1465 if( lem.nrule==0 ){ | 1544 if( lem.nrule==0 ){ |
| 1466 fprintf(stderr,"Empty grammar.\n"); | 1545 fprintf(stderr,"Empty grammar.\n"); |
| 1467 exit(1); | 1546 exit(1); |
| 1468 } | 1547 } |
| 1469 | 1548 |
| 1470 /* Count and index the symbols of the grammar */ | 1549 /* Count and index the symbols of the grammar */ |
| 1550 Symbol_new("{default}"); |
| 1471 lem.nsymbol = Symbol_count(); | 1551 lem.nsymbol = Symbol_count(); |
| 1472 Symbol_new("{default}"); | |
| 1473 lem.symbols = Symbol_arrayof(); | 1552 lem.symbols = Symbol_arrayof(); |
| 1474 for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; | 1553 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
| 1475 qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*), Symbolcmpp); | 1554 qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); |
| 1476 for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; | 1555 for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; |
| 1556 while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } |
| 1557 assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); |
| 1558 lem.nsymbol = i - 1; |
| 1477 for(i=1; isupper(lem.symbols[i]->name[0]); i++); | 1559 for(i=1; isupper(lem.symbols[i]->name[0]); i++); |
| 1478 lem.nterminal = i; | 1560 lem.nterminal = i; |
| 1479 | 1561 |
| 1480 /* Generate a reprint of the grammar, if requested on the command line */ | 1562 /* Generate a reprint of the grammar, if requested on the command line */ |
| 1481 if( rpflag ){ | 1563 if( rpflag ){ |
| 1482 Reprint(&lem); | 1564 Reprint(&lem); |
| 1483 }else{ | 1565 }else{ |
| 1484 /* Initialize the size for all follow and first sets */ | 1566 /* Initialize the size for all follow and first sets */ |
| 1485 SetSize(lem.nterminal+1); | 1567 SetSize(lem.nterminal+1); |
| 1486 | 1568 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1530 lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule); | 1612 lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule); |
| 1531 printf(" %d states, %d parser table entries, %d conflicts\
n", | 1613 printf(" %d states, %d parser table entries, %d conflicts\
n", |
| 1532 lem.nstate, lem.tablesize, lem.nconflict); | 1614 lem.nstate, lem.tablesize, lem.nconflict); |
| 1533 } | 1615 } |
| 1534 if( lem.nconflict > 0 ){ | 1616 if( lem.nconflict > 0 ){ |
| 1535 fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); | 1617 fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); |
| 1536 } | 1618 } |
| 1537 | 1619 |
| 1538 /* return 0 on success, 1 on failure. */ | 1620 /* return 0 on success, 1 on failure. */ |
| 1539 exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; | 1621 exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; |
| 1540 successful_exit = (exitcode == 0); | |
| 1541 exit(exitcode); | 1622 exit(exitcode); |
| 1542 return (exitcode); | 1623 return (exitcode); |
| 1543 } | 1624 } |
| 1544 /******************** From the file "msort.c" *******************************/ | 1625 /******************** From the file "msort.c" *******************************/ |
| 1545 /* | 1626 /* |
| 1546 ** A generic merge-sort program. | 1627 ** A generic merge-sort program. |
| 1547 ** | 1628 ** |
| 1548 ** USAGE: | 1629 ** USAGE: |
| 1549 ** Let "ptr" be a pointer to some structure which is at the head of | 1630 ** Let "ptr" be a pointer to some structure which is at the head of |
| 1550 ** a null-terminated list. Then to sort the list call: | 1631 ** a null-terminated list. Then to sort the list call: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1561 ** The function returns a new pointer which is the head of the list | 1642 ** The function returns a new pointer which is the head of the list |
| 1562 ** after sorting. | 1643 ** after sorting. |
| 1563 ** | 1644 ** |
| 1564 ** ALGORITHM: | 1645 ** ALGORITHM: |
| 1565 ** Merge-sort. | 1646 ** Merge-sort. |
| 1566 */ | 1647 */ |
| 1567 | 1648 |
| 1568 /* | 1649 /* |
| 1569 ** Return a pointer to the next structure in the linked list. | 1650 ** Return a pointer to the next structure in the linked list. |
| 1570 */ | 1651 */ |
| 1571 #define NEXT(A) (*(char**)(((unsigned long)A)+offset)) | 1652 #define NEXT(A) (*(char**)(((char*)A)+offset)) |
| 1572 | 1653 |
| 1573 /* | 1654 /* |
| 1574 ** Inputs: | 1655 ** Inputs: |
| 1575 ** a: A sorted, null-terminated linked list. (May be null). | 1656 ** a: A sorted, null-terminated linked list. (May be null). |
| 1576 ** b: A sorted, null-terminated linked list. (May be null). | 1657 ** b: A sorted, null-terminated linked list. (May be null). |
| 1577 ** cmp: A pointer to the comparison function. | 1658 ** cmp: A pointer to the comparison function. |
| 1578 ** offset: Offset in the structure to the "next" field. | 1659 ** offset: Offset in the structure to the "next" field. |
| 1579 ** | 1660 ** |
| 1580 ** Return Value: | 1661 ** Return Value: |
| 1581 ** A pointer to the head of a sorted list containing the elements | 1662 ** A pointer to the head of a sorted list containing the elements |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1955 LHS_ALIAS_3, | 2036 LHS_ALIAS_3, |
| 1956 RHS_ALIAS_1, | 2037 RHS_ALIAS_1, |
| 1957 RHS_ALIAS_2, | 2038 RHS_ALIAS_2, |
| 1958 PRECEDENCE_MARK_1, | 2039 PRECEDENCE_MARK_1, |
| 1959 PRECEDENCE_MARK_2, | 2040 PRECEDENCE_MARK_2, |
| 1960 RESYNC_AFTER_RULE_ERROR, | 2041 RESYNC_AFTER_RULE_ERROR, |
| 1961 RESYNC_AFTER_DECL_ERROR, | 2042 RESYNC_AFTER_DECL_ERROR, |
| 1962 WAITING_FOR_DESTRUCTOR_SYMBOL, | 2043 WAITING_FOR_DESTRUCTOR_SYMBOL, |
| 1963 WAITING_FOR_DATATYPE_SYMBOL, | 2044 WAITING_FOR_DATATYPE_SYMBOL, |
| 1964 WAITING_FOR_FALLBACK_ID, | 2045 WAITING_FOR_FALLBACK_ID, |
| 1965 WAITING_FOR_WILDCARD_ID | 2046 WAITING_FOR_WILDCARD_ID, |
| 2047 WAITING_FOR_CLASS_ID, |
| 2048 WAITING_FOR_CLASS_TOKEN |
| 1966 }; | 2049 }; |
| 1967 struct pstate { | 2050 struct pstate { |
| 1968 char *filename; /* Name of the input file */ | 2051 char *filename; /* Name of the input file */ |
| 1969 int tokenlineno; /* Linenumber at which current token starts */ | 2052 int tokenlineno; /* Linenumber at which current token starts */ |
| 1970 int errorcnt; /* Number of errors so far */ | 2053 int errorcnt; /* Number of errors so far */ |
| 1971 char *tokenstart; /* Text of current token */ | 2054 char *tokenstart; /* Text of current token */ |
| 1972 struct lemon *gp; /* Global state vector */ | 2055 struct lemon *gp; /* Global state vector */ |
| 1973 enum e_state state; /* The state of the parser */ | 2056 enum e_state state; /* The state of the parser */ |
| 1974 struct symbol *fallback; /* The fallback token */ | 2057 struct symbol *fallback; /* The fallback token */ |
| 2058 struct symbol *tkclass; /* Token class symbol */ |
| 1975 struct symbol *lhs; /* Left-hand side of current rule */ | 2059 struct symbol *lhs; /* Left-hand side of current rule */ |
| 1976 const char *lhsalias; /* Alias for the LHS */ | 2060 const char *lhsalias; /* Alias for the LHS */ |
| 1977 int nrhs; /* Number of right-hand side symbols seen */ | 2061 int nrhs; /* Number of right-hand side symbols seen */ |
| 1978 struct symbol *rhs[MAXRHS]; /* RHS symbols */ | 2062 struct symbol *rhs[MAXRHS]; /* RHS symbols */ |
| 1979 const char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */ | 2063 const char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */ |
| 1980 struct rule *prevrule; /* Previous rule parsed */ | 2064 struct rule *prevrule; /* Previous rule parsed */ |
| 1981 const char *declkeyword; /* Keyword of a declaration */ | 2065 const char *declkeyword; /* Keyword of a declaration */ |
| 1982 char **declargslot; /* Where the declaration argument should be put */ | 2066 char **declargslot; /* Where the declaration argument should be put */ |
| 1983 int insertLineMacro; /* Add #line before declaration insert */ | 2067 int insertLineMacro; /* Add #line before declaration insert */ |
| 1984 int *decllinenoslot; /* Where to write declaration line number */ | 2068 int *decllinenoslot; /* Where to write declaration line number */ |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2008 if( x[0]=='%' ){ | 2092 if( x[0]=='%' ){ |
| 2009 psp->state = WAITING_FOR_DECL_KEYWORD; | 2093 psp->state = WAITING_FOR_DECL_KEYWORD; |
| 2010 }else if( islower(x[0]) ){ | 2094 }else if( islower(x[0]) ){ |
| 2011 psp->lhs = Symbol_new(x); | 2095 psp->lhs = Symbol_new(x); |
| 2012 psp->nrhs = 0; | 2096 psp->nrhs = 0; |
| 2013 psp->lhsalias = 0; | 2097 psp->lhsalias = 0; |
| 2014 psp->state = WAITING_FOR_ARROW; | 2098 psp->state = WAITING_FOR_ARROW; |
| 2015 }else if( x[0]=='{' ){ | 2099 }else if( x[0]=='{' ){ |
| 2016 if( psp->prevrule==0 ){ | 2100 if( psp->prevrule==0 ){ |
| 2017 ErrorMsg(psp->filename,psp->tokenlineno, | 2101 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2018 "There is no prior rule opon which to attach the code \ | 2102 "There is no prior rule upon which to attach the code \ |
| 2019 fragment which begins on this line."); | 2103 fragment which begins on this line."); |
| 2020 psp->errorcnt++; | 2104 psp->errorcnt++; |
| 2021 » }else if( psp->prevrule->code!=0 ){ | 2105 }else if( psp->prevrule->code!=0 ){ |
| 2022 ErrorMsg(psp->filename,psp->tokenlineno, | 2106 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2023 "Code fragment beginning on this line is not the first \ | 2107 "Code fragment beginning on this line is not the first \ |
| 2024 to follow the previous rule."); | 2108 to follow the previous rule."); |
| 2025 psp->errorcnt++; | 2109 psp->errorcnt++; |
| 2026 }else{ | 2110 }else{ |
| 2027 psp->prevrule->line = psp->tokenlineno; | 2111 psp->prevrule->line = psp->tokenlineno; |
| 2028 psp->prevrule->code = &x[1]; | 2112 psp->prevrule->code = &x[1]; |
| 2029 » } | 2113 } |
| 2030 }else if( x[0]=='[' ){ | 2114 }else if( x[0]=='[' ){ |
| 2031 psp->state = PRECEDENCE_MARK_1; | 2115 psp->state = PRECEDENCE_MARK_1; |
| 2032 }else{ | 2116 }else{ |
| 2033 ErrorMsg(psp->filename,psp->tokenlineno, | 2117 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2034 "Token \"%s\" should be either \"%%\" or a nonterminal name.", | 2118 "Token \"%s\" should be either \"%%\" or a nonterminal name.", |
| 2035 x); | 2119 x); |
| 2036 psp->errorcnt++; | 2120 psp->errorcnt++; |
| 2037 } | 2121 } |
| 2038 break; | 2122 break; |
| 2039 case PRECEDENCE_MARK_1: | 2123 case PRECEDENCE_MARK_1: |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2112 case IN_RHS: | 2196 case IN_RHS: |
| 2113 if( x[0]=='.' ){ | 2197 if( x[0]=='.' ){ |
| 2114 struct rule *rp; | 2198 struct rule *rp; |
| 2115 rp = (struct rule *)calloc( sizeof(struct rule) + | 2199 rp = (struct rule *)calloc( sizeof(struct rule) + |
| 2116 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1); | 2200 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1); |
| 2117 if( rp==0 ){ | 2201 if( rp==0 ){ |
| 2118 ErrorMsg(psp->filename,psp->tokenlineno, | 2202 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2119 "Can't allocate enough memory for this rule."); | 2203 "Can't allocate enough memory for this rule."); |
| 2120 psp->errorcnt++; | 2204 psp->errorcnt++; |
| 2121 psp->prevrule = 0; | 2205 psp->prevrule = 0; |
| 2122 » }else{ | 2206 }else{ |
| 2123 int i; | 2207 int i; |
| 2124 rp->ruleline = psp->tokenlineno; | 2208 rp->ruleline = psp->tokenlineno; |
| 2125 rp->rhs = (struct symbol**)&rp[1]; | 2209 rp->rhs = (struct symbol**)&rp[1]; |
| 2126 rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); | 2210 rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); |
| 2127 for(i=0; i<psp->nrhs; i++){ | 2211 for(i=0; i<psp->nrhs; i++){ |
| 2128 rp->rhs[i] = psp->rhs[i]; | 2212 rp->rhs[i] = psp->rhs[i]; |
| 2129 rp->rhsalias[i] = psp->alias[i]; | 2213 rp->rhsalias[i] = psp->alias[i]; |
| 2130 » } | 2214 } |
| 2131 rp->lhs = psp->lhs; | 2215 rp->lhs = psp->lhs; |
| 2132 rp->lhsalias = psp->lhsalias; | 2216 rp->lhsalias = psp->lhsalias; |
| 2133 rp->nrhs = psp->nrhs; | 2217 rp->nrhs = psp->nrhs; |
| 2134 rp->code = 0; | 2218 rp->code = 0; |
| 2135 rp->precsym = 0; | 2219 rp->precsym = 0; |
| 2136 rp->index = psp->gp->nrule++; | 2220 rp->index = psp->gp->nrule++; |
| 2137 rp->nextlhs = rp->lhs->rule; | 2221 rp->nextlhs = rp->lhs->rule; |
| 2138 rp->lhs->rule = rp; | 2222 rp->lhs->rule = rp; |
| 2139 rp->next = 0; | 2223 rp->next = 0; |
| 2140 if( psp->firstrule==0 ){ | 2224 if( psp->firstrule==0 ){ |
| 2141 psp->firstrule = psp->lastrule = rp; | 2225 psp->firstrule = psp->lastrule = rp; |
| 2142 » }else{ | 2226 }else{ |
| 2143 psp->lastrule->next = rp; | 2227 psp->lastrule->next = rp; |
| 2144 psp->lastrule = rp; | 2228 psp->lastrule = rp; |
| 2145 » } | 2229 } |
| 2146 psp->prevrule = rp; | 2230 psp->prevrule = rp; |
| 2147 » } | 2231 } |
| 2148 psp->state = WAITING_FOR_DECL_OR_RULE; | 2232 psp->state = WAITING_FOR_DECL_OR_RULE; |
| 2149 }else if( isalpha(x[0]) ){ | 2233 }else if( isalpha(x[0]) ){ |
| 2150 if( psp->nrhs>=MAXRHS ){ | 2234 if( psp->nrhs>=MAXRHS ){ |
| 2151 ErrorMsg(psp->filename,psp->tokenlineno, | 2235 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2152 "Too many symbols on RHS of rule beginning at \"%s\".", | 2236 "Too many symbols on RHS of rule beginning at \"%s\".", |
| 2153 x); | 2237 x); |
| 2154 psp->errorcnt++; | 2238 psp->errorcnt++; |
| 2155 psp->state = RESYNC_AFTER_RULE_ERROR; | 2239 psp->state = RESYNC_AFTER_RULE_ERROR; |
| 2156 » }else{ | 2240 }else{ |
| 2157 psp->rhs[psp->nrhs] = Symbol_new(x); | 2241 psp->rhs[psp->nrhs] = Symbol_new(x); |
| 2158 psp->alias[psp->nrhs] = 0; | 2242 psp->alias[psp->nrhs] = 0; |
| 2159 psp->nrhs++; | 2243 psp->nrhs++; |
| 2160 » } | 2244 } |
| 2161 }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ | 2245 }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ |
| 2162 struct symbol *msp = psp->rhs[psp->nrhs-1]; | 2246 struct symbol *msp = psp->rhs[psp->nrhs-1]; |
| 2163 if( msp->type!=MULTITERMINAL ){ | 2247 if( msp->type!=MULTITERMINAL ){ |
| 2164 struct symbol *origsp = msp; | 2248 struct symbol *origsp = msp; |
| 2165 msp = (struct symbol *) calloc(1,sizeof(*msp)); | 2249 msp = (struct symbol *) calloc(1,sizeof(*msp)); |
| 2166 memset(msp, 0, sizeof(*msp)); | 2250 memset(msp, 0, sizeof(*msp)); |
| 2167 msp->type = MULTITERMINAL; | 2251 msp->type = MULTITERMINAL; |
| 2168 msp->nsubsym = 1; | 2252 msp->nsubsym = 1; |
| 2169 msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); | 2253 msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); |
| 2170 msp->subsym[0] = origsp; | 2254 msp->subsym[0] = origsp; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2214 case WAITING_FOR_DECL_KEYWORD: | 2298 case WAITING_FOR_DECL_KEYWORD: |
| 2215 if( isalpha(x[0]) ){ | 2299 if( isalpha(x[0]) ){ |
| 2216 psp->declkeyword = x; | 2300 psp->declkeyword = x; |
| 2217 psp->declargslot = 0; | 2301 psp->declargslot = 0; |
| 2218 psp->decllinenoslot = 0; | 2302 psp->decllinenoslot = 0; |
| 2219 psp->insertLineMacro = 1; | 2303 psp->insertLineMacro = 1; |
| 2220 psp->state = WAITING_FOR_DECL_ARG; | 2304 psp->state = WAITING_FOR_DECL_ARG; |
| 2221 if( strcmp(x,"name")==0 ){ | 2305 if( strcmp(x,"name")==0 ){ |
| 2222 psp->declargslot = &(psp->gp->name); | 2306 psp->declargslot = &(psp->gp->name); |
| 2223 psp->insertLineMacro = 0; | 2307 psp->insertLineMacro = 0; |
| 2224 » }else if( strcmp(x,"include")==0 ){ | 2308 }else if( strcmp(x,"include")==0 ){ |
| 2225 psp->declargslot = &(psp->gp->include); | 2309 psp->declargslot = &(psp->gp->include); |
| 2226 » }else if( strcmp(x,"code")==0 ){ | 2310 }else if( strcmp(x,"code")==0 ){ |
| 2227 psp->declargslot = &(psp->gp->extracode); | 2311 psp->declargslot = &(psp->gp->extracode); |
| 2228 » }else if( strcmp(x,"token_destructor")==0 ){ | 2312 }else if( strcmp(x,"token_destructor")==0 ){ |
| 2229 psp->declargslot = &psp->gp->tokendest; | 2313 psp->declargslot = &psp->gp->tokendest; |
| 2230 » }else if( strcmp(x,"default_destructor")==0 ){ | 2314 }else if( strcmp(x,"default_destructor")==0 ){ |
| 2231 psp->declargslot = &psp->gp->vardest; | 2315 psp->declargslot = &psp->gp->vardest; |
| 2232 » }else if( strcmp(x,"token_prefix")==0 ){ | 2316 }else if( strcmp(x,"token_prefix")==0 ){ |
| 2233 psp->declargslot = &psp->gp->tokenprefix; | 2317 psp->declargslot = &psp->gp->tokenprefix; |
| 2234 psp->insertLineMacro = 0; | 2318 psp->insertLineMacro = 0; |
| 2235 » }else if( strcmp(x,"syntax_error")==0 ){ | 2319 }else if( strcmp(x,"syntax_error")==0 ){ |
| 2236 psp->declargslot = &(psp->gp->error); | 2320 psp->declargslot = &(psp->gp->error); |
| 2237 » }else if( strcmp(x,"parse_accept")==0 ){ | 2321 }else if( strcmp(x,"parse_accept")==0 ){ |
| 2238 psp->declargslot = &(psp->gp->accept); | 2322 psp->declargslot = &(psp->gp->accept); |
| 2239 » }else if( strcmp(x,"parse_failure")==0 ){ | 2323 }else if( strcmp(x,"parse_failure")==0 ){ |
| 2240 psp->declargslot = &(psp->gp->failure); | 2324 psp->declargslot = &(psp->gp->failure); |
| 2241 » }else if( strcmp(x,"stack_overflow")==0 ){ | 2325 }else if( strcmp(x,"stack_overflow")==0 ){ |
| 2242 psp->declargslot = &(psp->gp->overflow); | 2326 psp->declargslot = &(psp->gp->overflow); |
| 2243 }else if( strcmp(x,"extra_argument")==0 ){ | 2327 }else if( strcmp(x,"extra_argument")==0 ){ |
| 2244 psp->declargslot = &(psp->gp->arg); | 2328 psp->declargslot = &(psp->gp->arg); |
| 2245 psp->insertLineMacro = 0; | 2329 psp->insertLineMacro = 0; |
| 2246 }else if( strcmp(x,"token_type")==0 ){ | 2330 }else if( strcmp(x,"token_type")==0 ){ |
| 2247 psp->declargslot = &(psp->gp->tokentype); | 2331 psp->declargslot = &(psp->gp->tokentype); |
| 2248 psp->insertLineMacro = 0; | 2332 psp->insertLineMacro = 0; |
| 2249 }else if( strcmp(x,"default_type")==0 ){ | 2333 }else if( strcmp(x,"default_type")==0 ){ |
| 2250 psp->declargslot = &(psp->gp->vartype); | 2334 psp->declargslot = &(psp->gp->vartype); |
| 2251 psp->insertLineMacro = 0; | 2335 psp->insertLineMacro = 0; |
| 2252 }else if( strcmp(x,"stack_size")==0 ){ | 2336 }else if( strcmp(x,"stack_size")==0 ){ |
| 2253 psp->declargslot = &(psp->gp->stacksize); | 2337 psp->declargslot = &(psp->gp->stacksize); |
| 2254 psp->insertLineMacro = 0; | 2338 psp->insertLineMacro = 0; |
| 2255 }else if( strcmp(x,"start_symbol")==0 ){ | 2339 }else if( strcmp(x,"start_symbol")==0 ){ |
| 2256 psp->declargslot = &(psp->gp->start); | 2340 psp->declargslot = &(psp->gp->start); |
| 2257 psp->insertLineMacro = 0; | 2341 psp->insertLineMacro = 0; |
| 2258 }else if( strcmp(x,"left")==0 ){ | 2342 }else if( strcmp(x,"left")==0 ){ |
| 2259 psp->preccounter++; | 2343 psp->preccounter++; |
| 2260 psp->declassoc = LEFT; | 2344 psp->declassoc = LEFT; |
| 2261 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; | 2345 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; |
| 2262 }else if( strcmp(x,"right")==0 ){ | 2346 }else if( strcmp(x,"right")==0 ){ |
| 2263 psp->preccounter++; | 2347 psp->preccounter++; |
| 2264 psp->declassoc = RIGHT; | 2348 psp->declassoc = RIGHT; |
| 2265 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; | 2349 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; |
| 2266 }else if( strcmp(x,"nonassoc")==0 ){ | 2350 }else if( strcmp(x,"nonassoc")==0 ){ |
| 2267 psp->preccounter++; | 2351 psp->preccounter++; |
| 2268 psp->declassoc = NONE; | 2352 psp->declassoc = NONE; |
| 2269 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; | 2353 psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; |
| 2270 » }else if( strcmp(x,"destructor")==0 ){ | 2354 }else if( strcmp(x,"destructor")==0 ){ |
| 2271 psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; | 2355 psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; |
| 2272 » }else if( strcmp(x,"type")==0 ){ | 2356 }else if( strcmp(x,"type")==0 ){ |
| 2273 psp->state = WAITING_FOR_DATATYPE_SYMBOL; | 2357 psp->state = WAITING_FOR_DATATYPE_SYMBOL; |
| 2274 }else if( strcmp(x,"fallback")==0 ){ | 2358 }else if( strcmp(x,"fallback")==0 ){ |
| 2275 psp->fallback = 0; | 2359 psp->fallback = 0; |
| 2276 psp->state = WAITING_FOR_FALLBACK_ID; | 2360 psp->state = WAITING_FOR_FALLBACK_ID; |
| 2277 }else if( strcmp(x,"wildcard")==0 ){ | 2361 }else if( strcmp(x,"wildcard")==0 ){ |
| 2278 psp->state = WAITING_FOR_WILDCARD_ID; | 2362 psp->state = WAITING_FOR_WILDCARD_ID; |
| 2363 }else if( strcmp(x,"token_class")==0 ){ |
| 2364 psp->state = WAITING_FOR_CLASS_ID; |
| 2279 }else{ | 2365 }else{ |
| 2280 ErrorMsg(psp->filename,psp->tokenlineno, | 2366 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2281 "Unknown declaration keyword: \"%%%s\".",x); | 2367 "Unknown declaration keyword: \"%%%s\".",x); |
| 2282 psp->errorcnt++; | 2368 psp->errorcnt++; |
| 2283 psp->state = RESYNC_AFTER_DECL_ERROR; | 2369 psp->state = RESYNC_AFTER_DECL_ERROR; |
| 2284 » } | 2370 } |
| 2285 }else{ | 2371 }else{ |
| 2286 ErrorMsg(psp->filename,psp->tokenlineno, | 2372 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2287 "Illegal declaration keyword: \"%s\".",x); | 2373 "Illegal declaration keyword: \"%s\".",x); |
| 2288 psp->errorcnt++; | 2374 psp->errorcnt++; |
| 2289 psp->state = RESYNC_AFTER_DECL_ERROR; | 2375 psp->state = RESYNC_AFTER_DECL_ERROR; |
| 2290 } | 2376 } |
| 2291 break; | 2377 break; |
| 2292 case WAITING_FOR_DESTRUCTOR_SYMBOL: | 2378 case WAITING_FOR_DESTRUCTOR_SYMBOL: |
| 2293 if( !isalpha(x[0]) ){ | 2379 if( !isalpha(x[0]) ){ |
| 2294 ErrorMsg(psp->filename,psp->tokenlineno, | 2380 ErrorMsg(psp->filename,psp->tokenlineno, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2329 case WAITING_FOR_PRECEDENCE_SYMBOL: | 2415 case WAITING_FOR_PRECEDENCE_SYMBOL: |
| 2330 if( x[0]=='.' ){ | 2416 if( x[0]=='.' ){ |
| 2331 psp->state = WAITING_FOR_DECL_OR_RULE; | 2417 psp->state = WAITING_FOR_DECL_OR_RULE; |
| 2332 }else if( isupper(x[0]) ){ | 2418 }else if( isupper(x[0]) ){ |
| 2333 struct symbol *sp; | 2419 struct symbol *sp; |
| 2334 sp = Symbol_new(x); | 2420 sp = Symbol_new(x); |
| 2335 if( sp->prec>=0 ){ | 2421 if( sp->prec>=0 ){ |
| 2336 ErrorMsg(psp->filename,psp->tokenlineno, | 2422 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2337 "Symbol \"%s\" has already be given a precedence.",x); | 2423 "Symbol \"%s\" has already be given a precedence.",x); |
| 2338 psp->errorcnt++; | 2424 psp->errorcnt++; |
| 2339 » }else{ | 2425 }else{ |
| 2340 sp->prec = psp->preccounter; | 2426 sp->prec = psp->preccounter; |
| 2341 sp->assoc = psp->declassoc; | 2427 sp->assoc = psp->declassoc; |
| 2342 » } | 2428 } |
| 2343 }else{ | 2429 }else{ |
| 2344 ErrorMsg(psp->filename,psp->tokenlineno, | 2430 ErrorMsg(psp->filename,psp->tokenlineno, |
| 2345 "Can't assign a precedence to \"%s\".",x); | 2431 "Can't assign a precedence to \"%s\".",x); |
| 2346 psp->errorcnt++; | 2432 psp->errorcnt++; |
| 2347 } | 2433 } |
| 2348 break; | 2434 break; |
| 2349 case WAITING_FOR_DECL_ARG: | 2435 case WAITING_FOR_DECL_ARG: |
| 2350 if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){ | 2436 if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){ |
| 2351 const char *zOld, *zNew; | 2437 const char *zOld, *zNew; |
| 2352 char *zBuf, *z; | 2438 char *zBuf, *z; |
| 2353 int nOld, n, nLine, nNew, nBack; | 2439 int nOld, n, nLine, nNew, nBack; |
| 2354 int addLineMacro; | 2440 int addLineMacro; |
| 2355 char zLine[50]; | 2441 char zLine[50]; |
| 2356 zNew = x; | 2442 zNew = x; |
| 2357 if( zNew[0]=='"' || zNew[0]=='{' ) zNew++; | 2443 if( zNew[0]=='"' || zNew[0]=='{' ) zNew++; |
| 2358 nNew = lemonStrlen(zNew); | 2444 nNew = lemonStrlen(zNew); |
| 2359 if( *psp->declargslot ){ | 2445 if( *psp->declargslot ){ |
| 2360 zOld = *psp->declargslot; | 2446 zOld = *psp->declargslot; |
| 2361 }else{ | 2447 }else{ |
| 2362 zOld = ""; | 2448 zOld = ""; |
| 2363 } | 2449 } |
| 2364 nOld = lemonStrlen(zOld); | 2450 nOld = lemonStrlen(zOld); |
| 2365 n = nOld + nNew + 20; | 2451 n = nOld + nNew + 20; |
| 2366 addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro && | 2452 addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro && |
| 2367 (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0); | 2453 (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0); |
| 2368 if( addLineMacro ){ | 2454 if( addLineMacro ){ |
| 2369 for(z=psp->filename, nBack=0; *z; z++){ | 2455 for(z=psp->filename, nBack=0; *z; z++){ |
| 2370 if( *z=='\\' ) nBack++; | 2456 if( *z=='\\' ) nBack++; |
| 2371 } | 2457 } |
| 2372 sprintf(zLine, "#line %d ", psp->tokenlineno); | 2458 lemon_sprintf(zLine, "#line %d ", psp->tokenlineno); |
| 2373 nLine = lemonStrlen(zLine); | 2459 nLine = lemonStrlen(zLine); |
| 2374 n += nLine + lemonStrlen(psp->filename) + nBack; | 2460 n += nLine + lemonStrlen(psp->filename) + nBack; |
| 2375 } | 2461 } |
| 2376 *psp->declargslot = (char *) realloc(*psp->declargslot, n); | 2462 *psp->declargslot = (char *) realloc(*psp->declargslot, n); |
| 2377 zBuf = *psp->declargslot + nOld; | 2463 zBuf = *psp->declargslot + nOld; |
| 2378 if( addLineMacro ){ | 2464 if( addLineMacro ){ |
| 2379 if( nOld && zBuf[-1]!='\n' ){ | 2465 if( nOld && zBuf[-1]!='\n' ){ |
| 2380 *(zBuf++) = '\n'; | 2466 *(zBuf++) = '\n'; |
| 2381 } | 2467 } |
| 2382 memcpy(zBuf, zLine, nLine); | 2468 memcpy(zBuf, zLine, nLine); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2437 struct symbol *sp = Symbol_new(x); | 2523 struct symbol *sp = Symbol_new(x); |
| 2438 if( psp->gp->wildcard==0 ){ | 2524 if( psp->gp->wildcard==0 ){ |
| 2439 psp->gp->wildcard = sp; | 2525 psp->gp->wildcard = sp; |
| 2440 }else{ | 2526 }else{ |
| 2441 ErrorMsg(psp->filename, psp->tokenlineno, | 2527 ErrorMsg(psp->filename, psp->tokenlineno, |
| 2442 "Extra wildcard to token: %s", x); | 2528 "Extra wildcard to token: %s", x); |
| 2443 psp->errorcnt++; | 2529 psp->errorcnt++; |
| 2444 } | 2530 } |
| 2445 } | 2531 } |
| 2446 break; | 2532 break; |
| 2533 case WAITING_FOR_CLASS_ID: |
| 2534 if( !islower(x[0]) ){ |
| 2535 ErrorMsg(psp->filename, psp->tokenlineno, |
| 2536 "%%token_class must be followed by an identifier: ", x); |
| 2537 psp->errorcnt++; |
| 2538 psp->state = RESYNC_AFTER_DECL_ERROR; |
| 2539 }else if( Symbol_find(x) ){ |
| 2540 ErrorMsg(psp->filename, psp->tokenlineno, |
| 2541 "Symbol \"%s\" already used", x); |
| 2542 psp->errorcnt++; |
| 2543 psp->state = RESYNC_AFTER_DECL_ERROR; |
| 2544 }else{ |
| 2545 psp->tkclass = Symbol_new(x); |
| 2546 psp->tkclass->type = MULTITERMINAL; |
| 2547 psp->state = WAITING_FOR_CLASS_TOKEN; |
| 2548 } |
| 2549 break; |
| 2550 case WAITING_FOR_CLASS_TOKEN: |
| 2551 if( x[0]=='.' ){ |
| 2552 psp->state = WAITING_FOR_DECL_OR_RULE; |
| 2553 }else if( isupper(x[0]) || ((x[0]=='|' || x[0]=='/') && isupper(x[1])) ){ |
| 2554 struct symbol *msp = psp->tkclass; |
| 2555 msp->nsubsym++; |
| 2556 msp->subsym = (struct symbol **) realloc(msp->subsym, |
| 2557 sizeof(struct symbol*)*msp->nsubsym); |
| 2558 if( !isupper(x[0]) ) x++; |
| 2559 msp->subsym[msp->nsubsym-1] = Symbol_new(x); |
| 2560 }else{ |
| 2561 ErrorMsg(psp->filename, psp->tokenlineno, |
| 2562 "%%token_class argument \"%s\" should be a token", x); |
| 2563 psp->errorcnt++; |
| 2564 psp->state = RESYNC_AFTER_DECL_ERROR; |
| 2565 } |
| 2566 break; |
| 2447 case RESYNC_AFTER_RULE_ERROR: | 2567 case RESYNC_AFTER_RULE_ERROR: |
| 2448 /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; | 2568 /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; |
| 2449 ** break; */ | 2569 ** break; */ |
| 2450 case RESYNC_AFTER_DECL_ERROR: | 2570 case RESYNC_AFTER_DECL_ERROR: |
| 2451 if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; | 2571 if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; |
| 2452 if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD; | 2572 if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD; |
| 2453 break; | 2573 break; |
| 2454 } | 2574 } |
| 2455 } | 2575 } |
| 2456 | 2576 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2531 fp = fopen(ps.filename,"rb"); | 2651 fp = fopen(ps.filename,"rb"); |
| 2532 if( fp==0 ){ | 2652 if( fp==0 ){ |
| 2533 ErrorMsg(ps.filename,0,"Can't open this file for reading."); | 2653 ErrorMsg(ps.filename,0,"Can't open this file for reading."); |
| 2534 gp->errorcnt++; | 2654 gp->errorcnt++; |
| 2535 return; | 2655 return; |
| 2536 } | 2656 } |
| 2537 fseek(fp,0,2); | 2657 fseek(fp,0,2); |
| 2538 filesize = ftell(fp); | 2658 filesize = ftell(fp); |
| 2539 rewind(fp); | 2659 rewind(fp); |
| 2540 filebuf = (char *)malloc( filesize+1 ); | 2660 filebuf = (char *)malloc( filesize+1 ); |
| 2541 if( filebuf==0 ){ | 2661 if( filesize>100000000 || filebuf==0 ){ |
| 2542 ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.", | 2662 ErrorMsg(ps.filename,0,"Input file too large."); |
| 2543 filesize+1); | |
| 2544 gp->errorcnt++; | 2663 gp->errorcnt++; |
| 2664 fclose(fp); |
| 2545 return; | 2665 return; |
| 2546 } | 2666 } |
| 2547 if( fread(filebuf,1,filesize,fp)!=filesize ){ | 2667 if( fread(filebuf,1,filesize,fp)!=filesize ){ |
| 2548 ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", | 2668 ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", |
| 2549 filesize); | 2669 filesize); |
| 2550 free(filebuf); | 2670 free(filebuf); |
| 2551 gp->errorcnt++; | 2671 gp->errorcnt++; |
| 2672 fclose(fp); |
| 2552 return; | 2673 return; |
| 2553 } | 2674 } |
| 2554 fclose(fp); | 2675 fclose(fp); |
| 2555 filebuf[filesize] = 0; | 2676 filebuf[filesize] = 0; |
| 2556 | 2677 |
| 2557 /* Make an initial pass through the file to handle %ifdef and %ifndef */ | 2678 /* Make an initial pass through the file to handle %ifdef and %ifndef */ |
| 2558 preprocess_input(filebuf); | 2679 preprocess_input(filebuf); |
| 2559 | 2680 |
| 2560 /* Now scan the text of the input file */ | 2681 /* Now scan the text of the input file */ |
| 2561 lineno = 1; | 2682 lineno = 1; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2600 else if( c=='{' ) level++; | 2721 else if( c=='{' ) level++; |
| 2601 else if( c=='}' ) level--; | 2722 else if( c=='}' ) level--; |
| 2602 else if( c=='/' && cp[1]=='*' ){ /* Skip comments */ | 2723 else if( c=='/' && cp[1]=='*' ){ /* Skip comments */ |
| 2603 int prevc; | 2724 int prevc; |
| 2604 cp = &cp[2]; | 2725 cp = &cp[2]; |
| 2605 prevc = 0; | 2726 prevc = 0; |
| 2606 while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){ | 2727 while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){ |
| 2607 if( c=='\n' ) lineno++; | 2728 if( c=='\n' ) lineno++; |
| 2608 prevc = c; | 2729 prevc = c; |
| 2609 cp++; | 2730 cp++; |
| 2610 » } | 2731 } |
| 2611 » }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */ | 2732 }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */ |
| 2612 cp = &cp[2]; | 2733 cp = &cp[2]; |
| 2613 while( (c= *cp)!=0 && c!='\n' ) cp++; | 2734 while( (c= *cp)!=0 && c!='\n' ) cp++; |
| 2614 if( c ) lineno++; | 2735 if( c ) lineno++; |
| 2615 » }else if( c=='\'' || c=='\"' ){ /* String a character literals */ | 2736 }else if( c=='\'' || c=='\"' ){ /* String a character literals */ |
| 2616 int startchar, prevc; | 2737 int startchar, prevc; |
| 2617 startchar = c; | 2738 startchar = c; |
| 2618 prevc = 0; | 2739 prevc = 0; |
| 2619 for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){ | 2740 for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){ |
| 2620 if( c=='\n' ) lineno++; | 2741 if( c=='\n' ) lineno++; |
| 2621 if( prevc=='\\' ) prevc = 0; | 2742 if( prevc=='\\' ) prevc = 0; |
| 2622 else prevc = c; | 2743 else prevc = c; |
| 2623 » } | 2744 } |
| 2624 » } | 2745 } |
| 2625 } | 2746 } |
| 2626 if( c==0 ){ | 2747 if( c==0 ){ |
| 2627 ErrorMsg(ps.filename,ps.tokenlineno, | 2748 ErrorMsg(ps.filename,ps.tokenlineno, |
| 2628 "C code starting on this line is not terminated before the end of the file."); | 2749 "C code starting on this line is not terminated before the end of the file."); |
| 2629 ps.errorcnt++; | 2750 ps.errorcnt++; |
| 2630 nextcp = cp; | 2751 nextcp = cp; |
| 2631 }else{ | 2752 }else{ |
| 2632 nextcp = cp+1; | 2753 nextcp = cp+1; |
| 2633 } | 2754 } |
| 2634 }else if( isalnum(c) ){ /* Identifiers */ | 2755 }else if( isalnum(c) ){ /* Identifiers */ |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2729 PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) | 2850 PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) |
| 2730 { | 2851 { |
| 2731 char *name; | 2852 char *name; |
| 2732 char *cp; | 2853 char *cp; |
| 2733 | 2854 |
| 2734 name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 ); | 2855 name = (char*)malloc( lemonStrlen(lemp->filename) + lemonStrlen(suffix) + 5 ); |
| 2735 if( name==0 ){ | 2856 if( name==0 ){ |
| 2736 fprintf(stderr,"Can't allocate space for a filename.\n"); | 2857 fprintf(stderr,"Can't allocate space for a filename.\n"); |
| 2737 exit(1); | 2858 exit(1); |
| 2738 } | 2859 } |
| 2739 strcpy(name,lemp->filename); | 2860 lemon_strcpy(name,lemp->filename); |
| 2740 cp = strrchr(name,'.'); | 2861 cp = strrchr(name,'.'); |
| 2741 if( cp ) *cp = 0; | 2862 if( cp ) *cp = 0; |
| 2742 strcat(name,suffix); | 2863 lemon_strcat(name,suffix); |
| 2743 return name; | 2864 return name; |
| 2744 } | 2865 } |
| 2745 | 2866 |
| 2746 /* Open a file with a name based on the name of the input file, | 2867 /* Open a file with a name based on the name of the input file, |
| 2747 ** but with a different (specified) suffix, and return a pointer | 2868 ** but with a different (specified) suffix, and return a pointer |
| 2748 ** to the stream */ | 2869 ** to the stream */ |
| 2749 PRIVATE FILE *file_open( | 2870 PRIVATE FILE *file_open( |
| 2750 struct lemon *lemp, | 2871 struct lemon *lemp, |
| 2751 const char *suffix, | 2872 const char *suffix, |
| 2752 const char *mode | 2873 const char *mode |
| 2753 ){ | 2874 ){ |
| 2754 FILE *fp; | 2875 FILE *fp; |
| 2755 | 2876 |
| 2756 if( lemp->outname ) free(lemp->outname); | 2877 if( lemp->outname ) free(lemp->outname); |
| 2757 lemp->outname = file_makename(lemp, suffix); | 2878 lemp->outname = file_makename(lemp, suffix); |
| 2758 fp = fopen(lemp->outname,mode); | 2879 fp = fopen(lemp->outname,mode); |
| 2759 if( fp==0 && *mode=='w' ){ | 2880 if( fp==0 && *mode=='w' ){ |
| 2760 fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname); | 2881 fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname); |
| 2761 lemp->errorcnt++; | 2882 lemp->errorcnt++; |
| 2762 return 0; | 2883 return 0; |
| 2763 } | 2884 } |
| 2764 | |
| 2765 /* Add files we create to a list, so we can delete them if we fail. This | |
| 2766 ** is to keep makefiles from getting confused. We don't include .out files, | |
| 2767 ** though: this is debug information, and you don't want it deleted if there | |
| 2768 ** was an error you need to track down. | |
| 2769 */ | |
| 2770 if(( *mode=='w' ) && (strcmp(suffix, ".out") != 0)){ | |
| 2771 const char **ptr = (const char **) | |
| 2772 realloc(made_files, sizeof (const char **) * (made_files_count + 1)); | |
| 2773 const char *fname = Strsafe(lemp->outname); | |
| 2774 if ((ptr == NULL) || (fname == NULL)) { | |
| 2775 free(ptr); | |
| 2776 memory_error(); | |
| 2777 } | |
| 2778 made_files = ptr; | |
| 2779 made_files[made_files_count++] = fname; | |
| 2780 } | |
| 2781 return fp; | 2885 return fp; |
| 2782 } | 2886 } |
| 2783 | 2887 |
| 2784 /* Duplicate the input file without comments and without actions | 2888 /* Duplicate the input file without comments and without actions |
| 2785 ** on rules */ | 2889 ** on rules */ |
| 2786 void Reprint(struct lemon *lemp) | 2890 void Reprint(struct lemon *lemp) |
| 2787 { | 2891 { |
| 2788 struct rule *rp; | 2892 struct rule *rp; |
| 2789 struct symbol *sp; | 2893 struct symbol *sp; |
| 2790 int i, j, maxlen, len, ncolumns, skip; | 2894 int i, j, maxlen, len, ncolumns, skip; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2806 printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name); | 2910 printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name); |
| 2807 } | 2911 } |
| 2808 printf("\n"); | 2912 printf("\n"); |
| 2809 } | 2913 } |
| 2810 for(rp=lemp->rule; rp; rp=rp->next){ | 2914 for(rp=lemp->rule; rp; rp=rp->next){ |
| 2811 printf("%s",rp->lhs->name); | 2915 printf("%s",rp->lhs->name); |
| 2812 /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */ | 2916 /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */ |
| 2813 printf(" ::="); | 2917 printf(" ::="); |
| 2814 for(i=0; i<rp->nrhs; i++){ | 2918 for(i=0; i<rp->nrhs; i++){ |
| 2815 sp = rp->rhs[i]; | 2919 sp = rp->rhs[i]; |
| 2816 printf(" %s", sp->name); | |
| 2817 if( sp->type==MULTITERMINAL ){ | 2920 if( sp->type==MULTITERMINAL ){ |
| 2921 printf(" %s", sp->subsym[0]->name); |
| 2818 for(j=1; j<sp->nsubsym; j++){ | 2922 for(j=1; j<sp->nsubsym; j++){ |
| 2819 printf("|%s", sp->subsym[j]->name); | 2923 printf("|%s", sp->subsym[j]->name); |
| 2820 } | 2924 } |
| 2925 }else{ |
| 2926 printf(" %s", sp->name); |
| 2821 } | 2927 } |
| 2822 /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ | 2928 /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ |
| 2823 } | 2929 } |
| 2824 printf("."); | 2930 printf("."); |
| 2825 if( rp->precsym ) printf(" [%s]",rp->precsym->name); | 2931 if( rp->precsym ) printf(" [%s]",rp->precsym->name); |
| 2826 /* if( rp->code ) printf("\n %s",rp->code); */ | 2932 /* if( rp->code ) printf("\n %s",rp->code); */ |
| 2827 printf("\n"); | 2933 printf("\n"); |
| 2828 } | 2934 } |
| 2829 } | 2935 } |
| 2830 | 2936 |
| 2831 void ConfigPrint(FILE *fp, struct config *cfp) | 2937 void ConfigPrint(FILE *fp, struct config *cfp) |
| 2832 { | 2938 { |
| 2833 struct rule *rp; | 2939 struct rule *rp; |
| 2834 struct symbol *sp; | 2940 struct symbol *sp; |
| 2835 int i, j; | 2941 int i, j; |
| 2836 rp = cfp->rp; | 2942 rp = cfp->rp; |
| 2837 fprintf(fp,"%s ::=",rp->lhs->name); | 2943 fprintf(fp,"%s ::=",rp->lhs->name); |
| 2838 for(i=0; i<=rp->nrhs; i++){ | 2944 for(i=0; i<=rp->nrhs; i++){ |
| 2839 if( i==cfp->dot ) fprintf(fp," *"); | 2945 if( i==cfp->dot ) fprintf(fp," *"); |
| 2840 if( i==rp->nrhs ) break; | 2946 if( i==rp->nrhs ) break; |
| 2841 sp = rp->rhs[i]; | 2947 sp = rp->rhs[i]; |
| 2842 fprintf(fp," %s", sp->name); | |
| 2843 if( sp->type==MULTITERMINAL ){ | 2948 if( sp->type==MULTITERMINAL ){ |
| 2949 fprintf(fp," %s", sp->subsym[0]->name); |
| 2844 for(j=1; j<sp->nsubsym; j++){ | 2950 for(j=1; j<sp->nsubsym; j++){ |
| 2845 fprintf(fp,"|%s",sp->subsym[j]->name); | 2951 fprintf(fp,"|%s",sp->subsym[j]->name); |
| 2846 } | 2952 } |
| 2953 }else{ |
| 2954 fprintf(fp," %s", sp->name); |
| 2847 } | 2955 } |
| 2848 } | 2956 } |
| 2849 } | 2957 } |
| 2850 | 2958 |
| 2851 /* #define TEST */ | 2959 /* #define TEST */ |
| 2852 #if 0 | 2960 #if 0 |
| 2853 /* Print a set */ | 2961 /* Print a set */ |
| 2854 PRIVATE void SetPrint(out,set,lemp) | 2962 PRIVATE void SetPrint(out,set,lemp) |
| 2855 FILE *out; | 2963 FILE *out; |
| 2856 char *set; | 2964 char *set; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2946 fp = file_open(lemp,".out","wb"); | 3054 fp = file_open(lemp,".out","wb"); |
| 2947 if( fp==0 ) return; | 3055 if( fp==0 ) return; |
| 2948 for(i=0; i<lemp->nstate; i++){ | 3056 for(i=0; i<lemp->nstate; i++){ |
| 2949 stp = lemp->sorted[i]; | 3057 stp = lemp->sorted[i]; |
| 2950 fprintf(fp,"State %d:\n",stp->statenum); | 3058 fprintf(fp,"State %d:\n",stp->statenum); |
| 2951 if( lemp->basisflag ) cfp=stp->bp; | 3059 if( lemp->basisflag ) cfp=stp->bp; |
| 2952 else cfp=stp->cfp; | 3060 else cfp=stp->cfp; |
| 2953 while( cfp ){ | 3061 while( cfp ){ |
| 2954 char buf[20]; | 3062 char buf[20]; |
| 2955 if( cfp->dot==cfp->rp->nrhs ){ | 3063 if( cfp->dot==cfp->rp->nrhs ){ |
| 2956 sprintf(buf,"(%d)",cfp->rp->index); | 3064 lemon_sprintf(buf,"(%d)",cfp->rp->index); |
| 2957 fprintf(fp," %5s ",buf); | 3065 fprintf(fp," %5s ",buf); |
| 2958 }else{ | 3066 }else{ |
| 2959 fprintf(fp," "); | 3067 fprintf(fp," "); |
| 2960 } | 3068 } |
| 2961 ConfigPrint(fp,cfp); | 3069 ConfigPrint(fp,cfp); |
| 2962 fprintf(fp,"\n"); | 3070 fprintf(fp,"\n"); |
| 2963 #if 0 | 3071 #if 0 |
| 2964 SetPrint(fp,cfp->fws,lemp); | 3072 SetPrint(fp,cfp->fws,lemp); |
| 2965 PlinkPrint(fp,cfp->fplp,"To "); | 3073 PlinkPrint(fp,cfp->fplp,"To "); |
| 2966 PlinkPrint(fp,cfp->bplp,"From"); | 3074 PlinkPrint(fp,cfp->bplp,"From"); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3011 | 3119 |
| 3012 #ifdef __WIN32__ | 3120 #ifdef __WIN32__ |
| 3013 cp = strrchr(argv0,'\\'); | 3121 cp = strrchr(argv0,'\\'); |
| 3014 #else | 3122 #else |
| 3015 cp = strrchr(argv0,'/'); | 3123 cp = strrchr(argv0,'/'); |
| 3016 #endif | 3124 #endif |
| 3017 if( cp ){ | 3125 if( cp ){ |
| 3018 c = *cp; | 3126 c = *cp; |
| 3019 *cp = 0; | 3127 *cp = 0; |
| 3020 path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); | 3128 path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); |
| 3021 if( path ) sprintf(path,"%s/%s",argv0,name); | 3129 if( path ) lemon_sprintf(path,"%s/%s",argv0,name); |
| 3022 *cp = c; | 3130 *cp = c; |
| 3023 }else{ | 3131 }else{ |
| 3024 pathlist = getenv("PATH"); | 3132 pathlist = getenv("PATH"); |
| 3025 if( pathlist==0 ) pathlist = ".:/bin:/usr/bin"; | 3133 if( pathlist==0 ) pathlist = ".:/bin:/usr/bin"; |
| 3026 pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 ); | 3134 pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 ); |
| 3027 path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); | 3135 path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); |
| 3028 if( (pathbuf != 0) && (path!=0) ){ | 3136 if( (pathbuf != 0) && (path!=0) ){ |
| 3029 pathbufptr = pathbuf; | 3137 pathbufptr = pathbuf; |
| 3030 strcpy(pathbuf, pathlist); | 3138 lemon_strcpy(pathbuf, pathlist); |
| 3031 while( *pathbuf ){ | 3139 while( *pathbuf ){ |
| 3032 cp = strchr(pathbuf,':'); | 3140 cp = strchr(pathbuf,':'); |
| 3033 if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)]; | 3141 if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)]; |
| 3034 c = *cp; | 3142 c = *cp; |
| 3035 *cp = 0; | 3143 *cp = 0; |
| 3036 sprintf(path,"%s/%s",pathbuf,name); | 3144 lemon_sprintf(path,"%s/%s",pathbuf,name); |
| 3037 *cp = c; | 3145 *cp = c; |
| 3038 if( c==0 ) pathbuf[0] = 0; | 3146 if( c==0 ) pathbuf[0] = 0; |
| 3039 else pathbuf = &cp[1]; | 3147 else pathbuf = &cp[1]; |
| 3040 if( access(path,modemask)==0 ) break; | 3148 if( access(path,modemask)==0 ) break; |
| 3041 } | 3149 } |
| 3042 free(pathbufptr); | 3150 free(pathbufptr); |
| 3043 } | 3151 } |
| 3044 } | 3152 } |
| 3045 return path; | 3153 return path; |
| 3046 } | 3154 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3117 if( in==0 ){ | 3225 if( in==0 ){ |
| 3118 fprintf(stderr,"Can't open the template file \"%s\".\n",user_templatename)
; | 3226 fprintf(stderr,"Can't open the template file \"%s\".\n",user_templatename)
; |
| 3119 lemp->errorcnt++; | 3227 lemp->errorcnt++; |
| 3120 return 0; | 3228 return 0; |
| 3121 } | 3229 } |
| 3122 return in; | 3230 return in; |
| 3123 } | 3231 } |
| 3124 | 3232 |
| 3125 cp = strrchr(lemp->filename,'.'); | 3233 cp = strrchr(lemp->filename,'.'); |
| 3126 if( cp ){ | 3234 if( cp ){ |
| 3127 sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); | 3235 lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); |
| 3128 }else{ | 3236 }else{ |
| 3129 sprintf(buf,"%s.lt",lemp->filename); | 3237 lemon_sprintf(buf,"%s.lt",lemp->filename); |
| 3130 } | 3238 } |
| 3131 if( access(buf,004)==0 ){ | 3239 if( access(buf,004)==0 ){ |
| 3132 tpltname = buf; | 3240 tpltname = buf; |
| 3133 }else if( access(templatename,004)==0 ){ | 3241 }else if( access(templatename,004)==0 ){ |
| 3134 tpltname = templatename; | 3242 tpltname = templatename; |
| 3135 }else{ | 3243 }else{ |
| 3136 tpltname = pathsearch(lemp->argv0,templatename,0); | 3244 tpltname = pathsearch(lemp->argv0,templatename,0); |
| 3137 } | 3245 } |
| 3138 if( tpltname==0 ){ | 3246 if( tpltname==0 ){ |
| 3139 fprintf(stderr,"Can't find the parser driver template file \"%s\".\n", | 3247 fprintf(stderr,"Can't find the parser driver template file \"%s\".\n", |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3270 n = lemonStrlen(zText); | 3378 n = lemonStrlen(zText); |
| 3271 } | 3379 } |
| 3272 if( (int) (n+sizeof(zInt)*2+used) >= alloced ){ | 3380 if( (int) (n+sizeof(zInt)*2+used) >= alloced ){ |
| 3273 alloced = n + sizeof(zInt)*2 + used + 200; | 3381 alloced = n + sizeof(zInt)*2 + used + 200; |
| 3274 z = (char *) realloc(z, alloced); | 3382 z = (char *) realloc(z, alloced); |
| 3275 } | 3383 } |
| 3276 if( z==0 ) return empty; | 3384 if( z==0 ) return empty; |
| 3277 while( n-- > 0 ){ | 3385 while( n-- > 0 ){ |
| 3278 c = *(zText++); | 3386 c = *(zText++); |
| 3279 if( c=='%' && n>0 && zText[0]=='d' ){ | 3387 if( c=='%' && n>0 && zText[0]=='d' ){ |
| 3280 sprintf(zInt, "%d", p1); | 3388 lemon_sprintf(zInt, "%d", p1); |
| 3281 p1 = p2; | 3389 p1 = p2; |
| 3282 strcpy(&z[used], zInt); | 3390 lemon_strcpy(&z[used], zInt); |
| 3283 used += lemonStrlen(&z[used]); | 3391 used += lemonStrlen(&z[used]); |
| 3284 zText++; | 3392 zText++; |
| 3285 n--; | 3393 n--; |
| 3286 }else{ | 3394 }else{ |
| 3287 z[used++] = c; | 3395 z[used++] = c; |
| 3288 } | 3396 } |
| 3289 } | 3397 } |
| 3290 z[used] = 0; | 3398 z[used] = 0; |
| 3291 return z; | 3399 return z; |
| 3292 } | 3400 } |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3421 struct lemon *lemp, /* The main info structure for this parser */ | 3529 struct lemon *lemp, /* The main info structure for this parser */ |
| 3422 int *plineno, /* Pointer to the line number */ | 3530 int *plineno, /* Pointer to the line number */ |
| 3423 int mhflag /* True if generating makeheaders output */ | 3531 int mhflag /* True if generating makeheaders output */ |
| 3424 ){ | 3532 ){ |
| 3425 int lineno = *plineno; /* The line number of the output */ | 3533 int lineno = *plineno; /* The line number of the output */ |
| 3426 char **types; /* A hash table of datatypes */ | 3534 char **types; /* A hash table of datatypes */ |
| 3427 int arraysize; /* Size of the "types" array */ | 3535 int arraysize; /* Size of the "types" array */ |
| 3428 int maxdtlength; /* Maximum length of any ".datatype" field. */ | 3536 int maxdtlength; /* Maximum length of any ".datatype" field. */ |
| 3429 char *stddt; /* Standardized name for a datatype */ | 3537 char *stddt; /* Standardized name for a datatype */ |
| 3430 int i,j; /* Loop counters */ | 3538 int i,j; /* Loop counters */ |
| 3431 int hash; /* For hashing the name of a type */ | 3539 unsigned hash; /* For hashing the name of a type */ |
| 3432 const char *name; /* Name of the parser */ | 3540 const char *name; /* Name of the parser */ |
| 3433 | 3541 |
| 3434 /* Allocate and initialize types[] and allocate stddt[] */ | 3542 /* Allocate and initialize types[] and allocate stddt[] */ |
| 3435 arraysize = lemp->nsymbol * 2; | 3543 arraysize = lemp->nsymbol * 2; |
| 3436 types = (char**)calloc( arraysize, sizeof(char*) ); | 3544 types = (char**)calloc( arraysize, sizeof(char*) ); |
| 3545 if( types==0 ){ |
| 3546 fprintf(stderr,"Out of memory.\n"); |
| 3547 exit(1); |
| 3548 } |
| 3437 for(i=0; i<arraysize; i++) types[i] = 0; | 3549 for(i=0; i<arraysize; i++) types[i] = 0; |
| 3438 maxdtlength = 0; | 3550 maxdtlength = 0; |
| 3439 if( lemp->vartype ){ | 3551 if( lemp->vartype ){ |
| 3440 maxdtlength = lemonStrlen(lemp->vartype); | 3552 maxdtlength = lemonStrlen(lemp->vartype); |
| 3441 } | 3553 } |
| 3442 for(i=0; i<lemp->nsymbol; i++){ | 3554 for(i=0; i<lemp->nsymbol; i++){ |
| 3443 int len; | 3555 int len; |
| 3444 struct symbol *sp = lemp->symbols[i]; | 3556 struct symbol *sp = lemp->symbols[i]; |
| 3445 if( sp->datatype==0 ) continue; | 3557 if( sp->datatype==0 ) continue; |
| 3446 len = lemonStrlen(sp->datatype); | 3558 len = lemonStrlen(sp->datatype); |
| 3447 if( len>maxdtlength ) maxdtlength = len; | 3559 if( len>maxdtlength ) maxdtlength = len; |
| 3448 } | 3560 } |
| 3449 stddt = (char*)malloc( maxdtlength*2 + 1 ); | 3561 stddt = (char*)malloc( maxdtlength*2 + 1 ); |
| 3450 if( types==0 || stddt==0 ){ | 3562 if( stddt==0 ){ |
| 3451 fprintf(stderr,"Out of memory.\n"); | 3563 fprintf(stderr,"Out of memory.\n"); |
| 3452 exit(1); | 3564 exit(1); |
| 3453 } | 3565 } |
| 3454 | 3566 |
| 3455 /* Build a hash table of datatypes. The ".dtnum" field of each symbol | 3567 /* Build a hash table of datatypes. The ".dtnum" field of each symbol |
| 3456 ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is | 3568 ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is |
| 3457 ** used for terminal symbols. If there is no %default_type defined then | 3569 ** used for terminal symbols. If there is no %default_type defined then |
| 3458 ** 0 is also used as the .dtnum value for nonterminals which do not specify | 3570 ** 0 is also used as the .dtnum value for nonterminals which do not specify |
| 3459 ** a datatype using the %type directive. | 3571 ** a datatype using the %type directive. |
| 3460 */ | 3572 */ |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3484 for(j=0; stddt[j]; j++){ | 3596 for(j=0; stddt[j]; j++){ |
| 3485 hash = hash*53 + stddt[j]; | 3597 hash = hash*53 + stddt[j]; |
| 3486 } | 3598 } |
| 3487 hash = (hash & 0x7fffffff)%arraysize; | 3599 hash = (hash & 0x7fffffff)%arraysize; |
| 3488 while( types[hash] ){ | 3600 while( types[hash] ){ |
| 3489 if( strcmp(types[hash],stddt)==0 ){ | 3601 if( strcmp(types[hash],stddt)==0 ){ |
| 3490 sp->dtnum = hash + 1; | 3602 sp->dtnum = hash + 1; |
| 3491 break; | 3603 break; |
| 3492 } | 3604 } |
| 3493 hash++; | 3605 hash++; |
| 3494 if( hash>=arraysize ) hash = 0; | 3606 if( hash>=(unsigned)arraysize ) hash = 0; |
| 3495 } | 3607 } |
| 3496 if( types[hash]==0 ){ | 3608 if( types[hash]==0 ){ |
| 3497 sp->dtnum = hash + 1; | 3609 sp->dtnum = hash + 1; |
| 3498 types[hash] = (char*)malloc( lemonStrlen(stddt)+1 ); | 3610 types[hash] = (char*)malloc( lemonStrlen(stddt)+1 ); |
| 3499 if( types[hash]==0 ){ | 3611 if( types[hash]==0 ){ |
| 3500 fprintf(stderr,"Out of memory.\n"); | 3612 fprintf(stderr,"Out of memory.\n"); |
| 3501 exit(1); | 3613 exit(1); |
| 3502 } | 3614 } |
| 3503 strcpy(types[hash],stddt); | 3615 lemon_strcpy(types[hash],stddt); |
| 3504 } | 3616 } |
| 3505 } | 3617 } |
| 3506 | 3618 |
| 3507 /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */ | 3619 /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */ |
| 3508 name = lemp->name ? lemp->name : "Parse"; | 3620 name = lemp->name ? lemp->name : "Parse"; |
| 3509 lineno = *plineno; | 3621 lineno = *plineno; |
| 3510 if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; } | 3622 if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; } |
| 3511 fprintf(out,"#define %sTOKENTYPE %s\n",name, | 3623 fprintf(out,"#define %sTOKENTYPE %s\n",name, |
| 3512 lemp->tokentype?lemp->tokentype:"void*"); lineno++; | 3624 lemp->tokentype?lemp->tokentype:"void*"); lineno++; |
| 3513 if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } | 3625 if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3579 } | 3691 } |
| 3580 | 3692 |
| 3581 /* | 3693 /* |
| 3582 ** Write text on "out" that describes the rule "rp". | 3694 ** Write text on "out" that describes the rule "rp". |
| 3583 */ | 3695 */ |
| 3584 static void writeRuleText(FILE *out, struct rule *rp){ | 3696 static void writeRuleText(FILE *out, struct rule *rp){ |
| 3585 int j; | 3697 int j; |
| 3586 fprintf(out,"%s ::=", rp->lhs->name); | 3698 fprintf(out,"%s ::=", rp->lhs->name); |
| 3587 for(j=0; j<rp->nrhs; j++){ | 3699 for(j=0; j<rp->nrhs; j++){ |
| 3588 struct symbol *sp = rp->rhs[j]; | 3700 struct symbol *sp = rp->rhs[j]; |
| 3589 fprintf(out," %s", sp->name); | 3701 if( sp->type!=MULTITERMINAL ){ |
| 3590 if( sp->type==MULTITERMINAL ){ | 3702 fprintf(out," %s", sp->name); |
| 3703 }else{ |
| 3591 int k; | 3704 int k; |
| 3705 fprintf(out," %s", sp->subsym[0]->name); |
| 3592 for(k=1; k<sp->nsubsym; k++){ | 3706 for(k=1; k<sp->nsubsym; k++){ |
| 3593 fprintf(out,"|%s",sp->subsym[k]->name); | 3707 fprintf(out,"|%s",sp->subsym[k]->name); |
| 3594 } | 3708 } |
| 3595 } | 3709 } |
| 3596 } | 3710 } |
| 3597 } | 3711 } |
| 3598 | 3712 |
| 3599 | 3713 |
| 3600 /* Generate C source code for the parser */ | 3714 /* Generate C source code for the parser */ |
| 3601 void ReportTable( | 3715 void ReportTable( |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3882 p->name, p->fallback->name); | 3996 p->name, p->fallback->name); |
| 3883 } | 3997 } |
| 3884 lineno++; | 3998 lineno++; |
| 3885 } | 3999 } |
| 3886 } | 4000 } |
| 3887 tplt_xfer(lemp->name, in, out, &lineno); | 4001 tplt_xfer(lemp->name, in, out, &lineno); |
| 3888 | 4002 |
| 3889 /* Generate a table containing the symbolic name of every symbol | 4003 /* Generate a table containing the symbolic name of every symbol |
| 3890 */ | 4004 */ |
| 3891 for(i=0; i<lemp->nsymbol; i++){ | 4005 for(i=0; i<lemp->nsymbol; i++){ |
| 3892 sprintf(line,"\"%s\",",lemp->symbols[i]->name); | 4006 lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name); |
| 3893 fprintf(out," %-15s",line); | 4007 fprintf(out," %-15s",line); |
| 3894 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } | 4008 if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } |
| 3895 } | 4009 } |
| 3896 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } | 4010 if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } |
| 3897 tplt_xfer(lemp->name,in,out,&lineno); | 4011 tplt_xfer(lemp->name,in,out,&lineno); |
| 3898 | 4012 |
| 3899 /* Generate a table containing a text string that describes every | 4013 /* Generate a table containing a text string that describes every |
| 3900 ** rule in the rule set of the grammar. This information is used | 4014 ** rule in the rule set of the grammar. This information is used |
| 3901 ** when tracing REDUCE actions. | 4015 ** when tracing REDUCE actions. |
| 3902 */ | 4016 */ |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4047 FILE *out, *in; | 4161 FILE *out, *in; |
| 4048 const char *prefix; | 4162 const char *prefix; |
| 4049 char line[LINESIZE]; | 4163 char line[LINESIZE]; |
| 4050 char pattern[LINESIZE]; | 4164 char pattern[LINESIZE]; |
| 4051 int i; | 4165 int i; |
| 4052 | 4166 |
| 4053 if( lemp->tokenprefix ) prefix = lemp->tokenprefix; | 4167 if( lemp->tokenprefix ) prefix = lemp->tokenprefix; |
| 4054 else prefix = ""; | 4168 else prefix = ""; |
| 4055 in = file_open(lemp,".h","rb"); | 4169 in = file_open(lemp,".h","rb"); |
| 4056 if( in ){ | 4170 if( in ){ |
| 4171 int nextChar; |
| 4057 for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ | 4172 for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ |
| 4058 sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); | 4173 lemon_sprintf(pattern,"#define %s%-30s %3d\n", |
| 4174 prefix,lemp->symbols[i]->name,i); |
| 4059 if( strcmp(line,pattern) ) break; | 4175 if( strcmp(line,pattern) ) break; |
| 4060 } | 4176 } |
| 4177 nextChar = fgetc(in); |
| 4061 fclose(in); | 4178 fclose(in); |
| 4062 if( i==lemp->nterminal ){ | 4179 if( i==lemp->nterminal && nextChar==EOF ){ |
| 4063 /* No change in the file. Don't rewrite it. */ | 4180 /* No change in the file. Don't rewrite it. */ |
| 4064 return; | 4181 return; |
| 4065 } | 4182 } |
| 4066 } | 4183 } |
| 4067 out = file_open(lemp,".h","wb"); | 4184 out = file_open(lemp,".h","wb"); |
| 4068 if( out ){ | 4185 if( out ){ |
| 4069 for(i=1; i<lemp->nterminal; i++){ | 4186 for(i=1; i<lemp->nterminal; i++){ |
| 4070 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); | 4187 fprintf(out,"#define %s%-30s %3d\n",prefix,lemp->symbols[i]->name,i); |
| 4071 } | 4188 } |
| 4072 fclose(out); | 4189 fclose(out); |
| 4073 } | 4190 } |
| 4074 return; | 4191 return; |
| 4075 } | 4192 } |
| 4076 | 4193 |
| 4077 /* Reduce the size of the action tables, if possible, by making use | 4194 /* Reduce the size of the action tables, if possible, by making use |
| 4078 ** of defaults. | 4195 ** of defaults. |
| 4079 ** | 4196 ** |
| 4080 ** In this version, we take the most frequent REDUCE action and make | 4197 ** In this version, we take the most frequent REDUCE action and make |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4258 ** from a specification in the file | 4375 ** from a specification in the file |
| 4259 ** "table.q" | 4376 ** "table.q" |
| 4260 ** by the associative array code building program "aagen". | 4377 ** by the associative array code building program "aagen". |
| 4261 ** Do not edit this file! Instead, edit the specification | 4378 ** Do not edit this file! Instead, edit the specification |
| 4262 ** file, then rerun aagen. | 4379 ** file, then rerun aagen. |
| 4263 */ | 4380 */ |
| 4264 /* | 4381 /* |
| 4265 ** Code for processing tables in the LEMON parser generator. | 4382 ** Code for processing tables in the LEMON parser generator. |
| 4266 */ | 4383 */ |
| 4267 | 4384 |
| 4268 PRIVATE int strhash(const char *x) | 4385 PRIVATE unsigned strhash(const char *x) |
| 4269 { | 4386 { |
| 4270 int h = 0; | 4387 unsigned h = 0; |
| 4271 while( *x) h = h*13 + *(x++); | 4388 while( *x ) h = h*13 + *(x++); |
| 4272 return h; | 4389 return h; |
| 4273 } | 4390 } |
| 4274 | 4391 |
| 4275 /* Works like strdup, sort of. Save a string in malloced memory, but | 4392 /* Works like strdup, sort of. Save a string in malloced memory, but |
| 4276 ** keep strings in a table so that the same string is not in more | 4393 ** keep strings in a table so that the same string is not in more |
| 4277 ** than one place. | 4394 ** than one place. |
| 4278 */ | 4395 */ |
| 4279 const char *Strsafe(const char *y) | 4396 const char *Strsafe(const char *y) |
| 4280 { | 4397 { |
| 4281 const char *z; | 4398 const char *z; |
| 4282 char *cpy; | 4399 char *cpy; |
| 4283 | 4400 |
| 4284 if( y==0 ) return 0; | 4401 if( y==0 ) return 0; |
| 4285 z = Strsafe_find(y); | 4402 z = Strsafe_find(y); |
| 4286 if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ | 4403 if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ |
| 4287 strcpy(cpy,y); | 4404 lemon_strcpy(cpy,y); |
| 4288 z = cpy; | 4405 z = cpy; |
| 4289 Strsafe_insert(z); | 4406 Strsafe_insert(z); |
| 4290 } | 4407 } |
| 4291 MemoryCheck(z); | 4408 MemoryCheck(z); |
| 4292 return z; | 4409 return z; |
| 4293 } | 4410 } |
| 4294 | 4411 |
| 4295 /* There is one instance of the following structure for each | 4412 /* There is one instance of the following structure for each |
| 4296 ** associative array of type "x1". | 4413 ** associative array of type "x1". |
| 4297 */ | 4414 */ |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4316 /* There is only one instance of the array, which is the following */ | 4433 /* There is only one instance of the array, which is the following */ |
| 4317 static struct s_x1 *x1a; | 4434 static struct s_x1 *x1a; |
| 4318 | 4435 |
| 4319 /* Allocate a new associative array */ | 4436 /* Allocate a new associative array */ |
| 4320 void Strsafe_init(){ | 4437 void Strsafe_init(){ |
| 4321 if( x1a ) return; | 4438 if( x1a ) return; |
| 4322 x1a = (struct s_x1*)malloc( sizeof(struct s_x1) ); | 4439 x1a = (struct s_x1*)malloc( sizeof(struct s_x1) ); |
| 4323 if( x1a ){ | 4440 if( x1a ){ |
| 4324 x1a->size = 1024; | 4441 x1a->size = 1024; |
| 4325 x1a->count = 0; | 4442 x1a->count = 0; |
| 4326 x1a->tbl = (x1node*)malloc( | 4443 x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*)); |
| 4327 (sizeof(x1node) + sizeof(x1node*))*1024 ); | |
| 4328 if( x1a->tbl==0 ){ | 4444 if( x1a->tbl==0 ){ |
| 4329 free(x1a); | 4445 free(x1a); |
| 4330 x1a = 0; | 4446 x1a = 0; |
| 4331 }else{ | 4447 }else{ |
| 4332 int i; | 4448 int i; |
| 4333 x1a->ht = (x1node**)&(x1a->tbl[1024]); | 4449 x1a->ht = (x1node**)&(x1a->tbl[1024]); |
| 4334 for(i=0; i<1024; i++) x1a->ht[i] = 0; | 4450 for(i=0; i<1024; i++) x1a->ht[i] = 0; |
| 4335 } | 4451 } |
| 4336 } | 4452 } |
| 4337 } | 4453 } |
| 4338 /* Insert a new record into the array. Return TRUE if successful. | 4454 /* Insert a new record into the array. Return TRUE if successful. |
| 4339 ** Prior data with the same key is NOT overwritten */ | 4455 ** Prior data with the same key is NOT overwritten */ |
| 4340 int Strsafe_insert(const char *data) | 4456 int Strsafe_insert(const char *data) |
| 4341 { | 4457 { |
| 4342 x1node *np; | 4458 x1node *np; |
| 4343 int h; | 4459 unsigned h; |
| 4344 int ph; | 4460 unsigned ph; |
| 4345 | 4461 |
| 4346 if( x1a==0 ) return 0; | 4462 if( x1a==0 ) return 0; |
| 4347 ph = strhash(data); | 4463 ph = strhash(data); |
| 4348 h = ph & (x1a->size-1); | 4464 h = ph & (x1a->size-1); |
| 4349 np = x1a->ht[h]; | 4465 np = x1a->ht[h]; |
| 4350 while( np ){ | 4466 while( np ){ |
| 4351 if( strcmp(np->data,data)==0 ){ | 4467 if( strcmp(np->data,data)==0 ){ |
| 4352 /* An existing entry with the same key is found. */ | 4468 /* An existing entry with the same key is found. */ |
| 4353 /* Fail because overwrite is not allows. */ | 4469 /* Fail because overwrite is not allows. */ |
| 4354 return 0; | 4470 return 0; |
| 4355 } | 4471 } |
| 4356 np = np->next; | 4472 np = np->next; |
| 4357 } | 4473 } |
| 4358 if( x1a->count>=x1a->size ){ | 4474 if( x1a->count>=x1a->size ){ |
| 4359 /* Need to make the hash table bigger */ | 4475 /* Need to make the hash table bigger */ |
| 4360 int i,size; | 4476 int i,size; |
| 4361 struct s_x1 array; | 4477 struct s_x1 array; |
| 4362 array.size = size = x1a->size*2; | 4478 array.size = size = x1a->size*2; |
| 4363 array.count = x1a->count; | 4479 array.count = x1a->count; |
| 4364 array.tbl = (x1node*)malloc( | 4480 array.tbl = (x1node*)calloc(size, sizeof(x1node) + sizeof(x1node*)); |
| 4365 (sizeof(x1node) + sizeof(x1node*))*size ); | |
| 4366 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4481 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
| 4367 array.ht = (x1node**)&(array.tbl[size]); | 4482 array.ht = (x1node**)&(array.tbl[size]); |
| 4368 for(i=0; i<size; i++) array.ht[i] = 0; | 4483 for(i=0; i<size; i++) array.ht[i] = 0; |
| 4369 for(i=0; i<x1a->count; i++){ | 4484 for(i=0; i<x1a->count; i++){ |
| 4370 x1node *oldnp, *newnp; | 4485 x1node *oldnp, *newnp; |
| 4371 oldnp = &(x1a->tbl[i]); | 4486 oldnp = &(x1a->tbl[i]); |
| 4372 h = strhash(oldnp->data) & (size-1); | 4487 h = strhash(oldnp->data) & (size-1); |
| 4373 newnp = &(array.tbl[i]); | 4488 newnp = &(array.tbl[i]); |
| 4374 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4489 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
| 4375 newnp->next = array.ht[h]; | 4490 newnp->next = array.ht[h]; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4388 np->next = x1a->ht[h]; | 4503 np->next = x1a->ht[h]; |
| 4389 x1a->ht[h] = np; | 4504 x1a->ht[h] = np; |
| 4390 np->from = &(x1a->ht[h]); | 4505 np->from = &(x1a->ht[h]); |
| 4391 return 1; | 4506 return 1; |
| 4392 } | 4507 } |
| 4393 | 4508 |
| 4394 /* Return a pointer to data assigned to the given key. Return NULL | 4509 /* Return a pointer to data assigned to the given key. Return NULL |
| 4395 ** if no such key. */ | 4510 ** if no such key. */ |
| 4396 const char *Strsafe_find(const char *key) | 4511 const char *Strsafe_find(const char *key) |
| 4397 { | 4512 { |
| 4398 int h; | 4513 unsigned h; |
| 4399 x1node *np; | 4514 x1node *np; |
| 4400 | 4515 |
| 4401 if( x1a==0 ) return 0; | 4516 if( x1a==0 ) return 0; |
| 4402 h = strhash(key) & (x1a->size-1); | 4517 h = strhash(key) & (x1a->size-1); |
| 4403 np = x1a->ht[h]; | 4518 np = x1a->ht[h]; |
| 4404 while( np ){ | 4519 while( np ){ |
| 4405 if( strcmp(np->data,key)==0 ) break; | 4520 if( strcmp(np->data,key)==0 ) break; |
| 4406 np = np->next; | 4521 np = np->next; |
| 4407 } | 4522 } |
| 4408 return np ? np->data : 0; | 4523 return np ? np->data : 0; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4430 sp->destructor = 0; | 4545 sp->destructor = 0; |
| 4431 sp->destLineno = 0; | 4546 sp->destLineno = 0; |
| 4432 sp->datatype = 0; | 4547 sp->datatype = 0; |
| 4433 sp->useCnt = 0; | 4548 sp->useCnt = 0; |
| 4434 Symbol_insert(sp,sp->name); | 4549 Symbol_insert(sp,sp->name); |
| 4435 } | 4550 } |
| 4436 sp->useCnt++; | 4551 sp->useCnt++; |
| 4437 return sp; | 4552 return sp; |
| 4438 } | 4553 } |
| 4439 | 4554 |
| 4440 /* Compare two symbols for working purposes | 4555 /* Compare two symbols for sorting purposes. Return negative, |
| 4556 ** zero, or positive if a is less then, equal to, or greater |
| 4557 ** than b. |
| 4441 ** | 4558 ** |
| 4442 ** Symbols that begin with upper case letters (terminals or tokens) | 4559 ** Symbols that begin with upper case letters (terminals or tokens) |
| 4443 ** must sort before symbols that begin with lower case letters | 4560 ** must sort before symbols that begin with lower case letters |
| 4444 ** (non-terminals). Other than that, the order does not matter. | 4561 ** (non-terminals). And MULTITERMINAL symbols (created using the |
| 4562 ** %token_class directive) must sort at the very end. Other than |
| 4563 ** that, the order does not matter. |
| 4445 ** | 4564 ** |
| 4446 ** We find experimentally that leaving the symbols in their original | 4565 ** We find experimentally that leaving the symbols in their original |
| 4447 ** order (the order they appeared in the grammar file) gives the | 4566 ** order (the order they appeared in the grammar file) gives the |
| 4448 ** smallest parser tables in SQLite. | 4567 ** smallest parser tables in SQLite. |
| 4449 */ | 4568 */ |
| 4450 int Symbolcmpp(const void *_a, const void *_b) | 4569 int Symbolcmpp(const void *_a, const void *_b) |
| 4451 { | 4570 { |
| 4452 const struct symbol **a = (const struct symbol **) _a; | 4571 const struct symbol *a = *(const struct symbol **) _a; |
| 4453 const struct symbol **b = (const struct symbol **) _b; | 4572 const struct symbol *b = *(const struct symbol **) _b; |
| 4454 int i1 = (**a).index + 10000000*((**a).name[0]>'Z'); | 4573 int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1; |
| 4455 int i2 = (**b).index + 10000000*((**b).name[0]>'Z'); | 4574 int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1; |
| 4456 assert( i1!=i2 || strcmp((**a).name,(**b).name)==0 ); | 4575 return i1==i2 ? a->index - b->index : i1 - i2; |
| 4457 return i1-i2; | |
| 4458 } | 4576 } |
| 4459 | 4577 |
| 4460 /* There is one instance of the following structure for each | 4578 /* There is one instance of the following structure for each |
| 4461 ** associative array of type "x2". | 4579 ** associative array of type "x2". |
| 4462 */ | 4580 */ |
| 4463 struct s_x2 { | 4581 struct s_x2 { |
| 4464 int size; /* The number of available slots. */ | 4582 int size; /* The number of available slots. */ |
| 4465 /* Must be a power of 2 greater than or */ | 4583 /* Must be a power of 2 greater than or */ |
| 4466 /* equal to 1 */ | 4584 /* equal to 1 */ |
| 4467 int count; /* Number of currently slots filled */ | 4585 int count; /* Number of currently slots filled */ |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4482 /* There is only one instance of the array, which is the following */ | 4600 /* There is only one instance of the array, which is the following */ |
| 4483 static struct s_x2 *x2a; | 4601 static struct s_x2 *x2a; |
| 4484 | 4602 |
| 4485 /* Allocate a new associative array */ | 4603 /* Allocate a new associative array */ |
| 4486 void Symbol_init(){ | 4604 void Symbol_init(){ |
| 4487 if( x2a ) return; | 4605 if( x2a ) return; |
| 4488 x2a = (struct s_x2*)malloc( sizeof(struct s_x2) ); | 4606 x2a = (struct s_x2*)malloc( sizeof(struct s_x2) ); |
| 4489 if( x2a ){ | 4607 if( x2a ){ |
| 4490 x2a->size = 128; | 4608 x2a->size = 128; |
| 4491 x2a->count = 0; | 4609 x2a->count = 0; |
| 4492 x2a->tbl = (x2node*)malloc( | 4610 x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*)); |
| 4493 (sizeof(x2node) + sizeof(x2node*))*128 ); | |
| 4494 if( x2a->tbl==0 ){ | 4611 if( x2a->tbl==0 ){ |
| 4495 free(x2a); | 4612 free(x2a); |
| 4496 x2a = 0; | 4613 x2a = 0; |
| 4497 }else{ | 4614 }else{ |
| 4498 int i; | 4615 int i; |
| 4499 x2a->ht = (x2node**)&(x2a->tbl[128]); | 4616 x2a->ht = (x2node**)&(x2a->tbl[128]); |
| 4500 for(i=0; i<128; i++) x2a->ht[i] = 0; | 4617 for(i=0; i<128; i++) x2a->ht[i] = 0; |
| 4501 } | 4618 } |
| 4502 } | 4619 } |
| 4503 } | 4620 } |
| 4504 /* Insert a new record into the array. Return TRUE if successful. | 4621 /* Insert a new record into the array. Return TRUE if successful. |
| 4505 ** Prior data with the same key is NOT overwritten */ | 4622 ** Prior data with the same key is NOT overwritten */ |
| 4506 int Symbol_insert(struct symbol *data, const char *key) | 4623 int Symbol_insert(struct symbol *data, const char *key) |
| 4507 { | 4624 { |
| 4508 x2node *np; | 4625 x2node *np; |
| 4509 int h; | 4626 unsigned h; |
| 4510 int ph; | 4627 unsigned ph; |
| 4511 | 4628 |
| 4512 if( x2a==0 ) return 0; | 4629 if( x2a==0 ) return 0; |
| 4513 ph = strhash(key); | 4630 ph = strhash(key); |
| 4514 h = ph & (x2a->size-1); | 4631 h = ph & (x2a->size-1); |
| 4515 np = x2a->ht[h]; | 4632 np = x2a->ht[h]; |
| 4516 while( np ){ | 4633 while( np ){ |
| 4517 if( strcmp(np->key,key)==0 ){ | 4634 if( strcmp(np->key,key)==0 ){ |
| 4518 /* An existing entry with the same key is found. */ | 4635 /* An existing entry with the same key is found. */ |
| 4519 /* Fail because overwrite is not allows. */ | 4636 /* Fail because overwrite is not allows. */ |
| 4520 return 0; | 4637 return 0; |
| 4521 } | 4638 } |
| 4522 np = np->next; | 4639 np = np->next; |
| 4523 } | 4640 } |
| 4524 if( x2a->count>=x2a->size ){ | 4641 if( x2a->count>=x2a->size ){ |
| 4525 /* Need to make the hash table bigger */ | 4642 /* Need to make the hash table bigger */ |
| 4526 int i,size; | 4643 int i,size; |
| 4527 struct s_x2 array; | 4644 struct s_x2 array; |
| 4528 array.size = size = x2a->size*2; | 4645 array.size = size = x2a->size*2; |
| 4529 array.count = x2a->count; | 4646 array.count = x2a->count; |
| 4530 array.tbl = (x2node*)malloc( | 4647 array.tbl = (x2node*)calloc(size, sizeof(x2node) + sizeof(x2node*)); |
| 4531 (sizeof(x2node) + sizeof(x2node*))*size ); | |
| 4532 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4648 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
| 4533 array.ht = (x2node**)&(array.tbl[size]); | 4649 array.ht = (x2node**)&(array.tbl[size]); |
| 4534 for(i=0; i<size; i++) array.ht[i] = 0; | 4650 for(i=0; i<size; i++) array.ht[i] = 0; |
| 4535 for(i=0; i<x2a->count; i++){ | 4651 for(i=0; i<x2a->count; i++){ |
| 4536 x2node *oldnp, *newnp; | 4652 x2node *oldnp, *newnp; |
| 4537 oldnp = &(x2a->tbl[i]); | 4653 oldnp = &(x2a->tbl[i]); |
| 4538 h = strhash(oldnp->key) & (size-1); | 4654 h = strhash(oldnp->key) & (size-1); |
| 4539 newnp = &(array.tbl[i]); | 4655 newnp = &(array.tbl[i]); |
| 4540 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4656 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
| 4541 newnp->next = array.ht[h]; | 4657 newnp->next = array.ht[h]; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4556 np->next = x2a->ht[h]; | 4672 np->next = x2a->ht[h]; |
| 4557 x2a->ht[h] = np; | 4673 x2a->ht[h] = np; |
| 4558 np->from = &(x2a->ht[h]); | 4674 np->from = &(x2a->ht[h]); |
| 4559 return 1; | 4675 return 1; |
| 4560 } | 4676 } |
| 4561 | 4677 |
| 4562 /* Return a pointer to data assigned to the given key. Return NULL | 4678 /* Return a pointer to data assigned to the given key. Return NULL |
| 4563 ** if no such key. */ | 4679 ** if no such key. */ |
| 4564 struct symbol *Symbol_find(const char *key) | 4680 struct symbol *Symbol_find(const char *key) |
| 4565 { | 4681 { |
| 4566 int h; | 4682 unsigned h; |
| 4567 x2node *np; | 4683 x2node *np; |
| 4568 | 4684 |
| 4569 if( x2a==0 ) return 0; | 4685 if( x2a==0 ) return 0; |
| 4570 h = strhash(key) & (x2a->size-1); | 4686 h = strhash(key) & (x2a->size-1); |
| 4571 np = x2a->ht[h]; | 4687 np = x2a->ht[h]; |
| 4572 while( np ){ | 4688 while( np ){ |
| 4573 if( strcmp(np->key,key)==0 ) break; | 4689 if( strcmp(np->key,key)==0 ) break; |
| 4574 np = np->next; | 4690 np = np->next; |
| 4575 } | 4691 } |
| 4576 return np ? np->data : 0; | 4692 return np ? np->data : 0; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4630 if( rc==0 ) rc = a->dot - b->dot; | 4746 if( rc==0 ) rc = a->dot - b->dot; |
| 4631 } | 4747 } |
| 4632 if( rc==0 ){ | 4748 if( rc==0 ){ |
| 4633 if( a ) rc = 1; | 4749 if( a ) rc = 1; |
| 4634 if( b ) rc = -1; | 4750 if( b ) rc = -1; |
| 4635 } | 4751 } |
| 4636 return rc; | 4752 return rc; |
| 4637 } | 4753 } |
| 4638 | 4754 |
| 4639 /* Hash a state */ | 4755 /* Hash a state */ |
| 4640 PRIVATE int statehash(struct config *a) | 4756 PRIVATE unsigned statehash(struct config *a) |
| 4641 { | 4757 { |
| 4642 int h=0; | 4758 unsigned h=0; |
| 4643 while( a ){ | 4759 while( a ){ |
| 4644 h = h*571 + a->rp->index*37 + a->dot; | 4760 h = h*571 + a->rp->index*37 + a->dot; |
| 4645 a = a->bp; | 4761 a = a->bp; |
| 4646 } | 4762 } |
| 4647 return h; | 4763 return h; |
| 4648 } | 4764 } |
| 4649 | 4765 |
| 4650 /* Allocate a new state structure */ | 4766 /* Allocate a new state structure */ |
| 4651 struct state *State_new() | 4767 struct state *State_new() |
| 4652 { | 4768 { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4681 /* There is only one instance of the array, which is the following */ | 4797 /* There is only one instance of the array, which is the following */ |
| 4682 static struct s_x3 *x3a; | 4798 static struct s_x3 *x3a; |
| 4683 | 4799 |
| 4684 /* Allocate a new associative array */ | 4800 /* Allocate a new associative array */ |
| 4685 void State_init(){ | 4801 void State_init(){ |
| 4686 if( x3a ) return; | 4802 if( x3a ) return; |
| 4687 x3a = (struct s_x3*)malloc( sizeof(struct s_x3) ); | 4803 x3a = (struct s_x3*)malloc( sizeof(struct s_x3) ); |
| 4688 if( x3a ){ | 4804 if( x3a ){ |
| 4689 x3a->size = 128; | 4805 x3a->size = 128; |
| 4690 x3a->count = 0; | 4806 x3a->count = 0; |
| 4691 x3a->tbl = (x3node*)malloc( | 4807 x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*)); |
| 4692 (sizeof(x3node) + sizeof(x3node*))*128 ); | |
| 4693 if( x3a->tbl==0 ){ | 4808 if( x3a->tbl==0 ){ |
| 4694 free(x3a); | 4809 free(x3a); |
| 4695 x3a = 0; | 4810 x3a = 0; |
| 4696 }else{ | 4811 }else{ |
| 4697 int i; | 4812 int i; |
| 4698 x3a->ht = (x3node**)&(x3a->tbl[128]); | 4813 x3a->ht = (x3node**)&(x3a->tbl[128]); |
| 4699 for(i=0; i<128; i++) x3a->ht[i] = 0; | 4814 for(i=0; i<128; i++) x3a->ht[i] = 0; |
| 4700 } | 4815 } |
| 4701 } | 4816 } |
| 4702 } | 4817 } |
| 4703 /* Insert a new record into the array. Return TRUE if successful. | 4818 /* Insert a new record into the array. Return TRUE if successful. |
| 4704 ** Prior data with the same key is NOT overwritten */ | 4819 ** Prior data with the same key is NOT overwritten */ |
| 4705 int State_insert(struct state *data, struct config *key) | 4820 int State_insert(struct state *data, struct config *key) |
| 4706 { | 4821 { |
| 4707 x3node *np; | 4822 x3node *np; |
| 4708 int h; | 4823 unsigned h; |
| 4709 int ph; | 4824 unsigned ph; |
| 4710 | 4825 |
| 4711 if( x3a==0 ) return 0; | 4826 if( x3a==0 ) return 0; |
| 4712 ph = statehash(key); | 4827 ph = statehash(key); |
| 4713 h = ph & (x3a->size-1); | 4828 h = ph & (x3a->size-1); |
| 4714 np = x3a->ht[h]; | 4829 np = x3a->ht[h]; |
| 4715 while( np ){ | 4830 while( np ){ |
| 4716 if( statecmp(np->key,key)==0 ){ | 4831 if( statecmp(np->key,key)==0 ){ |
| 4717 /* An existing entry with the same key is found. */ | 4832 /* An existing entry with the same key is found. */ |
| 4718 /* Fail because overwrite is not allows. */ | 4833 /* Fail because overwrite is not allows. */ |
| 4719 return 0; | 4834 return 0; |
| 4720 } | 4835 } |
| 4721 np = np->next; | 4836 np = np->next; |
| 4722 } | 4837 } |
| 4723 if( x3a->count>=x3a->size ){ | 4838 if( x3a->count>=x3a->size ){ |
| 4724 /* Need to make the hash table bigger */ | 4839 /* Need to make the hash table bigger */ |
| 4725 int i,size; | 4840 int i,size; |
| 4726 struct s_x3 array; | 4841 struct s_x3 array; |
| 4727 array.size = size = x3a->size*2; | 4842 array.size = size = x3a->size*2; |
| 4728 array.count = x3a->count; | 4843 array.count = x3a->count; |
| 4729 array.tbl = (x3node*)malloc( | 4844 array.tbl = (x3node*)calloc(size, sizeof(x3node) + sizeof(x3node*)); |
| 4730 (sizeof(x3node) + sizeof(x3node*))*size ); | |
| 4731 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4845 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
| 4732 array.ht = (x3node**)&(array.tbl[size]); | 4846 array.ht = (x3node**)&(array.tbl[size]); |
| 4733 for(i=0; i<size; i++) array.ht[i] = 0; | 4847 for(i=0; i<size; i++) array.ht[i] = 0; |
| 4734 for(i=0; i<x3a->count; i++){ | 4848 for(i=0; i<x3a->count; i++){ |
| 4735 x3node *oldnp, *newnp; | 4849 x3node *oldnp, *newnp; |
| 4736 oldnp = &(x3a->tbl[i]); | 4850 oldnp = &(x3a->tbl[i]); |
| 4737 h = statehash(oldnp->key) & (size-1); | 4851 h = statehash(oldnp->key) & (size-1); |
| 4738 newnp = &(array.tbl[i]); | 4852 newnp = &(array.tbl[i]); |
| 4739 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4853 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
| 4740 newnp->next = array.ht[h]; | 4854 newnp->next = array.ht[h]; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4755 np->next = x3a->ht[h]; | 4869 np->next = x3a->ht[h]; |
| 4756 x3a->ht[h] = np; | 4870 x3a->ht[h] = np; |
| 4757 np->from = &(x3a->ht[h]); | 4871 np->from = &(x3a->ht[h]); |
| 4758 return 1; | 4872 return 1; |
| 4759 } | 4873 } |
| 4760 | 4874 |
| 4761 /* Return a pointer to data assigned to the given key. Return NULL | 4875 /* Return a pointer to data assigned to the given key. Return NULL |
| 4762 ** if no such key. */ | 4876 ** if no such key. */ |
| 4763 struct state *State_find(struct config *key) | 4877 struct state *State_find(struct config *key) |
| 4764 { | 4878 { |
| 4765 int h; | 4879 unsigned h; |
| 4766 x3node *np; | 4880 x3node *np; |
| 4767 | 4881 |
| 4768 if( x3a==0 ) return 0; | 4882 if( x3a==0 ) return 0; |
| 4769 h = statehash(key) & (x3a->size-1); | 4883 h = statehash(key) & (x3a->size-1); |
| 4770 np = x3a->ht[h]; | 4884 np = x3a->ht[h]; |
| 4771 while( np ){ | 4885 while( np ){ |
| 4772 if( statecmp(np->key,key)==0 ) break; | 4886 if( statecmp(np->key,key)==0 ) break; |
| 4773 np = np->next; | 4887 np = np->next; |
| 4774 } | 4888 } |
| 4775 return np ? np->data : 0; | 4889 return np ? np->data : 0; |
| 4776 } | 4890 } |
| 4777 | 4891 |
| 4778 /* Return an array of pointers to all data in the table. | 4892 /* Return an array of pointers to all data in the table. |
| 4779 ** The array is obtained from malloc. Return NULL if memory allocation | 4893 ** The array is obtained from malloc. Return NULL if memory allocation |
| 4780 ** problems, or if the array is empty. */ | 4894 ** problems, or if the array is empty. */ |
| 4781 struct state **State_arrayof() | 4895 struct state **State_arrayof() |
| 4782 { | 4896 { |
| 4783 struct state **array; | 4897 struct state **array; |
| 4784 int i,size; | 4898 int i,size; |
| 4785 if( x3a==0 ) return 0; | 4899 if( x3a==0 ) return 0; |
| 4786 size = x3a->count; | 4900 size = x3a->count; |
| 4787 array = (struct state **)malloc( sizeof(struct state *)*size ); | 4901 array = (struct state **)calloc(size, sizeof(struct state *)); |
| 4788 if( array ){ | 4902 if( array ){ |
| 4789 for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; | 4903 for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; |
| 4790 } | 4904 } |
| 4791 return array; | 4905 return array; |
| 4792 } | 4906 } |
| 4793 | 4907 |
| 4794 /* Hash a configuration */ | 4908 /* Hash a configuration */ |
| 4795 PRIVATE int confighash(struct config *a) | 4909 PRIVATE unsigned confighash(struct config *a) |
| 4796 { | 4910 { |
| 4797 int h=0; | 4911 unsigned h=0; |
| 4798 h = h*571 + a->rp->index*37 + a->dot; | 4912 h = h*571 + a->rp->index*37 + a->dot; |
| 4799 return h; | 4913 return h; |
| 4800 } | 4914 } |
| 4801 | 4915 |
| 4802 /* There is one instance of the following structure for each | 4916 /* There is one instance of the following structure for each |
| 4803 ** associative array of type "x4". | 4917 ** associative array of type "x4". |
| 4804 */ | 4918 */ |
| 4805 struct s_x4 { | 4919 struct s_x4 { |
| 4806 int size; /* The number of available slots. */ | 4920 int size; /* The number of available slots. */ |
| 4807 /* Must be a power of 2 greater than or */ | 4921 /* Must be a power of 2 greater than or */ |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4823 /* There is only one instance of the array, which is the following */ | 4937 /* There is only one instance of the array, which is the following */ |
| 4824 static struct s_x4 *x4a; | 4938 static struct s_x4 *x4a; |
| 4825 | 4939 |
| 4826 /* Allocate a new associative array */ | 4940 /* Allocate a new associative array */ |
| 4827 void Configtable_init(){ | 4941 void Configtable_init(){ |
| 4828 if( x4a ) return; | 4942 if( x4a ) return; |
| 4829 x4a = (struct s_x4*)malloc( sizeof(struct s_x4) ); | 4943 x4a = (struct s_x4*)malloc( sizeof(struct s_x4) ); |
| 4830 if( x4a ){ | 4944 if( x4a ){ |
| 4831 x4a->size = 64; | 4945 x4a->size = 64; |
| 4832 x4a->count = 0; | 4946 x4a->count = 0; |
| 4833 x4a->tbl = (x4node*)malloc( | 4947 x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*)); |
| 4834 (sizeof(x4node) + sizeof(x4node*))*64 ); | |
| 4835 if( x4a->tbl==0 ){ | 4948 if( x4a->tbl==0 ){ |
| 4836 free(x4a); | 4949 free(x4a); |
| 4837 x4a = 0; | 4950 x4a = 0; |
| 4838 }else{ | 4951 }else{ |
| 4839 int i; | 4952 int i; |
| 4840 x4a->ht = (x4node**)&(x4a->tbl[64]); | 4953 x4a->ht = (x4node**)&(x4a->tbl[64]); |
| 4841 for(i=0; i<64; i++) x4a->ht[i] = 0; | 4954 for(i=0; i<64; i++) x4a->ht[i] = 0; |
| 4842 } | 4955 } |
| 4843 } | 4956 } |
| 4844 } | 4957 } |
| 4845 /* Insert a new record into the array. Return TRUE if successful. | 4958 /* Insert a new record into the array. Return TRUE if successful. |
| 4846 ** Prior data with the same key is NOT overwritten */ | 4959 ** Prior data with the same key is NOT overwritten */ |
| 4847 int Configtable_insert(struct config *data) | 4960 int Configtable_insert(struct config *data) |
| 4848 { | 4961 { |
| 4849 x4node *np; | 4962 x4node *np; |
| 4850 int h; | 4963 unsigned h; |
| 4851 int ph; | 4964 unsigned ph; |
| 4852 | 4965 |
| 4853 if( x4a==0 ) return 0; | 4966 if( x4a==0 ) return 0; |
| 4854 ph = confighash(data); | 4967 ph = confighash(data); |
| 4855 h = ph & (x4a->size-1); | 4968 h = ph & (x4a->size-1); |
| 4856 np = x4a->ht[h]; | 4969 np = x4a->ht[h]; |
| 4857 while( np ){ | 4970 while( np ){ |
| 4858 if( Configcmp((const char *) np->data,(const char *) data)==0 ){ | 4971 if( Configcmp((const char *) np->data,(const char *) data)==0 ){ |
| 4859 /* An existing entry with the same key is found. */ | 4972 /* An existing entry with the same key is found. */ |
| 4860 /* Fail because overwrite is not allows. */ | 4973 /* Fail because overwrite is not allows. */ |
| 4861 return 0; | 4974 return 0; |
| 4862 } | 4975 } |
| 4863 np = np->next; | 4976 np = np->next; |
| 4864 } | 4977 } |
| 4865 if( x4a->count>=x4a->size ){ | 4978 if( x4a->count>=x4a->size ){ |
| 4866 /* Need to make the hash table bigger */ | 4979 /* Need to make the hash table bigger */ |
| 4867 int i,size; | 4980 int i,size; |
| 4868 struct s_x4 array; | 4981 struct s_x4 array; |
| 4869 array.size = size = x4a->size*2; | 4982 array.size = size = x4a->size*2; |
| 4870 array.count = x4a->count; | 4983 array.count = x4a->count; |
| 4871 array.tbl = (x4node*)malloc( | 4984 array.tbl = (x4node*)calloc(size, sizeof(x4node) + sizeof(x4node*)); |
| 4872 (sizeof(x4node) + sizeof(x4node*))*size ); | |
| 4873 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ | 4985 if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ |
| 4874 array.ht = (x4node**)&(array.tbl[size]); | 4986 array.ht = (x4node**)&(array.tbl[size]); |
| 4875 for(i=0; i<size; i++) array.ht[i] = 0; | 4987 for(i=0; i<size; i++) array.ht[i] = 0; |
| 4876 for(i=0; i<x4a->count; i++){ | 4988 for(i=0; i<x4a->count; i++){ |
| 4877 x4node *oldnp, *newnp; | 4989 x4node *oldnp, *newnp; |
| 4878 oldnp = &(x4a->tbl[i]); | 4990 oldnp = &(x4a->tbl[i]); |
| 4879 h = confighash(oldnp->data) & (size-1); | 4991 h = confighash(oldnp->data) & (size-1); |
| 4880 newnp = &(array.tbl[i]); | 4992 newnp = &(array.tbl[i]); |
| 4881 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); | 4993 if( array.ht[h] ) array.ht[h]->from = &(newnp->next); |
| 4882 newnp->next = array.ht[h]; | 4994 newnp->next = array.ht[h]; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4919 ** as it is removed. ("f" may be null to avoid this step.) */ | 5031 ** as it is removed. ("f" may be null to avoid this step.) */ |
| 4920 void Configtable_clear(int(*f)(struct config *)) | 5032 void Configtable_clear(int(*f)(struct config *)) |
| 4921 { | 5033 { |
| 4922 int i; | 5034 int i; |
| 4923 if( x4a==0 || x4a->count==0 ) return; | 5035 if( x4a==0 || x4a->count==0 ) return; |
| 4924 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data); | 5036 if( f ) for(i=0; i<x4a->count; i++) (*f)(x4a->tbl[i].data); |
| 4925 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0; | 5037 for(i=0; i<x4a->size; i++) x4a->ht[i] = 0; |
| 4926 x4a->count = 0; | 5038 x4a->count = 0; |
| 4927 return; | 5039 return; |
| 4928 } | 5040 } |
| OLD | NEW |