| Index: third_party/sqlite/src/tool/lemon.c | 
| diff --git a/third_party/sqlite/src/tool/lemon.c b/third_party/sqlite/src/tool/lemon.c | 
| index 898022e28c1589b5c99bac7a990422dce6e089e4..85e94f7007f905754127fd81472f9ff64e631a2d 100644 | 
| --- a/third_party/sqlite/src/tool/lemon.c | 
| +++ b/third_party/sqlite/src/tool/lemon.c | 
| @@ -15,7 +15,7 @@ | 
|  | 
| #ifndef __WIN32__ | 
| #   if defined(_WIN32) || defined(WIN32) | 
| -#	define __WIN32__ | 
| +#       define __WIN32__ | 
| #   endif | 
| #endif | 
|  | 
| @@ -41,23 +41,6 @@ extern int access(const char *path, int mode); | 
| #endif | 
|  | 
| static int showPrecedenceConflict = 0; | 
| -static const char **made_files = NULL; | 
| -static int made_files_count = 0; | 
| -static int successful_exit = 0; | 
| -static void LemonAtExit(void) | 
| -{ | 
| -    /* if we failed, delete (most) files we made, to unconfuse build tools. */ | 
| -    int i; | 
| -    for (i = 0; i < made_files_count; i++) { | 
| -        if (!successful_exit) { | 
| -            remove(made_files[i]); | 
| -        } | 
| -    } | 
| -    free(made_files); | 
| -    made_files_count = 0; | 
| -    made_files = NULL; | 
| -} | 
| - | 
| static char *msort(char*,char**,int(*)(const char*,const char*)); | 
|  | 
| /* | 
| @@ -67,6 +50,107 @@ static char *msort(char*,char**,int(*)(const char*,const char*)); | 
| */ | 
| #define lemonStrlen(X)   ((int)strlen(X)) | 
|  | 
| +/* | 
| +** Compilers are starting to complain about the use of sprintf() and strcpy(), | 
| +** saying they are unsafe.  So we define our own versions of those routines too. | 
| +** | 
| +** There are three routines here:  lemon_sprintf(), lemon_vsprintf(), and | 
| +** lemon_addtext().  The first two are replacements for sprintf() and vsprintf(). | 
| +** The third is a helper routine for vsnprintf() that adds texts to the end of a | 
| +** buffer, making sure the buffer is always zero-terminated. | 
| +** | 
| +** The string formatter is a minimal subset of stdlib sprintf() supporting only | 
| +** a few simply conversions: | 
| +** | 
| +**   %d | 
| +**   %s | 
| +**   %.*s | 
| +** | 
| +*/ | 
| +static void lemon_addtext( | 
| +  char *zBuf,           /* The buffer to which text is added */ | 
| +  int *pnUsed,          /* Slots of the buffer used so far */ | 
| +  const char *zIn,      /* Text to add */ | 
| +  int nIn,              /* Bytes of text to add.  -1 to use strlen() */ | 
| +  int iWidth            /* Field width.  Negative to left justify */ | 
| +){ | 
| +  if( nIn<0 ) for(nIn=0; zIn[nIn]; nIn++){} | 
| +  while( iWidth>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth--; } | 
| +  if( nIn==0 ) return; | 
| +  memcpy(&zBuf[*pnUsed], zIn, nIn); | 
| +  *pnUsed += nIn; | 
| +  while( (-iWidth)>nIn ){ zBuf[(*pnUsed)++] = ' '; iWidth++; } | 
| +  zBuf[*pnUsed] = 0; | 
| +} | 
| +static int lemon_vsprintf(char *str, const char *zFormat, va_list ap){ | 
| +  int i, j, k, c; | 
| +  int nUsed = 0; | 
| +  const char *z; | 
| +  char zTemp[50]; | 
| +  str[0] = 0; | 
| +  for(i=j=0; (c = zFormat[i])!=0; i++){ | 
| +    if( c=='%' ){ | 
| +      int iWidth = 0; | 
| +      lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); | 
| +      c = zFormat[++i]; | 
| +      if( isdigit(c) || (c=='-' && isdigit(zFormat[i+1])) ){ | 
| +        if( c=='-' ) i++; | 
| +        while( isdigit(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; | 
| +        if( c=='-' ) iWidth = -iWidth; | 
| +        c = zFormat[i]; | 
| +      } | 
| +      if( c=='d' ){ | 
| +        int v = va_arg(ap, int); | 
| +        if( v<0 ){ | 
| +          lemon_addtext(str, &nUsed, "-", 1, iWidth); | 
| +          v = -v; | 
| +        }else if( v==0 ){ | 
| +          lemon_addtext(str, &nUsed, "0", 1, iWidth); | 
| +        } | 
| +        k = 0; | 
| +        while( v>0 ){ | 
| +          k++; | 
| +          zTemp[sizeof(zTemp)-k] = (v%10) + '0'; | 
| +          v /= 10; | 
| +        } | 
| +        lemon_addtext(str, &nUsed, &zTemp[sizeof(zTemp)-k], k, iWidth); | 
| +      }else if( c=='s' ){ | 
| +        z = va_arg(ap, const char*); | 
| +        lemon_addtext(str, &nUsed, z, -1, iWidth); | 
| +      }else if( c=='.' && memcmp(&zFormat[i], ".*s", 3)==0 ){ | 
| +        i += 2; | 
| +        k = va_arg(ap, int); | 
| +        z = va_arg(ap, const char*); | 
| +        lemon_addtext(str, &nUsed, z, k, iWidth); | 
| +      }else if( c=='%' ){ | 
| +        lemon_addtext(str, &nUsed, "%", 1, 0); | 
| +      }else{ | 
| +        fprintf(stderr, "illegal format\n"); | 
| +        exit(1); | 
| +      } | 
| +      j = i+1; | 
| +    } | 
| +  } | 
| +  lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); | 
| +  return nUsed; | 
| +} | 
| +static int lemon_sprintf(char *str, const char *format, ...){ | 
| +  va_list ap; | 
| +  int rc; | 
| +  va_start(ap, format); | 
| +  rc = lemon_vsprintf(str, format, ap); | 
| +  va_end(ap); | 
| +  return rc; | 
| +} | 
| +static void lemon_strcpy(char *dest, const char *src){ | 
| +  while( (*(dest++) = *(src++))!=0 ){} | 
| +} | 
| +static void lemon_strcat(char *dest, const char *src){ | 
| +  while( *dest ) dest++; | 
| +  lemon_strcpy(dest, src); | 
| +} | 
| + | 
| + | 
| /* a few forward declarations... */ | 
| struct rule; | 
| struct lemon; | 
| @@ -134,8 +218,6 @@ void ResortStates(struct lemon *); | 
| void  SetSize(int);             /* All sets will be of size N */ | 
| char *SetNew(void);               /* A new set for element 0..N */ | 
| void  SetFree(char*);             /* Deallocate a set */ | 
| - | 
| -char *SetNew(void);               /* A new set for element 0..N */ | 
| int SetAdd(char*,int);            /* Add element to a set */ | 
| int SetUnion(char *,char *);    /* A <- A U B, thru element N */ | 
| #define SetFind(X,Y) (X[Y])       /* True if Y is in set X */ | 
| @@ -672,7 +754,7 @@ void FindRulePrecedences(struct lemon *xp) | 
| } | 
| }else if( sp->prec>=0 ){ | 
| rp->precsym = rp->rhs[i]; | 
| -	} | 
| +        } | 
| } | 
| } | 
| } | 
| @@ -703,8 +785,9 @@ void FindFirstSets(struct lemon *lemp) | 
| for(rp=lemp->rule; rp; rp=rp->next){ | 
| if( rp->lhs->lambda ) continue; | 
| for(i=0; i<rp->nrhs; i++){ | 
| -         struct symbol *sp = rp->rhs[i]; | 
| -         if( sp->type!=TERMINAL || sp->lambda==LEMON_FALSE ) break; | 
| +        struct symbol *sp = rp->rhs[i]; | 
| +        assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE ); | 
| +        if( sp->lambda==LEMON_FALSE ) break; | 
| } | 
| if( i==rp->nrhs ){ | 
| rp->lhs->lambda = LEMON_TRUE; | 
| @@ -729,12 +812,12 @@ void FindFirstSets(struct lemon *lemp) | 
| progress += SetAdd(s1->firstset,s2->subsym[j]->index); | 
| } | 
| break; | 
| -	}else if( s1==s2 ){ | 
| +        }else if( s1==s2 ){ | 
| if( s1->lambda==LEMON_FALSE ) break; | 
| -	}else{ | 
| +        }else{ | 
| progress += SetUnion(s1->firstset,s2->firstset); | 
| if( s2->lambda==LEMON_FALSE ) break; | 
| -	} | 
| +        } | 
| } | 
| } | 
| }while( progress ); | 
| @@ -977,15 +1060,15 @@ void FindFollowSets(struct lemon *lemp) | 
| if( change ){ | 
| plp->cfp->status = INCOMPLETE; | 
| progress = 1; | 
| -	  } | 
| -	} | 
| +          } | 
| +        } | 
| cfp->status = COMPLETE; | 
| } | 
| } | 
| }while( progress ); | 
| } | 
|  | 
| -static int resolve_conflict(struct action *,struct action *, struct symbol *); | 
| +static int resolve_conflict(struct action *,struct action *); | 
|  | 
| /* Compute the reduce actions, and resolve conflicts. | 
| */ | 
| @@ -1011,7 +1094,7 @@ void FindActions(struct lemon *lemp) | 
| ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ | 
| Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); | 
| } | 
| -	} | 
| +        } | 
| } | 
| } | 
| } | 
| @@ -1039,7 +1122,7 @@ void FindActions(struct lemon *lemp) | 
| for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ | 
| /* The two actions "ap" and "nap" have the same lookahead. | 
| ** Figure out which one should be used */ | 
| -         lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym); | 
| +         lemp->nconflict += resolve_conflict(ap,nap); | 
| } | 
| } | 
| } | 
| @@ -1074,8 +1157,7 @@ void FindActions(struct lemon *lemp) | 
| */ | 
| static int resolve_conflict( | 
| struct action *apx, | 
| -  struct action *apy, | 
| -  struct symbol *errsym   /* The error symbol (if defined.  NULL otherwise) */ | 
| +  struct action *apy | 
| ){ | 
| struct symbol *spx, *spy; | 
| int errcnt = 0; | 
| @@ -1101,8 +1183,7 @@ static int resolve_conflict( | 
| apx->type = SH_RESOLVED; | 
| }else{ | 
| assert( spx->prec==spy->prec && spx->assoc==NONE ); | 
| -      apy->type = SRCONFLICT; | 
| -      errcnt++; | 
| +      apx->type = ERROR; | 
| } | 
| }else if( apx->type==REDUCE && apy->type==REDUCE ){ | 
| spx = apx->x.rp->precsym; | 
| @@ -1281,11 +1362,11 @@ void Configlist_closure(struct lemon *lemp) | 
| SetAdd(newcfp->fws, xsp->subsym[k]->index); | 
| } | 
| break; | 
| -	  }else{ | 
| +          }else{ | 
| SetUnion(newcfp->fws,xsp->firstset); | 
| if( xsp->lambda==LEMON_FALSE ) break; | 
| -	  } | 
| -	} | 
| +          } | 
| +        } | 
| if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); | 
| } | 
| } | 
| @@ -1386,7 +1467,7 @@ static void handle_D_option(char *z){ | 
| fprintf(stderr,"out of memory\n"); | 
| exit(1); | 
| } | 
| -  strcpy(*paz, z); | 
| +  lemon_strcpy(*paz, z); | 
| for(z=*paz; *z && *z!='='; z++){} | 
| *z = 0; | 
| } | 
| @@ -1397,7 +1478,7 @@ static void handle_T_option(char *z){ | 
| if( user_templatename==0 ){ | 
| memory_error(); | 
| } | 
| -  strcpy(user_templatename, z); | 
| +  lemon_strcpy(user_templatename, z); | 
| } | 
|  | 
| /* The main program.  Parse the command line and do it... */ | 
| @@ -1433,8 +1514,6 @@ int main(int argc, char **argv) | 
| int exitcode; | 
| struct lemon lem; | 
|  | 
| -  atexit(LemonAtExit); | 
| - | 
| OptInit(argv,options,stderr); | 
| if( version ){ | 
| printf("Lemon version 1.0\n"); | 
| @@ -1468,12 +1547,15 @@ int main(int argc, char **argv) | 
| } | 
|  | 
| /* Count and index the symbols of the grammar */ | 
| -  lem.nsymbol = Symbol_count(); | 
| Symbol_new("{default}"); | 
| +  lem.nsymbol = Symbol_count(); | 
| lem.symbols = Symbol_arrayof(); | 
| -  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; | 
| -  qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*), Symbolcmpp); | 
| -  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; | 
| +  for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; | 
| +  qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); | 
| +  for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; | 
| +  while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } | 
| +  assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); | 
| +  lem.nsymbol = i - 1; | 
| for(i=1; isupper(lem.symbols[i]->name[0]); i++); | 
| lem.nterminal = i; | 
|  | 
| @@ -1537,7 +1619,6 @@ int main(int argc, char **argv) | 
|  | 
| /* return 0 on success, 1 on failure. */ | 
| exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; | 
| -  successful_exit = (exitcode == 0); | 
| exit(exitcode); | 
| return (exitcode); | 
| } | 
| @@ -1568,7 +1649,7 @@ int main(int argc, char **argv) | 
| /* | 
| ** Return a pointer to the next structure in the linked list. | 
| */ | 
| -#define NEXT(A) (*(char**)(((unsigned long)A)+offset)) | 
| +#define NEXT(A) (*(char**)(((char*)A)+offset)) | 
|  | 
| /* | 
| ** Inputs: | 
| @@ -1962,7 +2043,9 @@ enum e_state { | 
| WAITING_FOR_DESTRUCTOR_SYMBOL, | 
| WAITING_FOR_DATATYPE_SYMBOL, | 
| WAITING_FOR_FALLBACK_ID, | 
| -  WAITING_FOR_WILDCARD_ID | 
| +  WAITING_FOR_WILDCARD_ID, | 
| +  WAITING_FOR_CLASS_ID, | 
| +  WAITING_FOR_CLASS_TOKEN | 
| }; | 
| struct pstate { | 
| char *filename;       /* Name of the input file */ | 
| @@ -1972,6 +2055,7 @@ struct pstate { | 
| struct lemon *gp;     /* Global state vector */ | 
| enum e_state state;        /* The state of the parser */ | 
| struct symbol *fallback;   /* The fallback token */ | 
| +  struct symbol *tkclass;    /* Token class symbol */ | 
| struct symbol *lhs;        /* Left-hand side of current rule */ | 
| const char *lhsalias;      /* Alias for the LHS */ | 
| int nrhs;                  /* Number of right-hand side symbols seen */ | 
| @@ -2015,10 +2099,10 @@ static void parseonetoken(struct pstate *psp) | 
| }else if( x[0]=='{' ){ | 
| if( psp->prevrule==0 ){ | 
| ErrorMsg(psp->filename,psp->tokenlineno, | 
| -"There is no prior rule opon which to attach the code \ | 
| +"There is no prior rule upon which to attach the code \ | 
| fragment which begins on this line."); | 
| psp->errorcnt++; | 
| -	}else if( psp->prevrule->code!=0 ){ | 
| +        }else if( psp->prevrule->code!=0 ){ | 
| ErrorMsg(psp->filename,psp->tokenlineno, | 
| "Code fragment beginning on this line is not the first \ | 
| to follow the previous rule."); | 
| @@ -2026,7 +2110,7 @@ to follow the previous rule."); | 
| }else{ | 
| psp->prevrule->line = psp->tokenlineno; | 
| psp->prevrule->code = &x[1]; | 
| -	} | 
| +        } | 
| }else if( x[0]=='[' ){ | 
| psp->state = PRECEDENCE_MARK_1; | 
| }else{ | 
| @@ -2119,7 +2203,7 @@ to follow the previous rule."); | 
| "Can't allocate enough memory for this rule."); | 
| psp->errorcnt++; | 
| psp->prevrule = 0; | 
| -	}else{ | 
| +        }else{ | 
| int i; | 
| rp->ruleline = psp->tokenlineno; | 
| rp->rhs = (struct symbol**)&rp[1]; | 
| @@ -2127,7 +2211,7 @@ to follow the previous rule."); | 
| for(i=0; i<psp->nrhs; i++){ | 
| rp->rhs[i] = psp->rhs[i]; | 
| rp->rhsalias[i] = psp->alias[i]; | 
| -	  } | 
| +          } | 
| rp->lhs = psp->lhs; | 
| rp->lhsalias = psp->lhsalias; | 
| rp->nrhs = psp->nrhs; | 
| @@ -2139,12 +2223,12 @@ to follow the previous rule."); | 
| rp->next = 0; | 
| if( psp->firstrule==0 ){ | 
| psp->firstrule = psp->lastrule = rp; | 
| -	  }else{ | 
| +          }else{ | 
| psp->lastrule->next = rp; | 
| psp->lastrule = rp; | 
| -	  } | 
| +          } | 
| psp->prevrule = rp; | 
| -	} | 
| +        } | 
| psp->state = WAITING_FOR_DECL_OR_RULE; | 
| }else if( isalpha(x[0]) ){ | 
| if( psp->nrhs>=MAXRHS ){ | 
| @@ -2153,11 +2237,11 @@ to follow the previous rule."); | 
| x); | 
| psp->errorcnt++; | 
| psp->state = RESYNC_AFTER_RULE_ERROR; | 
| -	}else{ | 
| +        }else{ | 
| psp->rhs[psp->nrhs] = Symbol_new(x); | 
| psp->alias[psp->nrhs] = 0; | 
| psp->nrhs++; | 
| -	} | 
| +        } | 
| }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ | 
| struct symbol *msp = psp->rhs[psp->nrhs-1]; | 
| if( msp->type!=MULTITERMINAL ){ | 
| @@ -2221,24 +2305,24 @@ to follow the previous rule."); | 
| if( strcmp(x,"name")==0 ){ | 
| psp->declargslot = &(psp->gp->name); | 
| psp->insertLineMacro = 0; | 
| -	}else if( strcmp(x,"include")==0 ){ | 
| +        }else if( strcmp(x,"include")==0 ){ | 
| psp->declargslot = &(psp->gp->include); | 
| -	}else if( strcmp(x,"code")==0 ){ | 
| +        }else if( strcmp(x,"code")==0 ){ | 
| psp->declargslot = &(psp->gp->extracode); | 
| -	}else if( strcmp(x,"token_destructor")==0 ){ | 
| +        }else if( strcmp(x,"token_destructor")==0 ){ | 
| psp->declargslot = &psp->gp->tokendest; | 
| -	}else if( strcmp(x,"default_destructor")==0 ){ | 
| +        }else if( strcmp(x,"default_destructor")==0 ){ | 
| psp->declargslot = &psp->gp->vardest; | 
| -	}else if( strcmp(x,"token_prefix")==0 ){ | 
| +        }else if( strcmp(x,"token_prefix")==0 ){ | 
| psp->declargslot = &psp->gp->tokenprefix; | 
| psp->insertLineMacro = 0; | 
| -	}else if( strcmp(x,"syntax_error")==0 ){ | 
| +        }else if( strcmp(x,"syntax_error")==0 ){ | 
| psp->declargslot = &(psp->gp->error); | 
| -	}else if( strcmp(x,"parse_accept")==0 ){ | 
| +        }else if( strcmp(x,"parse_accept")==0 ){ | 
| psp->declargslot = &(psp->gp->accept); | 
| -	}else if( strcmp(x,"parse_failure")==0 ){ | 
| +        }else if( strcmp(x,"parse_failure")==0 ){ | 
| psp->declargslot = &(psp->gp->failure); | 
| -	}else if( strcmp(x,"stack_overflow")==0 ){ | 
| +        }else if( strcmp(x,"stack_overflow")==0 ){ | 
| psp->declargslot = &(psp->gp->overflow); | 
| }else if( strcmp(x,"extra_argument")==0 ){ | 
| psp->declargslot = &(psp->gp->arg); | 
| @@ -2267,21 +2351,23 @@ to follow the previous rule."); | 
| psp->preccounter++; | 
| psp->declassoc = NONE; | 
| psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; | 
| -	}else if( strcmp(x,"destructor")==0 ){ | 
| +        }else if( strcmp(x,"destructor")==0 ){ | 
| psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; | 
| -	}else if( strcmp(x,"type")==0 ){ | 
| +        }else if( strcmp(x,"type")==0 ){ | 
| psp->state = WAITING_FOR_DATATYPE_SYMBOL; | 
| }else if( strcmp(x,"fallback")==0 ){ | 
| psp->fallback = 0; | 
| psp->state = WAITING_FOR_FALLBACK_ID; | 
| }else if( strcmp(x,"wildcard")==0 ){ | 
| psp->state = WAITING_FOR_WILDCARD_ID; | 
| +        }else if( strcmp(x,"token_class")==0 ){ | 
| +          psp->state = WAITING_FOR_CLASS_ID; | 
| }else{ | 
| ErrorMsg(psp->filename,psp->tokenlineno, | 
| "Unknown declaration keyword: \"%%%s\".",x); | 
| psp->errorcnt++; | 
| psp->state = RESYNC_AFTER_DECL_ERROR; | 
| -	} | 
| +        } | 
| }else{ | 
| ErrorMsg(psp->filename,psp->tokenlineno, | 
| "Illegal declaration keyword: \"%s\".",x); | 
| @@ -2336,10 +2422,10 @@ to follow the previous rule."); | 
| ErrorMsg(psp->filename,psp->tokenlineno, | 
| "Symbol \"%s\" has already be given a precedence.",x); | 
| psp->errorcnt++; | 
| -	}else{ | 
| +        }else{ | 
| sp->prec = psp->preccounter; | 
| sp->assoc = psp->declassoc; | 
| -	} | 
| +        } | 
| }else{ | 
| ErrorMsg(psp->filename,psp->tokenlineno, | 
| "Can't assign a precedence to \"%s\".",x); | 
| @@ -2369,7 +2455,7 @@ to follow the previous rule."); | 
| for(z=psp->filename, nBack=0; *z; z++){ | 
| if( *z=='\\' ) nBack++; | 
| } | 
| -          sprintf(zLine, "#line %d ", psp->tokenlineno); | 
| +          lemon_sprintf(zLine, "#line %d ", psp->tokenlineno); | 
| nLine = lemonStrlen(zLine); | 
| n += nLine + lemonStrlen(psp->filename) + nBack; | 
| } | 
| @@ -2444,6 +2530,40 @@ to follow the previous rule."); | 
| } | 
| } | 
| break; | 
| +    case WAITING_FOR_CLASS_ID: | 
| +      if( !islower(x[0]) ){ | 
| +        ErrorMsg(psp->filename, psp->tokenlineno, | 
| +          "%%token_class must be followed by an identifier: ", x); | 
| +        psp->errorcnt++; | 
| +        psp->state = RESYNC_AFTER_DECL_ERROR; | 
| +     }else if( Symbol_find(x) ){ | 
| +        ErrorMsg(psp->filename, psp->tokenlineno, | 
| +          "Symbol \"%s\" already used", x); | 
| +        psp->errorcnt++; | 
| +        psp->state = RESYNC_AFTER_DECL_ERROR; | 
| +      }else{ | 
| +        psp->tkclass = Symbol_new(x); | 
| +        psp->tkclass->type = MULTITERMINAL; | 
| +        psp->state = WAITING_FOR_CLASS_TOKEN; | 
| +      } | 
| +      break; | 
| +    case WAITING_FOR_CLASS_TOKEN: | 
| +      if( x[0]=='.' ){ | 
| +        psp->state = WAITING_FOR_DECL_OR_RULE; | 
| +      }else if( isupper(x[0]) || ((x[0]=='|' || x[0]=='/') && isupper(x[1])) ){ | 
| +        struct symbol *msp = psp->tkclass; | 
| +        msp->nsubsym++; | 
| +        msp->subsym = (struct symbol **) realloc(msp->subsym, | 
| +          sizeof(struct symbol*)*msp->nsubsym); | 
| +        if( !isupper(x[0]) ) x++; | 
| +        msp->subsym[msp->nsubsym-1] = Symbol_new(x); | 
| +      }else{ | 
| +        ErrorMsg(psp->filename, psp->tokenlineno, | 
| +          "%%token_class argument \"%s\" should be a token", x); | 
| +        psp->errorcnt++; | 
| +        psp->state = RESYNC_AFTER_DECL_ERROR; | 
| +      } | 
| +      break; | 
| case RESYNC_AFTER_RULE_ERROR: | 
| /*      if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; | 
| **      break; */ | 
| @@ -2538,10 +2658,10 @@ void Parse(struct lemon *gp) | 
| filesize = ftell(fp); | 
| rewind(fp); | 
| filebuf = (char *)malloc( filesize+1 ); | 
| -  if( filebuf==0 ){ | 
| -    ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.", | 
| -      filesize+1); | 
| +  if( filesize>100000000 || filebuf==0 ){ | 
| +    ErrorMsg(ps.filename,0,"Input file too large."); | 
| gp->errorcnt++; | 
| +    fclose(fp); | 
| return; | 
| } | 
| if( fread(filebuf,1,filesize,fp)!=filesize ){ | 
| @@ -2549,6 +2669,7 @@ void Parse(struct lemon *gp) | 
| filesize); | 
| free(filebuf); | 
| gp->errorcnt++; | 
| +    fclose(fp); | 
| return; | 
| } | 
| fclose(fp); | 
| @@ -2607,12 +2728,12 @@ void Parse(struct lemon *gp) | 
| if( c=='\n' ) lineno++; | 
| prevc = c; | 
| cp++; | 
| -	  } | 
| -	}else if( c=='/' && cp[1]=='/' ){  /* Skip C++ style comments too */ | 
| +          } | 
| +        }else if( c=='/' && cp[1]=='/' ){  /* Skip C++ style comments too */ | 
| cp = &cp[2]; | 
| while( (c= *cp)!=0 && c!='\n' ) cp++; | 
| if( c ) lineno++; | 
| -	}else if( c=='\'' || c=='\"' ){    /* String a character literals */ | 
| +        }else if( c=='\'' || c=='\"' ){    /* String a character literals */ | 
| int startchar, prevc; | 
| startchar = c; | 
| prevc = 0; | 
| @@ -2620,8 +2741,8 @@ void Parse(struct lemon *gp) | 
| if( c=='\n' ) lineno++; | 
| if( prevc=='\\' ) prevc = 0; | 
| else              prevc = c; | 
| -	  } | 
| -	} | 
| +          } | 
| +        } | 
| } | 
| if( c==0 ){ | 
| ErrorMsg(ps.filename,ps.tokenlineno, | 
| @@ -2736,10 +2857,10 @@ PRIVATE char *file_makename(struct lemon *lemp, const char *suffix) | 
| fprintf(stderr,"Can't allocate space for a filename.\n"); | 
| exit(1); | 
| } | 
| -  strcpy(name,lemp->filename); | 
| +  lemon_strcpy(name,lemp->filename); | 
| cp = strrchr(name,'.'); | 
| if( cp ) *cp = 0; | 
| -  strcat(name,suffix); | 
| +  lemon_strcat(name,suffix); | 
| return name; | 
| } | 
|  | 
| @@ -2761,23 +2882,6 @@ PRIVATE FILE *file_open( | 
| lemp->errorcnt++; | 
| return 0; | 
| } | 
| - | 
| -  /* Add files we create to a list, so we can delete them if we fail. This | 
| -  ** is to keep makefiles from getting confused. We don't include .out files, | 
| -  ** though: this is debug information, and you don't want it deleted if there | 
| -  ** was an error you need to track down. | 
| -  */ | 
| -  if(( *mode=='w' ) && (strcmp(suffix, ".out") != 0)){ | 
| -    const char **ptr = (const char **) | 
| -        realloc(made_files, sizeof (const char **) * (made_files_count + 1)); | 
| -    const char *fname = Strsafe(lemp->outname); | 
| -    if ((ptr == NULL) || (fname == NULL)) { | 
| -        free(ptr); | 
| -        memory_error(); | 
| -    } | 
| -    made_files = ptr; | 
| -    made_files[made_files_count++] = fname; | 
| -  } | 
| return fp; | 
| } | 
|  | 
| @@ -2813,11 +2917,13 @@ void Reprint(struct lemon *lemp) | 
| printf(" ::="); | 
| for(i=0; i<rp->nrhs; i++){ | 
| sp = rp->rhs[i]; | 
| -      printf(" %s", sp->name); | 
| if( sp->type==MULTITERMINAL ){ | 
| +        printf(" %s", sp->subsym[0]->name); | 
| for(j=1; j<sp->nsubsym; j++){ | 
| printf("|%s", sp->subsym[j]->name); | 
| } | 
| +      }else{ | 
| +        printf(" %s", sp->name); | 
| } | 
| /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ | 
| } | 
| @@ -2839,11 +2945,13 @@ void ConfigPrint(FILE *fp, struct config *cfp) | 
| if( i==cfp->dot ) fprintf(fp," *"); | 
| if( i==rp->nrhs ) break; | 
| sp = rp->rhs[i]; | 
| -    fprintf(fp," %s", sp->name); | 
| if( sp->type==MULTITERMINAL ){ | 
| +      fprintf(fp," %s", sp->subsym[0]->name); | 
| for(j=1; j<sp->nsubsym; j++){ | 
| fprintf(fp,"|%s",sp->subsym[j]->name); | 
| } | 
| +    }else{ | 
| +      fprintf(fp," %s", sp->name); | 
| } | 
| } | 
| } | 
| @@ -2953,7 +3061,7 @@ void ReportOutput(struct lemon *lemp) | 
| while( cfp ){ | 
| char buf[20]; | 
| if( cfp->dot==cfp->rp->nrhs ){ | 
| -        sprintf(buf,"(%d)",cfp->rp->index); | 
| +        lemon_sprintf(buf,"(%d)",cfp->rp->index); | 
| fprintf(fp,"    %5s ",buf); | 
| }else{ | 
| fprintf(fp,"          "); | 
| @@ -3018,7 +3126,7 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask) | 
| c = *cp; | 
| *cp = 0; | 
| path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); | 
| -    if( path ) sprintf(path,"%s/%s",argv0,name); | 
| +    if( path ) lemon_sprintf(path,"%s/%s",argv0,name); | 
| *cp = c; | 
| }else{ | 
| pathlist = getenv("PATH"); | 
| @@ -3027,13 +3135,13 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask) | 
| path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); | 
| if( (pathbuf != 0) && (path!=0) ){ | 
| pathbufptr = pathbuf; | 
| -      strcpy(pathbuf, pathlist); | 
| +      lemon_strcpy(pathbuf, pathlist); | 
| while( *pathbuf ){ | 
| cp = strchr(pathbuf,':'); | 
| if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)]; | 
| c = *cp; | 
| *cp = 0; | 
| -        sprintf(path,"%s/%s",pathbuf,name); | 
| +        lemon_sprintf(path,"%s/%s",pathbuf,name); | 
| *cp = c; | 
| if( c==0 ) pathbuf[0] = 0; | 
| else pathbuf = &cp[1]; | 
| @@ -3124,9 +3232,9 @@ PRIVATE FILE *tplt_open(struct lemon *lemp) | 
|  | 
| cp = strrchr(lemp->filename,'.'); | 
| if( cp ){ | 
| -    sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); | 
| +    lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); | 
| }else{ | 
| -    sprintf(buf,"%s.lt",lemp->filename); | 
| +    lemon_sprintf(buf,"%s.lt",lemp->filename); | 
| } | 
| if( access(buf,004)==0 ){ | 
| tpltname = buf; | 
| @@ -3277,9 +3385,9 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ | 
| while( n-- > 0 ){ | 
| c = *(zText++); | 
| if( c=='%' && n>0 && zText[0]=='d' ){ | 
| -      sprintf(zInt, "%d", p1); | 
| +      lemon_sprintf(zInt, "%d", p1); | 
| p1 = p2; | 
| -      strcpy(&z[used], zInt); | 
| +      lemon_strcpy(&z[used], zInt); | 
| used += lemonStrlen(&z[used]); | 
| zText++; | 
| n--; | 
| @@ -3428,12 +3536,16 @@ void print_stack_union( | 
| int maxdtlength;          /* Maximum length of any ".datatype" field. */ | 
| char *stddt;              /* Standardized name for a datatype */ | 
| int i,j;                  /* Loop counters */ | 
| -  int hash;                 /* For hashing the name of a type */ | 
| +  unsigned hash;            /* For hashing the name of a type */ | 
| const char *name;         /* Name of the parser */ | 
|  | 
| /* Allocate and initialize types[] and allocate stddt[] */ | 
| arraysize = lemp->nsymbol * 2; | 
| types = (char**)calloc( arraysize, sizeof(char*) ); | 
| +  if( types==0 ){ | 
| +    fprintf(stderr,"Out of memory.\n"); | 
| +    exit(1); | 
| +  } | 
| for(i=0; i<arraysize; i++) types[i] = 0; | 
| maxdtlength = 0; | 
| if( lemp->vartype ){ | 
| @@ -3447,7 +3559,7 @@ void print_stack_union( | 
| if( len>maxdtlength ) maxdtlength = len; | 
| } | 
| stddt = (char*)malloc( maxdtlength*2 + 1 ); | 
| -  if( types==0 || stddt==0 ){ | 
| +  if( stddt==0 ){ | 
| fprintf(stderr,"Out of memory.\n"); | 
| exit(1); | 
| } | 
| @@ -3491,7 +3603,7 @@ void print_stack_union( | 
| break; | 
| } | 
| hash++; | 
| -      if( hash>=arraysize ) hash = 0; | 
| +      if( hash>=(unsigned)arraysize ) hash = 0; | 
| } | 
| if( types[hash]==0 ){ | 
| sp->dtnum = hash + 1; | 
| @@ -3500,7 +3612,7 @@ void print_stack_union( | 
| fprintf(stderr,"Out of memory.\n"); | 
| exit(1); | 
| } | 
| -      strcpy(types[hash],stddt); | 
| +      lemon_strcpy(types[hash],stddt); | 
| } | 
| } | 
|  | 
| @@ -3586,9 +3698,11 @@ static void writeRuleText(FILE *out, struct rule *rp){ | 
| fprintf(out,"%s ::=", rp->lhs->name); | 
| for(j=0; j<rp->nrhs; j++){ | 
| struct symbol *sp = rp->rhs[j]; | 
| -    fprintf(out," %s", sp->name); | 
| -    if( sp->type==MULTITERMINAL ){ | 
| +    if( sp->type!=MULTITERMINAL ){ | 
| +      fprintf(out," %s", sp->name); | 
| +    }else{ | 
| int k; | 
| +      fprintf(out," %s", sp->subsym[0]->name); | 
| for(k=1; k<sp->nsubsym; k++){ | 
| fprintf(out,"|%s",sp->subsym[k]->name); | 
| } | 
| @@ -3889,7 +4003,7 @@ void ReportTable( | 
| /* Generate a table containing the symbolic name of every symbol | 
| */ | 
| for(i=0; i<lemp->nsymbol; i++){ | 
| -    sprintf(line,"\"%s\",",lemp->symbols[i]->name); | 
| +    lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name); | 
| fprintf(out,"  %-15s",line); | 
| if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } | 
| } | 
| @@ -4054,12 +4168,15 @@ void ReportHeader(struct lemon *lemp) | 
| else                    prefix = ""; | 
| in = file_open(lemp,".h","rb"); | 
| if( in ){ | 
| +    int nextChar; | 
| for(i=1; i<lemp->nterminal && fgets(line,LINESIZE,in); i++){ | 
| -      sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); | 
| +      lemon_sprintf(pattern,"#define %s%-30s %3d\n", | 
| +                    prefix,lemp->symbols[i]->name,i); | 
| if( strcmp(line,pattern) ) break; | 
| } | 
| +    nextChar = fgetc(in); | 
| fclose(in); | 
| -    if( i==lemp->nterminal ){ | 
| +    if( i==lemp->nterminal && nextChar==EOF ){ | 
| /* No change in the file.  Don't rewrite it. */ | 
| return; | 
| } | 
| @@ -4067,7 +4184,7 @@ void ReportHeader(struct lemon *lemp) | 
| out = file_open(lemp,".h","wb"); | 
| if( out ){ | 
| for(i=1; i<lemp->nterminal; i++){ | 
| -      fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); | 
| +      fprintf(out,"#define %s%-30s %3d\n",prefix,lemp->symbols[i]->name,i); | 
| } | 
| fclose(out); | 
| } | 
| @@ -4265,10 +4382,10 @@ int SetUnion(char *s1, char *s2) | 
| ** Code for processing tables in the LEMON parser generator. | 
| */ | 
|  | 
| -PRIVATE int strhash(const char *x) | 
| +PRIVATE unsigned strhash(const char *x) | 
| { | 
| -  int h = 0; | 
| -  while( *x) h = h*13 + *(x++); | 
| +  unsigned h = 0; | 
| +  while( *x ) h = h*13 + *(x++); | 
| return h; | 
| } | 
|  | 
| @@ -4284,7 +4401,7 @@ const char *Strsafe(const char *y) | 
| if( y==0 ) return 0; | 
| z = Strsafe_find(y); | 
| if( z==0 && (cpy=(char *)malloc( lemonStrlen(y)+1 ))!=0 ){ | 
| -    strcpy(cpy,y); | 
| +    lemon_strcpy(cpy,y); | 
| z = cpy; | 
| Strsafe_insert(z); | 
| } | 
| @@ -4323,8 +4440,7 @@ void Strsafe_init(){ | 
| if( x1a ){ | 
| x1a->size = 1024; | 
| x1a->count = 0; | 
| -    x1a->tbl = (x1node*)malloc( | 
| -      (sizeof(x1node) + sizeof(x1node*))*1024 ); | 
| +    x1a->tbl = (x1node*)calloc(1024, sizeof(x1node) + sizeof(x1node*)); | 
| if( x1a->tbl==0 ){ | 
| free(x1a); | 
| x1a = 0; | 
| @@ -4340,8 +4456,8 @@ void Strsafe_init(){ | 
| int Strsafe_insert(const char *data) | 
| { | 
| x1node *np; | 
| -  int h; | 
| -  int ph; | 
| +  unsigned h; | 
| +  unsigned ph; | 
|  | 
| if( x1a==0 ) return 0; | 
| ph = strhash(data); | 
| @@ -4361,8 +4477,7 @@ int Strsafe_insert(const char *data) | 
| struct s_x1 array; | 
| array.size = size = x1a->size*2; | 
| array.count = x1a->count; | 
| -    array.tbl = (x1node*)malloc( | 
| -      (sizeof(x1node) + sizeof(x1node*))*size ); | 
| +    array.tbl = (x1node*)calloc(size, sizeof(x1node) + sizeof(x1node*)); | 
| if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */ | 
| array.ht = (x1node**)&(array.tbl[size]); | 
| for(i=0; i<size; i++) array.ht[i] = 0; | 
| @@ -4395,7 +4510,7 @@ int Strsafe_insert(const char *data) | 
| ** if no such key. */ | 
| const char *Strsafe_find(const char *key) | 
| { | 
| -  int h; | 
| +  unsigned h; | 
| x1node *np; | 
|  | 
| if( x1a==0 ) return 0; | 
| @@ -4437,11 +4552,15 @@ struct symbol *Symbol_new(const char *x) | 
| return sp; | 
| } | 
|  | 
| -/* Compare two symbols for working purposes | 
| +/* Compare two symbols for sorting purposes.  Return negative, | 
| +** zero, or positive if a is less then, equal to, or greater | 
| +** than b. | 
| ** | 
| ** Symbols that begin with upper case letters (terminals or tokens) | 
| ** must sort before symbols that begin with lower case letters | 
| -** (non-terminals).  Other than that, the order does not matter. | 
| +** (non-terminals).  And MULTITERMINAL symbols (created using the | 
| +** %token_class directive) must sort at the very end. Other than | 
| +** that, the order does not matter. | 
| ** | 
| ** We find experimentally that leaving the symbols in their original | 
| ** order (the order they appeared in the grammar file) gives the | 
| @@ -4449,12 +4568,11 @@ struct symbol *Symbol_new(const char *x) | 
| */ | 
| int Symbolcmpp(const void *_a, const void *_b) | 
| { | 
| -  const struct symbol **a = (const struct symbol **) _a; | 
| -  const struct symbol **b = (const struct symbol **) _b; | 
| -  int i1 = (**a).index + 10000000*((**a).name[0]>'Z'); | 
| -  int i2 = (**b).index + 10000000*((**b).name[0]>'Z'); | 
| -  assert( i1!=i2 || strcmp((**a).name,(**b).name)==0 ); | 
| -  return i1-i2; | 
| +  const struct symbol *a = *(const struct symbol **) _a; | 
| +  const struct symbol *b = *(const struct symbol **) _b; | 
| +  int i1 = a->type==MULTITERMINAL ? 3 : a->name[0]>'Z' ? 2 : 1; | 
| +  int i2 = b->type==MULTITERMINAL ? 3 : b->name[0]>'Z' ? 2 : 1; | 
| +  return i1==i2 ? a->index - b->index : i1 - i2; | 
| } | 
|  | 
| /* There is one instance of the following structure for each | 
| @@ -4489,8 +4607,7 @@ void Symbol_init(){ | 
| if( x2a ){ | 
| x2a->size = 128; | 
| x2a->count = 0; | 
| -    x2a->tbl = (x2node*)malloc( | 
| -      (sizeof(x2node) + sizeof(x2node*))*128 ); | 
| +    x2a->tbl = (x2node*)calloc(128, sizeof(x2node) + sizeof(x2node*)); | 
| if( x2a->tbl==0 ){ | 
| free(x2a); | 
| x2a = 0; | 
| @@ -4506,8 +4623,8 @@ void Symbol_init(){ | 
| int Symbol_insert(struct symbol *data, const char *key) | 
| { | 
| x2node *np; | 
| -  int h; | 
| -  int ph; | 
| +  unsigned h; | 
| +  unsigned ph; | 
|  | 
| if( x2a==0 ) return 0; | 
| ph = strhash(key); | 
| @@ -4527,8 +4644,7 @@ int Symbol_insert(struct symbol *data, const char *key) | 
| struct s_x2 array; | 
| array.size = size = x2a->size*2; | 
| array.count = x2a->count; | 
| -    array.tbl = (x2node*)malloc( | 
| -      (sizeof(x2node) + sizeof(x2node*))*size ); | 
| +    array.tbl = (x2node*)calloc(size, sizeof(x2node) + sizeof(x2node*)); | 
| if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */ | 
| array.ht = (x2node**)&(array.tbl[size]); | 
| for(i=0; i<size; i++) array.ht[i] = 0; | 
| @@ -4563,7 +4679,7 @@ int Symbol_insert(struct symbol *data, const char *key) | 
| ** if no such key. */ | 
| struct symbol *Symbol_find(const char *key) | 
| { | 
| -  int h; | 
| +  unsigned h; | 
| x2node *np; | 
|  | 
| if( x2a==0 ) return 0; | 
| @@ -4637,9 +4753,9 @@ PRIVATE int statecmp(struct config *a, struct config *b) | 
| } | 
|  | 
| /* Hash a state */ | 
| -PRIVATE int statehash(struct config *a) | 
| +PRIVATE unsigned statehash(struct config *a) | 
| { | 
| -  int h=0; | 
| +  unsigned h=0; | 
| while( a ){ | 
| h = h*571 + a->rp->index*37 + a->dot; | 
| a = a->bp; | 
| @@ -4688,8 +4804,7 @@ void State_init(){ | 
| if( x3a ){ | 
| x3a->size = 128; | 
| x3a->count = 0; | 
| -    x3a->tbl = (x3node*)malloc( | 
| -      (sizeof(x3node) + sizeof(x3node*))*128 ); | 
| +    x3a->tbl = (x3node*)calloc(128, sizeof(x3node) + sizeof(x3node*)); | 
| if( x3a->tbl==0 ){ | 
| free(x3a); | 
| x3a = 0; | 
| @@ -4705,8 +4820,8 @@ void State_init(){ | 
| int State_insert(struct state *data, struct config *key) | 
| { | 
| x3node *np; | 
| -  int h; | 
| -  int ph; | 
| +  unsigned h; | 
| +  unsigned ph; | 
|  | 
| if( x3a==0 ) return 0; | 
| ph = statehash(key); | 
| @@ -4726,8 +4841,7 @@ int State_insert(struct state *data, struct config *key) | 
| struct s_x3 array; | 
| array.size = size = x3a->size*2; | 
| array.count = x3a->count; | 
| -    array.tbl = (x3node*)malloc( | 
| -      (sizeof(x3node) + sizeof(x3node*))*size ); | 
| +    array.tbl = (x3node*)calloc(size, sizeof(x3node) + sizeof(x3node*)); | 
| if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */ | 
| array.ht = (x3node**)&(array.tbl[size]); | 
| for(i=0; i<size; i++) array.ht[i] = 0; | 
| @@ -4762,7 +4876,7 @@ int State_insert(struct state *data, struct config *key) | 
| ** if no such key. */ | 
| struct state *State_find(struct config *key) | 
| { | 
| -  int h; | 
| +  unsigned h; | 
| x3node *np; | 
|  | 
| if( x3a==0 ) return 0; | 
| @@ -4784,7 +4898,7 @@ struct state **State_arrayof() | 
| int i,size; | 
| if( x3a==0 ) return 0; | 
| size = x3a->count; | 
| -  array = (struct state **)malloc( sizeof(struct state *)*size ); | 
| +  array = (struct state **)calloc(size, sizeof(struct state *)); | 
| if( array ){ | 
| for(i=0; i<size; i++) array[i] = x3a->tbl[i].data; | 
| } | 
| @@ -4792,9 +4906,9 @@ struct state **State_arrayof() | 
| } | 
|  | 
| /* Hash a configuration */ | 
| -PRIVATE int confighash(struct config *a) | 
| +PRIVATE unsigned confighash(struct config *a) | 
| { | 
| -  int h=0; | 
| +  unsigned h=0; | 
| h = h*571 + a->rp->index*37 + a->dot; | 
| return h; | 
| } | 
| @@ -4830,8 +4944,7 @@ void Configtable_init(){ | 
| if( x4a ){ | 
| x4a->size = 64; | 
| x4a->count = 0; | 
| -    x4a->tbl = (x4node*)malloc( | 
| -      (sizeof(x4node) + sizeof(x4node*))*64 ); | 
| +    x4a->tbl = (x4node*)calloc(64, sizeof(x4node) + sizeof(x4node*)); | 
| if( x4a->tbl==0 ){ | 
| free(x4a); | 
| x4a = 0; | 
| @@ -4847,8 +4960,8 @@ void Configtable_init(){ | 
| int Configtable_insert(struct config *data) | 
| { | 
| x4node *np; | 
| -  int h; | 
| -  int ph; | 
| +  unsigned h; | 
| +  unsigned ph; | 
|  | 
| if( x4a==0 ) return 0; | 
| ph = confighash(data); | 
| @@ -4868,8 +4981,7 @@ int Configtable_insert(struct config *data) | 
| struct s_x4 array; | 
| array.size = size = x4a->size*2; | 
| array.count = x4a->count; | 
| -    array.tbl = (x4node*)malloc( | 
| -      (sizeof(x4node) + sizeof(x4node*))*size ); | 
| +    array.tbl = (x4node*)calloc(size, sizeof(x4node) + sizeof(x4node*)); | 
| if( array.tbl==0 ) return 0;  /* Fail due to malloc failure */ | 
| array.ht = (x4node**)&(array.tbl[size]); | 
| for(i=0; i<size; i++) array.ht[i] = 0; | 
|  |