home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1991 / 04 / txl / 2_preis / source / intutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-21  |  28.1 KB  |  1,123 lines

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