diff --git a/harbour/source/common/Makefile b/harbour/source/common/Makefile index 8c54f12af6..9bd761530a 100644 --- a/harbour/source/common/Makefile +++ b/harbour/source/common/Makefile @@ -9,6 +9,7 @@ C_SOURCES=\ hbstr.c \ hbtrace.c \ hbver.c \ + hash.c \ reserved.c \ expropt1.c \ expropt2.c \ diff --git a/harbour/source/common/hash.c b/harbour/source/common/hash.c new file mode 100644 index 0000000000..50f126c102 --- /dev/null +++ b/harbour/source/common/hash.c @@ -0,0 +1,151 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Harbour common hash table implementation + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +#include "hbhash.h" + +static HB_HASH_ITEM_PTR hb_hashItemNew( ULONG ulKey, void * pValue ) +{ + HB_HASH_ITEM_PTR pItem = (HB_HASH_ITEM_PTR) hb_xgrab( sizeof( HB_HASH_ITEM ) ); + + pItem->key = ulKey; + pItem->cargo = pValue; + pItem->next = NULL; + + return pItem; +} + +/* create a new hash table +* ulSize = initial numer of items in the table +* pHashTable = a function that calculates a hash key value +* (first parameter is a value to add) +* pDelete = a function that clears item's value before item's releasing +* (first parameter is a value to clear) +* pComp = a function for comparing a values +* (first and second are values to compare, function have to return +* zero if values match or nonzero if they don't match) +*/ +HB_HASH_TABLE_PTR hb_hashTableCreate( ULONG ulSize, + HB_HASH_FUNC_PTR pHashFunc, + HB_HASH_FUNC_PTR pDelete, + HB_HASH_FUNC_PTR pComp ) +{ + HB_HASH_TABLE_PTR pTable = ( HB_HASH_TABLE_PTR ) hb_xgrab( sizeof( HB_HASH_TABLE ) ); + + pTable->ulTableSize = ulSize; + pTable->pKeyFunc = pHashFunc; + pTable->pDeleteItemFunc = pDelete; + pTable->pCompFunc = pComp; + + pTable->pItems = ( HB_HASH_ITEM_PTR * ) hb_xgrab( sizeof( HB_HASH_ITEM_PTR ) * ulSize ); + memset( pTable->pItems, 0, sizeof( HB_HASH_ITEM_PTR ) * ulSize ); + + return pTable; +} + +/* Delete all items in the hash table and next delete the table +*/ +void hb_hashTableKill( HB_HASH_TABLE_PTR pTable ) +{ + ULONG ulSize = 0; + + while( ulSize < pTable->ulTableSize ) + { + if( pTable->pItems[ ulSize ] ) + { + HB_HASH_ITEM_PTR pItem; + HB_HASH_ITEM_PTR pNext; + + pItem = pTable->pItems[ ulSize ]; + while( pItem ) + { + if( pTable->pDeleteItemFunc ) + ( pTable->pDeleteItemFunc )( pItem->cargo, NULL ); + pNext = pItem->next; + hb_xfree( ( void * ) pItem ); + pItem = pNext; + } + } + ++ulSize; + } + hb_xfree( ( void * ) pTable ); +} + +/* add a new value into th ehash table */ +BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pValue ) +{ + ULONG ulKey; + HB_HASH_ITEM_PTR pItem; + + ulKey = ( pTable->pKeyFunc )( pValue, NULL ); + pItem = pTable->pItems[ ulKey ]; + if( pItem ) + { + while( pItem->next ) + pItem = pItem->next; + pItem->next = hb_hashItemNew( ulKey, pValue ); + } + else + pTable->pItems[ ulKey ] = hb_hashItemNew( ulKey, pValue ); + + return TRUE; +} + +/* return the pointer to item's value or NULL if not found +*/ +void * hb_hashTableFind( HB_HASH_TABLE_PTR pTable, void *pValue ) +{ + ULONG ulKey; + HB_HASH_ITEM_PTR pItem; + void * pFound = NULL; + + ulKey = ( pTable->pKeyFunc )( pValue, NULL ); + pItem = pTable->pItems[ ulKey ]; + if( pItem ) + { + while( pItem && (( pTable->pCompFunc )( pItem->cargo, pValue ) != 0) ) + pItem = pItem->next; + + if( pItem ) + pFound = pItem->cargo; + } + + return pFound; +} + +/* return the hash table size */ +ULONG hb_hashTableBucket( HB_HASH_TABLE_PTR pTable ) +{ + return pTable->ulTableSize; +} diff --git a/harbour/source/compiler/Makefile b/harbour/source/compiler/Makefile index dec18a21a3..de15fa0a95 100644 --- a/harbour/source/compiler/Makefile +++ b/harbour/source/compiler/Makefile @@ -32,6 +32,7 @@ C_SOURCES=\ hbpcode.c \ hbusage.c \ hbfix.c \ + hbident.c \ expropta.c \ exproptb.c \ exproptc.c \ diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index 4562b2e300..e82b0fbfcc 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -49,6 +49,7 @@ #include /* required for allocating and freeing memory */ #include "hbcomp.h" +#include "hbhash.h" #if defined(HB_OS_DOS) && defined(__BORLANDC__) #include @@ -224,6 +225,9 @@ int main( int argc, char * argv[] ) /* Set standard rules */ hb_pp_SetRules( hb_compInclude, hb_comp_bQuiet ); + /* Prepare the table of identifiers */ + hb_compIdentifierOpen(); + /* Process all files passed via the command line. */ bAnyFiles = FALSE; @@ -241,6 +245,8 @@ int main( int argc, char * argv[] ) break; } } + + hb_compIdentifierClose(); if( ! bAnyFiles ) { @@ -1120,6 +1126,7 @@ void hb_compAnnounce( char * szFunName ) } } +/* NOTE: Names of variables and functions are released in hbident.c on exit */ PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) { PFUNCTION pNext = pFunc->pNext; @@ -1130,9 +1137,6 @@ PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) pVar = pFunc->pLocals; pFunc->pLocals = pVar->pNext; - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pVar->szName ); - hb_xfree( ( void * ) pVar ); } @@ -1141,9 +1145,6 @@ PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) pVar = pFunc->pStatics; pFunc->pStatics = pVar->pNext; - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pVar->szName ); - hb_xfree( ( void * ) pVar ); } @@ -1152,15 +1153,6 @@ PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) pVar = pFunc->pFields; pFunc->pFields = pVar->pNext; - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pVar->szName ); - - if( pVar->szAlias ) - { - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pVar->szAlias ); - } - hb_xfree( ( void * ) pVar ); } @@ -1169,15 +1161,6 @@ PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) pVar = pFunc->pMemvars; pFunc->pMemvars = pVar->pNext; - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pVar->szName ); - - if( pVar->szAlias ) - { - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pVar->szAlias ); - } - hb_xfree( ( void * ) pVar ); } @@ -1186,15 +1169,6 @@ PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) pVar = pFunc->pPrivates; pFunc->pPrivates = pVar->pNext; - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pVar->szName ); - - if( pVar->szAlias ) - { - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pVar->szAlias ); - } - hb_xfree( ( void * ) pVar ); } @@ -1213,13 +1187,11 @@ PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) return pNext; } +/* NOTE: Name of symbols are released in hbident.c on exit */ PCOMSYMBOL hb_compSymbolKill( PCOMSYMBOL pSym ) { PCOMSYMBOL pNext = pSym->pNext; - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pSym->szName ); - hb_xfree( ( void * ) pSym ); return pNext; @@ -3270,9 +3242,6 @@ void hb_compCodeBlockEnd( void ) pFree = pVar; - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pFree->szName ); - pVar = pVar->pNext; hb_xfree( ( void * ) pFree ); } @@ -3291,9 +3260,6 @@ void hb_compCodeBlockEnd( void ) /* free used variables */ pFree = pVar; - if( ! hb_comp_bSimpLex ) - hb_xfree( ( void * ) pFree->szName ); - pVar = pVar->pNext; hb_xfree( ( void * ) pFree ); } diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 5eefd8a702..720b4aeea9 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -69,6 +69,7 @@ int yy_lex_input( char *, int ); if ( yyleng > 0 ) \ yy_current_buffer->yy_at_bol = ( yytext[yyleng - 1] == '\n' || yytext[0] == '\n' ); + #define LOOKUP 0 /* scan from the begining of line */ #define OPERATOR -1 #define SEPARATOR -2 @@ -383,7 +384,7 @@ Separator {SpaceTab} BEGIN BREAK_; else { - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -406,7 +407,7 @@ Separator {SpaceTab} %} {Separator}*(":="|"+="|"-="|"->"|"*="|"/="|"^="|"==") { /* operators */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "BREAK" ); + yylval.string = hb_compIdentifierNew( "BREAK", TRUE ); unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); hb_comp_iState =IDENTIFIER; @@ -418,7 +419,7 @@ Separator {SpaceTab} * For this reason we are allowing the BREAK statement only */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "BREAK" ); + yylval.string = hb_compIdentifierNew( "BREAK", TRUE ); unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); hb_comp_iState =BREAK; @@ -426,7 +427,7 @@ Separator {SpaceTab} } {Separator}*[\=\(] { /* operators = ( */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "BREAK" ); + yylval.string = hb_compIdentifierNew( "BREAK", TRUE ); unput( yytext[ yyleng-1 ] ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; @@ -445,7 +446,7 @@ Separator {SpaceTab} "case" BEGIN CASE_; {Separator}*[\:\=\|\$\%\*\,\/\]\)\}\^] { /* there is an operator after "case" */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "CASE" ); + yylval.string = hb_compIdentifierNew( "CASE", TRUE ); hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; @@ -457,7 +458,7 @@ Separator {SpaceTab} } {Separator}*("+="|"-="|"->") { /* operators */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "CASE" ); + yylval.string = hb_compIdentifierNew( "CASE", TRUE ); hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); @@ -480,7 +481,7 @@ Separator {SpaceTab} } else { /* there is another item in line already */ - yylval.string = hb_strdup( "CASE" ); + yylval.string = hb_compIdentifierNew( "CASE", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -492,12 +493,12 @@ Separator {SpaceTab} ^{Separator}*"_procreq_"{Separator}*"(" { return PROCREQ; } "decl"("are"|"ar"|"a")? { BEGIN DECLARE_; - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); } {Separator}+({Identifier}|{MacroVar}){Separator}*"[" { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - unput( '[' ); + unput( '[' ); yyleng--; /* Remove possible white space between the Identifier and the Index. */ @@ -507,14 +508,13 @@ Separator {SpaceTab} /* Pushback the Identifier */ while( yytext[ yyleng - 1 ] > 32 ) unput( yytext[ --yyleng ] ); - //printf( "\nPushing: %c\n", yytext[ --yyleng ] ); + /* printf( "\nPushing: %c\n", yytext[ --yyleng ] ); */ yytext[ yyleng ] = 0; if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState = PRIVATE; return PRIVATE; } @@ -531,7 +531,6 @@ Separator {SpaceTab} if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState = DECLARE; return DECLARE; } @@ -546,20 +545,20 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - hb_comp_iState = IDENTIFIER; + hb_comp_iState = IDENTIFIER; return IDENTIFIER; } "opti"("onal"|"ona"|"on"|"o")? { BEGIN OPTIONAL_; - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); } {Separator}+"with"{Separator}+[^ .] { /* DO OPTIONAL WITH ...*/ /* Push back the last character. */ - unput( yytext[ --yyleng ] ); + unput( yytext[ --yyleng ] ); - /* Remove possible white space trailing the "with". */ - while( yytext[ yyleng - 1 ] < 48 ) - yyleng--; + /* Remove possible white space trailing the "with". */ + while( yytext[ yyleng - 1 ] < 48 ) + yyleng--; unput( ' ' ); @@ -572,18 +571,18 @@ Separator {SpaceTab} yyleng -= 4; yytext[ yyleng ] = 0; - if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; + if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - hb_comp_iState = IDENTIFIER; + hb_comp_iState = IDENTIFIER; return IDENTIFIER; - } + } {Separator}+"to"{Separator}+[^ .] { /* FOR nVar := OPTIONAL TO ...*/ - /* Push back the last character. */ - unput( yytext[ --yyleng ] ); + /* Push back the last character. */ + unput( yytext[ --yyleng ] ); - /* Remove possible white space trailing the "to". */ - while( yytext[ yyleng - 1 ] < 48 ) - yyleng--; + /* Remove possible white space trailing the "to". */ + while( yytext[ yyleng - 1 ] < 48 ) + yyleng--; unput( ' ' ); @@ -594,11 +593,11 @@ Separator {SpaceTab} yyleng -= 2; yytext[ yyleng ] = 0; - if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; + if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - hb_comp_iState = IDENTIFIER; + hb_comp_iState = IDENTIFIER; return IDENTIFIER; - } + } {Separator}+[_a-zA-Z\&] { /* an Identifier after OPTIONAL */ unput( yytext[ yyleng-1 ] ); @@ -612,21 +611,18 @@ Separator {SpaceTab} } else { /* Now it should be a qalifier. */ - hb_xfree( (void *) yylval.string ); - hb_comp_iState = OPTIONAL; return OPTIONAL; } - } + } {Separator}*[^a-zA-Z] { /* any character (not identifier) after OPTIONAL */ unput( yytext[ yyleng-1 ] ); - if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; + if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - hb_comp_iState = IDENTIFIER; + hb_comp_iState = IDENTIFIER; return IDENTIFIER; } - %{ /* ************************************************************************ */ %} @@ -663,7 +659,7 @@ Separator {SpaceTab} } else { /* there is another item in line already */ - yylval.string = hb_strdup( "DO" ); + yylval.string = hb_compIdentifierNew( "DO", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -671,7 +667,7 @@ Separator {SpaceTab} {Separator}*(.|\n) { /* end of line or any operator */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - yylval.string = hb_strdup( "DO" ); + yylval.string = hb_compIdentifierNew( "DO", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -724,7 +720,7 @@ Separator {SpaceTab} { /* Clipper does not like end[] & end() at the begining of line */ hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_ENDIF, NULL, NULL ); } - yylval.string = hb_strdup( "END" ); + yylval.string = hb_compIdentifierNew( "END", TRUE ); hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; @@ -735,7 +731,7 @@ Separator {SpaceTab} { /* Clipper does not like end-> & end++ at the begining of line */ hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_ENDIF, NULL, NULL ); } - yylval.string = hb_strdup( "END" ); + yylval.string = hb_compIdentifierNew( "END", TRUE ); hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); @@ -743,7 +739,7 @@ Separator {SpaceTab} } {Separator}*[\+\-\:\=\|\$\%\*\,\/\[\]\)\}\^] { /* there is an operator after "end" */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "END" ); + yylval.string = hb_compIdentifierNew( "END", TRUE ); hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; @@ -758,7 +754,7 @@ Separator {SpaceTab} } else { /* there is another item in line already */ - yylval.string = hb_strdup( "END" ); + yylval.string = hb_compIdentifierNew( "END", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -780,7 +776,7 @@ Separator {SpaceTab} } else { /* there is another item in line already */ - yylval.string = hb_strdup( "EXIT" ); + yylval.string = hb_compIdentifierNew( "EXIT", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -795,14 +791,14 @@ Separator {SpaceTab} } else { /* there is another item in line already */ - yylval.string = hb_strdup( "EXIT" ); + yylval.string = hb_compIdentifierNew( "EXIT", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}*. { /* any character (not identifier) after EXIT */ unput( yytext[ yyleng-1 ] ); - yylval.string = hb_strdup( "EXIT" ); + yylval.string = hb_compIdentifierNew( "EXIT", TRUE ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; hb_comp_iState =IDENTIFIER; return IDENTIFIER; @@ -811,14 +807,13 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "exte"|"exter"|"extern"|"externa"|"external" { BEGIN EXTERNAL_; - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); } {Separator}+[_a-zA-Z] { /* an identifier after the EXTERNAL */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { - hb_xfree( (void *) yylval.string ); hb_comp_iState =EXTERN; return EXTERN; } @@ -839,18 +834,17 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "_fie"|"_fiel"|"_field" { BEGIN FIELD_; - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); } "fiel"|"field" { BEGIN FIELD_; - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); } {Separator}+[_a-zA-Z] { /* an identifier after the FIELD */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { - hb_xfree( (void *) yylval.string ); hb_comp_iState =FIELD; return FIELD; } @@ -864,7 +858,6 @@ Separator {SpaceTab} unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - hb_xfree( (void *) yylval.string ); hb_comp_iState =FIELD; return FIELD; } @@ -889,7 +882,7 @@ Separator {SpaceTab} } else { /* for example: DO for WITH variable */ - yylval.string = hb_strdup( "FOR" ); + yylval.string = hb_compIdentifierNew( "FOR", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -900,14 +893,14 @@ Separator {SpaceTab} { /* Clipper does not like FOR() at the begining of line */ hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_SYNTAX, yytext, NULL ); } - yylval.string = hb_strdup( "FOR" ); + yylval.string = hb_compIdentifierNew( "FOR", TRUE ); hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } {Separator}*[^_a-zA-Z] { /* there is no identifier after "FOR" */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "FOR" ); + yylval.string = hb_compIdentifierNew( "FOR", TRUE ); unput( yytext[ yyleng-1 ] ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; @@ -996,7 +989,7 @@ Separator {SpaceTab} return IN; else { - yylval.string =hb_strdup( "IN" ); + yylval.string = hb_compIdentifierNew( "IN", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -1004,7 +997,7 @@ Separator {SpaceTab} {Separator}*\n { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - yylval.string =hb_strdup( "IN" ); + yylval.string = hb_compIdentifierNew( "IN", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -1014,7 +1007,7 @@ Separator {SpaceTab} {Separator}*. { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - yylval.string =hb_strdup( "IN" ); + yylval.string = hb_compIdentifierNew( "IN", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -1032,14 +1025,14 @@ Separator {SpaceTab} } else { /* there is another item in line already */ - yylval.string = hb_strdup( "INIT" ); + yylval.string = hb_compIdentifierNew( "INIT", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}*[^fFpP] { /* any character (not identifier) after EXIT */ unput( yytext[ yyleng-1 ] ); - yylval.string = hb_strdup( "INIT" ); + yylval.string = hb_compIdentifierNew( "INIT", TRUE ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; hb_comp_iState =IDENTIFIER; return IDENTIFIER; @@ -1049,15 +1042,14 @@ Separator {SpaceTab} %} "#"{Separator}*"line" return LINE; "loca"|"local" { - yylval.string = hb_strupr( hb_strdup( yytext ) ); - BEGIN LOCAL_; + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); + BEGIN LOCAL_; } {Separator}+[_a-zA-Z] { /* an identifier after LOCAL */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState =LOCAL; return LOCAL; } @@ -1089,14 +1081,14 @@ Separator {SpaceTab} } else { /* there is another item in line already */ - yylval.string = hb_strdup( "LOOP" ); + yylval.string = hb_compIdentifierNew( "LOOP", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}*. { /* any character (not LF) after LOOP */ unput( yytext[ yyleng-1 ] ); - yylval.string = hb_strdup( "LOOP" ); + yylval.string = hb_compIdentifierNew( "LOOP", TRUE ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; hb_comp_iState =IDENTIFIER; return IDENTIFIER; @@ -1105,14 +1097,13 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "memv"|"memva"|"memvar" { BEGIN MEMVAR_; - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); } {Separator}+[_a-zA-Z] { /* an identifier after MEMVAR */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is the first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState =MEMVAR; return MEMVAR; } @@ -1144,7 +1135,7 @@ Separator {SpaceTab} } else { /* there is another item in line already */ - yylval.string = hb_strdup( "NEXT" ); + yylval.string = hb_compIdentifierNew( "NEXT", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -1155,7 +1146,7 @@ Separator {SpaceTab} { /* Clipper does not like NEXT[] & NEXT() at the begining of line */ hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_NEXTFOR, NULL, NULL ); } - yylval.string = hb_strdup( "NEXT" ); + yylval.string = hb_compIdentifierNew( "NEXT", TRUE ); hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; @@ -1166,7 +1157,7 @@ Separator {SpaceTab} { /* Clipper does not like next-> & next++ at the begining of line */ hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_NEXTFOR, NULL, NULL ); } - yylval.string = hb_strdup( "NEXT" ); + yylval.string = hb_compIdentifierNew( "NEXT", TRUE ); hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); @@ -1174,7 +1165,7 @@ Separator {SpaceTab} } {Separator}*[^_a-zA-Z] { /* there is no identifier after "next" */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "NEXT" ); + yylval.string = hb_compIdentifierNew( "NEXT", TRUE ); unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } @@ -1190,7 +1181,7 @@ Separator {SpaceTab} } else { - yylval.string = hb_strdup( "NEXT" ); + yylval.string = hb_compIdentifierNew( "NEXT", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -1203,7 +1194,7 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "othe"|"other"|"otherw"|"otherwi"|"otherwis"|"otherwise" { - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); BEGIN OTHERWISE_; } {Separator}*[\n\;] { /* end of line */ @@ -1211,7 +1202,6 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is the first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState = OTHERWISE; return OTHERWISE; } @@ -1231,7 +1221,7 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "para"|"param"|"parame"|"paramet"|"paramete"|"parameter"|"parameters" { - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); BEGIN PARAM_; } {Separator}+[_a-zA-Z] { /* an identifier after PARAMETERS */ @@ -1239,7 +1229,6 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is the first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState =PARAMETERS; return PARAMETERS; } @@ -1259,14 +1248,13 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "priv"("ate"|"at"|"a")? { BEGIN PRIVATE_; - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); } {Separator}+[_a-zA-Z\&] { /* an Identifier after PRIVATE */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState =PRIVATE; return PRIVATE; } @@ -1299,14 +1287,13 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "publ"("ic"|"i")? { BEGIN PUBLIC_; - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); } {Separator}+[_a-zA-Z\&] { /* an identifier after PUBLIC */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState =PUBLIC; return PUBLIC; } @@ -1330,7 +1317,7 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "reco"|"recov"|"recove"|"recover" { - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); BEGIN RECOVER_; } {Separator}*[\n] { /* end of line */ @@ -1338,7 +1325,6 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState = RECOVER; return RECOVER; } @@ -1350,7 +1336,6 @@ Separator {SpaceTab} } {Separator}+("using"|"usin") { /* USING */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - hb_xfree( (void *) yylval.string ); hb_comp_iState = RECOVERUSING; return RECOVERUSING; } @@ -1364,7 +1349,7 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "retu"|"retur"|"return" { - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); BEGIN RETURN_; } {Separator}+[\&_a-zA-Z0-9] { /* an identifier, numbers or macro */ @@ -1372,7 +1357,6 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is the first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState = RETURN; return RETURN; } @@ -1395,7 +1379,6 @@ Separator {SpaceTab} unput( yytext[ yyleng-2 ] ); if( hb_comp_iState == LOOKUP ) { /* it is the first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState = RETURN; return RETURN; } @@ -1407,7 +1390,6 @@ Separator {SpaceTab} } {Separator}*("::") { /* SELF operator */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - hb_xfree( (void *) yylval.string ); hb_comp_iState = RETURN; unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); @@ -1419,7 +1401,6 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is the first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState = RETURN; return RETURN; } @@ -1439,7 +1420,7 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "stat"|"stati"|"static" { - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); BEGIN STATIC_; } {Separator}+[_a-zA-Z] { /* an identifier after STATIC */ @@ -1447,7 +1428,6 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - hb_xfree( (void *) yylval.string ); hb_comp_iState = STATIC; return STATIC; } @@ -1479,7 +1459,7 @@ Separator {SpaceTab} { /* we have DO while - replace it with while() */ unput( ')' ); unput( '(' ); } - yylval.string = hb_strdup( "WHILE" ); + yylval.string = hb_compIdentifierNew( "WHILE", TRUE ); return IDENTIFIER; } {Separator}*[\[] { /* array */ @@ -1489,13 +1469,13 @@ Separator {SpaceTab} } {Separator}*[\:\=\|\$\%\*\,\/\]\)\}\^] { /* there is an operator after "case" */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "WHILE" ); + yylval.string = hb_compIdentifierNew( "WHILE", TRUE ); unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } {Separator}*("+="|"-="|"->") { /* operators */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - yylval.string = hb_strdup( "WHILE" ); + yylval.string = hb_compIdentifierNew( "WHILE", TRUE ); unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); return IDENTIFIER; @@ -1517,7 +1497,7 @@ Separator {SpaceTab} } else { /* there is another item in line already */ - yylval.string = hb_strdup( "WHILE" ); + yylval.string = hb_compIdentifierNew( "WHILE", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -1529,7 +1509,7 @@ Separator {SpaceTab} {Separator}*\n { /* at the end of line */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( '\n' ); - yylval.string = hb_strdup( "WITH" ); + yylval.string = hb_compIdentifierNew( "WITH", TRUE ); return IDENTIFIER; } {Separator}*"with" { @@ -1538,7 +1518,7 @@ Separator {SpaceTab} if( hb_comp_iState == DO ) { /* DO with */ hb_comp_iState =IDENTIFIER; - yylval.string = hb_strdup( "WITH" ); + yylval.string = hb_compIdentifierNew( "WITH", TRUE ); return IDENTIFIER; } else @@ -1566,7 +1546,7 @@ Separator {SpaceTab} } else { - yylval.string = hb_strdup( "WITH" ); + yylval.string = hb_compIdentifierNew( "WITH", TRUE ); hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -1727,7 +1707,7 @@ Separator {SpaceTab} yytext[ HB_SYMBOL_NAME_LEN ] = '\0'; yyleng = HB_SYMBOL_NAME_LEN; } - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); /*printf( "\nIdentifier = '%s'\n", hb_strupr( hb_strdup( yytext ) ) );*/ hb_comp_iState = IDENTIFIER; return IDENTIFIER; @@ -1751,7 +1731,7 @@ Separator {SpaceTab} yytext[yyleng] = 0; if( yytext[ yyleng-1 ] == '.' ) yytext[ yyleng-1 ] = '\0'; - yylval.string = hb_strupr( hb_strdup( yytext+1 ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext+1 ), TRUE ); hb_comp_iState = MACROVAR; return MACROVAR; } @@ -1823,7 +1803,7 @@ Separator {SpaceTab} {MacroVar} { if( yytext[ yyleng-1 ] == '.' ) yytext[ yyleng-1 ] = '\0'; - yylval.string = hb_strupr( hb_strdup( yytext+1 ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext+1 ), TRUE ); hb_comp_iState = MACROVAR; return MACROVAR; } @@ -1853,7 +1833,7 @@ Separator {SpaceTab} yytext[ HB_SYMBOL_NAME_LEN ] = '\0'; yyleng = HB_SYMBOL_NAME_LEN; } - yylval.string = hb_strupr( hb_strdup( yytext ) ); + yylval.string = hb_compIdentifierNew( hb_strupr( yytext ), TRUE ); hb_comp_iState = IDENTIFIER; return IDENTIFIER; } @@ -1915,6 +1895,7 @@ static int yy_ConvertNumber( char * szBuffer ) } } + void hb_compReleaseStrings( void ) { } diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 39f60473e5..70130d05ae 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -418,8 +418,8 @@ ExtList : IdentName { hb_compExternAdd( $1 ); } ; IdentName : IDENTIFIER { $$ = $1; } - | STEP { $$ = hb_strdup( "STEP" ); } - | TO { $$ = hb_strdup( "TO" ); } + | STEP { $$ = hb_compIdentifierNew( "STEP", TRUE ); } + | TO { $$ = hb_compIdentifierNew( "TO", TRUE ); } ; /* Numeric values @@ -1549,7 +1549,7 @@ DoProc : DO DoName | DO DoName WITH DoArgList { $$ = hb_compExprNewFunCall( $2, $4 ); } | WHILE WITH DoArgList - { hb_compAutoOpenAdd( "WHILE" ); $$ = hb_compExprNewFunCall( hb_compExprNewFunName( hb_strdup("WHILE") ), $3 ); } + { hb_compAutoOpenAdd( "WHILE" ); $$ = hb_compExprNewFunCall( hb_compExprNewFunName( hb_compIdentifierNew("WHILE", TRUE) ), $3 ); } ; DoArgList : ',' { $$ = hb_compExprAddListExpr( hb_compExprNewArgList( hb_compExprNewNil() ), hb_compExprNewNil() ); } diff --git a/harbour/source/compiler/hbident.c b/harbour/source/compiler/hbident.c new file mode 100644 index 0000000000..f71a13b238 --- /dev/null +++ b/harbour/source/compiler/hbident.c @@ -0,0 +1,104 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * The cache for identifiers + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +#include + +#include "hbhash.h" +#include "hbcomp.h" + +static HB_HASH_TABLE_PTR s_comp_Identifiers; /* table of identifiers for reuse */ + +#define HB_IDENT_BUCKET 211 + +/* create a new identifier or return the existing one +*/ +char * hb_compIdentifierNew( char * szName, BOOL bCopy ) +{ + char * szIdent; + + szIdent = ( char * )hb_hashTableFind( s_comp_Identifiers, (void *) szName ); + if( !szIdent ) + { + if( bCopy ) + szIdent = hb_strdup( szName ); + else + szIdent = szName; + + hb_hashTableAdd( s_comp_Identifiers, (void *)szIdent ); + } + + return szIdent; +} + +/* returns a hash key */ +HB_HASH_FUNC( hb_comp_IdentKey ) /* ULONG func (void *Value, void *Cargo) */ +{ + unsigned char ucSum = 0; + char *szName = ( char * )Value; + + while( *szName ) + ucSum += *szName++; + + HB_SYMBOL_UNUSED( Cargo ); + + return ucSum % HB_IDENT_BUCKET; +} + +/* deletes an identifier */ +HB_HASH_FUNC( hb_comp_IdentDel ) +{ + hb_xfree( Value ); + HB_SYMBOL_UNUSED( Cargo ); + return 1; +} + +/* compares two identifiers */ +HB_HASH_FUNC( hb_comp_IdentComp ) +{ + return strcmp( (char *)Value, (char *)Cargo ); +} + +/* initialize the hash table for identifiers */ +void hb_compIdentifierOpen( ) +{ + s_comp_Identifiers = hb_hashTableCreate( HB_IDENT_BUCKET, hb_comp_IdentKey, + hb_comp_IdentDel, hb_comp_IdentComp ); +} + +/* release identifiers table */ +void hb_compIdentifierClose( ) +{ + hb_hashTableKill( s_comp_Identifiers ); +}