#ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include SYMBOL *symlist = NULL; static SYMTAB *symtab = NULL; static int constants_counter = 0; static int sections_counter = 0; static int repos_counter = 0; static SYMBOL *free_const( SYMBOL *sp ) { SYMBOL *next = NULL; if( !sp ) return next; next = sp->next; free( sp->name ); switch( sp->type ) { case STRING: if( sp->u.string ) free( sp->u.string ); break; case PATH: if( sp->u.string ) free( sp->u.path ); break; case NUMERICAL: default: break; } free( sp ); return next; } static void free_symlist( SYMBOL *sp ); static SYMBOL *free_symbol( SYMBOL *sp ) { SYMBOL *next = NULL; if( !sp ) return next; if( sp->list ) (void)free_symlist( sp->list ); next = sp->next; free( sp->name ); switch( sp->type ) { case SECTION: case STRING: if( sp->u.string ) free( sp->u.string ); break; case REPO: case PATH: if( sp->u.string ) free( sp->u.path ); break; case VARIABLE: case NUMERICAL: default: break; } free( sp ); return next; } static void free_symlist( SYMBOL *sp ) { SYMBOL *next = NULL; if( !sp ) return; next = free_symbol( sp ); while( next ) { next = free_symbol( next ); } } /****************************************** Initialize the stak of symlist pointers: */ void init_symtab( void ) { SYMTAB *sa = (SYMTAB *)xmalloc( sizeof( SYMTAB ) ); symtab = NULL; symlist = NULL; constants_counter = 0; sections_counter = 0; repos_counter = 0; sa->symlist = (SYMBOL **)&symlist; sa->next = symtab; symtab = sa; } /******************************************* Push the address of symlist to the stack: */ void push_symlist( SYMBOL **head ) { if( head ) { SYMTAB *sa = (SYMTAB *)xmalloc( sizeof( SYMTAB ) ); sa->symlist = head; sa->next = symtab; symtab = sa; } } /******************************************** Pop the address of symlist from the stack: */ void pop_symlist( void ) { if( symtab && symtab->next ) { SYMTAB *sa = symtab; symtab = symtab->next; free( sa ); } } /************************************ Free the stak of symlist pointers: */ void fini_symtab( void ) { if( !symtab ) return; while( symtab ) { SYMTAB *sa = symtab; symtab = symtab->next; free( sa ); } constants_counter = 0; sections_counter = 0; repos_counter = 0; symtab = NULL; free_symlist( symlist ); /* free main symlist */ symlist = NULL; } /****************************** Reverse symlist recursively: */ void reverse_symlist( SYMBOL **head ) { SYMBOL *prev = NULL, *curr = *head, *next; while( curr ) { if( curr->list ) reverse_symlist( (SYMBOL **)&(curr->list) ); next = curr->next; curr->next = prev; prev = curr; curr = next; } *head = prev; } /****************************************************** Remove temporary constants from symlist recursively: */ void remove_consts( SYMBOL **head ) { SYMBOL *tmp = NULL; while( *head ) { tmp = *head; if( !strncmp( tmp->name, "__const.", 8 ) ) { *head = tmp->next; (void)free_const( tmp ); } else { head = &tmp->next; if( tmp->list ) remove_consts( (SYMBOL **)&(tmp->list) ); } } } SYMBOL *assign_value( SYMBOL *dest, SYMBOL *src ) { SYMBOL *ret = NULL; if( !dest || !src ) return ret; if( dest->type == VARIABLE ) /* always not initialized */ { dest->type = src->type; dest->u.value = 0; switch( src->type ) { case NUMERICAL: dest->u.value = src->u.value; break; case STRING: dest->u.string = strdup( (const char *)src->u.string ); break; case PATH: dest->u.path = strdup( (const char *)src->u.path ); break; default: /* error */ break; } } else if( dest->type == STRING || dest->type == SECTION ) { switch( src->type ) { case STRING: if( src->u.string ) { if( dest->u.string ) free( dest->u.string ); dest->u.string = strdup( (const char *)src->u.string ); } else { if( dest->u.string ) free( dest->u.string ); dest->u.string = NULL; } break; default: /* error */ break; } } else if( dest->type == PATH || dest->type == REPO ) { switch( src->type ) { case PATH: if( src->u.path ) { if( dest->u.path ) free( dest->u.path ); dest->u.path = strdup( (const char *)src->u.path ); } else { if( dest->u.path ) free( dest->u.path ); dest->u.path = NULL; } break; default: /* error */ break; } } else if( dest->type == src->type ) { switch( src->type ) { case NUMERICAL: dest->u.value = src->u.value; break; case STRING: if( dest->u.string ) free( dest->u.string ); dest->u.string = strdup( (const char *)src->u.string ); break; case PATH: if( dest->u.path ) free( dest->u.path ); dest->u.path = strdup( (const char *)src->u.path ); break; default: /* error */ break; } } else { /* error */ } return dest; } SYMBOL *install( const char *s, int type, ... ) { SYMBOL *sp = NULL; char name[80] = "__undef"; if( !symtab ) return sp; va_list argp; if( ! type ) return( sp ); sp = (SYMBOL *)xmalloc( sizeof( SYMBOL ) ); switch( type ) { case NUMERICAL: case STRING: case PATH: sprintf( (char *)&name[0], "__const.%d", constants_counter++ ); sp->name = strdup( (const char *)&name[0] ); break; case REPO: sprintf( (char *)&name[0], "__repo.%d", repos_counter++ ); sp->name = strdup( (const char *)&name[0] ); break; case SECTION: sprintf( (char *)&name[0], "__section.%d", sections_counter++ ); sp->name = strdup( (const char *)&name[0] ); break; default: if( !s ) sp->name = strdup( (const char *)&name[0] ); else sp->name = strdup( s ); break; } sp->type = type; va_start( argp, type ); switch( type ) { case SECTION: case STRING: { char *string = (char *)va_arg( argp, char * ); if( string ) sp->u.string = strdup( (const char *)string ); break; } case REPO: case PATH: { char *path = (char *)va_arg( argp, char * ); if( path ) sp->u.path = strdup( (const char *)path ); break; } case VARIABLE: case NUMERICAL: default: sp->u.value = (int)va_arg( argp, int ); break; } sp->next = *(symtab->symlist); /* alloc in begin of list */ *(symtab->symlist) = sp; return( sp ); } /*********************************** Find variable in current symlist: */ SYMBOL *lookup( const char *s ) { SYMBOL *sp; for( sp = *(symtab->symlist); sp != (SYMBOL *)0; sp = sp->next ) { if( strcmp( sp->name, s ) == 0 ) return( sp ); } return( 0 ); /* запись не найдена */ } /********************************* Find section in global symlist: */ SYMBOL *lookup_section( const char *s ) { SYMBOL *sp; for( sp = symlist; sp != (SYMBOL *)0; sp = sp->next ) { if( sp->type == SECTION && sp->u.string && strcmp( sp->u.string, s ) == 0 ) return( sp ); } return( 0 ); /* запись не найдена */ } /******************************** Find repo globally in symlist: */ #if 0 SYMBOL *lookup_repo_global( const char *s ) { SYMBOL *sp; for( sp = symlist; sp != (SYMBOL *)0; sp = sp->next ) { /*************************** lookup in global section: */ if( sp->type == REPO && sp->u.path && strcmp( sp->u.path, s ) == 0 ) return( sp ); /************************* lookup in each section: */ if( sp->type == SECTION && sp->list ) { SYMBOL *rp; for( rp = sp->list; rp != (SYMBOL *)0; rp = rp->next ) { if( rp->type == REPO && rp->u.path && strcmp( rp->u.path, s ) == 0 ) return( rp ); } } } return( 0 ); /* запись не найдена */ } #endif /******************************* Find repo in current symlist: */ SYMBOL *lookup_repo( const char *s ) { SYMBOL *sp; for( sp = *(symtab->symlist); sp != (SYMBOL *)0; sp = sp->next ) { if( sp->type == REPO && sp->u.path && strcmp( sp->u.path, s ) == 0 ) return( sp ); } return( 0 ); /* запись не найдена */ }