home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / spezial / 20 / st_txl / intutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1985-07-18  |  27.5 KB  |  1,096 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 <string.h>
  10. #include "interp.h"
  11. #include <math.h>;
  12.  
  13. /* Funktionsprototypen */
  14. void SetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type);
  15. void GetValue (VARDEF *Wert,VARDEF *NewVar,unsigned char Type);
  16. void PushExp (void);
  17. void CalcResult (int Op, int Ops);
  18. void SetResultValue (VAR *Result);
  19.  
  20. void     ReadValue (VAR    *Wert);
  21. EXPDEF    *PopExp (void);
  22.  
  23. int        CmpVar (void);
  24. int        Compare (int Op);
  25. int     ReadComp (int *Op);
  26.  
  27. void    ClearProg (void);
  28.  /* die neuen Funktionen */
  29.  
  30. void    Expression (void);
  31. void    Term (void);
  32. void    Faktor (void);
  33. int     TestFunc (int *func);
  34.  
  35. void    NewString (VARDEF *Var,size_t len);
  36. void    MinMax (int Ops, int minmax);
  37. void    Length (void);
  38. void    Left (void);
  39. void    Right (void);
  40. void    Mid (void);
  41. void    InStr(void);
  42.  
  43. int TestComma (void);
  44. int GetStringVar (VAR **str);
  45. int GetLong (long *val);
  46.  
  47.  
  48. /* Benötigte Globalvariablen */
  49. extern    int            IntError;        /* Interpreterfehler */
  50. extern    PRGZEILE    *FirstLine;        /* erste Interpreterzeile */
  51. extern    PRGZEILE    *ActLine;        /* aktuelle interpretierte Zeile */
  52. extern    char        *LinePos;        /* Zeilenposition der aktuellen Zeile*/
  53. extern    int        Steuer;                /* der aufrufenden Routine wird mit-    */
  54.                                     /* geteilt, um was es sich handelt.         */
  55. extern    char    ScanBuffer[ZEILENLAENGE]; /* Ergebnisbuffer des Scanners */
  56.  
  57. extern    VAR        *FirstVar;            /* Zeiger auf die erste Variable */
  58.  
  59. static  int     expOk;  /* ist der ausgewertete Ausdruck korrekt */
  60.  
  61. /* die Namen der Interpreterfunktionen */
  62. static  char    *ifuncs[] = { "sqr","sqrt","sin","cos","tan","atan",
  63.                               "ln","exp","min","max",
  64.                               "laenge","links","rechts","mitte",
  65.                               "suche",
  66.                               NULL };
  67.  
  68. /* und zugehörige Tokens zum Aufruf */
  69. #define  NEGOP  'a'
  70. #define  SQROP  'b'
  71. #define  SQRTOP 'c'
  72. #define  SINOP  'd'
  73. #define  COSOP  'e'
  74. #define  TANOP  'f'
  75. #define  ATANOP 'g'
  76. #define  LNOP   'h'
  77. #define  EXPOP  'i'
  78.  
  79. /* BEACHTE : einige der Funktionen werden direkt ( also nicht über
  80.              CalcResult aufgerufen ), und brauchen daher kein Token
  81. */
  82.  
  83.  
  84. /*    ShowLine
  85.     Zeile wieder zurückwandeln und ausgeben.
  86. */
  87. extern    TOKBEF        TokBefDesc[];
  88.  
  89. void
  90. ShowLine (FindZeile)
  91. PRGZEILE *FindZeile;
  92. {
  93. char    *Line;
  94.  
  95.     Line = FindZeile->Zeile;
  96.     if (*Line) {            /* Ist die Programmzeile leer? */
  97.       printf ("\n%03d %s ",
  98.                  FindZeile->LineNumber,
  99.                  TokBefDesc[(*Line-TOKMIN)&0xff].Befehl
  100.                  );
  101.        Line++;
  102.        if (*Line) printf ("%s",Line);
  103.     }        
  104.  
  105. }
  106.  
  107.  
  108. /* "IsVariable" sucht nach einer Variablen mit gleichem Namen.
  109.     Gibt es keine, wird ein NULL-Zeiger zurückgeliefert.
  110. */
  111.  
  112. VAR *
  113. IsVariable (Name)
  114. char    *Name;
  115. {
  116. register    VAR  *i;
  117.  
  118.   for (i = FirstVar;
  119.        i && (strcmp(Name,i->VarName) != 0);
  120.        i = i->NextVar);
  121.  
  122. return (i);
  123. }
  124.  
  125. /* "SetVar" sieht nach, ob es die Varible schon gibt.
  126.    Wenn ja, wird ihr Wert verändert. Ansonsten wird
  127.    eine neue Variable angelegt.
  128. */
  129.  
  130. int
  131. SetVar (Wert)
  132. VAR        *Wert;
  133. {
  134. VAR        *Variable;
  135. VAR        Value;
  136.  
  137.         /* Lies den zu setzenden Wert ein */
  138.     if (CalcExpression (&Value) == ERROR) return (ERROR);
  139.     
  140.     if ( Steuer != EOLCHAR ){
  141.       serror( "unerwartetes Zeilenende" ); return(ERROR);
  142.     }
  143.  
  144.         /* Gibt es eine Variable mit dem Namen, dann setze Zeiger */
  145.     if ((Variable = IsVariable (Wert->VarName)) != NULL) {
  146.       SetValue (&Variable->VarWert,&Value.VarWert,Value.VarType);
  147.       return (OK);
  148.     }
  149.     
  150.     if ((Variable = malloc(sizeof (VAR))) == NULL) {
  151.       printf ("\n Kein Speicherplatz mehr für die Variable! ");
  152.       return (FALSE);
  153.     }
  154.  
  155.     strcpy (Variable->VarName,Wert->VarName);    /* Variablennamen eintragen */
  156.     Variable->VarType = Value.VarType;            /* Variablen-Type eintragen  */
  157.     SetValue (&Variable->VarWert,&Value.VarWert,Value.VarType);
  158.     Variable->NextVar = FirstVar;
  159.     FirstVar = Variable;        /* Variable oben einfügen  */
  160.  
  161. return (OK);
  162. }
  163.  
  164. /* NewString : neuen String bereitstellen oder
  165.                den Speicher auf neue Grö₧e erweitern
  166. */
  167.  
  168. void NewString ( Var,len )
  169. VARDEF   *Var;
  170. size_t   len;
  171. {
  172.  
  173.   len++; /* für '\0' Abschlu₧ */
  174.   if ( Var->variable.text == NULL )
  175.     Var->variable.text = calloc( len,sizeof(char));
  176.   else
  177.      Var->variable.text = realloc( Var->variable.text,len );
  178. }
  179.  
  180. /*    Einlesen eines Ausdrucks von der gerade aktuellen Eingabeposition
  181.     ab.
  182. */
  183.  
  184. void
  185. ReadValue (Wert)
  186. VAR    *Wert;
  187. {
  188.  
  189.     Scan ();            /* Nächster Ausdruck von Eingabezeile */
  190.     switch (Steuer) {
  191.       case ZIFFER:
  192.       /*
  193.         Wert->VarType = FIXNUM;
  194.         Wert->VarWert.variable.integer = atoi (ScanBuffer);
  195.       break;
  196.       führt sonst zu Fehler, da CalcExpression nur FLONUM liefert
  197.       */
  198.       case FLONUM:
  199.         Wert->VarType = FLONUM;
  200.         Wert->VarWert.variable.Flotype = atof (ScanBuffer);
  201.       break;
  202.       case STRING:
  203.         Wert->VarType = STRING;
  204.         NewString ( &Wert->VarWert,strlen( ScanBuffer ));
  205.         strcpy (Wert->VarWert.variable.text,ScanBuffer);
  206.       break;
  207.       case ALPHA:
  208.         printf ("\n Variablenzuweisung noch nicht implementiert! ");
  209.       break;
  210.       case SONDER:
  211.         if (*ScanBuffer == '(') {
  212.     
  213.         }
  214.         else
  215.           printf ("\nUngültiges Zeichen in Ausdruck gefunden! ");
  216.     }
  217.  
  218. }
  219.  
  220.  
  221. /* SetValue Setze den Wert der Variable */
  222. void
  223. SetValue (NewVar,Wert,Type)
  224. VARDEF    *NewVar,*Wert;
  225. unsigned char    Type;
  226. {
  227.  
  228.     switch (Type) {
  229.       case    FIXNUM:
  230.         NewVar->variable.integer = Wert->variable.integer;
  231.       break;
  232.       case    FLONUM:
  233.         NewVar->variable.Flotype = Wert->variable.Flotype;
  234.       break;
  235.       case    ALPHA:  /* ist das so korrekt ? was mit Variablen ? */
  236.         NewVar->variable.zeichen = Wert->variable.zeichen;
  237.       break;
  238.       case    STRING:
  239.         if ( NewVar->variable.text != NULL )
  240.           free( NewVar->variable.text );
  241.         NewVar->variable.text = Wert->variable.text;
  242.       break;
  243.       default:
  244.         printf ("\n Variablenzuweisung für diesen Typ nicht implementiert! ");
  245.       break;
  246.     }
  247.     
  248. }
  249.  
  250. void
  251. GetValue (Var,Wert,Type)
  252. VARDEF    *Var,*Wert;
  253. unsigned char    Type;
  254. {
  255.  
  256.     switch (Type) {
  257.       case    FLONUM:
  258.         Wert->variable.integer = Var->variable.integer;
  259.       break;
  260.       case    FIXNUM:
  261.         Wert->variable.Flotype = Var->variable.Flotype;
  262.       break;
  263.       case    ALPHA: /* siehe SetValue */
  264.         Wert->variable.zeichen = Var->variable.zeichen;
  265.       break;
  266.       case    STRING:
  267.         strcpy (Wert->variable.text,Var->variable.text);
  268.       break;
  269.       default:
  270.         printf ("\n Variablenzuweisung für diesen Typ nicht implementiert! ");
  271.       break;
  272.     }
  273. }
  274.  
  275.  
  276. /*static*/ EXPDEF    *BotStack;
  277. static EXPDEF    *TopStack;
  278.  
  279.  
  280. /*    CmpVar vergleicht zwei Variablen auf Größer, Kleiner oder Gleich */
  281.  
  282. int
  283. CmpVar ()
  284. {
  285. int  rel;
  286. int  Op;
  287.  
  288.     BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF));
  289.  
  290.     Scan ();            /* Erstes Argument lesen... */
  291.     expOk = TRUE; Expression();       /* ... und auswerten */
  292.     if ( !expOk ){
  293.       serror ("Ungültiger 1. Ausdruck gefunden! ");
  294.       return (FALSE);    /* Bedingung fehlerhaft */
  295.     }
  296.           
  297.     if ( ReadComp( &Op ) == FALSE ){
  298.         serror ("Vergleichsoperator erwartet! ");
  299.       return (FALSE);    /* Bedingung fehlerhaft */
  300.     }
  301.  
  302.     Scan();                  /* Zweites Argument lesen... */
  303.     expOk = TRUE; Expression();       /* ... und auswerten */
  304.     if ( !expOk ){
  305.       serror ("Ungültiger 2. Ausdruck gefunden! ");
  306.       return (FALSE);    /* Bedingung fehlerhaft */
  307.     }
  308.  
  309.     rel = Compare( Op );
  310.     free ( BotStack );
  311.       /* Beachte : Stack wird im Fehlerfall nicht freigegeben */
  312.     return (rel);    
  313. }
  314.  
  315. /* ReadComp: lies Vergleichsoperator ein
  316. */
  317.  
  318. int
  319. ReadComp ( Op )
  320. int  *Op;
  321. {
  322. int  relop;  /* zeigt an ob korrekter Vergleichoperetor gefunden */
  323.  
  324.       relop = TRUE; /* wir sind ja Optimisten */
  325.       switch (*ScanBuffer) {
  326.         case    '/':
  327.           Scan ();
  328.           if (*ScanBuffer == '=')
  329.             *Op = UNGL;
  330.           else {
  331.             SkipChar ();
  332.           }
  333.         break;
  334.         case    '>':
  335.           Scan ();
  336.             if (*ScanBuffer == '=')
  337.               *Op = GRGL;
  338.             else {
  339.               SkipChar ();
  340.               *Op = GR;
  341.             }
  342.         break;
  343.         case    '<':
  344.           Scan ();
  345.             if (*ScanBuffer == '=')
  346.               *Op = KLGL;
  347.             else {
  348.               SkipChar ();
  349.               *Op = KL;
  350.             }
  351.         break;
  352.         case    '=':
  353.           *Op = GL;
  354.         break;
  355.         default:
  356.           relop = FALSE;
  357.         break;
  358.       }
  359.       return( relop );
  360. }
  361.  
  362. /*    Compare
  363.     Vergleiche die Ausdrücke auf dem Stack.
  364. */
  365.  
  366. int
  367. Compare ( Op )
  368. int Op;
  369. {
  370. EXPDEF    *Var1,*Var2;
  371. int     rel;
  372.  
  373.     if ((Var2 = PopExp()) == NULL) {
  374.       return(FALSE);
  375.     }
  376.     if ((Var1 = PopExp()) == NULL) {
  377.       return( Var2->val.wert != 0 );
  378.     }
  379.     if (Var1->type == Var2->type) {
  380.       if ( Var1->type == ZAHL ){
  381.           switch (Op) {    /* hier wird endlich verglichen */
  382.         case    GL:
  383.           return ((Var1->val.wert == Var2->val.wert) ?
  384.                    TRUE : FALSE);
  385.         case    GRGL:
  386.           return ((Var1->val.wert >= Var2->val.wert) ?
  387.                    TRUE : FALSE);
  388.         case    GR:
  389.           return ((Var1->val.wert > Var2->val.wert) ?
  390.                    TRUE : FALSE);
  391.         case    KLGL:
  392.           return ((Var1->val.wert <= Var2->val.wert) ?
  393.                    TRUE : FALSE);
  394.         case    KL:
  395.           return ((Var1->val.wert < Var2->val.wert) ?
  396.                    TRUE : FALSE);
  397.         case    UNGL:
  398.           return ((Var1->val.wert != Var2->val.wert) ?
  399.                    TRUE : FALSE);
  400.         }/*switch*/
  401.       }/* ZAHL */
  402.       else if ( Var1->type == TEXT ){
  403.         rel = strcmp( Var1->val.text,Var2->val.text );
  404.         switch ( Op ) {
  405.          case   GL : return (( rel == 0 ) ? TRUE : FALSE );
  406.          case GRGL : return (( rel >= 0 ) ? TRUE : FALSE );
  407.          case   GR : return (( rel >  0 ) ? TRUE : FALSE );
  408.          case KLGL : return (( rel <= 0 ) ? TRUE : FALSE );
  409.          case   KL : return (( rel <  0 ) ? TRUE : FALSE );
  410.          case UNGL : return (( rel != 0 ) ? TRUE : FALSE );
  411.         }
  412.      }/* TEXT */
  413.     }/* type equal */
  414.     return(TRUE); /* nur für den Compiler */
  415. }/* Compare */
  416.  
  417. /* druckt eine Variable aus */
  418.  
  419. void
  420. PrintVar (Name)
  421. char    *Name;
  422. {
  423. VAR        *Variable;
  424.  
  425.     /* wenn es eine Variable mit dem gesuchten Namen gibt, merken! */
  426.     if ((Variable = IsVariable (Name)) != NULL) {
  427.       switch (Variable->VarType) {
  428.         case    FIXNUM:
  429.           printf ("%d",Variable->VarWert.variable.integer);
  430.         break;
  431.         case    FLONUM:
  432.           printf ("%f",Variable->VarWert.variable.Flotype);
  433.         break;
  434.         case    STRING:
  435.           printf( "%s",Variable->VarWert.variable.text );
  436.         break;
  437.         default:
  438.           printf ("\n Variablen dieses Typs können nicht gedruckt werden! ");
  439.         break;
  440.       }
  441.     }
  442.     else {
  443.       char buffer[40];
  444.       sprintf (buffer,"Variable <%s> unbekannt! ",Name);
  445.       fatal_error (buffer);
  446.     }
  447. }
  448.  
  449.  
  450. /*    CalcExpression: berechnet das Ergebnis eines Ausdrucks
  451. */
  452.  
  453. int
  454. CalcExpression (Result)
  455. VAR *Result;
  456. {
  457. /* VAR    *Variable; */
  458.  
  459.     BotStack = TopStack = malloc (EXPSTACK * sizeof(EXPDEF));
  460.  
  461.     Scan ();        /* den ersten Ausdruck einlesen */
  462.     if (Steuer == EOLCHAR)
  463.       return (ERROR);
  464.     
  465.     expOk = TRUE; Expression();
  466.  
  467.     SetResultValue( Result );
  468.     free (BotStack);        /* Speicher wieder freigeben */
  469.     if ( expOk ) return (OK);
  470.     else return (ERROR);
  471. }
  472.  
  473. /* Expression, Term und Faktor werten einen Ausdruck aus */
  474.  
  475. void Expression (void)
  476. {
  477. char  addop;
  478.  
  479.   if (( Steuer == SONDER ) &&
  480.       (( *ScanBuffer == '+' ) || ( *ScanBuffer == '-' )) &&
  481.       expOk ){
  482.     addop = *ScanBuffer;
  483.     Scan(); Term();
  484.     if ( addop == '-' ) CalcResult( NEGOP,1 );
  485.   }
  486.   else Term();
  487.   
  488.   while (( Steuer == SONDER ) &&
  489.          (( *ScanBuffer == '+' ) || ( *ScanBuffer == '-' )) &&
  490.          expOk ){
  491.     addop = *ScanBuffer;
  492.     Scan(); Term();
  493.     CalcResult( addop,2 );
  494.   }
  495. }/* Expression */
  496.  
  497. void Term (void )
  498. {
  499. char  mulop;
  500.  
  501.   Faktor();
  502.   while (( Steuer == SONDER ) &&
  503.          (( *ScanBuffer == '*' ) || ( *ScanBuffer == '/' )) &&
  504.          expOk ){
  505.     mulop = *ScanBuffer;
  506.     Scan(); Faktor();
  507.     CalcResult( mulop,2 );
  508.   }
  509. }/* Term */
  510.  
  511. void Faktor (void)
  512. {
  513. int  f;
  514. int  o;
  515.  
  516.   if (( Steuer == SONDER ) && ( *ScanBuffer == '(' )){
  517.     Scan(); Expression();
  518.     if ( *ScanBuffer == ')' ) Scan();
  519.     else{ expOk = FALSE; serror ( ")  erwartet" ); }
  520.   }
  521.   else if ( Steuer == ALPHA ){
  522.     if ( TestFunc( &f ) == 0 ){
  523.       Scan();
  524.       if (( Steuer == SONDER ) && ( *ScanBuffer == '(' )){
  525.         o = 0;
  526.         do{
  527.           Scan();
  528.           if (( Steuer == SONDER ) && ( *ScanBuffer == ')' )) break;
  529.             /* nur für den Fall das kein Parameter angegeben wird
  530.                z.B.  sqr() */
  531.           Expression(); o++;
  532.         } while(( Steuer == SONDER ) && ( *ScanBuffer == ',' ));
  533.         if ( *ScanBuffer == ')' ){
  534.           switch ( f ){
  535.            case 0 : 
  536.              if ( o == 1 ) CalcResult( SQROP,1 );
  537.              else serror( "<sqr> erwartet 1 Parameter" );
  538.            break;
  539.            case 1 :
  540.              if ( o == 1 ) CalcResult( SQRTOP,1 );
  541.              else serror( "<sqrt> erwartet 1 Parameter" );
  542.            break;
  543.            case 2 :
  544.              if ( o == 1 )CalcResult ( SINOP,1 );
  545.              else serror( "<sin> erwartet 1 Parameter" );
  546.            break;
  547.            case 3 :
  548.              if ( o == 1 ) CalcResult ( COSOP,1 );
  549.              else serror( "<cos> erwartet 1 Parameter" );
  550.            break;
  551.            case 4 :
  552.              if ( o == 1 ) CalcResult ( TANOP,1 );
  553.              else serror( "<tan> erwartet 1 Parameter" );
  554.            break;
  555.            case 5 :
  556.              if ( o == 1 ) CalcResult ( ATANOP,1 );
  557.              else serror( "<atan> erwartet 1 Parameter" );
  558.            break;
  559.            case 6 :
  560.              if ( o == 1 ) CalcResult ( LNOP,1 );
  561.              else serror( "<ln> erwarte 1 Parameter" );
  562.            break;
  563.            case 7 :
  564.              if ( o == 1 ) CalcResult ( EXPOP,1 );
  565.              else serror( "<exp> erwartet 1 Parameter" );
  566.            break;
  567.            case 8 :
  568.              if ( o > 0 ) MinMax( o,0 );
  569.              else serror( "mindestens ein Parameter für <min>" );
  570.            break;
  571.            case 9 :
  572.              if ( o > 0 ) MinMax( o,1 );
  573.              else serror( "mindestens 1 parameter für <max>" );
  574.            break;
  575.            case 10 :
  576.              if ( o == 1 ) Length();
  577.              else serror( "<laenge> erwartet 1 Parameter" );
  578.            break;
  579.            case 11 :
  580.              if ( o == 2 ) Left();
  581.              else serror( "<links> erwartet 2 Parameter" );
  582.            break;
  583.            case 12 :
  584.              if ( o == 2 ) Right();
  585.              else serror( "<rechts> erwartet 2 Parameter" );
  586.            break;
  587.            case 13 :
  588.              if ( o == 3 ) Mid();
  589.              else serror( "<mitte> erwartet 3 Parameter" );
  590.            break;
  591.            case 14 :
  592.              if ( o == 3 ) InStr();
  593.              else serror( "<suche> erwartet 3 Parameter" );
  594.            break;
  595.           }/*switch*/
  596.           Scan();
  597.         }
  598.         else{ expOk = FALSE; serror( ")  erwartet" ); }
  599.       }
  600.       else{ expOk = FALSE; serror( "(  erwartet" ); }
  601.     }
  602.     else{ PushExp(); Scan(); }
  603.   }
  604.   else if (( Steuer == ZIFFER ) || ( Steuer == FLONUM ) ||
  605.            ( Steuer == STRING )){
  606.     PushExp(); Scan();
  607.   }
  608.   else{ expOk = FALSE; serror( "Fehler in Ausdruck" ); }
  609. }/* Faktor */
  610.  
  611. /* TestFunc : ist der Bezeichner der in Faktor gefunden wurde
  612.               ein Funktionsname ?
  613. */
  614.  
  615. int TestFunc ( func )
  616. int  *func;
  617. {
  618. register int i,j;
  619.  
  620.   for ( i=0;
  621.         ( ifuncs[ i ] != NULL ) &&
  622.         ( j = strcmp( ifuncs[ i ],ScanBuffer ) != 0 );
  623.         i++ );
  624.   *func = i;
  625.   return( j );
  626. }/* TestFunc */
  627.  
  628. /* SetResultValue: wandelt das Berechnungsergebnis in die Variablenstruktur
  629. */
  630.  
  631. void
  632. SetResultValue (Result)
  633. VAR *Result;
  634. {
  635.  
  636.     switch (BotStack->type) {
  637.       case    ZAHL:        /* Zahlen in Fließkommadarstellung */
  638.         Result->VarWert.variable.Flotype = BotStack->val.wert;
  639.         Result->VarType = FLONUM;
  640.       break;
  641.       case    TEXT:
  642.         Result->VarWert.variable.text = BotStack->val.text;
  643.         Result->VarType = STRING;
  644.       break;
  645.       case    FELD:
  646.         fatal_error ("Arrayzuweisung noch nicht implementiert! ");
  647.       break;
  648.       default:
  649.         fatal_error ("Unbekannter Zahlentyp gefunden! ");
  650.       break;
  651.     }
  652. }
  653.  
  654.  
  655. /*    PushExp
  656.     welche in ScanBuffer steht auf Stack ablegen.
  657. */
  658. void
  659. PushExp ()
  660. {
  661. VAR    *Variable;
  662.  
  663.       switch (Steuer) {
  664.         case  ZIFFER:
  665.         case  FLONUM:
  666.           TopStack->type = ZAHL;
  667.           TopStack->val.wert = atof (ScanBuffer);
  668.         break;
  669.         case  ALPHA:
  670. /* Wenn es die gesuchte Variable gibt, Zeiger drauf und merken! */
  671.           if ((Variable = IsVariable (ScanBuffer)) != NULL) {
  672.             switch (Variable->VarType) {
  673.               case ZIFFER:
  674.                 TopStack->type = ZAHL;
  675.                 TopStack->val.wert = Variable->VarWert.variable.integer;
  676.               break;
  677.               case FLONUM:
  678.                 TopStack->type = ZAHL;
  679.                 TopStack->val.wert = Variable->VarWert.variable.Flotype;
  680.               break;
  681.               case STRING :
  682.                TopStack->type = TEXT;
  683.                TopStack->val.text = malloc( strlen( Variable->VarWert.variable.text )+1);
  684.                strcpy( TopStack->val.text,
  685.                        Variable->VarWert.variable.text );
  686.               break;
  687.               default :
  688.                 serror ("Variablentyp für Operation nicht erlaubt! ");
  689.               break;
  690.             }
  691.           }
  692.           else
  693.             serror ("Variable nicht definiert! ");
  694.         break;
  695.         case    STRING:
  696.           TopStack->type = TEXT;
  697.           TopStack->val.text = malloc( strlen( ScanBuffer )+1);
  698.           strcpy( TopStack->val.text,ScanBuffer );
  699.         break;
  700.         default:
  701.           serror ("Keine Operation für diesen Typ vorhanden! ");
  702.         break;
  703.       }
  704.       TopStack++;        /* Stackpointer an die nächste Position */
  705. }
  706.  
  707.  
  708. /* CalcResult: berechnet das Ergebnis eines Ausdrucks,
  709. der sich auf dem Stack befindet
  710. */
  711. void
  712. CalcResult ( Op,Ops )
  713. int  Op,Ops;
  714. {
  715. EXPDEF    *Var1,*Var2,Result;
  716. char    *v1,*v2;
  717. size_t  l1,l2;
  718.  
  719.  
  720.   /* da die Anzahl der Parameter schon in <Faktor> überprüft
  721.      wird, sparen wir uns hier weitere Kontrollen
  722.   */
  723.   Var1 = PopExp();
  724.   
  725.   if( Ops > 1 ) Var2 = PopExp();
  726.  
  727.   if (( Ops == 1 ) || ( Var1->type == Var2->type )) {
  728.       if ( Var1->type == ZAHL ){
  729.         switch (Op) {
  730.           case    '+':
  731.             Result.val.wert = Var2->val.wert + Var1->val.wert;
  732.           break;
  733.           case    '-':
  734.             Result.val.wert = Var2->val.wert - Var1->val.wert;
  735.           break;
  736.           case    '*':
  737.             Result.val.wert = Var2->val.wert * Var1->val.wert;
  738.           break;
  739.           case    '/':
  740.             Result.val.wert = Var2->val.wert / Var1->val.wert;
  741.           break;
  742.           case  NEGOP :
  743.             Result.val.wert = -Var1->val.wert;
  744.           break;
  745.           case  SQROP :
  746.             Result.val.wert = Var1->val.wert * Var1->val.wert;
  747.           break;
  748.           case  SQRTOP :
  749.             Result.val.wert = sqrt ( Var1->val.wert );
  750.           break;
  751.           case  SINOP :
  752.             Result.val.wert = sin ( Var1->val.wert*M_PI/180 );
  753.           break;
  754.           case  COSOP :
  755.             Result.val.wert = cos ( Var1->val.wert*M_PI/180 );
  756.           break;
  757.           case  TANOP :
  758.             Result.val.wert = tan ( Var1->val.wert*M_PI/180 );
  759.           break;
  760.           case  ATANOP :
  761.             Result.val.wert = 180/M_PI*atan ( Var1->val.wert );
  762.           break;
  763.           case  LNOP   :
  764.             Result.val.wert = log ( Var1->val.wert );
  765.           break;
  766.           case  EXPOP  :
  767.             Result.val.wert = exp ( Var1->val.wert );
  768.           break;
  769.         }/* switch */
  770.         TopStack->val.wert = Result.val.wert;
  771.       }/* ZAHL */
  772.       else if ( Var1->type == TEXT ){
  773.         /* für / + *  gemeinsame Anweisungen */
  774.         l1 = strlen( Var1->val.text );
  775.         l2 = strlen( Var2->val.text );
  776.         v1 = Var1->val.text;
  777.         switch ( Op ){
  778.           case '+' :
  779.             Var2->val.text = realloc( Var2->val.text,l1+l2+1 );
  780.             v2 = Var2->val.text;
  781.             while ( *v2++ != '\0' ); v2--; /* ohne '\0' */
  782.             v1 = Var1->val.text;
  783.             while (( *v2++ = *v1++ ) != '\0' );
  784.           break;
  785.           case '*' :
  786.           case '/' :
  787.             if ( l1 > l2 ) l1 = l2;
  788.             v2 = Var2->val.text;
  789.             if ( Op == '/' ) v2 += ( l2 - l1 );
  790.               /* bis auf diese Anweisung, sind die beiden gleich */
  791.             while ( l1-- > 0 ) *v2++ = *v1++; /* ohne '\0' */
  792.           break;
  793.         }/* switch Op */
  794.         free( Var1->val.text );
  795.         TopStack->val.text = Var2->val.text;
  796.        }/* TEXT */
  797.      TopStack->type = Var1->type;
  798.      TopStack++;
  799.   }
  800.   else
  801.     serror ("Operation für Variablentyp nicht implementiert! ");
  802.  
  803. }/* CalcResult */
  804.  
  805. /* MinMax : je nach Wert des Parameters minmax, Minimum oder
  806.             Maximum der durch Ops bestimmten Anzahl Werte auf
  807.             dem Stack ermitteln
  808.   eine Funktion für min und max, weil beide bis auf den Ver-
  809.   gleich identisch sind
  810. */
  811.  
  812. void MinMax ( Ops,minmax )
  813. int Ops,minmax;
  814. {
  815. EXPDEF  Result,*Var;
  816.  
  817.   Var = PopExp();
  818.   Result.val.wert = Var->val.wert;
  819.   Result.type = Var->type;  /* eigentlich müssen wir noch auf ZAHL testen */
  820.   while ( --Ops > 0 ){
  821.     Var = PopExp();
  822.     if ( Var->type != Result.type ){
  823.       serror( "nur gleiche Typen für <max> erlaubt" );
  824.       break;
  825.     }
  826.     if ( minmax == 1 ){
  827.       if ( Var->val.wert > Result.val.wert )
  828.         Result.val.wert = Var->val.wert;
  829.     }
  830.     else{
  831.       if ( Var->val.wert < Result.val.wert ) 
  832.         Result.val.wert = Var->val.wert;
  833.     }
  834.   }
  835.   TopStack->type = Result.type;
  836.   TopStack->val.wert = Result.val.wert;
  837.   TopStack++;
  838. }/* MinMax */
  839.  
  840. /* Length : die Länge eines Strings */
  841.  
  842. void Length( void )
  843. {
  844. EXPDEF  *top;
  845. size_t  len;
  846.  
  847.   top = PopExp();
  848.   if ( top->type != TEXT ){
  849.     fatal_error( "STRING erwartet in <laenge>" ); return;
  850.   }
  851.   len = strlen( top->val.text );
  852.   free( top->val.text );
  853.   TopStack->type = ZAHL;
  854.   TopStack->val.wert = (float)len;
  855.   TopStack++;
  856. }/* Length */
  857.  
  858. /* Left : die durch anz bestimmte Anzahl Zeichen von links her
  859.           aus einem String
  860.    Syntax : links "(" String "," Zahl ")"
  861.             String und zahl können jeweils ein Ausdruck des
  862.             entsprechenden Typs sein
  863.    Bsp.  setze l=links(s+"...",x-2);
  864. */
  865.  
  866. void Left( void )
  867. {
  868. EXPDEF  *str,*anz;
  869. char    *s;
  870.  
  871.   anz = PopExp();
  872.   if ( anz->type != ZAHL ){
  873.     fatal_error( "<links> erwartet ZAHL als 2. P." ); return;
  874.   }
  875.   str = PopExp();
  876.   if ( str->type != TEXT ){
  877.     fatal_error( "<links> erwartet STRING als 1. P." ); return;
  878.   }
  879.   s = str->val.text + (long)anz->val.wert;
  880.   *s = '\0';     /* den Rest einfach abschneiden */
  881.   TopStack->type = TEXT;
  882.   TopStack->val.text = str->val.text;
  883.   TopStack++;
  884. }/* Left */
  885.  
  886. /* Right : wie Left, nur sind hier die Zeichen vom rechten Ende
  887.            her gewünscht
  888.    Syntax : rechts "(" String "," Zahl ")"
  889. */
  890.  
  891. void Right( void )
  892. {
  893. EXPDEF  *str,*anz;
  894. char    *s,*d;
  895. size_t  l;
  896.  
  897.   anz = PopExp();
  898.   if ( anz->type != ZAHL ){
  899.     fatal_error( "<rechts> erwartet ZAHL als 2. P." ); return;
  900.   }
  901.   str = PopExp();
  902.   if ( str->type != TEXT ){
  903.     fatal_error( "<rechts> STRING als 1. P." ); return;
  904.   }
  905.   l = strlen( str->val.text );
  906.   if ( (long)anz->val.wert > l ) anz->val.wert = l;
  907.   s = str->val.text;
  908.   d = s + ( l - (long)anz->val.wert );
  909.   while ( (*s++ = *d++ ) != '\0' );    /* den rechten Teil zum
  910.                                       Stringanfang hinziehen */
  911.   TopStack->type = TEXT;
  912.   TopStack->val.text = str->val.text;
  913.   TopStack++;
  914. }/* Right */
  915.  
  916. /* Mid : hier wird mitten hinein gegriffen
  917.  
  918.    Syntax mitte "(" String "," Zahl1 "," Zahl2 ")"
  919.    
  920.    Zahl1 bestimmt ab welcher Position
  921.    Zahl viel zeichen genommen werden
  922. */
  923.  
  924. void Mid ( void )
  925. {
  926. EXPDEF  *str,*start,*anzahl;
  927. char    *mid,*s,*d;
  928. int     ab,anz,len;
  929.  
  930.   anzahl = PopExp();
  931.   if ( anzahl->type != ZAHL ){
  932.     fatal_error( "<mitte> erwartet ZAHL als 3.P." ); return;
  933.   }
  934.   else anz = (int)anzahl->val.wert;
  935.   start = PopExp();
  936.   if ( start->type != ZAHL ){
  937.     fatal_error( "<mitte> erwartet ZAHL als 2.P." ); return;
  938.   }
  939.   else ab = (int)start->val.wert;
  940.   str = PopExp();
  941.   if ( str->type != TEXT ){
  942.     fatal_error( "<mitte> erwartet STRING als 1.P." ); return;
  943.   }
  944.   else len = (int)strlen( str->val.text );
  945.   
  946.   if ( ab > len ){     /* Anfangsposition hinter Stringende */
  947.     *TopStack->val.text = '\0';
  948.   }
  949.   else {
  950.     if ( anz > ( len - ab )) anz = len - ab;  /* nicht mehr als da */
  951.     mid = calloc( anz,sizeof( char ));   /* Speicher für mid */
  952.     s = str->val.text + (long)ab;        /* von hier ... */
  953.     d = mid;                             /* ... nach da */
  954.     while ( anz-- > 0 ) *d++ = *s++;  *d = '\0';
  955.     free( str->val.text );
  956.     TopStack->val.text = mid;
  957.   }
  958.   TopStack->type = TEXT;
  959.   TopStack++;
  960. }/* Mid */
  961.  
  962. /* Instr : suche pattern in String ab Position start
  963.  
  964.    Syntax : suche "(" String "," Stringvariable "," Zahl ")"
  965.    Bsp.  setze pos=suche("wie","na wie geht's",0);
  966. */
  967.  
  968. void InStr( void )
  969. {
  970. EXPDEF  *pattern,*str,*start;
  971. char    *search,*find;
  972. size_t  len;
  973. long    ab,pos;
  974.  
  975.   start = PopExp();
  976.   if ( start->type != ZAHL ){
  977.     serror( "<suche> erwartet ZAHL als 2.P." ); return;
  978.   }
  979.   else ab = (long)start->val.wert;
  980.   
  981.   str = PopExp();
  982.   if ( str->type != TEXT ){
  983.     serror( "<suche> erwartet STRING als 2.P." ); return;
  984.   }
  985.   else len = strlen( str->val.text );
  986.   
  987.   pattern = PopExp();
  988.   if ( pattern->type != TEXT ){
  989.     serror( "<suche> erwartet STRING als 1.P." ); return;
  990.   }
  991.   
  992.   if ( ab > len ){   /* Anfangsposition hinter Stringende */
  993.     TopStack->val.wert = -1;
  994.   }
  995.   else {
  996.     search = str->val.text + ab;               /* ab hier ... */
  997.     find = strstr( search,pattern->val.text ); /* ...suchen */
  998.     if ( find == NULL ) pos = -1;      /* nicht gefunden */
  999.     else pos = find - str->val.text;   /* bei pos gefunden */
  1000.     free( str->val.text );
  1001.     free( pattern->val.text );
  1002.     TopStack->val.wert = (float)pos;
  1003.   }
  1004.   TopStack->type = ZAHL;
  1005.   TopStack++;
  1006.   
  1007. }/* InStr */
  1008.  
  1009.  
  1010. /*    PopExp
  1011.     Holt einen Ausdruck vom Variablenstack
  1012. */
  1013.  
  1014. EXPDEF *
  1015. PopExp ()
  1016. {
  1017.   if (TopStack-- != BotStack)
  1018.     return (TopStack);
  1019.   else
  1020.     return (NULL);
  1021. }
  1022.  
  1023. /* ClearProg: den Speicherplatz, der durch das Programm
  1024. belegt ist, freigeben
  1025. */
  1026.  
  1027. void
  1028. ClearProg ()
  1029. {
  1030. PRGZEILE    *Memory;
  1031.  
  1032.     ActLine = FirstLine;        /* Zeiger auf erste Programmzeile */
  1033.     while (ActLine) {
  1034.       Memory = ActLine;            /* wird gleich benötigt */
  1035.       ActLine = ActLine->NextZeile;    /* das ist die nächste Zeile */
  1036.       free (Memory);            /* Speicherplatz freigeben */
  1037.     }
  1038.  
  1039.     FirstLine = ActLine = NULL;    /* Zeiger zurücksetzen */
  1040.  
  1041. }
  1042.  
  1043. /* TestComma : teste ob das zeichen im ScanBuffer ein "," ist */
  1044. int TestComma()
  1045. {
  1046.   if (( Steuer == SONDER ) && ( *ScanBuffer == ',' ))
  1047.     return ( TRUE );
  1048.   else{
  1049.     serror( ", erwartet" ); return ( FALSE );
  1050.   }
  1051. }
  1052.  
  1053. /* GetStringVar : lies den nächsten Bezeichner und liefere
  1054.                   die zugehörige Variable
  1055. */
  1056.  
  1057. int GetStringVar ( str )
  1058. VAR  **str;
  1059. {
  1060.   Scan();
  1061.   if( Steuer != ALPHA ){
  1062.     serror( "Bezeichner erwartet" );
  1063.     return( FALSE );
  1064.   }
  1065.   if (( *str = IsVariable( ScanBuffer )) == NULL ){
  1066.     fatal_error( "Variable existiert nicht" );
  1067.     return( FALSE );
  1068.   }
  1069.   return ( TRUE );
  1070. }
  1071.  
  1072. /* GetLong : lies und berechne den nächsten Ausdruck, und
  1073.               liefere seinen Wert als long-Grö₧e
  1074. */
  1075.  
  1076. int GetLong ( val )
  1077. long  *val;
  1078. {
  1079. VAR  Var;
  1080.  
  1081.   CalcExpression( &Var );
  1082.   if ( Var.VarType == FLONUM ){
  1083.     *val = (long)Var.VarWert.variable.Flotype;
  1084.     return ( TRUE );
  1085.   }
  1086.   else if ( Var.VarType == FIXNUM ){
  1087.     *val = (long)Var.VarWert.variable.integer;
  1088.     return ( TRUE );
  1089.   }
  1090.   else{
  1091.     serror( "ZAHL erwartet" ); return( FALSE );
  1092.   }
  1093. }
  1094.  
  1095. /* Ende des Files INTUTIL.C */
  1096.