/* * Copyright 1993, 1995 Christopher Seiwald. * * This file is part of Jam - see jam.c for Copyright information. */ # include "jam.h" # include "lists.h" # include "parse.h" # include "scan.h" # include "newstr.h" /* * parse.c - make and destroy parse trees as driven by the parser */ static PARSE *yypsave; void parse_file( f ) char *f; { /* Suspend scan of current file */ /* and push this new file in the stream */ yyfparse(f); /* Now parse each block of rules and execute it. */ /* Execute it outside of the parser so that recursive */ /* calls to yyrun() work (no recursive yyparse's). */ for(;;) { LOL l; PARSE *p; lol_init( &l ); yypsave = 0; if( yyparse() || !( p = yypsave ) ) break; (*(p->func))( p, &l ); parse_decref( p ); } } void parse_save( p ) PARSE *p; { yypsave = p; } PARSE * parse_make( func, left, right, string, string1, llist, rlist, num ) void (*func)(); PARSE *left; PARSE *right; char *string; char *string1; LIST *llist; LIST *rlist; int num; { PARSE *p = (PARSE *)malloc( sizeof( PARSE ) ); p->func = func; p->left = left; p->right = right; p->string = string; p->string1 = string1; p->llist = llist; p->rlist = rlist; p->num = num; p->refs = 1; return p; } void parse_incref( p ) PARSE *p; { ++p->refs; } void parse_decref( p ) PARSE *p; { if (--p->refs) return; if( p->string ) freestr( p->string ); if( p->string1 ) freestr( p->string1 ); if( p->llist ) list_free( p->llist ); if( p->rlist ) list_free( p->rlist ); if( p->left ) parse_decref( p->left ); if( p->right ) parse_decref( p->right ); free( (char *)p ); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#4 | 1270 | Matt Armstrong | In prep for publishing all my patches to jam. | ||
#3 | 1088 | Matt Armstrong | Merge in changes from upstream. | ||
#2 | 293 | Matt Armstrong |
Fix a crash bug in jam by adding reference counting to the PARSE struct. The bug occurs when a rule re-defines itself. This can only happen by using the include statement, as follows. JamfileA: ---------------------------------------------------- rule DoInclude { ECHO JamfileA DoInclude $(<) start ; include $(<) ; ECHO JamfileA DoInclude $(<) end ; } DoInclude JambileB ; ---------------------------------------------------- JamfileB: ---------------------------------------------------- rule DoInclude { ECHO JamfileB DoInclude ; } DoInclude JambileC ; ---------------------------------------------------- With these two jamfiles you can reproduce the crash bug by running "jam -fJamfileA". If that doesn't work, change parse_free() such that it memsets PARSE struct being freed to something bogus like 0x03 and try again (or use Purify and watch the free memory read warnings). The problem is that compile_setcomp() just frees the PARSE without regard for the possibility that it might be executing. In the case above, JamfileA's DoInclude is re-defined by JamfileB while it is still being executed. The simple fix is to just have compile_setcomp() not free the PARSE. This would introduce a memory leak for every re-defined rule. My fix introduces reference counting of the PARSE struct. A PARSE is allocated with a reference count of 1 and when it goes to 0 it is freed. Every place that was a parse_free() is now a parse_decref(). In addition, compile_rules() increments the reference count of its PARSE around the calls to its left and right functions. Perhaps there a better fix! |
||
#1 | 289 | Matt Armstrong | Initial branch. | ||
//guest/perforce_software/jam/src/parse.c | |||||
#1 | 2 | laura | Add Jam/MR 2.2 source |