home *** CD-ROM | disk | FTP | other *** search
- /* intutil.c
- Dieses File enthält Utility-Funktionen zum Erstellen eines neuen
- Interpreterbefehls oder dessen Ausführung.
- (c) 1990 Michael Beising & TOOLBOX
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "interp.h"
- #include <math.h>;
-
- /* Funktionsprototypen */
- void SetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type);
- void GetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type);
- void PushExp (void);
- void CalcResult (int Op, int Ops);
- void SetResultValue (VAR *Result);
-
- void ReadValue (VAR *Wert);
- EXPDEF *PopExp (void);
-
- int CmpVar (void);
- int Compare (int Op);
- int ReadComp (int *Op);
-
- void ClearProg (void);
- /* die neuen Funktionen */
-
- void Expression (void);
- void Term (void);
- void Faktor (void);
- int TestFunc (int *func);
-
- void NewString (VARDEF *Var,size_t len);
- void MinMax (int Ops, int minmax);
- void Length (void);
- void Left (void);
- void Right (void);
- void Mid (void);
- void InStr(void);
-
- int TestComma (void);
- int GetStringVar (VAR **str);
- int GetLong (long *val);
-
-
- /* Benötigte Globalvariablen */
- extern int IntError; /* Interpreterfehler */
- extern PRGZEILE *FirstLine; /* erste Interpreterzeile */
- extern PRGZEILE *ActLine; /* aktuelle interpretierte Zeile */
- extern char *LinePos; /* Zeilenposition der aktuellen Zeile*/
- extern int Steuer; /* der aufrufenden Routine wird mit- */
- /* geteilt, um was es sich handelt. */
- extern char ScanBuffer[ZEILENLAENGE]; /* Ergebnisbuffer des Scanners */
-
- extern VAR *FirstVar; /* Zeiger auf die erste Variable */
-
- static int expOk; /* ist der ausgewertete Ausdruck korrekt */
-
- /* die Namen der Interpreterfunktionen */
- static char *ifuncs[] = { "sqr","sqrt","sin","cos","tan","atan",
- "ln","exp","min","max",
- "laenge","links","rechts","mitte",
- "suche",
- NULL };
-
- /* und zugehörige Tokens zum Aufruf */
- #define NEGOP 'a'
- #define SQROP 'b'
- #define SQRTOP 'c'
- #define SINOP 'd'
- #define COSOP 'e'
- #define TANOP 'f'
- #define ATANOP 'g'
- #define LNOP 'h'
- #define EXPOP 'i'
-
- /* BEACHTE : einige der Funktionen werden direkt ( also nicht über
- CalcResult aufgerufen ), und brauchen daher kein Token
- */
-
-
- /* ShowLine
- Zeile wieder zurückwandeln und ausgeben.
- */
- extern TOKBEF TokBefDesc[];
-
- void
- ShowLine (FindZeile)
- PRGZEILE *FindZeile;
- {
- char *Line;
-
- Line = FindZeile->Zeile;
- if (*Line) { /* Ist die Programmzeile leer? */
- printf ("\n%03d %s ",
- FindZeile->LineNumber,
- TokBefDesc[(*Line-TOKMIN)&0xff].Befehl
- );
- Line++;
- if (*Line) printf ("%s",Line);
- }
-
- }
-
-
- /* "IsVariable" sucht nach einer Variablen mit gleichem Namen.
- Gibt es keine, wird ein NULL-Zeiger zurückgeliefert.
- */
-
- VAR *
- IsVariable (Name)
- char *Name;
- {
- register VAR *i;
-
- for (i = FirstVar;
- i && (strcmp(Name,i->VarName) != 0);
- i = i->NextVar);
-
- return (i);
- }
-
- /* "SetVar" sieht nach, ob es die Varible schon gibt.
- Wenn ja, wird ihr Wert verändert. Ansonsten wird
- eine neue Variable angelegt.
- */
-
- int
- SetVar (Wert)
- VAR *Wert;
- {
- VAR *Variable;
- VAR Value;
-
- /* Lies den zu setzenden Wert ein */
- if (CalcExpression (&Value) == ERROR) return (ERROR);
-
- if ( Steuer != EOLCHAR ){
- serror( "unerwartetes Zeilenende" ); return(ERROR);
- }
-
- /* Gibt es eine Variable mit dem Namen, dann setze Zeiger */
- if ((Variable = IsVariable (Wert->VarName)) != NULL) {
- SetValue (&Variable->VarWert,&Value.VarWert,Value.VarType);
- return (OK);
- }
-
- if ((Variable = malloc(sizeof (VAR))) == NULL) {
- printf ("\n Kein Speicherplatz mehr für die Variable! ");
- return (FALSE);
- }
-
- strcpy (Variable->VarName,Wert->VarName); /* Variablennamen eintragen */
- Variable->VarType = Value.VarType; /* Variablen-Type eintragen */
- SetValue (&Variable->VarWert,&Value.VarWert,Value.VarType);
- Variable->NextVar = FirstVar;
- FirstVar = Variable; /* Variable oben einfügen */
-
- return (OK);
- }
-
- /* NewString : neuen String bereitstellen oder
- den Speicher auf neue Grö₧e erweitern
- */
-
- void NewString ( Var,len )
- VARDEF *Var;
- size_t len;
- {
-
- len++; /* für '\0' Abschlu₧ */
- if ( Var->variable.text == NULL )
- Var->variable.text = calloc( len,sizeof(char));
- else
- Var->variable.text = realloc( Var->variable.text,len );
- }
-
- /* Einlesen eines Ausdrucks von der gerade aktuellen Eingabeposition
- ab.
- */
-
- void
- ReadValue (Wert)
- VAR *Wert;
- {
-
- Scan (); /* Nächster Ausdruck von Eingabezeile */
- switch (Steuer) {
- case ZIFFER:
- /*
- Wert->VarType = FIXNUM;
- Wert->VarWert.variable.integer = atoi (ScanBuffer);
- break;
- führt sonst zu Fehler, da CalcExpression nur FLONUM liefert
- */
- case FLONUM:
- Wert->VarType = FLONUM;
- Wert->VarWert.variable.Flotype = atof (ScanBuffer);
- break;
- case STRING:
- Wert->VarType = STRING;
- NewString ( &Wert->VarWert,strlen( ScanBuffer ));
- strcpy (Wert->VarWert.variable.text,ScanBuffer);
- break;
- case ALPHA:
- printf ("\n Variablenzuweisung noch nicht implementiert! ");
- break;
- case SONDER:
- if (*ScanBuffer == '(') {
-
- }
- else
- printf ("\nUngültiges Zeichen in Ausdruck gefunden! ");
- }
-
- }
-
-
- /* SetValue Setze den Wert der Variable */
- void
- SetValue (NewVar,Wert,Type)
- VARDEF *NewVar,*Wert;
- unsigned char Type;
- {
-
- switch (Type) {
- case FIXNUM:
- NewVar->variable.integer = Wert->variable.integer;
- break;
- case FLONUM:
- NewVar->variable.Flotype = Wert->variable.Flotype;
- break;
- case ALPHA: /* ist das so korrekt ? was mit Variablen ? */
- NewVar->variable.zeichen = Wert->variable.zeichen;
- break;
- case STRING:
- if ( NewVar->variable.text != NULL )
- free( NewVar->variable.text );
- NewVar->variable.text = Wert->variable.text;
- break;
- default:
- printf ("\n Variablenzuweisung für diesen Typ nicht implementiert! ");
- break;
- }
-
- }
-
- void
- GetValue (Var,Wert,Type)
- VARDEF *Var,*Wert;
- unsigned char Type;
- {
-
- switch (Type) {
- case FLONUM:
- Wert->variable.integer = Var->variable.integer;
- break;
- case FIXNUM:
- Wert->variable.Flotype = Var->variable.Flotype;
- break;
- case ALPHA: /* siehe SetValue */
- Wert->variable.zeichen = Var->variable.zeichen;
- break;
- case STRING:
- strcpy (Wert->variable.text,Var->variable.text);
- break;
- default:
- printf ("\n Variablenzuweisung für diesen Typ nicht implementiert! ");
- break;
- }
- }
-
-
- /*static*/ EXPDEF *BotStack;
- static EXPDEF *TopStack;
-
-
- /* CmpVar vergleicht zwei Variablen auf Größer, Kleiner oder Gleich */
-
- int
- CmpVar ()
- {
- int rel;
- int Op;
-
- BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF));
-
- Scan (); /* Erstes Argument lesen... */
- expOk = TRUE; Expression(); /* ... und auswerten */
- if ( !expOk ){
- serror ("Ungültiger 1. Ausdruck gefunden! ");
- return (FALSE); /* Bedingung fehlerhaft */
- }
-
- if ( ReadComp( &Op ) == FALSE ){
- serror ("Vergleichsoperator erwartet! ");
- return (FALSE); /* Bedingung fehlerhaft */
- }
-
- Scan(); /* Zweites Argument lesen... */
- expOk = TRUE; Expression(); /* ... und auswerten */
- if ( !expOk ){
- serror ("Ungültiger 2. Ausdruck gefunden! ");
- return (FALSE); /* Bedingung fehlerhaft */
- }
-
- rel = Compare( Op );
- free ( BotStack );
- /* Beachte : Stack wird im Fehlerfall nicht freigegeben */
- return (rel);
- }
-
- /* ReadComp: lies Vergleichsoperator ein
- */
-
- int
- ReadComp ( Op )
- int *Op;
- {
- int relop; /* zeigt an ob korrekter Vergleichoperetor gefunden */
-
- relop = TRUE; /* wir sind ja Optimisten */
- switch (*ScanBuffer) {
- case '/':
- Scan ();
- if (*ScanBuffer == '=')
- *Op = UNGL;
- else {
- SkipChar ();
- }
- break;
- case '>':
- Scan ();
- if (*ScanBuffer == '=')
- *Op = GRGL;
- else {
- SkipChar ();
- *Op = GR;
- }
- break;
- case '<':
- Scan ();
- if (*ScanBuffer == '=')
- *Op = KLGL;
- else {
- SkipChar ();
- *Op = KL;
- }
- break;
- case '=':
- *Op = GL;
- break;
- default:
- relop = FALSE;
- break;
- }
- return( relop );
- }
-
- /* Compare
- Vergleiche die Ausdrücke auf dem Stack.
- */
-
- int
- Compare ( Op )
- int Op;
- {
- EXPDEF *Var1,*Var2;
- int rel;
-
- if ((Var2 = PopExp()) == NULL) {
- return(FALSE);
- }
- if ((Var1 = PopExp()) == NULL) {
- return( Var2->val.wert != 0 );
- }
- if (Var1->type == Var2->type) {
- if ( Var1->type == ZAHL ){
- switch (Op) { /* hier wird endlich verglichen */
- case GL:
- return ((Var1->val.wert == Var2->val.wert) ?
- TRUE : FALSE);
- case GRGL:
- return ((Var1->val.wert >= Var2->val.wert) ?
- TRUE : FALSE);
- case GR:
- return ((Var1->val.wert > Var2->val.wert) ?
- TRUE : FALSE);
- case KLGL:
- return ((Var1->val.wert <= Var2->val.wert) ?
- TRUE : FALSE);
- case KL:
- return ((Var1->val.wert < Var2->val.wert) ?
- TRUE : FALSE);
- case UNGL:
- return ((Var1->val.wert != Var2->val.wert) ?
- TRUE : FALSE);
- }/*switch*/
- }/* ZAHL */
- else if ( Var1->type == TEXT ){
- rel = strcmp( Var1->val.text,Var2->val.text );
- switch ( Op ) {
- case GL : return (( rel == 0 ) ? TRUE : FALSE );
- case GRGL : return (( rel >= 0 ) ? TRUE : FALSE );
- case GR : return (( rel > 0 ) ? TRUE : FALSE );
- case KLGL : return (( rel <= 0 ) ? TRUE : FALSE );
- case KL : return (( rel < 0 ) ? TRUE : FALSE );
- case UNGL : return (( rel != 0 ) ? TRUE : FALSE );
- }
- }/* TEXT */
- }/* type equal */
- return(TRUE); /* nur für den Compiler */
- }/* Compare */
-
- /* druckt eine Variable aus */
-
- void
- PrintVar (Name)
- char *Name;
- {
- VAR *Variable;
-
- /* wenn es eine Variable mit dem gesuchten Namen gibt, merken! */
- if ((Variable = IsVariable (Name)) != NULL) {
- switch (Variable->VarType) {
- case FIXNUM:
- printf ("%d",Variable->VarWert.variable.integer);
- break;
- case FLONUM:
- printf ("%f",Variable->VarWert.variable.Flotype);
- break;
- case STRING:
- printf( "%s",Variable->VarWert.variable.text );
- break;
- default:
- printf ("\n Variablen dieses Typs können nicht gedruckt werden! ");
- break;
- }
- }
- else {
- char buffer[40];
- sprintf (buffer,"Variable <%s> unbekannt! ",Name);
- fatal_error (buffer);
- }
- }
-
-
- /* CalcExpression: berechnet das Ergebnis eines Ausdrucks
- */
-
- int
- CalcExpression (Result)
- VAR *Result;
- {
- /* VAR *Variable; */
-
- BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF));
-
- Scan (); /* den ersten Ausdruck einlesen */
- if (Steuer == EOLCHAR)
- return (ERROR);
-
- expOk = TRUE; Expression();
-
- SetResultValue( Result );
- free (BotStack); /* Speicher wieder freigeben */
- if ( expOk ) return (OK);
- else return (ERROR);
- }
-
- /* Expression, Term und Faktor werten einen Ausdruck aus */
-
- void Expression (void)
- {
- char addop;
-
- if (( Steuer == SONDER ) &&
- (( *ScanBuffer == '+' ) || ( *ScanBuffer == '-' )) &&
- expOk ){
- addop = *ScanBuffer;
- Scan(); Term();
- if ( addop == '-' ) CalcResult( NEGOP,1 );
- }
- else Term();
-
- while (( Steuer == SONDER ) &&
- (( *ScanBuffer == '+' ) || ( *ScanBuffer == '-' )) &&
- expOk ){
- addop = *ScanBuffer;
- Scan(); Term();
- CalcResult( addop,2 );
- }
- }/* Expression */
-
- void Term (void )
- {
- char mulop;
-
- Faktor();
- while (( Steuer == SONDER ) &&
- (( *ScanBuffer == '*' ) || ( *ScanBuffer == '/' )) &&
- expOk ){
- mulop = *ScanBuffer;
- Scan(); Faktor();
- CalcResult( mulop,2 );
- }
- }/* Term */
-
- void Faktor (void)
- {
- int f;
- int o;
-
- if (( Steuer == SONDER ) && ( *ScanBuffer == '(' )){
- Scan(); Expression();
- if ( *ScanBuffer == ')' ) Scan();
- else{ expOk = FALSE; serror ( ") erwartet" ); }
- }
- else if ( Steuer == ALPHA ){
- if ( TestFunc( &f ) == 0 ){
- Scan();
- if (( Steuer == SONDER ) && ( *ScanBuffer == '(' )){
- o = 0;
- do{
- Scan();
- if (( Steuer == SONDER ) && ( *ScanBuffer == ')' )) break;
- /* nur für den Fall das kein Parameter angegeben wird
- z.B. sqr() */
- Expression(); o++;
- } while(( Steuer == SONDER ) && ( *ScanBuffer == ',' ));
- if ( *ScanBuffer == ')' ){
- switch ( f ){
- case 0 :
- if ( o == 1 ) CalcResult( SQROP,1 );
- else serror( "<sqr> erwartet 1 Parameter" );
- break;
- case 1 :
- if ( o == 1 ) CalcResult( SQRTOP,1 );
- else serror( "<sqrt> erwartet 1 Parameter" );
- break;
- case 2 :
- if ( o == 1 )CalcResult ( SINOP,1 );
- else serror( "<sin> erwartet 1 Parameter" );
- break;
- case 3 :
- if ( o == 1 ) CalcResult ( COSOP,1 );
- else serror( "<cos> erwartet 1 Parameter" );
- break;
- case 4 :
- if ( o == 1 ) CalcResult ( TANOP,1 );
- else serror( "<tan> erwartet 1 Parameter" );
- break;
- case 5 :
- if ( o == 1 ) CalcResult ( ATANOP,1 );
- else serror( "<atan> erwartet 1 Parameter" );
- break;
- case 6 :
- if ( o == 1 ) CalcResult ( LNOP,1 );
- else serror( "<ln> erwarte 1 Parameter" );
- break;
- case 7 :
- if ( o == 1 ) CalcResult ( EXPOP,1 );
- else serror( "<exp> erwartet 1 Parameter" );
- break;
- case 8 :
- if ( o > 0 ) MinMax( o,0 );
- else serror( "mindestens ein Parameter für <min>" );
- break;
- case 9 :
- if ( o > 0 ) MinMax( o,1 );
- else serror( "mindestens 1 parameter für <max>" );
- break;
- case 10 :
- if ( o == 1 ) Length();
- else serror( "<laenge> erwartet 1 Parameter" );
- break;
- case 11 :
- if ( o == 2 ) Left();
- else serror( "<links> erwartet 2 Parameter" );
- break;
- case 12 :
- if ( o == 2 ) Right();
- else serror( "<rechts> erwartet 2 Parameter" );
- break;
- case 13 :
- if ( o == 3 ) Mid();
- else serror( "<mitte> erwartet 3 Parameter" );
- break;
- case 14 :
- if ( o == 3 ) InStr();
- else serror( "<suche> erwartet 3 Parameter" );
- break;
- }/*switch*/
- Scan();
- }
- else{ expOk = FALSE; serror( ") erwartet" ); }
- }
- else{ expOk = FALSE; serror( "( erwartet" ); }
- }
- else{ PushExp(); Scan(); }
- }
- else if (( Steuer == ZIFFER ) || ( Steuer == FLONUM ) ||
- ( Steuer == STRING )){
- PushExp(); Scan();
- }
- else{ expOk = FALSE; serror( "Fehler in Ausdruck" ); }
- }/* Faktor */
-
- /* TestFunc : ist der Bezeichner der in Faktor gefunden wurde
- ein Funktionsname ?
- */
-
- int TestFunc ( func )
- int *func;
- {
- register int i,j;
-
- for ( i=0;
- ( ifuncs[ i ] != NULL ) &&
- ( j = strcmp( ifuncs[ i ],ScanBuffer ) != 0 );
- i++ );
- *func = i;
- return( j );
- }/* TestFunc */
-
- /* SetResultValue: wandelt das Berechnungsergebnis in die Variablenstruktur
- */
-
- void
- SetResultValue (Result)
- VAR *Result;
- {
-
- switch (BotStack->type) {
- case ZAHL: /* Zahlen in Fließkommadarstellung */
- Result->VarWert.variable.Flotype = BotStack->val.wert;
- Result->VarType = FLONUM;
- break;
- case TEXT:
- Result->VarWert.variable.text = BotStack->val.text;
- Result->VarType = STRING;
- break;
- case FELD:
- fatal_error ("Arrayzuweisung noch nicht implementiert! ");
- break;
- default:
- fatal_error ("Unbekannter Zahlentyp gefunden! ");
- break;
- }
- }
-
-
- /* PushExp
- welche in ScanBuffer steht auf Stack ablegen.
- */
- void
- PushExp ()
- {
- VAR *Variable;
-
- switch (Steuer) {
- case ZIFFER:
- case FLONUM:
- TopStack->type = ZAHL;
- TopStack->val.wert = atof (ScanBuffer);
- break;
- case ALPHA:
- /* Wenn es die gesuchte Variable gibt, Zeiger drauf und merken! */
- if ((Variable = IsVariable (ScanBuffer)) != NULL) {
- switch (Variable->VarType) {
- case ZIFFER:
- TopStack->type = ZAHL;
- TopStack->val.wert = Variable->VarWert.variable.integer;
- break;
- case FLONUM:
- TopStack->type = ZAHL;
- TopStack->val.wert = Variable->VarWert.variable.Flotype;
- break;
- case STRING :
- TopStack->type = TEXT;
- TopStack->val.text = malloc( strlen( Variable->VarWert.variable.text )+1);
- strcpy( TopStack->val.text,
- Variable->VarWert.variable.text );
- break;
- default :
- serror ("Variablentyp für Operation nicht erlaubt! ");
- break;
- }
- }
- else
- serror ("Variable nicht definiert! ");
- break;
- case STRING:
- TopStack->type = TEXT;
- TopStack->val.text = malloc( strlen( ScanBuffer )+1);
- strcpy( TopStack->val.text,ScanBuffer );
- break;
- default:
- serror ("Keine Operation für diesen Typ vorhanden! ");
- break;
- }
- TopStack++; /* Stackpointer an die nächste Position */
- }
-
-
- /* CalcResult: berechnet das Ergebnis eines Ausdrucks,
- der sich auf dem Stack befindet
- */
- void
- CalcResult ( Op,Ops )
- int Op,Ops;
- {
- EXPDEF *Var1,*Var2,Result;
- char *v1,*v2;
- size_t l1,l2;
-
-
- /* da die Anzahl der Parameter schon in <Faktor> überprüft
- wird, sparen wir uns hier weitere Kontrollen
- */
- Var1 = PopExp();
-
- if( Ops > 1 ) Var2 = PopExp();
-
- if (( Ops == 1 ) || ( Var1->type == Var2->type )) {
- if ( Var1->type == ZAHL ){
- switch (Op) {
- case '+':
- Result.val.wert = Var2->val.wert + Var1->val.wert;
- break;
- case '-':
- Result.val.wert = Var2->val.wert - Var1->val.wert;
- break;
- case '*':
- Result.val.wert = Var2->val.wert * Var1->val.wert;
- break;
- case '/':
- Result.val.wert = Var2->val.wert / Var1->val.wert;
- break;
- case NEGOP :
- Result.val.wert = -Var1->val.wert;
- break;
- case SQROP :
- Result.val.wert = Var1->val.wert * Var1->val.wert;
- break;
- case SQRTOP :
- Result.val.wert = sqrt ( Var1->val.wert );
- break;
- case SINOP :
- Result.val.wert = sin ( Var1->val.wert*M_PI/180 );
- break;
- case COSOP :
- Result.val.wert = cos ( Var1->val.wert*M_PI/180 );
- break;
- case TANOP :
- Result.val.wert = tan ( Var1->val.wert*M_PI/180 );
- break;
- case ATANOP :
- Result.val.wert = 180/M_PI*atan ( Var1->val.wert );
- break;
- case LNOP :
- Result.val.wert = log ( Var1->val.wert );
- break;
- case EXPOP :
- Result.val.wert = exp ( Var1->val.wert );
- break;
- }/* switch */
- TopStack->val.wert = Result.val.wert;
- }/* ZAHL */
- else if ( Var1->type == TEXT ){
- /* für / + * gemeinsame Anweisungen */
- l1 = strlen( Var1->val.text );
- l2 = strlen( Var2->val.text );
- v1 = Var1->val.text;
- switch ( Op ){
- case '+' :
- Var2->val.text = realloc( Var2->val.text,l1+l2+1 );
- v2 = Var2->val.text;
- while ( *v2++ != '\0' ); v2--; /* ohne '\0' */
- v1 = Var1->val.text;
- while (( *v2++ = *v1++ ) != '\0' );
- break;
- case '*' :
- case '/' :
- if ( l1 > l2 ) l1 = l2;
- v2 = Var2->val.text;
- if ( Op == '/' ) v2 += ( l2 - l1 );
- /* bis auf diese Anweisung, sind die beiden gleich */
- while ( l1-- > 0 ) *v2++ = *v1++; /* ohne '\0' */
- break;
- }/* switch Op */
- free( Var1->val.text );
- TopStack->val.text = Var2->val.text;
- }/* TEXT */
- TopStack->type = Var1->type;
- TopStack++;
- }
- else
- serror ("Operation für Variablentyp nicht implementiert! ");
-
- }/* CalcResult */
-
- /* MinMax : je nach Wert des Parameters minmax, Minimum oder
- Maximum der durch Ops bestimmten Anzahl Werte auf
- dem Stack ermitteln
- eine Funktion für min und max, weil beide bis auf den Ver-
- gleich identisch sind
- */
-
- void MinMax ( Ops,minmax )
- int Ops,minmax;
- {
- EXPDEF Result,*Var;
-
- Var = PopExp();
- Result.val.wert = Var->val.wert;
- Result.type = Var->type; /* eigentlich müssen wir noch auf ZAHL testen */
- while ( --Ops > 0 ){
- Var = PopExp();
- if ( Var->type != Result.type ){
- serror( "nur gleiche Typen für <max> erlaubt" );
- break;
- }
- if ( minmax == 1 ){
- if ( Var->val.wert > Result.val.wert )
- Result.val.wert = Var->val.wert;
- }
- else{
- if ( Var->val.wert < Result.val.wert )
- Result.val.wert = Var->val.wert;
- }
- }
- TopStack->type = Result.type;
- TopStack->val.wert = Result.val.wert;
- TopStack++;
- }/* MinMax */
-
- /* Length : die Länge eines Strings */
-
- void Length( void )
- {
- EXPDEF *top;
- size_t len;
-
- top = PopExp();
- if ( top->type != TEXT ){
- fatal_error( "STRING erwartet in <laenge>" ); return;
- }
- len = strlen( top->val.text );
- free( top->val.text );
- TopStack->type = ZAHL;
- TopStack->val.wert = (float)len;
- TopStack++;
- }/* Length */
-
- /* Left : die durch anz bestimmte Anzahl Zeichen von links her
- aus einem String
- Syntax : links "(" String "," Zahl ")"
- String und zahl können jeweils ein Ausdruck des
- entsprechenden Typs sein
- Bsp. setze l=links(s+"...",x-2);
- */
-
- void Left( void )
- {
- EXPDEF *str,*anz;
- char *s;
-
- anz = PopExp();
- if ( anz->type != ZAHL ){
- fatal_error( "<links> erwartet ZAHL als 2. P." ); return;
- }
- str = PopExp();
- if ( str->type != TEXT ){
- fatal_error( "<links> erwartet STRING als 1. P." ); return;
- }
- s = str->val.text + (long)anz->val.wert;
- *s = '\0'; /* den Rest einfach abschneiden */
- TopStack->type = TEXT;
- TopStack->val.text = str->val.text;
- TopStack++;
- }/* Left */
-
- /* Right : wie Left, nur sind hier die Zeichen vom rechten Ende
- her gewünscht
- Syntax : rechts "(" String "," Zahl ")"
- */
-
- void Right( void )
- {
- EXPDEF *str,*anz;
- char *s,*d;
- size_t l;
-
- anz = PopExp();
- if ( anz->type != ZAHL ){
- fatal_error( "<rechts> erwartet ZAHL als 2. P." ); return;
- }
- str = PopExp();
- if ( str->type != TEXT ){
- fatal_error( "<rechts> STRING als 1. P." ); return;
- }
- l = strlen( str->val.text );
- if ( (long)anz->val.wert > l ) anz->val.wert = l;
- s = str->val.text;
- d = s + ( l - (long)anz->val.wert );
- while ( (*s++ = *d++ ) != '\0' ); /* den rechten Teil zum
- Stringanfang hinziehen */
- TopStack->type = TEXT;
- TopStack->val.text = str->val.text;
- TopStack++;
- }/* Right */
-
- /* Mid : hier wird mitten hinein gegriffen
-
- Syntax mitte "(" String "," Zahl1 "," Zahl2 ")"
-
- Zahl1 bestimmt ab welcher Position
- Zahl viel zeichen genommen werden
- */
-
- void Mid ( void )
- {
- EXPDEF *str,*start,*anzahl;
- char *mid,*s,*d;
- int ab,anz,len;
-
- anzahl = PopExp();
- if ( anzahl->type != ZAHL ){
- fatal_error( "<mitte> erwartet ZAHL als 3.P." ); return;
- }
- else anz = (int)anzahl->val.wert;
- start = PopExp();
- if ( start->type != ZAHL ){
- fatal_error( "<mitte> erwartet ZAHL als 2.P." ); return;
- }
- else ab = (int)start->val.wert;
- str = PopExp();
- if ( str->type != TEXT ){
- fatal_error( "<mitte> erwartet STRING als 1.P." ); return;
- }
- else len = (int)strlen( str->val.text );
-
- if ( ab > len ){ /* Anfangsposition hinter Stringende */
- *TopStack->val.text = '\0';
- }
- else {
- if ( anz > ( len - ab )) anz = len - ab; /* nicht mehr als da */
- mid = calloc( anz,sizeof( char )); /* Speicher für mid */
- s = str->val.text + (long)ab; /* von hier ... */
- d = mid; /* ... nach da */
- while ( anz-- > 0 ) *d++ = *s++; *d = '\0';
- free( str->val.text );
- TopStack->val.text = mid;
- }
- TopStack->type = TEXT;
- TopStack++;
- }/* Mid */
-
- /* Instr : suche pattern in String ab Position start
-
- Syntax : suche "(" String "," Stringvariable "," Zahl ")"
- Bsp. setze pos=suche("wie","na wie geht's",0);
- */
-
- void InStr( void )
- {
- EXPDEF *pattern,*str,*start;
- char *search,*find;
- size_t len;
- long ab,pos;
-
- start = PopExp();
- if ( start->type != ZAHL ){
- serror( "<suche> erwartet ZAHL als 2.P." ); return;
- }
- else ab = (long)start->val.wert;
-
- str = PopExp();
- if ( str->type != TEXT ){
- serror( "<suche> erwartet STRING als 2.P." ); return;
- }
- else len = strlen( str->val.text );
-
- pattern = PopExp();
- if ( pattern->type != TEXT ){
- serror( "<suche> erwartet STRING als 1.P." ); return;
- }
-
- if ( ab > len ){ /* Anfangsposition hinter Stringende */
- TopStack->val.wert = -1;
- }
- else {
- search = str->val.text + ab; /* ab hier ... */
- find = strstr( search,pattern->val.text ); /* ...suchen */
- if ( find == NULL ) pos = -1; /* nicht gefunden */
- else pos = find - str->val.text; /* bei pos gefunden */
- free( str->val.text );
- free( pattern->val.text );
- TopStack->val.wert = (float)pos;
- }
- TopStack->type = ZAHL;
- TopStack++;
-
- }/* InStr */
-
-
- /* PopExp
- Holt einen Ausdruck vom Variablenstack
- */
-
- EXPDEF *
- PopExp ()
- {
- if (TopStack-- != BotStack)
- return (TopStack);
- else
- return (NULL);
- }
-
- /* ClearProg: den Speicherplatz, der durch das Programm
- belegt ist, freigeben
- */
-
- void
- ClearProg ()
- {
- PRGZEILE *Memory;
-
- ActLine = FirstLine; /* Zeiger auf erste Programmzeile */
- while (ActLine) {
- Memory = ActLine; /* wird gleich benötigt */
- ActLine = ActLine->NextZeile; /* das ist die nächste Zeile */
- free (Memory); /* Speicherplatz freigeben */
- }
-
- FirstLine = ActLine = NULL; /* Zeiger zurücksetzen */
-
- }
-
- /* TestComma : teste ob das zeichen im ScanBuffer ein "," ist */
- int TestComma()
- {
- if (( Steuer == SONDER ) && ( *ScanBuffer == ',' ))
- return ( TRUE );
- else{
- serror( ", erwartet" ); return ( FALSE );
- }
- }
-
- /* GetStringVar : lies den nächsten Bezeichner und liefere
- die zugehörige Variable
- */
-
- int GetStringVar ( str )
- VAR **str;
- {
- Scan();
- if( Steuer != ALPHA ){
- serror( "Bezeichner erwartet" );
- return( FALSE );
- }
- if (( *str = IsVariable( ScanBuffer )) == NULL ){
- fatal_error( "Variable existiert nicht" );
- return( FALSE );
- }
- return ( TRUE );
- }
-
- /* GetLong : lies und berechne den nächsten Ausdruck, und
- liefere seinen Wert als long-Grö₧e
- */
-
- int GetLong ( val )
- long *val;
- {
- VAR Var;
-
- CalcExpression( &Var );
- if ( Var.VarType == FLONUM ){
- *val = (long)Var.VarWert.variable.Flotype;
- return ( TRUE );
- }
- else if ( Var.VarType == FIXNUM ){
- *val = (long)Var.VarWert.variable.integer;
- return ( TRUE );
- }
- else{
- serror( "ZAHL erwartet" ); return( FALSE );
- }
- }
-
- /* Ende des Files INTUTIL.C */
-