home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / spezial / 20 / dos_txl / source / intutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-07  |  17.4 KB  |  762 lines

  1. /* intutil.c
  2. Dieses File enthält Utility-Funktionen zum Erstellen eines neuen
  3. Interpreterbefehls oder dessen Ausführung.
  4. (c) 1990 Michael Beising & TOOLBOX
  5. */
  6.  
  7. #include <string.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "interp.h"
  11.  
  12. /* Funktionsprototypen */
  13. void SetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type, int neu);
  14. void GetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type);
  15. void PushExp (void);
  16. void CalcResult (void);
  17. void SetResultValue (VAR *Result);
  18.  
  19. void     ReadValue (VAR    *Wert);
  20. EXPDEF    *PopExp (void);
  21.  
  22. int        CmpVar (void);
  23. int        Compare (void);
  24. void    ReadComp (void);
  25.  
  26. void    ClearProg (void);
  27.  
  28.  
  29. /* Benötigte Globalvariablen */
  30. extern    int            IntError;        /* Interpreterfehler */
  31. extern    PRGZEILE    *FirstLine;        /* erste Interpreterzeile */
  32. extern    PRGZEILE    *ActLine;        /* aktuelle interpretierte Zeile */
  33. extern    char        *LinePos;        /* Zeilenposition der aktuellen Zeile*/
  34. extern    int        Steuer;                /* der aufrufenden Routine wird mit-    */
  35.                                     /* geteilt, um was es sich handelt.         */
  36. extern    char    ScanBuffer[ZEILENLAENGE]; /* Ergebnisbuffer des Scanners */
  37.  
  38. extern    VAR        *FirstVar;            /* Zeiger auf die erste Variable */
  39.  
  40.  
  41. /*    ShowLine
  42.     Zeile wieder zurückwandeln und ausgeben.
  43. */
  44. extern    TOKBEF        TokBefDesc[];
  45.  
  46. void
  47. ShowLine (FindZeile)
  48. PRGZEILE *FindZeile;
  49. {
  50. char    *Line;
  51.  
  52.     Line = FindZeile->Zeile;
  53.     if (*Line) {            /* Ist die Programmzeile leer? */
  54.       printf ("\n%03d %s ",
  55.                  FindZeile->LineNumber,
  56.                  TokBefDesc[(*Line-TOKMIN)&0xff].Befehl
  57.                  );
  58.        Line++;
  59.        if (*Line) printf ("%s",Line);
  60.     }        
  61.  
  62. }
  63.  
  64.  
  65. /* "IsVariable" sucht nach einer Variablen mit gleichem Namen.
  66.     Gibt es keine, wird ein NULL-Zeiger zurückgeliefert.
  67. */
  68.  
  69. VAR *
  70. IsVariable (Name)
  71. char    *Name;
  72. {
  73. register    VAR  *i;
  74.  
  75.   for (i = FirstVar;
  76.        i && (strcmp(Name,i->VarName) != 0);
  77.        i = i->NextVar);
  78.  
  79. return (i);
  80. }
  81.  
  82. /* "SetVar" sieht nach, ob es die Varible schon gibt.
  83.    Wenn ja, wird ihr Wert verändert. Ansonsten wird
  84.    eine neue Variable angelegt.
  85. */
  86.  
  87. int
  88. SetVar (Wert)
  89. VAR        *Wert;
  90. {
  91. VAR        *Variable;
  92. VAR        Value;
  93.  
  94.         /* Lies den zu setzenden Wert ein */
  95.     if (CalcExpression (&Value) == ERROR)
  96.         return (ERROR);
  97.  
  98.         /* Gibt es eine Variable mit dem Namen, dann setze Zeiger */
  99.     if ((Variable = IsVariable (Wert->VarName)) != NULL)
  100.         {
  101.         SetValue (&Variable->VarWert,&Value.VarWert,Value.VarType,0);
  102.         return (OK);
  103.         }
  104.  
  105.     if ((Variable = malloc(sizeof (VAR))) == NULL)
  106.         {
  107.         fatal_error("\n<setvar>  Kein Speicherplatz mehr für die Variable! ");
  108.         return (FALSE);
  109.         }
  110.  
  111.     strcpy (Variable->VarName,Wert->VarName);    /* Variablennamen eintragen */
  112.     Variable->VarType = Value.VarType;                      /* Variablen-Type eintragen  */
  113.  
  114.     SetValue (&Variable->VarWert,&Value.VarWert,Value.VarType,1);
  115.     Variable->NextVar = FirstVar;
  116.     FirstVar = Variable;        /* Variable oben einfügen  */
  117.  
  118. return (OK);
  119. }
  120.  
  121. /*    Einlesen eines Ausdrucks von der gerade aktuellen Eingabeposition
  122.     ab.
  123. */
  124.  
  125. void
  126. ReadValue (Wert)
  127. VAR    *Wert;
  128. {
  129.  
  130.     Scan ();                        /* Nächster Ausdruck von Eingabezeile */
  131.  
  132.     switch (Steuer) {
  133.       case ZIFFER:
  134.         Wert->VarType = FIXNUM;
  135.         Wert->VarWert.variable.integer = atoi (ScanBuffer);
  136.       break;
  137.       case FLONUM:
  138.         Wert->VarType = FLONUM;
  139.         Wert->VarWert.variable.Flotype = atof (ScanBuffer);
  140.       break;
  141.       case STRING:
  142.         Wert->VarType = STRING;
  143.         if(Wert->VarWert.dim1 < strlen(ScanBuffer))
  144.         if( (Wert->VarWert.variable.text = realloc(Wert->VarWert.variable.text,strlen(ScanBuffer)+1)) == NULL )
  145.             {
  146.             printf("\n <ReadValue>  Nicht genügend Speicherplatz !");
  147.             break;
  148.             }
  149.         strcpy(Wert->VarWert.variable.text,ScanBuffer);
  150.         Wert->VarWert.dim1 = strlen(ScanBuffer);
  151.         break;
  152.       case ALPHA:
  153.         printf ("\n Variablenzuweisung noch nicht implementiert! ");
  154.         break;
  155.       case SONDER:
  156.         if (*ScanBuffer == '(') {
  157.  
  158.         }
  159.         else
  160.           printf ("\nUngültiges Zeichen in Ausdruck gefunden! ");
  161.     }
  162.  
  163. }
  164.  
  165.  
  166. /* SetValue Setze den Wert der Variable */
  167. void
  168. SetValue (NewVar,Wert,Type,neu)
  169. VARDEF    *NewVar,*Wert;
  170. unsigned char   Type;
  171. int neu;
  172. {
  173.     switch (Type) {
  174.       case    FIXNUM:
  175.         NewVar->variable.integer = Wert->variable.integer;
  176.       break;
  177.       case    FLONUM:
  178.         NewVar->variable.Flotype = Wert->variable.Flotype;
  179.       break;
  180.       case    ALPHA:
  181.         NewVar->variable.zeichen = Wert->variable.zeichen;
  182.       break;
  183.       case  STRING:
  184.         if (neu)
  185.         {
  186.         if( (NewVar->variable.text = malloc(strlen(Wert->variable.text)+1)) == NULL )
  187.           {
  188.           fatal_error("\n <ReadValue>  Nicht genügend Speicherplatz !");
  189.           break;
  190.           }
  191.         NewVar->dim1 = strlen(Wert->variable.text);
  192.         }
  193.  
  194.         else
  195.         {
  196.         if(NewVar->dim1 != strlen(Wert->variable.text))
  197.            {
  198.            if( (NewVar->variable.text = realloc(NewVar->variable.text,strlen(Wert->variable.text)+1)) == NULL )
  199.             {
  200.             fatal_error("\n <ReadValue>  Nicht genügend Speicherplatz !");
  201.             break;
  202.             }
  203.            }
  204.         }
  205.  
  206.         strcpy (NewVar->variable.text,Wert->variable.text);
  207.         NewVar->dim1 = strlen(Wert->variable.text);
  208.         free(Wert->variable.text);
  209.       break;
  210.       default:
  211.         printf ("\n Variablenzuweisung für diesen Typ nicht implementiert! ");
  212.       break;
  213.     }
  214.  
  215. }
  216.  
  217. void
  218. GetValue (Var,Wert,Type)
  219. VARDEF    *Var,*Wert;
  220. unsigned char    Type;
  221. {
  222.  
  223.     switch (Type) {
  224.       case  FIXNUM:
  225.         Wert->variable.integer = Var->variable.integer;
  226.         break;
  227.       case  FLONUM:
  228.         Wert->variable.Flotype = Var->variable.Flotype;
  229.         break;
  230.       case    ALPHA:
  231.         Wert->variable.zeichen = Var->variable.zeichen;
  232.         break;
  233.       case    STRING:
  234.         Wert->variable.text=Var->variable.text;
  235.         break;
  236.       default:
  237.         printf ("\n Variablenzuweisung für diesen Typ nicht implementiert! ");
  238.         break;
  239.     }
  240.  
  241. }
  242.  
  243.  
  244.  
  245. /*static*/ EXPDEF    *BotStack;
  246. static EXPDEF    *TopStack;
  247. static unsigned char     OpStckBot[OPSTACK];
  248. static unsigned char    *ActOp;
  249.  
  250. /*    CmpVar vergleicht zwei Variablen auf Größer, Kleiner oder Gleich */
  251.  
  252. int
  253. CmpVar ()
  254. {
  255.     int ret;
  256.     ActOp = OpStckBot;    /* Zeiger auf bottom OpStckBot stack */
  257.     if ( (BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF))) == NULL )
  258.         {
  259.         fatal_error("\n <CmpVar>  Nicht genügend Speicherplatz !");
  260.         return(FALSE);
  261.         }
  262.  
  263.     Scan ();            /* Erstes Argument lesen */
  264.     if ((Steuer == ZIFFER) || (Steuer == ALPHA))
  265.       PushExp ();
  266.     else {
  267.       serror ("Ungültiger 1. Ausdruck gefunden! ");
  268.       free(BotStack);       /* Speicher freigeben */
  269.       return (FALSE);    /* Bedingung fehlerhaft */
  270.     }
  271.  
  272.     Scan();                /* Vergleichsoperator lesen */
  273.     if (Steuer == SONDER)
  274.       ReadComp ();
  275.     else {
  276.       serror ("Vergleichsoperator erwartet! ");
  277.       free(BotStack);       /* Speicher freigeben */
  278.       return (FALSE);    /* Bedingung fehlerhaft */
  279.     }
  280.  
  281.     Scan();                  /* Zweites Argument lesen */
  282.     if ((Steuer == ZIFFER) || (Steuer == ALPHA))
  283.       PushExp ();
  284.     else {
  285.       serror ("Ungültiger 2. Ausdruck gefunden! ");
  286.       free(BotStack);       /* Speicher freigeben */
  287.       return (FALSE);    /* Bedingung fehlerhaft */
  288.     }
  289.  
  290.     ret=Compare();
  291.     free(BotStack);       /* Speicher freigeben */
  292.  
  293.     return (ret);
  294. }
  295.  
  296. /* ReadComp: lies Vergleichsoperator ein
  297. */
  298.  
  299. void
  300. ReadComp ()
  301. {
  302.  
  303.       switch (*ScanBuffer) {
  304.         case    '/':
  305.           Scan ();
  306.           if (*ScanBuffer == '=')
  307.             *ActOp++ = UNGL;
  308.           else {
  309.             SkipChar ();
  310.           }
  311.         break;
  312.         case    '>':
  313.           Scan ();
  314.             if (*ScanBuffer == '=')
  315.               *ActOp++ = GRGL;
  316.             else {
  317.               SkipChar ();
  318.               *ActOp++ = GR;
  319.             }
  320.         break;
  321.         case    '<':
  322.           Scan ();
  323.             if (*ScanBuffer == '=')
  324.               *ActOp++ = KLGL;
  325.             else {
  326.               SkipChar ();
  327.               *ActOp++ = KL;
  328.             }
  329.         break;
  330.         case    '=':
  331.           *ActOp++ = GL;
  332.         break;
  333.         default:
  334.           serror ("Ungültiger Vergleichsoperator! ");
  335.         break;
  336.       }
  337. }
  338.  
  339. /*    Compare
  340.     Vergleiche die Ausdrücke auf dem Stack.
  341. */
  342.  
  343. int
  344. Compare ()
  345. {
  346. EXPDEF    *Var1,*Var2;
  347. int        Op;
  348.  
  349.         /* solange beide Stacks noch Werte besitzen, ... */
  350.     while ((TopStack != BotStack) && (ActOp != OpStckBot)) {
  351.         if ((Var2 = PopExp()) == NULL) {
  352.           break;
  353.         }
  354.         if ((Var1 = PopExp()) == NULL) {
  355.           break;
  356.         }
  357.         if (Var1->type == Var2->type) {
  358.           ActOp--;
  359.           Op = *ActOp;
  360.           switch (Op) {            /* hier wird endlich verglichen */
  361.             case    GL:
  362.               return ((Var1->val.wert == Var2->val.wert) ?
  363.                        TRUE : FALSE);
  364.             case    GRGL:
  365.               return ((Var1->val.wert >= Var2->val.wert) ?
  366.                        TRUE : FALSE);
  367.             case    GR:
  368.               return ((Var1->val.wert > Var2->val.wert) ?
  369.                        TRUE : FALSE);
  370.             case    KLGL:
  371.               return ((Var1->val.wert <= Var2->val.wert) ?
  372.                        TRUE : FALSE);
  373.             case    KL:
  374.               return ((Var1->val.wert < Var2->val.wert) ?
  375.                        TRUE : FALSE);
  376.             case    UNGL:
  377.               return ((Var1->val.wert != Var2->val.wert) ?
  378.                        TRUE : FALSE);
  379.           }
  380.         }
  381.     }
  382. return (TRUE);
  383. }
  384.  
  385. /* druckt eine Variable aus */
  386.  
  387. void
  388. PrintVar (Name)
  389. char    *Name;
  390. {
  391. VAR        *Variable;
  392.  
  393.  
  394.  
  395.         /* wenn es eine Variable mit dem gesuchten Namen gibt, merken! */
  396.     if ((Variable = IsVariable (Name)) != NULL)
  397.       {
  398.  
  399.  
  400.       switch (Variable->VarType)
  401.         {
  402.         case    FIXNUM:
  403.           printf ("%ld",Variable->VarWert.variable.integer);
  404.           break;
  405.         case    FLONUM:
  406.           printf ("%lf",Variable->VarWert.variable.Flotype);
  407.           break;
  408.         case    STRING:
  409.               printf (Variable->VarWert.variable.text);
  410.  /* alte Version:  printf ("%s",Variable->VarWert.variable.text);  */
  411.           break;
  412.         default:
  413.           printf ("\n Variablen dieses Typs können nicht gedruckt werden! ");
  414.           break;
  415.         }
  416.       }
  417.     else
  418.       {
  419.       char buffer[40];
  420.       sprintf (buffer,"Variable <%s> unbekannt! ",Name);
  421.       fatal_error (buffer);
  422.       }
  423. }
  424.  
  425.  
  426. /* monadische Vorzeichen merker */
  427. static    int    Monadneg = FALSE;
  428.  
  429. /*    CalcExpression: berechnet das Ergebnis eines Ausdrucks
  430. */
  431.  
  432. int
  433. CalcExpression (Result)
  434. VAR *Result;
  435. {
  436. VAR    *Variable;
  437.  
  438.     Scan ();                /* den ersten Ausdruck einlesen */
  439.  
  440.     if (Steuer == STRING)   /* String zuweisung             */
  441.         {
  442.         if( (Result->VarWert.variable.text = malloc(strlen(ScanBuffer)+1)) == NULL )
  443.             {
  444.             fatal_error("\n <CalcExpression>  Nicht genügend Speicherplatz !");
  445.             return(ERROR);
  446.             }
  447.         strcpy(Result->VarWert.variable.text,ScanBuffer);
  448.         Result->VarWert.dim1 = strlen(ScanBuffer);
  449.         Result->VarType = STRING;
  450.         return(OK);
  451.         }
  452.  
  453.     ActOp = OpStckBot;      /* Zeiger auf bottom OpStckBot stack */
  454.     if ( (BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF))) == NULL )
  455.         {
  456.         fatal_error("\n <CalcExpression>  Nicht genügend Speicherplatz !");
  457.         return(ERROR);
  458.         }
  459.  
  460.  
  461.     if (Steuer == EOLCHAR)
  462.       {
  463.       free (BotStack);                /* Speicher wieder freigeben */
  464.       return (ERROR);
  465.       }
  466.  
  467.     if ((Steuer == SONDER) && (*ScanBuffer == '-'))
  468.       Monadneg = TRUE;
  469.  
  470.         /* gesamten Rechenausdruck auf den Stack */
  471.     do
  472.       {
  473.       if ((Steuer == ZIFFER) || (Steuer == ALPHA) || (Steuer == FLONUM) )
  474.         PushExp ();
  475.       else
  476.         {
  477.         if (Steuer == SONDER)
  478.           {
  479.           if ((*ScanBuffer == '+') || (*ScanBuffer == '-') ||
  480.           (*ScanBuffer == '*') || (*ScanBuffer == '/'))
  481.         {
  482.             *ActOp = *ScanBuffer;
  483.             ActOp++;
  484.         }
  485.           else
  486.         {
  487.         serror ("Ungültiger Operand gefunden! ");
  488.         free (BotStack);                /* Speicher wieder freigeben */
  489.             return (ERROR);
  490.         }
  491.           }
  492.         else
  493.           {
  494.           serror ("Operand erwartet!");
  495.           free (BotStack);                /* Speicher wieder freigeben */
  496.           return (ERROR);
  497.           }
  498.         }
  499.           /* nächsten Ausdruck einlesen */
  500.       if (Scan () == UNEOL)
  501.         {
  502.         fatal_error (" Unerwartetes Zeilenende! ");
  503.         free (BotStack);                /* Speicher wieder freigeben */
  504.         return (ERROR);
  505.         }
  506.  
  507.       }  while (Steuer != EOLCHAR) ;
  508.  
  509.     CalcResult ();            /* berechnet das Ergebnis und hinterläßt */
  510.                             /* es auf dem Stack                     */
  511.  
  512.     SetResultValue(Result);
  513.     if(IntError)
  514.         {
  515.         IntError=FALSE;
  516.         free (BotStack);        /* Speicher wieder freigeben */
  517.         return(ERROR);
  518.         }
  519.     else
  520.         free (BotStack);        /* Speicher wieder freigeben */
  521.  
  522. return (OK);
  523. }
  524.  
  525. /* SetResultValue: wandelt das Berechnungsergebnis in die Variablenstruktur
  526. */
  527.  
  528. void
  529. SetResultValue (Result)
  530. VAR *Result;
  531. {
  532.  
  533.     switch (BotStack->type) {
  534.       case  ZAHL:           /* Zahlen in interger */
  535.         Result->VarWert.variable.integer = BotStack->val.wert;
  536.         Result->VarType = FIXNUM;
  537.         break;
  538.       case  DEZ:           /* Zahlen in Fließkommadarstellung */
  539.         Result->VarWert.variable.Flotype = BotStack->val.dez;
  540.         Result->VarType = FLONUM;
  541.         break;
  542.       case  TEXT:
  543.         fatal_error("\n <SetResultValue> String nicht implementiert !");
  544.         break;
  545.       case    FELD:
  546.         fatal_error ("Arrayzuweisung noch nicht implementiert! ");
  547.         break;
  548.       default:
  549.         fatal_error ("Unbekannter Zahlentyp gefunden! ");
  550.         break;
  551.     }
  552. }
  553.  
  554.  
  555. /*    PushExp
  556.     welche in ScanBuffer steht auf Stack ablegen.
  557. */
  558. void
  559. PushExp ()
  560. {
  561. VAR    *Variable;
  562.  
  563.       switch (Steuer)
  564.         {
  565.  
  566.         case  FLONUM:
  567.           TopStack->type = DEZ;
  568.           TopStack->val.dez = atof (ScanBuffer);
  569.           if (Monadneg)
  570.         {
  571.         TopStack->val.dez *= -1;
  572.         Monadneg = FALSE;
  573.         }
  574.           break;
  575.  
  576.         case  ZIFFER:
  577.           TopStack->type = ZAHL;
  578.           TopStack->val.wert = atol (ScanBuffer);
  579.           if (Monadneg)
  580.         {
  581.             TopStack->val.wert *= -1;
  582.             Monadneg = FALSE;
  583.         }
  584.           break;
  585.  
  586.         case  ALPHA:
  587. /* Wenn es die gesuchte Variable gibt, Zeiger drauf und merken! */
  588.           if ((Variable = IsVariable (ScanBuffer)) != NULL)
  589.         {
  590.         switch (Variable->VarType)
  591.           {
  592.           case ZIFFER:
  593.                 TopStack->type = ZAHL;
  594.                 TopStack->val.wert = Variable->VarWert.variable.integer;
  595.             break;
  596.               case FLONUM:
  597.             TopStack->type = DEZ;
  598.             TopStack->val.dez = Variable->VarWert.variable.Flotype;
  599.             break;
  600.               default :
  601.                 serror ("Variablentyp für Operation nicht erlaubt! ");
  602.               break;
  603.           }
  604.         }
  605.           else
  606.             serror ("Variable nicht definiert! ");
  607.  
  608.           break;
  609.  
  610.         case        STRING:
  611.           serror ("Keine Operation für den Typ STRING vorhanden! ");
  612.           break;
  613.  
  614.         default:
  615.           serror ("Keine Operation für diesen Typ vorhanden! ");
  616.           break;
  617.         }
  618.       TopStack++;        /* Stackpointer an die nächste Position */
  619. }
  620.  
  621.  
  622. /* CalcResult: berechnet das Ergebnis eines Ausdrucks,
  623. der sich auf dem Stack befindet
  624. */
  625. void
  626. CalcResult ()
  627. {
  628. EXPDEF    *Var1,*Var2,Result;
  629. int        Op;
  630.  
  631. /* solange beide Stacks noch Werte besitzen, ... */
  632.     while ((TopStack != BotStack) && (ActOp != OpStckBot)) {
  633.         if ((Var1 = PopExp()) == NULL) {
  634.           break;
  635.         }
  636.         if ((Var2 = PopExp()) == NULL) {
  637.           break;
  638.         }
  639.  
  640.  
  641.         if (Var2->type == ZAHL && (Var1->type == ZAHL || Var1->type == DEZ))
  642.           {
  643.           ActOp--;
  644.           Op = *ActOp;        /* OpStckBot vom Stack holen */
  645.           switch (Op)
  646.             {
  647.  
  648.             case        '+':
  649.               if(Var1->type == ZAHL)
  650.             Result.val.wert = Var2->val.wert + Var1->val.wert;
  651.               else
  652.             Result.val.wert = Var1->val.dez + Var2->val.wert;
  653.               break;
  654.             case        '-':
  655.               if(Var1->type == ZAHL)
  656.             Result.val.wert = Var2->val.wert - Var1->val.wert;
  657.               else
  658.             Result.val.wert = Var1->val.dez - Var2->val.wert;
  659.               break;
  660.             case        '*':
  661.               if(Var1->type == ZAHL)
  662.             Result.val.wert = Var2->val.wert * Var1->val.wert;
  663.               else
  664.             Result.val.wert = Var1->val.dez * Var2->val.wert;
  665.               break;
  666.             case        '/':
  667.               if(Var1->type == ZAHL)
  668.             Result.val.wert = Var2->val.wert / Var1->val.wert;
  669.               else
  670.             Result.val.wert = Var1->val.dez / Var2->val.wert;
  671.               break;
  672.             }
  673.           }
  674.         else
  675.             {
  676.             if (Var2->type == DEZ && (Var1->type == ZAHL || Var1->type == DEZ))
  677.                 {
  678.                 ActOp--;
  679.                 Op = *ActOp;          /* OpStckBot vom Stack holen */
  680.                 switch (Op)
  681.                     {
  682.                     case        '+':
  683.                         if(Var1->type == ZAHL)
  684.                           Result.val.dez = Var2->val.dez + Var1->val.wert;
  685.                         else
  686.                           Result.val.dez = Var1->val.dez + Var2->val.dez;
  687.                         break;
  688.                     case        '-':
  689.                         if(Var1->type == ZAHL)
  690.                           Result.val.dez = Var2->val.dez - Var1->val.wert;
  691.                         else
  692.                           Result.val.dez = Var1->val.dez - Var2->val.dez;
  693.                         break;
  694.                     case        '*':
  695.                         if(Var1->type == ZAHL)
  696.                           Result.val.dez = Var2->val.dez * Var1->val.wert;
  697.                         else
  698.                           Result.val.dez = Var1->val.dez * Var2->val.dez;
  699.                         break;
  700.                     case        '/':
  701.                         if(Var1->type == ZAHL)
  702.                           Result.val.dez = Var2->val.dez / Var1->val.wert;
  703.                         else
  704.                           Result.val.dez = Var1->val.dez / Var2->val.dez;
  705.                         break;
  706.                     }
  707.                 }
  708.             else
  709.                 serror ("Operation für Variablentyp nicht implementiert! ");
  710.             }
  711.  
  712.         TopStack->type  = Var2->type;
  713.  
  714.         if(Var2->type == ZAHL)
  715.             TopStack->val.wert = Result.val.wert;
  716.  
  717.         if(Var2->type == DEZ)
  718.             TopStack->val.dez = Result.val.dez;
  719.  
  720.         TopStack ++;
  721.  
  722.     }
  723.  
  724. }
  725.  
  726.  
  727. /*    PopExp
  728.     Holt einen Ausdruck vom Variablenstack
  729. */
  730.  
  731. EXPDEF *
  732. PopExp ()
  733. {
  734.   if (TopStack-- != BotStack)
  735.     return (TopStack);
  736.   else
  737.     return (NULL);
  738. }
  739.  
  740. /* ClearProg: den Speicherplatz, der durch das Programm
  741. belegt ist, freigeben
  742. */
  743.  
  744. void
  745. ClearProg ()
  746. {
  747. PRGZEILE    *Memory;
  748.  
  749.     ActLine = FirstLine;        /* Zeiger auf erste Programmzeile */
  750.     while (ActLine) {
  751.       Memory = ActLine;            /* wird gleich benötigt */
  752.       ActLine = ActLine->NextZeile;    /* das ist die nächste Zeile */
  753.       free (Memory);            /* Speicherplatz freigeben */
  754.     }
  755.  
  756.     FirstLine = ActLine = NULL;     /* ProgZeile-Zeiger zurücksetzen */
  757.  
  758. }
  759.  
  760.  
  761. /* Ende des Files INTUTIL.C */
  762.