Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* operator.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* defintion of operators                                                    */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <math.h>
  13.  
  14. #include "stdinc.h"
  15. #include "errmsg.h"
  16. #include "asmdef.h"
  17. #include "asmerr.h"
  18. #include "asmpars.h"
  19. #include "asmrelocs.h"
  20. #include "operator.h"
  21.  
  22. #define PromoteLValFlags() \
  23.         do \
  24.         { \
  25.           if (pErg->Typ != TempNone) \
  26.           { \
  27.             pErg->Flags |= (pLVal->Flags & eSymbolFlags_Promotable); \
  28.             pErg->AddrSpaceMask |= pLVal->AddrSpaceMask; \
  29.             if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = pLVal->DataSize; \
  30.           } \
  31.         } \
  32.         while (0)
  33.  
  34. #define PromoteLRValFlags() \
  35.         do \
  36.         { \
  37.           if (pErg->Typ != TempNone) \
  38.           { \
  39.             pErg->Flags |= ((pLVal->Flags | pRVal->Flags) & eSymbolFlags_Promotable); \
  40.             pErg->AddrSpaceMask |= pLVal->AddrSpaceMask | pRVal->AddrSpaceMask; \
  41.             if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = pLVal->DataSize; \
  42.             if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = pRVal->DataSize; \
  43.           } \
  44.         } \
  45.         while (0)
  46.  
  47. /*!------------------------------------------------------------------------
  48.  * \fn     reg_cmp(const tRegDescr *p_reg1, tSymbolSize data_size1,
  49.                    const tRegDescr *p_reg2, tSymbolSize data_size2)
  50.  * \brief  compare two register symbols
  51.  * \param  p_reg1, p_reg2 registers to compare
  52.  * \return -1 : reg1 < reg2
  53.  *          0 : reg1 = reg2
  54.  *         +1 : reg1 > reg2
  55.  *         -2 : unequal, but no smaller/greater relation can be given
  56.  * ------------------------------------------------------------------------ */
  57.  
  58. static int reg_cmp(const TempResult *p_val1, const TempResult *p_val2)
  59. {
  60.   tRegInt num1, num2;
  61.  
  62.   /* If the two symbols are for different target architectures,
  63.      they are for sure unequal, but no ordering critera can be given: */
  64.  
  65.   if ((p_val1->Contents.RegDescr.Dissect != p_val2->Contents.RegDescr.Dissect)
  66.    || (p_val1->Contents.RegDescr.compare != p_val2->Contents.RegDescr.compare))
  67.     return -2;
  68.  
  69.   /* architecture-specific comparison function? */
  70.  
  71.   if (p_val1->Contents.RegDescr.compare)
  72.     return p_val1->Contents.RegDescr.compare(p_val1->Contents.RegDescr.Reg, p_val1->DataSize,
  73.                                              p_val2->Contents.RegDescr.Reg, p_val2->DataSize);
  74.  
  75.   /* The generic comparison: If operand sizes differ, they are 'just unequal',
  76.      otherwise compare register numbers: */
  77.  
  78.   if (p_val1->DataSize != p_val2->DataSize)
  79.     return -2;
  80.   num1 = p_val1->Contents.RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
  81.   num2 = p_val2->Contents.RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
  82.   if (num1 < num2)
  83.     return -1;
  84.   else if (num1 > num2)
  85.     return 1;
  86.   else
  87.     return 0;
  88. }
  89.  
  90. static void DummyOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  91. {
  92.   UNUSED(pLVal);
  93.   UNUSED(pRVal);
  94.   UNUSED(pErg);
  95. }
  96.  
  97. static void OneComplOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  98. {
  99.   UNUSED(pLVal);
  100.   as_tempres_set_int(pErg, ~(pRVal->Contents.Int));
  101.   PromoteLValFlags();
  102. }
  103.  
  104. static void ShLeftOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  105. {
  106.   as_tempres_set_int(pErg, pLVal->Contents.Int << pRVal->Contents.Int);
  107.   PromoteLRValFlags();
  108. }
  109.  
  110. static void ShRightOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  111. {
  112.   as_tempres_set_int(pErg, pLVal->Contents.Int >> pRVal->Contents.Int);
  113.   PromoteLRValFlags();
  114. }
  115.  
  116. static void BitMirrorOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  117. {
  118.   int z;
  119.  
  120.   if ((pRVal->Contents.Int < 1) || (pRVal->Contents.Int > 32)) WrError(ErrNum_OverRange);
  121.   else
  122.   {
  123.     LargeInt Result = (pLVal->Contents.Int >> pRVal->Contents.Int) << pRVal->Contents.Int;
  124.  
  125.     for (z = 0; z < pRVal->Contents.Int; z++)
  126.     {
  127.       if ((pLVal->Contents.Int & (1 << (pRVal->Contents.Int - 1 - z))) != 0)
  128.         Result |= (1 << z);
  129.     }
  130.     as_tempres_set_int(pErg, Result);
  131.   }
  132.   PromoteLRValFlags();
  133. }
  134.  
  135. static void BinAndOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  136. {
  137.   as_tempres_set_int(pErg, pLVal->Contents.Int & pRVal->Contents.Int);
  138.   PromoteLRValFlags();
  139. }
  140.  
  141. static void BinOrOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  142. {
  143.   as_tempres_set_int(pErg, pLVal->Contents.Int | pRVal->Contents.Int);
  144.   PromoteLRValFlags();
  145. }
  146.  
  147. static void BinXorOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  148. {
  149.   as_tempres_set_int(pErg, pLVal->Contents.Int ^ pRVal->Contents.Int);
  150.   PromoteLRValFlags();
  151. }
  152.  
  153. static void PotOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  154. {
  155.   LargeInt HVal;
  156.  
  157.   switch (pLVal->Typ)
  158.   {
  159.     case TempInt:
  160.       if (pRVal->Contents.Int < 0) as_tempres_set_int(pErg, 0);
  161.       else
  162.       {
  163.         LargeInt l = pLVal->Contents.Int, r = pRVal->Contents.Int;
  164.  
  165.         HVal = 1;
  166.         while (r > 0)
  167.         {
  168.           if (r & 1)
  169.             HVal *= l;
  170.           r >>= 1;
  171.           if (r)
  172.             l *= l;
  173.         }
  174.         as_tempres_set_int(pErg, HVal);
  175.       }
  176.       break;
  177.     case TempFloat:
  178.       if (pRVal->Contents.Float == 0.0)
  179.         as_tempres_set_float(pErg, 1.0);
  180.       else if (pLVal->Contents.Float == 0.0)
  181.         as_tempres_set_float(pErg, 0.0);
  182.       else if (pLVal->Contents.Float > 0)
  183.         as_tempres_set_float(pErg, pow(pLVal->Contents.Float, pRVal->Contents.Float));
  184.       else if ((fabs(pRVal->Contents.Float) <= ((double)MaxLongInt)) && (floor(pRVal->Contents.Float) == pRVal->Contents.Float))
  185.       {
  186.         Double Base = pLVal->Contents.Float, Result;
  187.  
  188.         HVal = (LongInt) floor(pRVal->Contents.Float + 0.5);
  189.         if (HVal < 0)
  190.         {
  191.           Base = 1 / Base;
  192.           HVal = -HVal;
  193.         }
  194.         Result = 1.0;
  195.         while (HVal > 0)
  196.         {
  197.           if (HVal & 1)
  198.             Result *= Base;
  199.           Base *= Base;
  200.           HVal >>= 1;
  201.         }
  202.         as_tempres_set_float(pErg, Result);
  203.       }
  204.       else
  205.       {
  206.         WrError(ErrNum_InvArgPair);
  207.         pErg->Typ = TempNone;
  208.       }
  209.       break;
  210.     default:
  211.       break;
  212.   }
  213.   PromoteLRValFlags();
  214. }
  215.  
  216. static void MultOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  217. {
  218.   switch (pLVal->Typ)
  219.   {
  220.     case TempInt:
  221.       as_tempres_set_int(pErg, pLVal->Contents.Int * pRVal->Contents.Int);
  222.       break;
  223.     case TempFloat:
  224.       as_tempres_set_float(pErg, pLVal->Contents.Float * pRVal->Contents.Float);
  225.       break;
  226.     default:
  227.       break;
  228.   }
  229.   PromoteLRValFlags();
  230. }
  231.  
  232. static void DivOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  233. {
  234.   switch (pLVal->Typ)
  235.   {
  236.     case TempInt:
  237.       if (pRVal->Contents.Int == 0) WrError(ErrNum_DivByZero);
  238.       else
  239.         as_tempres_set_int(pErg, pLVal->Contents.Int / pRVal->Contents.Int);
  240.       break;
  241.     case TempFloat:
  242.       if (pRVal->Contents.Float == 0.0) WrError(ErrNum_DivByZero);
  243.       else
  244.         as_tempres_set_float(pErg, pLVal->Contents.Float / pRVal->Contents.Float);
  245.     default:
  246.       break;
  247.   }
  248.   PromoteLRValFlags();
  249. }
  250.  
  251. static void ModOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  252. {
  253.   if (pRVal->Contents.Int == 0) WrError(ErrNum_DivByZero);
  254.   else
  255.     as_tempres_set_int(pErg, pLVal->Contents.Int % pRVal->Contents.Int);
  256.   PromoteLRValFlags();
  257. }
  258.  
  259. /* TODO: handle return code of NonZString2Int() better */
  260.  
  261. static void AddOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  262. {
  263.   as_tempres_set_none(pErg);
  264.   switch (pLVal->Typ)
  265.   {
  266.     case TempInt:
  267.       switch (pRVal->Typ)
  268.       {
  269.         case TempInt:
  270.           as_tempres_set_int(pErg, pLVal->Contents.Int + pRVal->Contents.Int);
  271.           pErg->Relocs = MergeRelocs(&(pLVal->Relocs), &(pRVal->Relocs), TRUE);
  272.           break;
  273.         case TempString:
  274.         {
  275.           LargeInt RIntVal;
  276.           tErrorNum error_num = NonZString2Int(&pRVal->Contents.str, &RIntVal);
  277.  
  278.           if (ErrNum_None == error_num)
  279.           {
  280.             as_tempres_set_c_str(pErg, "");
  281.             Int2NonZString(&pErg->Contents.str, RIntVal + pLVal->Contents.Int);
  282.           }
  283.           else
  284.             WrError(error_num);
  285.           break;
  286.         }
  287.         default:
  288.           break;
  289.       }
  290.       break;
  291.     case TempFloat:
  292.       if (TempFloat == pRVal->Typ)
  293.         as_tempres_set_float(pErg, pLVal->Contents.Float + pRVal->Contents.Float);
  294.       break;
  295.     case TempString:
  296.     {
  297.       switch (pRVal->Typ)
  298.       {
  299.         case TempString:
  300.           as_tempres_set_str(pErg, &pLVal->Contents.str);
  301.           as_nonz_dynstr_append(&pErg->Contents.str, &pRVal->Contents.str);
  302.           break;
  303.         case TempInt:
  304.         {
  305.           LargeInt LIntVal;
  306.           tErrorNum error_num = NonZString2Int(&pLVal->Contents.str, &LIntVal);
  307.  
  308.           if (ErrNum_None == error_num)
  309.           {
  310.             as_tempres_set_c_str(pErg, "");
  311.             Int2NonZString(&pErg->Contents.str, LIntVal + pRVal->Contents.Int);
  312.           }
  313.           else
  314.             WrError(error_num);
  315.           break;
  316.         }
  317.         default:
  318.           break;
  319.       }
  320.       break;
  321.     }
  322.     default:
  323.       break;
  324.   }
  325.   PromoteLRValFlags();
  326. }
  327.  
  328. static void SubOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  329. {
  330.   switch (pLVal->Typ)
  331.   {
  332.     case TempInt:
  333.       as_tempres_set_int(pErg, pLVal->Contents.Int - pRVal->Contents.Int);
  334.       break;
  335.     case TempFloat:
  336.       as_tempres_set_float(pErg, pLVal->Contents.Float - pRVal->Contents.Float);
  337.       break;
  338.     default:
  339.       break;
  340.   }
  341.   PromoteLRValFlags();
  342. }
  343.  
  344. static void LogNotOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  345. {
  346.   UNUSED(pLVal);
  347.   as_tempres_set_int(pErg, pRVal->Contents.Int ? 0 : 1);
  348.   PromoteLValFlags();
  349. }
  350.  
  351. static void LogAndOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  352. {
  353.   as_tempres_set_int(pErg, (pLVal->Contents.Int && pRVal->Contents.Int) ? 1 : 0);
  354.   PromoteLRValFlags();
  355. }
  356.  
  357. static void LogOrOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  358. {
  359.   as_tempres_set_int(pErg, (pLVal->Contents.Int || pRVal->Contents.Int) ? 1 : 0);
  360.   PromoteLRValFlags();
  361. }
  362.  
  363. static void LogXorOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  364. {
  365.   as_tempres_set_int(pErg, ((pLVal->Contents.Int != 0) != (pRVal->Contents.Int != 0)) ? 1 : 0);
  366.   PromoteLRValFlags();
  367. }
  368.  
  369. static void EqOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  370. {
  371.   switch (pLVal->Typ)
  372.   {
  373.     case TempInt:
  374.       as_tempres_set_int(pErg, (pLVal->Contents.Int == pRVal->Contents.Int) ? 1 : 0);
  375.       break;
  376.     case TempFloat:
  377.       as_tempres_set_int(pErg, (pLVal->Contents.Float == pRVal->Contents.Float) ? 1 : 0);
  378.       break;
  379.     case TempString:
  380.       as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) == 0) ? 1 : 0);
  381.       break;
  382.     case TempReg:
  383.       as_tempres_set_int(pErg, 0 == reg_cmp(pLVal, pRVal));
  384.       break;
  385.     default:
  386.       break;
  387.   }
  388.   PromoteLRValFlags();
  389. }
  390.  
  391. static void GtOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  392. {
  393.   switch (pLVal->Typ)
  394.   {
  395.     case TempInt:
  396.       as_tempres_set_int(pErg, (pLVal->Contents.Int > pRVal->Contents.Int) ? 1 : 0);
  397.       break;
  398.     case TempFloat:
  399.       as_tempres_set_int(pErg, (pLVal->Contents.Float > pRVal->Contents.Float) ? 1 : 0);
  400.       break;
  401.     case TempString:
  402.       as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) > 0) ? 1 : 0);
  403.       break;
  404.     case TempReg:
  405.       as_tempres_set_int(pErg, reg_cmp(pLVal, pRVal) == 1);
  406.       break;
  407.     default:
  408.       break;
  409.   }
  410.   PromoteLRValFlags();
  411. }
  412.  
  413. static void LtOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  414. {
  415.   switch (pLVal->Typ)
  416.   {
  417.     case TempInt:
  418.       as_tempres_set_int(pErg, (pLVal->Contents.Int < pRVal->Contents.Int) ? 1 : 0);
  419.       break;
  420.     case TempFloat:
  421.       as_tempres_set_int(pErg, (pLVal->Contents.Float < pRVal->Contents.Float) ? 1 : 0);
  422.       break;
  423.     case TempString:
  424.       as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) < 0) ? 1 : 0);
  425.       break;
  426.     case TempReg:
  427.       as_tempres_set_int(pErg, reg_cmp(pLVal, pRVal) == -1);
  428.       break;
  429.     default:
  430.       break;
  431.   }
  432.   PromoteLRValFlags();
  433. }
  434.  
  435. static void LeOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  436. {
  437.   switch (pLVal->Typ)
  438.   {
  439.     case TempInt:
  440.       as_tempres_set_int(pErg, (pLVal->Contents.Int <= pRVal->Contents.Int) ? 1 : 0);
  441.       break;
  442.     case TempFloat:
  443.       as_tempres_set_int(pErg, (pLVal->Contents.Float <= pRVal->Contents.Float) ? 1 : 0);
  444.       break;
  445.     case TempString:
  446.       as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) <= 0) ? 1 : 0);
  447.       break;
  448.     case TempReg:
  449.     {
  450.       int cmp_res = reg_cmp(pLVal, pRVal);
  451.       as_tempres_set_int(pErg, (cmp_res == -1) || (cmp_res == 0));
  452.       break;
  453.     }
  454.     default:
  455.       break;
  456.   }
  457.   PromoteLRValFlags();
  458. }
  459.  
  460. static void GeOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  461. {
  462.   switch (pLVal->Typ)
  463.   {
  464.     case TempInt:
  465.       as_tempres_set_int(pErg, (pLVal->Contents.Int >= pRVal->Contents.Int) ? 1 : 0);
  466.       break;
  467.     case TempFloat:
  468.       as_tempres_set_int(pErg, (pLVal->Contents.Float >= pRVal->Contents.Float) ? 1 : 0);
  469.       break;
  470.     case TempString:
  471.       as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) >= 0) ? 1 : 0);
  472.       break;
  473.     case TempReg:
  474.     {
  475.       int cmp_res = reg_cmp(pLVal, pRVal);
  476.       as_tempres_set_int(pErg, (cmp_res == 1) || (cmp_res == 0));
  477.       break;
  478.     }
  479.     default:
  480.       break;
  481.   }
  482.   PromoteLRValFlags();
  483. }
  484.  
  485. static void UneqOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
  486. {
  487.   switch (pLVal->Typ)
  488.   {
  489.     case TempInt:
  490.       as_tempres_set_int(pErg, (pLVal->Contents.Int != pRVal->Contents.Int) ? 1 : 0);
  491.       break;
  492.     case TempFloat:
  493.       as_tempres_set_int(pErg, (pLVal->Contents.Float != pRVal->Contents.Float) ? 1 : 0);
  494.       break;
  495.     case TempString:
  496.       as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) != 0) ? 1 : 0);
  497.       break;
  498.     case TempReg:
  499.       as_tempres_set_int(pErg, reg_cmp(pLVal, pRVal) != 0);
  500.       break;
  501.     default:
  502.       break;
  503.   }
  504.   PromoteLRValFlags();
  505. }
  506.  
  507. #define Int2Int       (TempInt    | (TempInt << 4)   )
  508. #define Float2Float   (TempFloat  | (TempFloat << 4) )
  509. #define String2String (TempString | (TempString << 4))
  510. #define Reg2Reg       (TempReg    | (TempReg << 4)   )
  511. #define Int2String    (TempInt    | (TempString << 4))
  512. #define String2Int    (TempString | (TempInt << 4)   )
  513.  
  514. const Operator Operators[] =
  515. {
  516.   {" " , 1 , False,  0, { 0, 0, 0, 0, 0 }, DummyOp},
  517.   {"~" , 1 , False,  1, { TempInt << 4, 0, 0, 0, 0 }, OneComplOp},
  518.   {"<<", 2 , True ,  3, { Int2Int, 0, 0, 0, 0 }, ShLeftOp},
  519.   {">>", 2 , True ,  3, { Int2Int, 0, 0, 0, 0 }, ShRightOp},
  520.   {"><", 2 , True ,  4, { Int2Int, 0, 0, 0, 0 }, BitMirrorOp},
  521.   {"&" , 1 , True ,  5, { Int2Int, 0, 0, 0, 0 }, BinAndOp},
  522.   {"|" , 1 , True ,  6, { Int2Int, 0, 0, 0, 0 }, BinOrOp},
  523.   {"!" , 1 , True ,  7, { Int2Int, 0, 0, 0, 0 }, BinXorOp},
  524.   {"^" , 1 , True ,  8, { Int2Int, Float2Float, 0, 0, 0 }, PotOp},
  525.   {"*" , 1 , True , 11, { Int2Int, Float2Float, 0, 0, 0 }, MultOp},
  526.   {"/" , 1 , True , 11, { Int2Int, Float2Float, 0, 0, 0 }, DivOp},
  527.   {"#" , 1 , True , 11, { Int2Int, 0, 0, 0, 0 }, ModOp},
  528.   {"+" , 1 , True , 13, { Int2Int, Float2Float, String2String, Int2String, String2Int }, AddOp},
  529.   {"-" , 1 , True , 13, { Int2Int, Float2Float, 0, 0, 0 }, SubOp},
  530.   {"~~", 2 , False,  2, { TempInt << 4, 0, 0, 0, 0 }, LogNotOp},
  531.   {"&&", 2 , True , 15, { Int2Int, 0, 0, 0, 0 }, LogAndOp},
  532.   {"||", 2 , True , 16, { Int2Int, 0, 0, 0, 0 }, LogOrOp},
  533.   {"!!", 2 , True , 17, { Int2Int, 0, 0, 0, 0 }, LogXorOp},
  534.   {"=" , 1 , True , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, EqOp},
  535.   {"==", 2 , True , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, EqOp},
  536.   {">" , 1 , True , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, GtOp},
  537.   {"<" , 1 , True , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, LtOp},
  538.   {"<=", 2 , True , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, LeOp},
  539.   {">=", 2 , True , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, GeOp},
  540.   {"<>", 2 , True , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, UneqOp},
  541.   {"!=", 2 , True , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, UneqOp},
  542.   /* termination marker */
  543.   {NULL, 0 , False,  0, { 0, 0, 0, 0, 0 }, NULL}
  544. },
  545. /* minus may have one or two operands */
  546. MinusMonadicOperator =
  547. {
  548.   "-" ,1 , False, 13, { TempInt << 4, TempFloat << 4, 0, 0, 0 }, SubOp
  549. };
  550.  
  551. const Operator *pPotMonadicOperator = NULL;
  552.