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 "interp.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 (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);
- 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);
- }
-
- /* 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:
- printf ("\n Stringzuweisung noch nicht implementiert! ");
- 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:
- NewVar->variable.zeichen = Wert->variable.zeichen;
- break;
- case STRING:
- strcpy (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:
- 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;
- static unsigned char OpStckBot[OPSTACK];
- static unsigned char *ActOp;
-
- /* CmpVar vergleicht zwei Variablen auf Größer, Kleiner oder Gleich */
-
- int
- CmpVar ()
- {
-
- ActOp = OpStckBot; /* Zeiger auf bottom OpStckBot stack */
- BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF));
-
- Scan (); /* Erstes Argument lesen */
- if ((Steuer == ZIFFER) || (Steuer == ALPHA))
- PushExp ();
- else {
- serror ("Ungültiger 1. Ausdruck gefunden! ");
- return (FALSE); /* Bedingung fehlerhaft */
- }
-
- Scan(); /* Vergleichsoperator lesen */
- if (Steuer == SONDER)
- ReadComp ();
- else {
- serror ("Vergleichsoperator erwartet! ");
- return (FALSE); /* Bedingung fehlerhaft */
- }
-
- Scan(); /* Zweites Argument lesen */
- if ((Steuer == ZIFFER) || (Steuer == ALPHA))
- PushExp ();
- else {
- serror ("Ungültiger 2. Ausdruck gefunden! ");
- return (FALSE); /* Bedingung fehlerhaft */
- }
-
- return (Compare());
- }
-
- /* 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 ("%d",Variable->VarWert.variable.integer);
- break;
- case FLONUM:
- printf ("%ld",Variable->VarWert.variable.Flotype);
- break;
- case STRING:
- 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;
-
- ActOp = OpStckBot; /* Zeiger auf bottom OpStckBot stack */
- BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF));
-
- Scan (); /* den ersten Ausdruck einlesen */
- if (Steuer == EOLCHAR)
- return (ERROR);
-
- if ((Steuer == SONDER) && (*ScanBuffer == '-'))
- Monadneg = TRUE;
-
- /* gesamten Rechenausdruck auf den Stack */
- do {
- if ((Steuer == ZIFFER) || (Steuer == ALPHA))
- PushExp ();
- else {
- if (Steuer == SONDER) {
- if ((*ScanBuffer == '+') || (*ScanBuffer == '-') ||
- (*ScanBuffer == '*') || (*ScanBuffer == '/')) {
- *ActOp = *ScanBuffer;
- ActOp++;
- }
- else {
- serror ("Ungültiger Operand gefunden! ");
- return (ERROR);
- }
- }
- else {
- serror ("Operand erwartet!");
- return (ERROR);
- }
- }
- /* nächsten Ausdruck einlesen */
- if (Scan () == UNEOL) {
- fatal_error (" Unerwartetes Zeilenende! ");
- return (ERROR);
- }
-
- } while (Steuer != EOLCHAR) ;
-
- CalcResult (); /* berechnet das Ergebnis und hinterläßt */
- /* es auf dem Stack */
-
- SetResultValue (Result);
- 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 Fließkommadarstellung */
- Result->VarWert.variable.Flotype = BotStack->val.wert;
- Result->VarType = FLONUM;
- break;
- case TEXT:
- fatal_error ("Textwandlung noch 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 ZIFFER:
- case FLONUM:
- TopStack->type = ZAHL;
- TopStack->val.wert = atof (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 = ZAHL;
- TopStack->val.wert = Variable->VarWert.variable.Flotype;
- break;
- default :
- serror ("Variablentyp für Operation nicht erlaubt! ");
- break;
- }
- }
- else
- serror ("Variable nicht definiert! ");
- break;
- case STRING:
- fatal_error ("Stringzuweisung nicht implementiert! ");
- 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 (Var1->type == Var2->type /*== ZIFFER*/) {
- ActOp--;
- Op = *ActOp; /* OpStckBot vom Stack holen */
- 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;
- }
- }
- else
- serror ("Operation für Variablentyp nicht implementiert! ");
- TopStack->type = Var1->type;
- TopStack->val.wert = Result.val.wert;
- 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; /* Zeiger zurücksetzen */
-
- }
-
-
- /* Ende des Files INTUTIL.C */
-