home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1990 / 10 / int / source / intutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-20  |  13.0 KB  |  585 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 <stdio.h>
  8. #include <stdlib.h>
  9. #include "interp.h"
  10.  
  11. /* Funktionsprototypen */
  12. void SetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type);
  13. void GetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type);
  14. void PushExp (void);
  15. void CalcResult (void);
  16. void SetResultValue (VAR *Result);
  17.  
  18. void     ReadValue (VAR    *Wert);
  19. EXPDEF    *PopExp (void);
  20.  
  21. int        CmpVar (void);
  22. int        Compare (void);
  23. void    ReadComp (void);
  24.  
  25. void    ClearProg (void);
  26.  
  27.  
  28. /* Benötigte Globalvariablen */
  29. extern    int            IntError;        /* Interpreterfehler */
  30. extern    PRGZEILE    *FirstLine;        /* erste Interpreterzeile */
  31. extern    PRGZEILE    *ActLine;        /* aktuelle interpretierte Zeile */
  32. extern    char        *LinePos;        /* Zeilenposition der aktuellen Zeile*/
  33. extern    int        Steuer;                /* der aufrufenden Routine wird mit-    */
  34.                                     /* geteilt, um was es sich handelt.         */
  35. extern    char    ScanBuffer[ZEILENLAENGE]; /* Ergebnisbuffer des Scanners */
  36.  
  37. extern    VAR        *FirstVar;            /* Zeiger auf die erste Variable */
  38.  
  39.  
  40. /*    ShowLine
  41.     Zeile wieder zurückwandeln und ausgeben.
  42. */
  43. extern    TOKBEF        TokBefDesc[];
  44.  
  45. void
  46. ShowLine (FindZeile)
  47. PRGZEILE *FindZeile;
  48. {
  49. char    *Line;
  50.  
  51.     Line = FindZeile->Zeile;
  52.     if (*Line) {            /* Ist die Programmzeile leer? */
  53.       printf ("\n%03d %s ",
  54.                  FindZeile->LineNumber,
  55.                  TokBefDesc[(*Line-TOKMIN)&0xff].Befehl
  56.                  );
  57.        Line++;
  58.        if (*Line) printf ("%s",Line);
  59.     }        
  60.  
  61. }
  62.  
  63.  
  64. /* "IsVariable" sucht nach einer Variablen mit gleichem Namen.
  65.     Gibt es keine, wird ein NULL-Zeiger zurückgeliefert.
  66. */
  67.  
  68. VAR *
  69. IsVariable (Name)
  70. char    *Name;
  71. {
  72. register    VAR  *i;
  73.  
  74.   for (i = FirstVar;
  75.        i && (strcmp(Name,i->VarName) != 0);
  76.        i = i->NextVar);
  77.  
  78. return (i);
  79. }
  80.  
  81. /* "SetVar" sieht nach, ob es die Varible schon gibt.
  82.    Wenn ja, wird ihr Wert verändert. Ansonsten wird
  83.    eine neue Variable angelegt.
  84. */
  85.  
  86. int
  87. SetVar (Wert)
  88. VAR        *Wert;
  89. {
  90. VAR        *Variable;
  91. VAR        Value;
  92.  
  93.         /* Lies den zu setzenden Wert ein */
  94.     if (CalcExpression (&Value) == ERROR) return (ERROR);
  95.     
  96.         /* Gibt es eine Variable mit dem Namen, dann setze Zeiger */
  97.     if ((Variable = IsVariable (Wert->VarName)) != NULL) {
  98.       SetValue (&Variable->VarWert,&Value.VarWert,Value.VarType);
  99.       return (OK);
  100.     }
  101.     
  102.     if ((Variable = malloc(sizeof (VAR))) == NULL) {
  103.       printf ("\n Kein Speicherplatz mehr für die Variable! ");
  104.       return (FALSE);
  105.     }
  106.  
  107.     strcpy (Variable->VarName,Wert->VarName);    /* Variablennamen eintragen */
  108.     Variable->VarType = Value.VarType;            /* Variablen-Type eintragen  */
  109.     SetValue (&Variable->VarWert,&Value.VarWert,Value.VarType);
  110.     Variable->NextVar = FirstVar;
  111.     FirstVar = Variable;        /* Variable oben einfügen  */
  112.  
  113. return (OK);
  114. }
  115.  
  116. /*    Einlesen eines Ausdrucks von der gerade aktuellen Eingabeposition
  117.     ab.
  118. */
  119.  
  120. void
  121. ReadValue (Wert)
  122. VAR    *Wert;
  123. {
  124.  
  125.     Scan ();            /* Nächster Ausdruck von Eingabezeile */
  126.     switch (Steuer) {
  127.       case ZIFFER:
  128.         Wert->VarType = FIXNUM;
  129.         Wert->VarWert.variable.integer = atoi (ScanBuffer);
  130.       break;
  131.       case FLONUM:
  132.         Wert->VarType = FLONUM;
  133.         Wert->VarWert.variable.Flotype = atof (ScanBuffer);
  134.       break;
  135.       case STRING:
  136.         printf ("\n Stringzuweisung noch nicht implementiert! ");
  137.       break;
  138.       case ALPHA:
  139.         printf ("\n Variablenzuweisung noch nicht implementiert! ");
  140.       break;
  141.       case SONDER:
  142.         if (*ScanBuffer == '(') {
  143.     
  144.         }
  145.         else
  146.           printf ("\nUngültiges Zeichen in Ausdruck gefunden! ");
  147.     }
  148.  
  149. }
  150.  
  151.  
  152. /* SetValue Setze den Wert der Variable */
  153. void
  154. SetValue (NewVar,Wert,Type)
  155. VARDEF    *NewVar,*Wert;
  156. unsigned char    Type;
  157. {
  158.  
  159.     switch (Type) {
  160.       case    FIXNUM:
  161.         NewVar->variable.integer = Wert->variable.integer;
  162.       break;
  163.       case    FLONUM:
  164.         NewVar->variable.Flotype = Wert->variable.Flotype;
  165.       break;
  166.       case    ALPHA:
  167.         NewVar->variable.zeichen = Wert->variable.zeichen;
  168.       break;
  169.       case    STRING:
  170.         strcpy (NewVar->variable.text,Wert->variable.text);
  171.       break;
  172.       default:
  173.         printf ("\n Variablenzuweisung für diesen Typ nicht implementiert! ");
  174.       break;
  175.     }
  176.     
  177. }
  178.  
  179. void
  180. GetValue (Var,Wert,Type)
  181. VARDEF    *Var,*Wert;
  182. unsigned char    Type;
  183. {
  184.  
  185.     switch (Type) {
  186.       case    FLONUM:
  187.         Wert->variable.integer = Var->variable.integer;
  188.       break;
  189.       case    FIXNUM:
  190.         Wert->variable.Flotype = Var->variable.Flotype;
  191.       break;
  192.       case    ALPHA:
  193.         Wert->variable.zeichen = Var->variable.zeichen;
  194.       break;
  195.       case    STRING:
  196.         strcpy (Wert->variable.text,Var->variable.text);
  197.       break;
  198.       default:
  199.         printf ("\n Variablenzuweisung für diesen Typ nicht implementiert! ");
  200.       break;
  201.     }
  202.     
  203. }
  204.  
  205.  
  206.  
  207. /*static*/ EXPDEF    *BotStack;
  208. static EXPDEF    *TopStack;
  209. static unsigned char     OpStckBot[OPSTACK];
  210. static unsigned char    *ActOp;
  211.  
  212. /*    CmpVar vergleicht zwei Variablen auf Größer, Kleiner oder Gleich */
  213.  
  214. int
  215. CmpVar ()
  216. {
  217.  
  218.     ActOp = OpStckBot;    /* Zeiger auf bottom OpStckBot stack */
  219.     BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF));
  220.  
  221.     Scan ();            /* Erstes Argument lesen */
  222.     if ((Steuer == ZIFFER) || (Steuer == ALPHA))
  223.       PushExp ();
  224.     else {
  225.       serror ("Ungültiger 1. Ausdruck gefunden! ");
  226.       return (FALSE);    /* Bedingung fehlerhaft */
  227.     }
  228.  
  229.     Scan();                /* Vergleichsoperator lesen */
  230.     if (Steuer == SONDER)
  231.       ReadComp ();
  232.     else {
  233.       serror ("Vergleichsoperator erwartet! ");
  234.       return (FALSE);    /* Bedingung fehlerhaft */
  235.     }
  236.  
  237.     Scan();                  /* Zweites Argument lesen */
  238.     if ((Steuer == ZIFFER) || (Steuer == ALPHA))
  239.       PushExp ();
  240.     else {
  241.       serror ("Ungültiger 2. Ausdruck gefunden! ");
  242.       return (FALSE);    /* Bedingung fehlerhaft */
  243.     }
  244.  
  245.     return (Compare());    
  246. }
  247.  
  248. /* ReadComp: lies Vergleichsoperator ein
  249. */
  250.  
  251. void
  252. ReadComp ()
  253. {
  254.  
  255.       switch (*ScanBuffer) {
  256.         case    '/':
  257.           Scan ();
  258.           if (*ScanBuffer == '=')
  259.             *ActOp++ = UNGL;
  260.           else {
  261.             SkipChar ();
  262.           }
  263.         break;
  264.         case    '>':
  265.           Scan ();
  266.             if (*ScanBuffer == '=')
  267.               *ActOp++ = GRGL;
  268.             else {
  269.               SkipChar ();
  270.               *ActOp++ = GR;
  271.             }
  272.         break;
  273.         case    '<':
  274.           Scan ();
  275.             if (*ScanBuffer == '=')
  276.               *ActOp++ = KLGL;
  277.             else {
  278.               SkipChar ();
  279.               *ActOp++ = KL;
  280.             }
  281.         break;
  282.         case    '=':
  283.           *ActOp++ = GL;
  284.         break;
  285.         default:
  286.           serror ("Ungültiger Vergleichsoperator! ");
  287.         break;
  288.       }
  289. }
  290.  
  291. /*    Compare
  292.     Vergleiche die Ausdrücke auf dem Stack.
  293. */
  294.  
  295. int
  296. Compare ()
  297. {
  298. EXPDEF    *Var1,*Var2;
  299. int        Op;
  300.  
  301.         /* solange beide Stacks noch Werte besitzen, ... */
  302.     while ((TopStack != BotStack) && (ActOp != OpStckBot)) {
  303.         if ((Var2 = PopExp()) == NULL) {
  304.           break;
  305.         }
  306.         if ((Var1 = PopExp()) == NULL) {
  307.           break;
  308.         }
  309.         if (Var1->type == Var2->type) {
  310.           ActOp--;
  311.           Op = *ActOp;
  312.           switch (Op) {            /* hier wird endlich verglichen */
  313.             case    GL:
  314.               return ((Var1->val.wert == Var2->val.wert) ?
  315.                        TRUE : FALSE);
  316.             case    GRGL:
  317.               return ((Var1->val.wert >= Var2->val.wert) ?
  318.                        TRUE : FALSE);
  319.             case    GR:
  320.               return ((Var1->val.wert > Var2->val.wert) ?
  321.                        TRUE : FALSE);
  322.             case    KLGL:
  323.               return ((Var1->val.wert <= Var2->val.wert) ?
  324.                        TRUE : FALSE);
  325.             case    KL:
  326.               return ((Var1->val.wert < Var2->val.wert) ?
  327.                        TRUE : FALSE);
  328.             case    UNGL:
  329.               return ((Var1->val.wert != Var2->val.wert) ?
  330.                        TRUE : FALSE);
  331.           }
  332.         }
  333.     }
  334. return (TRUE);
  335. }
  336.  
  337. /* druckt eine Variable aus */
  338.  
  339. void
  340. PrintVar (Name)
  341. char    *Name;
  342. {
  343. VAR        *Variable;
  344.  
  345.         /* wenn es eine Variable mit dem gesuchten Namen gibt, merken! */
  346.     if ((Variable = IsVariable (Name)) != NULL) {
  347.       switch (Variable->VarType) {
  348.         case    FIXNUM:
  349.           printf ("%d",Variable->VarWert.variable.integer);
  350.         break;
  351.         case    FLONUM:
  352.           printf ("%ld",Variable->VarWert.variable.Flotype);
  353.         break;
  354.         case    STRING:
  355.         break;
  356.         default:
  357.           printf ("\n Variablen dieses Typs können nicht gedruckt werden! ");
  358.         break;
  359.       }
  360.     }
  361.     else {
  362.       char buffer[40];
  363.       sprintf (buffer,"Variable <%s> unbekannt! ",Name);
  364.       fatal_error (buffer);
  365.     }
  366. }
  367.  
  368.  
  369. /* monadische Vorzeichen merker */
  370. static    int    Monadneg = FALSE;
  371.  
  372. /*    CalcExpression: berechnet das Ergebnis eines Ausdrucks
  373. */
  374.  
  375. int
  376. CalcExpression (Result)
  377. VAR *Result;
  378. {
  379. VAR    *Variable;
  380.  
  381.     ActOp = OpStckBot;    /* Zeiger auf bottom OpStckBot stack */
  382.     BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF));
  383.  
  384.     Scan ();        /* den ersten Ausdruck einlesen */
  385.     if (Steuer == EOLCHAR)
  386.       return (ERROR);
  387.  
  388.     if ((Steuer == SONDER) && (*ScanBuffer == '-'))
  389.       Monadneg = TRUE;
  390.     
  391.         /* gesamten Rechenausdruck auf den Stack */
  392.     do {
  393.       if ((Steuer == ZIFFER) || (Steuer == ALPHA))
  394.         PushExp ();
  395.       else {
  396.         if (Steuer == SONDER) {
  397.           if ((*ScanBuffer == '+') || (*ScanBuffer == '-') ||
  398.               (*ScanBuffer == '*') || (*ScanBuffer == '/')) {
  399.             *ActOp = *ScanBuffer;
  400.             ActOp++;
  401.           }
  402.           else {
  403.             serror ("Ungültiger Operand gefunden! ");
  404.             return (ERROR);
  405.           }
  406.         }
  407.         else {
  408.           serror ("Operand erwartet!");
  409.           return (ERROR);
  410.         }
  411.       }
  412.           /* nächsten Ausdruck einlesen */
  413.       if (Scan () == UNEOL) {
  414.         fatal_error (" Unerwartetes Zeilenende! ");
  415.         return (ERROR);
  416.       }
  417.  
  418.     }    while (Steuer != EOLCHAR) ;
  419.  
  420.     CalcResult ();            /* berechnet das Ergebnis und hinterläßt */
  421.                             /* es auf dem Stack                     */
  422.  
  423.     SetResultValue (Result);
  424.     free (BotStack);        /* Speicher wieder freigeben */
  425.  
  426. return (OK);
  427. }
  428.  
  429. /* SetResultValue: wandelt das Berechnungsergebnis in die Variablenstruktur
  430. */
  431.  
  432. void
  433. SetResultValue (Result)
  434. VAR *Result;
  435. {
  436.  
  437.     switch (BotStack->type) {
  438.       case    ZAHL:        /* Zahlen in Fließkommadarstellung */
  439.         Result->VarWert.variable.Flotype = BotStack->val.wert;
  440.         Result->VarType = FLONUM;
  441.       break;
  442.       case    TEXT:
  443.         fatal_error ("Textwandlung noch nicht implementiert! ");
  444.       break;
  445.       case    FELD:
  446.         fatal_error ("Arrayzuweisung noch nicht implementiert! ");
  447.       break;
  448.       default:
  449.         fatal_error ("Unbekannter Zahlentyp gefunden! ");
  450.       break;
  451.     }
  452. }
  453.  
  454.  
  455. /*    PushExp
  456.     welche in ScanBuffer steht auf Stack ablegen.
  457. */
  458. void
  459. PushExp ()
  460. {
  461. VAR    *Variable;
  462.  
  463.       switch (Steuer) {
  464.         case  ZIFFER:
  465.         case  FLONUM:
  466.           TopStack->type = ZAHL;
  467.           TopStack->val.wert = atof (ScanBuffer);
  468.           if (Monadneg) {
  469.             TopStack->val.wert *= -1;
  470.             Monadneg = FALSE;
  471.           }
  472.         break;
  473.         case  ALPHA:
  474. /* Wenn es die gesuchte Variable gibt, Zeiger drauf und merken! */
  475.           if ((Variable = IsVariable (ScanBuffer)) != NULL) {
  476.             switch (Variable->VarType) {
  477.               case ZIFFER:
  478.                 TopStack->type = ZAHL;
  479.                 TopStack->val.wert = Variable->VarWert.variable.integer;
  480.               break;
  481.               case FLONUM:
  482.                 TopStack->type = ZAHL;
  483.                 TopStack->val.wert = Variable->VarWert.variable.Flotype;
  484.               break;
  485.               default :
  486.                 serror ("Variablentyp für Operation nicht erlaubt! ");
  487.               break;
  488.             }
  489.           }
  490.           else
  491.             serror ("Variable nicht definiert! ");
  492.         break;
  493.         case    STRING:
  494.             fatal_error ("Stringzuweisung nicht implementiert! ");    
  495.         break;
  496.         default:
  497.           serror ("Keine Operation für diesen Typ vorhanden! ");
  498.         break;
  499.       }
  500.       TopStack++;        /* Stackpointer an die nächste Position */
  501. }
  502.  
  503.  
  504. /* CalcResult: berechnet das Ergebnis eines Ausdrucks,
  505. der sich auf dem Stack befindet
  506. */
  507. void
  508. CalcResult ()
  509. {
  510. EXPDEF    *Var1,*Var2,Result;
  511. int        Op;
  512.  
  513. /* solange beide Stacks noch Werte besitzen, ... */
  514.     while ((TopStack != BotStack) && (ActOp != OpStckBot)) {
  515.         if ((Var1 = PopExp()) == NULL) {
  516.           break;
  517.         }
  518.         if ((Var2 = PopExp()) == NULL) {
  519.           break;
  520.         }
  521.         if (Var1->type == Var2->type /*== ZIFFER*/) {
  522.           ActOp--;
  523.           Op = *ActOp;        /* OpStckBot vom Stack holen */
  524.           switch (Op) {
  525.             case    '+':
  526.               Result.val.wert = Var2->val.wert + Var1->val.wert;
  527.             break;
  528.             case    '-':
  529.               Result.val.wert = Var2->val.wert - Var1->val.wert;
  530.             break;
  531.             case    '*':
  532.               Result.val.wert = Var2->val.wert * Var1->val.wert;
  533.             break;
  534.             case    '/':
  535.               Result.val.wert = Var2->val.wert / Var1->val.wert;
  536.             break;
  537.           }    
  538.         }
  539.         else
  540.           serror ("Operation für Variablentyp nicht implementiert! ");
  541.         TopStack->type    = Var1->type;
  542.         TopStack->val.wert = Result.val.wert;
  543.         TopStack ++;
  544.  
  545.     }
  546.  
  547. }
  548.  
  549.  
  550. /*    PopExp
  551.     Holt einen Ausdruck vom Variablenstack
  552. */
  553.  
  554. EXPDEF *
  555. PopExp ()
  556. {
  557.   if (TopStack-- != BotStack)
  558.     return (TopStack);
  559.   else
  560.     return (NULL);
  561. }
  562.  
  563. /* ClearProg: den Speicherplatz, der durch das Programm
  564. belegt ist, freigeben
  565. */
  566.  
  567. void
  568. ClearProg ()
  569. {
  570. PRGZEILE    *Memory;
  571.  
  572.     ActLine = FirstLine;        /* Zeiger auf erste Programmzeile */
  573.     while (ActLine) {
  574.       Memory = ActLine;            /* wird gleich benötigt */
  575.       ActLine = ActLine->NextZeile;    /* das ist die nächste Zeile */
  576.       free (Memory);            /* Speicherplatz freigeben */
  577.     }
  578.  
  579.     FirstLine = ActLine = NULL;    /* Zeiger zurücksetzen */
  580.  
  581. }
  582.  
  583.  
  584. /* Ende des Files INTUTIL.C */
  585.