/*
* 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 <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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++;
}
}
syntax highlighted by Code2HTML, v. 0.9.1