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 <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include "interp.h"
-
- /* Funktionsprototypen */
- void SetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type, int neu);
- void GetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type);
- void PushExp (void);
- void CalcResult (void);
- void SetResultValue (VAR *Result);
-
- void ReadValue (VAR *Wert);
- EXPDEF *PopExp (void);
-
- int CmpVar (void);
- int Compare (void);
- void ReadComp (void);
-
- void ClearProg (void);
-
-
- /* 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 */
-
-
- /* 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);
-
- /* Gibt es eine Variable mit dem Namen, dann setze Zeiger */
- if ((Variable = IsVariable (Wert->VarName)) != NULL)
- {
- SetValue (&Variable->VarWert,&Value.VarWert,Value.VarType,0);
- return (OK);
- }
-
- if ((Variable = malloc(sizeof (VAR))) == NULL)
- {
- fatal_error("\n<setvar> 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,1);
- Variable->NextVar = FirstVar;
- FirstVar = Variable; /* Variable oben einfügen */
-
- return (OK);
- }
-
- /* 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;
- case FLONUM:
- Wert->VarType = FLONUM;
- Wert->VarWert.variable.Flotype = atof (ScanBuffer);
- break;
- case STRING:
- Wert->VarType = STRING;
- if(Wert->VarWert.dim1 < strlen(ScanBuffer))
- if( (Wert->VarWert.variable.text = realloc(Wert->VarWert.variable.text,strlen(ScanBuffer)+1)) == NULL )
- {
- printf("\n <ReadValue> Nicht genügend Speicherplatz !");
- break;
- }
- strcpy(Wert->VarWert.variable.text,ScanBuffer);
- Wert->VarWert.dim1 = strlen(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,neu)
- VARDEF *NewVar,*Wert;
- unsigned char Type;
- int neu;
- {
- switch (Type) {
- case FIXNUM:
- NewVar->variable.integer = Wert->variable.integer;
- break;
- case FLONUM:
- NewVar->variable.Flotype = Wert->variable.Flotype;
- break;
- case ALPHA:
- NewVar->variable.zeichen = Wert->variable.zeichen;
- break;
- case STRING:
- if (neu)
- {
- if( (NewVar->variable.text = malloc(strlen(Wert->variable.text)+1)) == NULL )
- {
- fatal_error("\n <ReadValue> Nicht genügend Speicherplatz !");
- break;
- }
- NewVar->dim1 = strlen(Wert->variable.text);
- }
-
- else
- {
- if(NewVar->dim1 != strlen(Wert->variable.text))
- {
- if( (NewVar->variable.text = realloc(NewVar->variable.text,strlen(Wert->variable.text)+1)) == NULL )
- {
- fatal_error("\n <ReadValue> Nicht genügend Speicherplatz !");
- break;
- }
- }
- }
-
- strcpy (NewVar->variable.text,Wert->variable.text);
- NewVar->dim1 = strlen(Wert->variable.text);
- free(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 FIXNUM:
- Wert->variable.integer = Var->variable.integer;
- break;
- case FLONUM:
- Wert->variable.Flotype = Var->variable.Flotype;
- break;
- case ALPHA:
- Wert->variable.zeichen = Var->variable.zeichen;
- break;
- case STRING:
- Wert->variable.text=Var->variable.text;
- break;
- default:
- printf ("\n Variablenzuweisung für diesen Typ nicht implementiert! ");
- break;
- }
-
- }
-
-
-
- /*static*/ EXPDEF *BotStack;
- static EXPDEF *TopStack;
- static unsigned char OpStckBot[OPSTACK];
- static unsigned char *ActOp;
-
- /* CmpVar vergleicht zwei Variablen auf Größer, Kleiner oder Gleich */
-
- int
- CmpVar ()
- {
- int ret;
- ActOp = OpStckBot; /* Zeiger auf bottom OpStckBot stack */
- if ( (BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF))) == NULL )
- {
- fatal_error("\n <CmpVar> Nicht genügend Speicherplatz !");
- return(FALSE);
- }
-
- Scan (); /* Erstes Argument lesen */
- if ((Steuer == ZIFFER) || (Steuer == ALPHA))
- PushExp ();
- else {
- serror ("Ungültiger 1. Ausdruck gefunden! ");
- free(BotStack); /* Speicher freigeben */
- return (FALSE); /* Bedingung fehlerhaft */
- }
-
- Scan(); /* Vergleichsoperator lesen */
- if (Steuer == SONDER)
- ReadComp ();
- else {
- serror ("Vergleichsoperator erwartet! ");
- free(BotStack); /* Speicher freigeben */
- return (FALSE); /* Bedingung fehlerhaft */
- }
-
- Scan(); /* Zweites Argument lesen */
- if ((Steuer == ZIFFER) || (Steuer == ALPHA))
- PushExp ();
- else {
- serror ("Ungültiger 2. Ausdruck gefunden! ");
- free(BotStack); /* Speicher freigeben */
- return (FALSE); /* Bedingung fehlerhaft */
- }
-
- ret=Compare();
- free(BotStack); /* Speicher freigeben */
-
- return (ret);
- }
-
- /* ReadComp: lies Vergleichsoperator ein
- */
-
- void
- ReadComp ()
- {
-
- switch (*ScanBuffer) {
- case '/':
- Scan ();
- if (*ScanBuffer == '=')
- *ActOp++ = UNGL;
- else {
- SkipChar ();
- }
- break;
- case '>':
- Scan ();
- if (*ScanBuffer == '=')
- *ActOp++ = GRGL;
- else {
- SkipChar ();
- *ActOp++ = GR;
- }
- break;
- case '<':
- Scan ();
- if (*ScanBuffer == '=')
- *ActOp++ = KLGL;
- else {
- SkipChar ();
- *ActOp++ = KL;
- }
- break;
- case '=':
- *ActOp++ = GL;
- break;
- default:
- serror ("Ungültiger Vergleichsoperator! ");
- break;
- }
- }
-
- /* Compare
- Vergleiche die Ausdrücke auf dem Stack.
- */
-
- int
- Compare ()
- {
- EXPDEF *Var1,*Var2;
- int Op;
-
- /* solange beide Stacks noch Werte besitzen, ... */
- while ((TopStack != BotStack) && (ActOp != OpStckBot)) {
- if ((Var2 = PopExp()) == NULL) {
- break;
- }
- if ((Var1 = PopExp()) == NULL) {
- break;
- }
- if (Var1->type == Var2->type) {
- ActOp--;
- Op = *ActOp;
- 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);
- }
- }
- }
- return (TRUE);
- }
-
- /* 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 ("%ld",Variable->VarWert.variable.integer);
- break;
- case FLONUM:
- printf ("%lf",Variable->VarWert.variable.Flotype);
- break;
- case STRING:
- printf (Variable->VarWert.variable.text);
- /* alte Version: 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);
- }
- }
-
-
- /* monadische Vorzeichen merker */
- static int Monadneg = FALSE;
-
- /* CalcExpression: berechnet das Ergebnis eines Ausdrucks
- */
-
- int
- CalcExpression (Result)
- VAR *Result;
- {
- VAR *Variable;
-
- Scan (); /* den ersten Ausdruck einlesen */
-
- if (Steuer == STRING) /* String zuweisung */
- {
- if( (Result->VarWert.variable.text = malloc(strlen(ScanBuffer)+1)) == NULL )
- {
- fatal_error("\n <CalcExpression> Nicht genügend Speicherplatz !");
- return(ERROR);
- }
- strcpy(Result->VarWert.variable.text,ScanBuffer);
- Result->VarWert.dim1 = strlen(ScanBuffer);
- Result->VarType = STRING;
- return(OK);
- }
-
- ActOp = OpStckBot; /* Zeiger auf bottom OpStckBot stack */
- if ( (BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF))) == NULL )
- {
- fatal_error("\n <CalcExpression> Nicht genügend Speicherplatz !");
- return(ERROR);
- }
-
-
- if (Steuer == EOLCHAR)
- {
- free (BotStack); /* Speicher wieder freigeben */
- return (ERROR);
- }
-
- if ((Steuer == SONDER) && (*ScanBuffer == '-'))
- Monadneg = TRUE;
-
- /* gesamten Rechenausdruck auf den Stack */
- do
- {
- if ((Steuer == ZIFFER) || (Steuer == ALPHA) || (Steuer == FLONUM) )
- PushExp ();
- else
- {
- if (Steuer == SONDER)
- {
- if ((*ScanBuffer == '+') || (*ScanBuffer == '-') ||
- (*ScanBuffer == '*') || (*ScanBuffer == '/'))
- {
- *ActOp = *ScanBuffer;
- ActOp++;
- }
- else
- {
- serror ("Ungültiger Operand gefunden! ");
- free (BotStack); /* Speicher wieder freigeben */
- return (ERROR);
- }
- }
- else
- {
- serror ("Operand erwartet!");
- free (BotStack); /* Speicher wieder freigeben */
- return (ERROR);
- }
- }
- /* nächsten Ausdruck einlesen */
- if (Scan () == UNEOL)
- {
- fatal_error (" Unerwartetes Zeilenende! ");
- free (BotStack); /* Speicher wieder freigeben */
- return (ERROR);
- }
-
- } while (Steuer != EOLCHAR) ;
-
- CalcResult (); /* berechnet das Ergebnis und hinterläßt */
- /* es auf dem Stack */
-
- SetResultValue(Result);
- if(IntError)
- {
- IntError=FALSE;
- free (BotStack); /* Speicher wieder freigeben */
- return(ERROR);
- }
- else
- free (BotStack); /* Speicher wieder freigeben */
-
- return (OK);
- }
-
- /* SetResultValue: wandelt das Berechnungsergebnis in die Variablenstruktur
- */
-
- void
- SetResultValue (Result)
- VAR *Result;
- {
-
- switch (BotStack->type) {
- case ZAHL: /* Zahlen in interger */
- Result->VarWert.variable.integer = BotStack->val.wert;
- Result->VarType = FIXNUM;
- break;
- case DEZ: /* Zahlen in Fließkommadarstellung */
- Result->VarWert.variable.Flotype = BotStack->val.dez;
- Result->VarType = FLONUM;
- break;
- case TEXT:
- fatal_error("\n <SetResultValue> String nicht implementiert !");
- 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 FLONUM:
- TopStack->type = DEZ;
- TopStack->val.dez = atof (ScanBuffer);
- if (Monadneg)
- {
- TopStack->val.dez *= -1;
- Monadneg = FALSE;
- }
- break;
-
- case ZIFFER:
- TopStack->type = ZAHL;
- TopStack->val.wert = atol (ScanBuffer);
- if (Monadneg)
- {
- TopStack->val.wert *= -1;
- Monadneg = FALSE;
- }
- 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 = DEZ;
- TopStack->val.dez = Variable->VarWert.variable.Flotype;
- break;
- default :
- serror ("Variablentyp für Operation nicht erlaubt! ");
- break;
- }
- }
- else
- serror ("Variable nicht definiert! ");
-
- break;
-
- case STRING:
- serror ("Keine Operation für den Typ STRING vorhanden! ");
- 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 ()
- {
- EXPDEF *Var1,*Var2,Result;
- int Op;
-
- /* solange beide Stacks noch Werte besitzen, ... */
- while ((TopStack != BotStack) && (ActOp != OpStckBot)) {
- if ((Var1 = PopExp()) == NULL) {
- break;
- }
- if ((Var2 = PopExp()) == NULL) {
- break;
- }
-
-
- if (Var2->type == ZAHL && (Var1->type == ZAHL || Var1->type == DEZ))
- {
- ActOp--;
- Op = *ActOp; /* OpStckBot vom Stack holen */
- switch (Op)
- {
-
- case '+':
- if(Var1->type == ZAHL)
- Result.val.wert = Var2->val.wert + Var1->val.wert;
- else
- Result.val.wert = Var1->val.dez + Var2->val.wert;
- break;
- case '-':
- if(Var1->type == ZAHL)
- Result.val.wert = Var2->val.wert - Var1->val.wert;
- else
- Result.val.wert = Var1->val.dez - Var2->val.wert;
- break;
- case '*':
- if(Var1->type == ZAHL)
- Result.val.wert = Var2->val.wert * Var1->val.wert;
- else
- Result.val.wert = Var1->val.dez * Var2->val.wert;
- break;
- case '/':
- if(Var1->type == ZAHL)
- Result.val.wert = Var2->val.wert / Var1->val.wert;
- else
- Result.val.wert = Var1->val.dez / Var2->val.wert;
- break;
- }
- }
- else
- {
- if (Var2->type == DEZ && (Var1->type == ZAHL || Var1->type == DEZ))
- {
- ActOp--;
- Op = *ActOp; /* OpStckBot vom Stack holen */
- switch (Op)
- {
- case '+':
- if(Var1->type == ZAHL)
- Result.val.dez = Var2->val.dez + Var1->val.wert;
- else
- Result.val.dez = Var1->val.dez + Var2->val.dez;
- break;
- case '-':
- if(Var1->type == ZAHL)
- Result.val.dez = Var2->val.dez - Var1->val.wert;
- else
- Result.val.dez = Var1->val.dez - Var2->val.dez;
- break;
- case '*':
- if(Var1->type == ZAHL)
- Result.val.dez = Var2->val.dez * Var1->val.wert;
- else
- Result.val.dez = Var1->val.dez * Var2->val.dez;
- break;
- case '/':
- if(Var1->type == ZAHL)
- Result.val.dez = Var2->val.dez / Var1->val.wert;
- else
- Result.val.dez = Var1->val.dez / Var2->val.dez;
- break;
- }
- }
- else
- serror ("Operation für Variablentyp nicht implementiert! ");
- }
-
- TopStack->type = Var2->type;
-
- if(Var2->type == ZAHL)
- TopStack->val.wert = Result.val.wert;
-
- if(Var2->type == DEZ)
- TopStack->val.dez = Result.val.dez;
-
- TopStack ++;
-
- }
-
- }
-
-
- /* 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; /* ProgZeile-Zeiger zurücksetzen */
-
- }
-
-
- /* Ende des Files INTUTIL.C */
-