home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / sun / volume1 / tooltool2.1c / part05 / expr.c next >
Encoding:
C/C++ Source or Header  |  1989-06-06  |  14.1 KB  |  459 lines

  1. /************************************************************************/
  2. /*    Copyright 1988 by Chuck Musciano and Harris Corporation        */
  3. /*                                    */
  4. /*    Permission to use, copy, modify, and distribute this software    */
  5. /*    and its documentation for any purpose and without fee is    */
  6. /*    hereby granted, provided that the above copyright notice    */
  7. /*    appear in all copies and that both that copyright notice and    */
  8. /*    this permission notice appear in supporting documentation, and    */
  9. /*    that the name of Chuck Musciano and Harris Corporation not be    */
  10. /*    used in advertising or publicity pertaining to distribution    */
  11. /*    of the software without specific, written prior permission.    */
  12. /*    Chuck Musciano and Harris Corporation make no representations    */
  13. /*    about the suitability of this software for any purpose.  It is    */
  14. /*    provided "as is" without express or implied warranty.        */
  15. /*                                    */
  16. /*    The sale of any product based wholely or in part upon the     */
  17. /*    technology provided by tooltool is strictly forbidden without    */
  18. /*    specific, prior written permission from Harris Corporation.    */
  19. /*    Tooltool technology includes, but is not limited to, the source    */
  20. /*    code, executable binary files, specification language, and    */
  21. /*    sample specification files.                    */
  22. /************************************************************************/
  23.  
  24. #include    <stdio.h>
  25. #include    <ctype.h>
  26. #include    <math.h>
  27.  
  28. #include    "tooltool.h"
  29.  
  30. /************************************************************************/
  31. PRIVATE    v_ptr    do_compare(op, l, r)
  32.  
  33. register    int    op;
  34. register    v_ptr    l;
  35. register    v_ptr    r;
  36.  
  37. {    register    char    *p, *q;
  38.  
  39.     if (is_number(l) && is_number(r))
  40.        switch (op) {
  41.           case E_EQUAL         : return(tt_int_result(l->number == r->number));
  42.           case E_GREATER       : return(tt_int_result(l->number > r->number));
  43.           case E_GREATER_EQUAL : return(tt_int_result(l->number >= r->number));
  44.           case E_LESS          : return(tt_int_result(l->number < r->number));
  45.           case E_LESS_EQUAL    : return(tt_int_result(l->number <= r->number));
  46.           case E_NOT_EQUAL     : return(tt_int_result(l->number != r->number));
  47.           }
  48.     else {
  49.        p = tt_string_of(l);
  50.        q = tt_string_of(r);
  51.        switch (op) {
  52.           case E_EQUAL         : return(tt_int_result(strcmp(p, q) == 0));
  53.           case E_GREATER       : return(tt_int_result(strcmp(p, q) > 0));
  54.           case E_GREATER_EQUAL : return(tt_int_result(strcmp(p, q) >= 0));
  55.           case E_LESS          : return(tt_int_result(strcmp(p, q) < 0));
  56.           case E_LESS_EQUAL    : return(tt_int_result(strcmp(p, q) <= 0));
  57.           case E_NOT_EQUAL     : return(tt_int_result(strcmp(p, q) != 0));
  58.           }
  59.        }
  60. }
  61.  
  62. /************************************************************************/
  63. PRIVATE    v_ptr    do_array_ref(a, i)
  64.  
  65. register    v_ptr    a;
  66. register    v_ptr    i;
  67.  
  68. {    register    v_ptr    v;
  69.     register    char    *s;
  70.     register    int    cmp;
  71.  
  72.     s = tt_string_of(i);
  73.     if (is_array(a)) {
  74.        for (v = a->value; v; )
  75.           if ((cmp = tt_dict_compare(s, v->index)) == 0)
  76.              break;
  77.           else if (cmp < 0)
  78.              v = v->left;
  79.           else
  80.              v = v->right;
  81.        if (v)
  82.           return(v);
  83.        }
  84.     else {
  85.        a->kind = V_ARRAY;
  86.        a->value = NULL;
  87.        }
  88.     v = (v_ptr) safe_malloc(sizeof(v_data));
  89.     v->kind = V_NOTHING;
  90.     v->number = 0.0;
  91.     v->str = "";
  92.     v->value = NULL;
  93.     v->left = NULL;
  94.     v->right = NULL;
  95.     tt_insert_array(&(a->value), strsave(s), v);
  96.     return(v);
  97. }
  98.  
  99. /************************************************************************/
  100. PRIVATE    v_ptr    dup_array(v)
  101.  
  102. register    v_ptr    v;
  103.  
  104. {    register    v_ptr    new;
  105.  
  106.     if (v == NULL)
  107.        return(NULL);
  108.     new = (v_ptr) safe_malloc(sizeof(v_data));
  109.     new->kind = v->kind;
  110.     new->number = v->number;
  111.     new->left = dup_array(v->left);
  112.     new->right = dup_array(v->right);
  113.     new->index = strsave(v->index);
  114.     if (is_array(new))
  115.        new->value = dup_array(v->value);
  116.     else
  117.        new->str = is_number(new)? NULL : strsave(v->str);
  118.     return(new);
  119. }
  120.  
  121. /************************************************************************/
  122. PRIVATE    char    *concatenate(v, separator)
  123.  
  124. register    v_ptr    v;
  125. char        separator;
  126.  
  127. {    register    char    *l, *m, *r, *p;
  128.     char    buf[2];
  129.  
  130.     if (v == NULL)
  131.        return("");
  132.     buf[0] = separator;
  133.     buf[1] = '\0';
  134.     l = concatenate(v->left, separator);
  135.     m = tt_string_of(v);
  136.     r = concatenate(v->right, separator);
  137.     p = tt_emalloc(strlen(l) + strlen(m) + strlen(r) + 3);
  138.     strcpy(p, l);
  139.     if (*m) {
  140.        if (*p)
  141.           strcat(p, buf);
  142.        strcat(p, m);
  143.        }
  144.     if (*r) {
  145.        if (*p)
  146.           strcat(p, buf);
  147.        strcat(p, r);
  148.        }
  149.     return(p);
  150. }
  151.  
  152. /************************************************************************/
  153. PRIVATE    free_array(v)
  154.  
  155. v_ptr    v;
  156.  
  157. {
  158.     if (v) {
  159.        if (is_array(v))
  160.           safe_free(v->value);
  161.        safe_free(v->index);
  162.        free_array(v->left);
  163.        free_array(v->right);
  164.        safe_free(v);
  165.        }
  166. }
  167.  
  168. /************************************************************************/
  169. PRIVATE    do_assign(l, r)
  170.  
  171. register    v_ptr    l;
  172. register    v_ptr    r;
  173.  
  174. {
  175.     if (is_array(l))
  176.        free_array(l->value);
  177.     l->kind = (r->kind & V_TYPES) | (l->kind & V_SPECIAL);
  178.     if (is_gadget(l))
  179.        switch (l->gadget->kind) {
  180.           case GADGET_CHOICE :
  181.           case GADGET_SLIDER : panel_set(l->gadget->panel_item, PANEL_VALUE, (int) r->number, 0);
  182.                          break;
  183.           case GADGET_TEXT   : panel_set(l->gadget->panel_item, PANEL_VALUE, tt_string_of(r), 0);
  184.                          break;
  185. /*          case GADGET_LABEL  : panel_set(l->gadget->panel_item, PANEL_LABEL_STRING, tt_string_of(r), 0);
  186.                          break;*/
  187.           default         : abend("cannot assign a value to a button or menu");
  188.           }
  189.     if (is_array(l))
  190.        l->value = dup_array(r->value);
  191.     else if (is_number(l))
  192.        l->number = r->number;
  193.     else {
  194.        l->str = strsave(r->str);
  195.        l->number = r->number;
  196.        }
  197.     if (is_interval(l))
  198.        tt_set_timer((int) l->number, ((int) (l->number * 1000000.0)) % 1000000);
  199. }
  200.  
  201. /************************************************************************/
  202. EXPORT    v_ptr    tt_int_result(i)
  203.  
  204. int    i;
  205.  
  206. {    char    buf[20];
  207.     register    v_ptr    v;
  208.  
  209.     v = (v_ptr) tt_emalloc(sizeof(v_data));
  210.     v->str = NULL;
  211.     v->kind = V_NUMBER;
  212.     v->number = i;
  213.     v->left = NULL;
  214.     v->right = NULL;
  215.     return(v);
  216. }
  217.  
  218. /************************************************************************/
  219. EXPORT    v_ptr    tt_double_result(r)
  220.  
  221. double    r;
  222.  
  223. {    char    buf[20];
  224.     register    v_ptr    v;
  225.  
  226.     v = (v_ptr) tt_emalloc(sizeof(v_data));
  227.     v->str = NULL;
  228.     v->kind = V_NUMBER;
  229.     v->number = r;
  230.     v->left = NULL;
  231.     v->right = NULL;
  232.     return(v);
  233. }
  234.  
  235. /************************************************************************/
  236. EXPORT    v_ptr    tt_string_result(s)
  237.  
  238. char    *s;
  239.  
  240. {    char    buf[20];
  241.     double    atof();
  242.     register    v_ptr    v;
  243.  
  244.     v = (v_ptr) tt_emalloc(sizeof(v_data));
  245.     if (tt_is_temp(s))
  246.        v->str = s;
  247.     else
  248.        v->str = estrsave(s);
  249.     v->kind = V_NOTHING;
  250.     v->number = tt_is_number(s)? atof(s) : 0.0;
  251.     v->left = NULL;
  252.     v->right = NULL;
  253.     return(v);
  254. }
  255.  
  256. /************************************************************************/
  257. EXPORT    char    *tt_string_of(v)
  258.  
  259. register    v_ptr    v;
  260.  
  261. {    register    char    *p;
  262.     char    buf[20], *delimiters;
  263.  
  264.     if (is_array(v)) {
  265.        if (is_array(tt_delimiters->value) || (delimiters = tt_string_of(tt_delimiters->value)) == NULL)
  266.           delimiters = " ";
  267.        return(concatenate(v->value, *delimiters));
  268.        }
  269.     else if (is_number(v)) {
  270.        sprintf(buf, "%1.12g", v->number);
  271.        return(estrsave(buf));
  272.        }
  273.     else
  274.        return(v->str);
  275. }
  276.  
  277. /************************************************************************/
  278. EXPORT    v_ptr    tt_insert_array(array, index, value)
  279.  
  280. register    v_ptr    *array;
  281. register    char    *index;
  282. register    v_ptr    value;
  283.  
  284. {    int    cmp;
  285.  
  286.     while (*array)
  287.        if ((cmp = tt_dict_compare(index, (*array)->index)) == 0)
  288.           abend("%s should not exist in array", index);
  289.        else if (cmp < 0)
  290.           array = &((*array)->left);
  291.        else
  292.           array = &((*array)->right);
  293.     *array = value;
  294.     value->index = index;
  295. }
  296.  
  297. /************************************************************************/
  298. EXPORT    e_ptr    tt_make_expr(op, arg1, arg2, arg3)
  299.  
  300. int    op;
  301. e_ptr    arg1, arg2, arg3;
  302.  
  303. {    e_ptr    e;
  304.  
  305.     e = (e_ptr) safe_malloc(sizeof(e_data));
  306.     switch (e->op = op) {
  307.        case E_QUESTION      : 
  308.                      e->extra = arg3;
  309.        case E_AND           :
  310.        case E_ARRAY_REF     :
  311.        case E_ASSIGN_AND    :
  312.        case E_ASSIGN_DIVIDE :
  313.        case E_ASSIGN_MINUS  :
  314.        case E_ASSIGN_MODULO :
  315.        case E_ASSIGN_OR     :
  316.        case E_ASSIGN_PLUS   :
  317.        case E_ASSIGN_TIMES  :
  318.        case E_ASSIGN_XOR    :
  319.        case E_ASSIGNMENT    :
  320.        case E_COMMA         :
  321.        case E_DIVIDE        :
  322.        case E_EQUAL         :
  323.        case E_GREATER       :
  324.        case E_GREATER_EQUAL :
  325.        case E_LEFT_SHIFT    :
  326.        case E_LESS          :
  327.        case E_LESS_EQUAL    :
  328.        case E_LOGICAL_AND   :
  329.        case E_LOGICAL_NOT   :
  330.        case E_LOGICAL_OR    :
  331.        case E_MINUS         :
  332.        case E_MODULO        :
  333.        case E_NOT_EQUAL     :
  334.        case E_OR            :
  335.        case E_PLUS          :
  336.        case E_RIGHT_SHIFT   :
  337.        case E_TIMES         :
  338.        case E_XOR           : 
  339.                      e->right = arg2;
  340.        case E_COMPLEMENT    :
  341.        case E_PAREN         :
  342.        case E_POSTDECREMENT :
  343.        case E_POSTINCREMENT :
  344.        case E_PREDECREMENT  :
  345.        case E_PREINCREMENT  :
  346.        case E_UMINUS        :
  347.                      e->left = arg1;
  348.                      break;
  349.        case E_FUNC_ID       : e->func = (f_ptr) arg1;
  350.                      e->left = arg2;
  351.                      break;
  352.        case E_STRING        : e->string = (char *) arg1;
  353.                      break;
  354.        case E_NUMBER    : e->value = *((double *) arg1);
  355.                      break;
  356.        case E_SYMBOL        : e->symbol = (s_ptr) arg1;
  357.                      break;
  358.        }
  359.     return(e);
  360. }
  361.  
  362. /************************************************************************/
  363. EXPORT    v_ptr    tt_eval(e)
  364.  
  365. register    e_ptr    e;
  366.  
  367. {    double    r;
  368.     int    i;
  369.     v_ptr    v, w;
  370.     char    *p, *q, *s;
  371.  
  372.     if (e == NULL)
  373.        return(NULL);
  374.     switch (e->op) {
  375.        case E_AND           : return(tt_int_result(((int) tt_eval(e->left)->number) & ((int) tt_eval(e->right)->number)));
  376.        case E_ARRAY_REF     : return(do_array_ref(tt_eval(e->left), tt_eval(e->right)));
  377.        case E_ASSIGN_AND    : v = tt_eval(e->left);
  378.                      do_assign(v, tt_int_result(((int) v->number) & ((int) tt_eval(e->right)->number)));
  379.                      return(v);
  380.        case E_ASSIGN_DIVIDE : v = tt_eval(e->left);
  381.                      if ((r = tt_eval(e->right)->number) == 0.0)
  382.                         abend("division by zero");
  383.                      else {
  384.                         do_assign(v, tt_double_result(v->number / r));
  385.                         return(v);
  386.                         }
  387.        case E_ASSIGN_MINUS  : v = tt_eval(e->left);
  388.                      do_assign(v, tt_double_result(v->number - tt_eval(e->right)->number));
  389.                      return(v);
  390.        case E_ASSIGN_MODULO : v = tt_eval(e->left);
  391.                      do_assign(v, tt_int_result(((int) v->number) % ((int) tt_eval(e->right)->number)));
  392.                      return(v);
  393.        case E_ASSIGN_OR     : v = tt_eval(e->left);
  394.                      do_assign(v, tt_int_result(((int) v->number) | ((int) tt_eval(e->right)->number)));
  395.                      return(v);
  396.        case E_ASSIGN_PLUS   : v = tt_eval(e->left);
  397.                      do_assign(v, tt_double_result(v->number + tt_eval(e->right)->number));
  398.                      return(v);
  399.        case E_ASSIGN_TIMES  : v = tt_eval(e->left);
  400.                      do_assign(v, tt_double_result(v->number * tt_eval(e->right)->number));
  401.                      return(v);
  402.        case E_ASSIGN_XOR    : v = tt_eval(e->left);
  403.                      do_assign(v, tt_int_result(((int) v->number) ^ ((int) tt_eval(e->right)->number)));
  404.                      return(v);
  405.        case E_ASSIGNMENT    : do_assign(tt_eval(e->left), v = tt_eval(e->right));
  406.                      return(v);
  407.        case E_COMMA         : p = tt_string_of(tt_eval(e->left));
  408.                      q = tt_string_of(tt_eval(e->right));
  409.                      s = tt_emalloc(strlen(p) + strlen(q) + 1);
  410.                      strcpy(s, p);
  411.                      strcat(s, q);
  412.                      return(tt_string_result(s));
  413.        case E_COMPLEMENT    : return(tt_int_result(~((int) tt_eval(e->left)->number)));
  414.        case E_DIVIDE        : if ((r = tt_eval(e->right)->number) == 0.0)
  415.                         abend("division by zero");
  416.                      else
  417.                         return(tt_double_result(tt_eval(e->left)->number / r));
  418.        case E_EQUAL         :
  419.        case E_GREATER       :
  420.        case E_GREATER_EQUAL :
  421.        case E_LESS          :
  422.        case E_LESS_EQUAL    :
  423.        case E_NOT_EQUAL     : return(do_compare(e->op, tt_eval(e->left), tt_eval(e->right)));
  424.        case E_FUNC_ID       : return(e->func(e->left));
  425.        case E_LEFT_SHIFT    : return(tt_int_result(((int) tt_eval(e->left)->number) << ((int) tt_eval(e->right)->number)));
  426.        case E_LOGICAL_AND   : return(tt_int_result(((int) tt_eval(e->left)->number) && ((int) tt_eval(e->right)->number)));
  427.        case E_LOGICAL_NOT   : return(tt_int_result(!((int) tt_eval(e->left)->number)));
  428.        case E_LOGICAL_OR    : return(tt_int_result(((int) tt_eval(e->left)->number) || ((int) tt_eval(e->right)->number)));
  429.        case E_MINUS         : return(tt_double_result(tt_eval(e->left)->number - tt_eval(e->right)->number));
  430.        case E_MODULO        : if ((i = ((int) tt_eval(e->right)->number)) == 0)
  431.                         abend("modulus by zero");
  432.                      else
  433.                         return(tt_int_result(((int) tt_eval(e->left)->number) % i));
  434.        case E_NUMBER    : return(tt_double_result(e->value));
  435.        case E_OR            : return(tt_int_result(((int) tt_eval(e->left)->number) | ((int) tt_eval(e->right)->number)));
  436.        case E_PAREN         : return(tt_eval(e->left));
  437.        case E_PLUS          : return(tt_double_result(tt_eval(e->left)->number + tt_eval(e->right)->number));
  438.        case E_POSTDECREMENT : v = tt_eval(e->left);
  439.                      do_assign(v, tt_double_result((r = v->number) - 1.0));
  440.                      return(tt_double_result(r));
  441.        case E_POSTINCREMENT : v = tt_eval(e->left);
  442.                      do_assign(v, tt_double_result((r = v->number) + 1.0));
  443.                      return(tt_double_result(r));
  444.        case E_PREDECREMENT  : v = tt_eval(e->left);
  445.                      do_assign(v, tt_double_result(v->number - 1.0));
  446.                      return(v);
  447.        case E_PREINCREMENT  : v = tt_eval(e->left);
  448.                      do_assign(v, tt_double_result(v->number + 1.0));
  449.                      return(v);
  450.        case E_QUESTION      : return(((int) tt_eval(e->left)->number)? tt_eval(e->right) : tt_eval(e->extra));
  451.        case E_RIGHT_SHIFT   : return(tt_int_result(((int) tt_eval(e->left)->number) >> ((int) tt_eval(e->right)->number)));
  452.        case E_STRING        : return(tt_string_result(e->string));
  453.        case E_SYMBOL        : return(tt_get_value(e->symbol));
  454.        case E_TIMES         : return(tt_double_result(tt_eval(e->left)->number * tt_eval(e->right)->number));
  455.        case E_UMINUS        : return(tt_double_result(-tt_eval(e->left)->number));
  456.        case E_XOR           : return(tt_int_result(((int) tt_eval(e->left)->number) ^ ((int) tt_eval(e->right)->number)));
  457.        }
  458. }
  459.