home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turbo Toolbox
/
Turbo_Toolbox.iso
/
1991
/
04
/
txl
/
3_preis
/
fast
/
intutil.c
< prev
next >
Wrap
Text File
|
1990-11-21
|
18KB
|
761 lines
/* 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 ("%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 */