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