diff options
Diffstat (limited to 'cscmd/symtab.c')
-rw-r--r-- | cscmd/symtab.c | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/cscmd/symtab.c b/cscmd/symtab.c new file mode 100644 index 0000000..62899c1 --- /dev/null +++ b/cscmd/symtab.c @@ -0,0 +1,471 @@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> + +#include <defs.h> + +#include <main.h> +#include <error.h> +#include <msglog.h> +#include <xalloc.h> +#include <utf8ing.h> +#include <lex.h> + +#include <symtab.h> +#include <parse.h> + + +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 ); /* запись не найдена */ +} |