/* * surf - visualizing algebraic curves and algebraic surfaces * Copyright (C) 1996-1997 Friedrich-Alexander-Universitaet * Erlangen-Nuernberg * 1997-2000 Johannes Gutenberg-Universitaet Mainz * Authors: Stephan Endrass, Hans Huelf, Ruediger Oertel, * Kai Schneider, Ralf Schmitt, Johannes Beigel * * 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. * * 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. * */ #include #include #include #include #include "mymemory.h" #include "monomarith.h" #include "polyarith.h" #include "polylexyacc.h" #include "polyyacc.h" extern "C" { #ifdef YYTEXT_POINTER extern char *yytext; #else extern char yytext[]; #endif } // Static Data static symtab *s_first = (symtab*)NULL; static symtab *s_last = (symtab*)NULL; static int main_formula_data_index = 0; static int main_formula_data_length = 0; static char *main_formula_data_ptr = 0; /* ------------------------------------------------------------------------- */ /* Global data: pointers to first and last element of out symbol table */ /* ------------------------------------------------------------------------- */ int error_begin_char; long int char_number; /* current position in input_string */ long int line_number; /* current lineno in input_string */ long int goto_label; long int goto_line; int goto_flag; /* ------------------------------------------------------------------------- */ /* Own input and unput functions */ /* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */ /* set yacc/lex input to buffer */ /* ------------------------------------------------------------------------- */ void set_the_yyinput( char *buffer,long int ch_no,long int ln_no ) { main_formula_data_ptr = buffer; main_formula_data_length = strlen( buffer ); main_formula_data_index = 0; char_number = ch_no; line_number = ln_no; } extern "C" int the_yyinput( char *buffer,int max_size ) { /* -------------------------------------------- */ /* input from the string: main_formula_data_ptr */ /* -------------------------------------------- */ int n; int d; d = main_formula_data_length - main_formula_data_index; n = ( max_size > d ? d : max_size ); if( n > 0 ) { memcpy( (void*)buffer,(void*)main_formula_data_ptr,n ); main_formula_data_ptr += n; main_formula_data_index += n; } return n; } /* ------------------------------------------------------------------------- */ /* Add name to symbol table at begin */ /* ------------------------------------------------------------------------- */ symtab *symtab_add_name( const char *name ) { symtab *s = new symtab(); // new_symtab( 1 ); s->name = strdup( name ); s->type = SYM_UNSPEC; s->surface = FALSE; s->constant= FALSE; s->ptr = NULL; s->label = char_number; s->lineno = line_number; s->prev = (symtab*)NULL; /* at begin ... */ s->next = s_first; if( s_first != (symtab*)NULL ) { s_first->prev = s; } if( s_last == (symtab*)NULL ) { s_last = s; } s_first = s; return s; } /* ------------------------------------------------------------------------- */ /* Add name to symbol table at begin which is a surface variable or command */ /* ------------------------------------------------------------------------- */ symtab *symtab_add_surface_name( const char *name, symtyp type, int constant, void *ptr) { symtab *s = symtab_add_name( name ); s->type = type; s->surface = TRUE; s->constant= constant; s->ptr = ptr; return s; } /* ------------------------------------------------------------------------- */ /* Find name of symbol and return symtab pointer */ /* ------------------------------------------------------------------------- */ symtab *symtab_find_name( const char *name ) { symtab *s = s_first; while( s != (symtab*)NULL && strcmp( name,s->name ) != 0 ) { s = s->next; } return s; } /* ------------------------------------------------------------------------- */ /* Delete symbol in symtab by symtab */ /* ------------------------------------------------------------------------- */ void symtab_delete_element( symtab *s ) { if( s != (symtab*)NULL ) { if( s->prev == (symtab*)NULL && s->next == (symtab*)NULL ) { s_first = s_last = (symtab*)NULL; } else if( s->prev == (symtab*)NULL ) { s_first = s->next; s->next->prev = (symtab*)NULL; } else if( s->next == (symtab*)NULL ) { s_last = s->prev; s->prev->next = (symtab*)NULL; } else { s->prev->next = s->next; s->next->prev = s->prev; } symtab_clean( s ); delete s; // s = delete_symtab( s ); } } /* ------------------------------------------------------------------------- */ /* Delete symbol in symtab by name */ /* ------------------------------------------------------------------------- */ void symtab_delete_name( const char *name ) { symtab *s = symtab_find_name( name ); symtab_delete_element( s ); } /* ------------------------------------------------------------------------- */ /* Delete user defined symbols in symtab */ /* ------------------------------------------------------------------------- */ void symtab_delete_user_names( void ) { symtab *s = s_first; symtab *s_next = (symtab*)NULL; while( s != (symtab*)NULL ) { if( !s->surface ) { s_next = s->next; symtab_delete_element( s ); s = s_next; } else { s = s->next; } } } /* ------------------------------------------------------------------------- */ /* Delete system symbols in symtab */ /* ------------------------------------------------------------------------- */ void symtab_delete_surface_names( void ) { symtab *s = s_first; symtab *s_next = (symtab*)NULL; while( s != (symtab*)NULL ) { if( s->surface ) { s_next = s->next; symtab_delete_element( s ); s = s_next; } else { s = s->next; } } } /* ------------------------------------------------------------------------- */ /* Set all surface variables to the default value */ /* ------------------------------------------------------------------------- */ #if 0 void symtab_set_default( void ) { symtab *s = s_first; while( s != (symtab*)NULL ) { if( s->surface && s->constant == FALSE && s->def != (void*)NULL ) { switch( s->type ) { case SYM_STRING: { int l = strlen( (char*)s->def ) + 1; delete_char((char *)s->ptr); s->ptr = new_char(l); memcpy( s->ptr,s->def,l ); break; } case SYM_POLYXYZ: delete_coeff_polyxyz_control( (polyxyz*)s->ptr ); *((polyxyz*)s->ptr) = polyxyz_copy( (polyxyz*)s->def ); break; case SYM_MONOM: *((monxyz*)s->ptr) = *((monxyz*)s->def); break; case SYM_DOUBLE: *((double*)s->ptr) = atof( *((char**)(s->def)) ); break; case SYM_INTEGER: *((int*)s->ptr) = *((int*)s->def); break; case SYM_COMMAND: case SYM_LABEL: case SYM_UNSPEC: break; } } s = s->next; } } #endif /* ------------------------------------------------------------------------- */ /* Set all surface variables to the default value */ /* ------------------------------------------------------------------------- */ #if 0 void symtab_write_default( FILE *picfile ) { symtab *s = s_last; while( s != (symtab*)NULL ) { if( s->surface && s->constant == FALSE && s->def != (void*)NULL ) { switch( s->type ) { case SYM_STRING: break; case SYM_POLYXYZ: break; case SYM_MONOM: break; case SYM_DOUBLE: if( *((double*)s->ptr) != atof( *((char**)(s->def)) ) ) { fprintf( picfile,"%s = %f;\n", s->name,*((double*)s->ptr) ); } break; case SYM_INTEGER: if( *((int*)s->ptr) != *((int*)s->def) ) { fprintf( picfile,"%s = %d;\n", s->name,*((int*)s->ptr) ); } break; case SYM_COMMAND: case SYM_LABEL: case SYM_UNSPEC: break; } } s = s->prev; } } #endif /* ------------------------------------------------------------------------- */ /* Delete all symbols in symtab */ /* ------------------------------------------------------------------------- */ void symtab_delete_total( void ) { symtab *s = s_first; while( s != (symtab*)NULL ) { symtab *s_next = s->next; symtab_delete_element( s ); s = s_next; } } /* ------------------------------------------------------------------------- */ /* Lookup a name in the symbol table. */ /* Add name if not already there */ /* ------------------------------------------------------------------------- */ symtab *symtab_lookup_name( const char *name ) { symtab *s = symtab_find_name( name ); return ( s == (symtab*)NULL ? symtab_add_name( name ) : s ); } /* ------------------------------------------------------------------------- */ /* Free memory associated with a symtab */ /* ------------------------------------------------------------------------- */ void symtab_clean( symtab *s ) { switch( s->type ) { case SYM_STRING: if( s->str != (char*)NULL && !s->surface ) { delete_char( s->str ); s->str = 0; } break; case SYM_POLYXYZ: if( s->p.n > 0 && !s->surface ) { delete_coeff_polyxyz( &s->p ); } break; case SYM_MONOM: case SYM_DOUBLE: case SYM_INTEGER: case SYM_COMMAND: case SYM_LABEL: case SYM_UNSPEC: break; } } /* ------------------------------------------------------------------------- */ /* Default error routine */ /* ------------------------------------------------------------------------- */ /* Global error strings */ char yyerrorstring[1024]; void yyerror( const char *s ) { sprintf( yyerrorstring,"%.900s at line number %ld at '%.16s'", s, line_number, yytext ); error_begin_char = char_number-strlen(yytext); } /* ------------------------------------------------------------------------- */ /* scan labels before interpreting */ /* ------------------------------------------------------------------------- */ #define STATE_START 0 #define STATE_STRING 1 #define STATE_COMMENTA 2 #define STATE_COMMENTB 3 #define STATE_LABEL 4 #define STATE_ACCEPT 5 #define MAXNAMELENGTH 1024 void scan_labels( char *buffer ) { int c = 0; /* char number */ int l = 0; /* line number */ int length = strlen( buffer ); int state = STATE_START; int name_length = 0; char name[MAXNAMELENGTH+1]; symtab *s; while( c < length ) { if( buffer[c]=='\n' ) l++; switch( state ) { case STATE_START: if( buffer[c]=='\"' ) state = STATE_STRING; else if( isalpha( buffer[c] ) || buffer[c]=='_' ) state = STATE_LABEL; else if( buffer[c]=='/' ) state = STATE_COMMENTA; break; case STATE_STRING: if( buffer[c]=='\"' ) state = STATE_START; break; case STATE_COMMENTA: if( buffer[c]=='/' ) state = STATE_COMMENTB; else if( buffer[c]=='\"' ) state = STATE_STRING; else if( isalpha( buffer[c] ) || buffer[c]=='_' ) state = STATE_LABEL; else state = STATE_START; break; case STATE_COMMENTB: if( buffer[c]=='\n' ) state = STATE_START; break; case STATE_LABEL: if( buffer[c]=='\"' ) { state = STATE_STRING; name_length = 0; } else if( buffer[c]==':' ) state = STATE_ACCEPT; else if( isalnum( buffer[c] ) || buffer[c]=='_' ) { state = STATE_LABEL; name_length++; } else if( buffer[c]=='/' ) state = STATE_COMMENTA; else { state = STATE_START; name_length = 0; } break; case STATE_ACCEPT: if( buffer[c]=='\"' ) state = STATE_STRING; else if( isalpha( buffer[c] ) || buffer[c]=='_' ) state = STATE_LABEL; else if( buffer[c]=='/' ) state = STATE_COMMENTA; else state = STATE_START; strncpy( name,&(buffer[c-name_length-2]),name_length+1 ); name[name_length+1]='\0'; /* printf( "accept: %s\n",name ); */ s = symtab_add_name( name ); /* if( s->type != SYM_UNSPEC ) { yyerror( "Label already in use" ); } */ s->type = SYM_LABEL; s->label = c+1; s->lineno = l; name_length=0; break; default: break; } c++; } }