home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / keybind / parsecond.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  11.5 KB  |  380 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7.  
  8. #define PARSECOND_C
  9. #define I_SET_C
  10.  
  11. #include "keybind.h"
  12. #include <lib/ori_add_lib.h>
  13. /*}}}  */
  14.  
  15. /*{{{  parse_cond*/
  16. /*{{{  l_parse_cond*/
  17. private TOKEN* l_parse_cond(TOKEN *buff,tokens to,boolean allow_comma,int dummy_base,boolean *ret_used)
  18. {
  19.   for (;;)
  20.    { check_length(buff);
  21.      switch(to) {
  22.        /*{{{  comma*/
  23.        case COMMA:
  24.         { if (allow_comma)
  25.            /*{{{  ignore it*/
  26.            { to=get_full_token();
  27.              continue;
  28.            }
  29.            /*}}}  */
  30.           else
  31.            /*{{{  error*/
  32.              m_exit(M_NOTEST);
  33.            /*}}}  */
  34.         }
  35.        /*}}}  */
  36.        /*{{{  single tests*/
  37.        case EDITING:         *buff++ = M_EDITING;            break;
  38.        case TEST_GEN_FOLD:   *buff++ = M_TEST_FOLD;          break;
  39.        case TEST_FILED:      *buff++ = M_FILED_FOLD;         break;
  40.        case TEST_FOLD_LINE:  *buff++ = M_CLOSED_FOLD;        break;
  41.        case TEST_BEGIN_FOLD: *buff++ = M_BEGIN_FOLD_COMMENT; break;
  42.        case TEST_END_FOLD:   *buff++ = M_END_FOLD_COMMENT;   break;
  43.        case TEST_TEXT:       *buff++ = M_TEXTLINE;           break;
  44.        case TEST_TOP:        *buff++ = M_TOP_OF_FOLD;        break;
  45.        case TEST_BOTTOM:     *buff++ = M_BOT_OF_FOLD;        break;
  46.        case TEST_BEGIN_LINE: *buff++ = M_BEGIN_OF_LINE;      break;
  47.        case TEST_END_LINE:   *buff++ = M_END_OF_LINE;        break;
  48.        case TEST_CHANGED:    *buff++ = M_CHANGED;            break;
  49.        case TEST_OVER:       *buff++ = M_TEST_OVER;          break;
  50.        case TEST_HASH:       *buff++ = M_TEST_HASH;          break;
  51.        case TEST_VERBOSE:    *buff++ = M_TEST_VERBOSE;       break;
  52.        case TEST_VIEW:       *buff++ = M_TEST_VIEW;          break;
  53.        case TEST_AUTO:       *buff++ = M_TEST_AUTO;          break;
  54.        case TEST_ECHO:       *buff++ = M_TEST_ECHO;          break;
  55.        /*}}}  */
  56.        /*{{{  test-str*/
  57.        case TEST_STR:
  58.           *buff++ = M_TEST_STR;
  59.           if (!(buff=get_message(buff)))
  60.              m_exit(M_NOPROMPT);
  61.           *buff++ = M_END_MACRO;
  62.           break;
  63.        /*}}}  */
  64.        /*{{{  test with one counter/term argument*/
  65.        case TEST_CHAR_LOW_C:
  66.        case TEST_CHAR_HIGH_C:
  67.        case TEST_CHAR_C:
  68.         { tokens token;
  69.           boolean d=False;
  70. #         define dummy_off (def_dummy_vars/2)
  71.  
  72.           token=name_to_var(get_full_token(),0,new_vars_enabled);
  73.           if (token!=VARIABLE || tk_var->size!=1)
  74.            { if (!(buff=parse_term(token,buff,dummy_var(dummy_base+dummy_off),dummy_base+dummy_off+1,ret_used))) return(0);
  75.              d=True;
  76.            }
  77.           *buff++ =
  78.                     (to==TEST_CHAR_C)         ? M_TEST_CC :
  79.                     (to==TEST_CHAR_HIGH_C)    ? M_TEST_H_CC :
  80.                                                 M_TEST_L_CC;
  81.           *buff++=(TOKEN)(d?dummy_var(dummy_base+dummy_off):tk_var->no);
  82.           break;
  83.         }
  84.        /*}}}  */
  85.        /*{{{  test with names*/
  86.        case TEST_TERM:
  87.           switch (get_full_token())
  88.            { case MACRO:
  89.              case NAME:
  90.               /*{{{  test a single terminal*/
  91.               { unsigned char *s;
  92.  
  93.                 *buff++=M_ENV_CMD;
  94.                 *buff++=(TOKEN)0;
  95.                 for (s=tk_string;*s;)
  96.                    *buff++=(TOKEN)*s++;
  97.                 *buff++=M_END_MACRO;
  98.                 break;
  99.               }
  100.               /*}}}  */
  101.              case BEGIN:
  102.               /*{{{  test a list of terminals*/
  103.               { unsigned char *s;
  104.                 TOKEN *first_ad;
  105.  
  106.                 for (first_ad=0;;)
  107.                  { switch (get_full_token())
  108.                     { case MACRO:
  109.                       case NAME:
  110.                          *buff++=M_ENV_CMD;
  111.                          *buff++=(TOKEN)0;
  112.                          for (s=tk_string;*s;)
  113.                             *buff++=(TOKEN)*s++;
  114.                          *buff++=M_END_MACRO;
  115.                          if (!first_ad)
  116.                             first_ad=buff;
  117.                          buff=generate_jmp(M_JMP_TRUE,buff,first_ad);
  118.                          continue;
  119.                       case END:
  120.                          if (!first_ad)
  121.                           /*{{{  set flag to False*/
  122.                           { buff=generate_jmp(M_JMP_FALSE,first_ad=buff,buff);
  123.                             *buff++=M_NOT;
  124.                             generate_jmp(M_JMP_FALSE,first_ad,buff);
  125.                           }
  126.                           /*}}}  */
  127.                          else
  128.                           /*{{{  backpatch first jump*/
  129.                             generate_jmp(M_JMP_TRUE,first_ad,buff);
  130.                           /*}}}  */
  131.                          break;
  132.                       default:
  133.                          goto t_t_err;
  134.                     }
  135.                    break;
  136.                  }
  137.                 break;
  138.               }
  139.               /*}}}  */
  140.              default:
  141.              t_t_err:
  142.                 m_exit(M_T_NAME);
  143.            }
  144.           break;
  145.        /*}}}  */
  146.        /*{{{  relops*/
  147.        case REL_EQ:
  148.        case REL_LOW:
  149.        case REL_LOW_EQ:
  150.        case REL_HIGH:
  151.        case REL_HIGH_EQ:
  152.        case REL_NEQ:
  153.         { int arg1,arg2;
  154.           tokens arg_token;
  155.           TOKEN *jmp_end=0;
  156.  
  157.           begin_parse();
  158.           /*{{{  get first argument*/
  159.           arg1=dummy_var(dummy_base++);
  160.           if (!(buff=parse_term(get_full_token(),buff,arg1,dummy_base,ret_used))) return(0);
  161.           /*}}}  */
  162.           arg_token=name_to_var(get_full_token(),0,new_vars_enabled);
  163.           do
  164.            { *buff++=M_INV_COUNTER;
  165.              *buff++=(TOKEN)arg1;
  166.              /*{{{  get second argument*/
  167.              if (arg_token==VARIABLE && tk_var->size==1)
  168.                 arg2=tk_var->no;
  169.              else
  170.               { arg2=dummy_var(dummy_base);
  171.                 if (!(buff=parse_term(arg_token,buff,arg2,dummy_base+1,ret_used))) return(0);
  172.               }
  173.              /*}}}  */
  174.              arg_token=name_to_var(get_full_token(),0,new_vars_enabled);
  175.              if (arg_token!=END)
  176.               /*{{{  save arg2*/
  177.               { *buff++=M_PUSH_INT;
  178.                 *buff++=(TOKEN)arg2;
  179.                 *buff++=M_POP_INT;
  180.                 *buff++=(TOKEN)(arg2=rel_op_var);
  181.               }
  182.               /*}}}  */
  183.              /*{{{  arg1=arg2-arg1*/
  184.              *buff++=M_SUM_COUNTER;
  185.              *buff++=(TOKEN)arg1;
  186.              *buff++=(TOKEN)arg2;
  187.              /*}}}  */
  188.              /*{{{  test for rel*/
  189.              switch (to)
  190.               { case REL_EQ:
  191.                 case REL_NEQ:
  192.                    *buff++=M_NULL_COUNTER;
  193.                    *buff++=(TOKEN)arg1;
  194.                    break;
  195.                 case REL_LOW_EQ:
  196.                 case REL_HIGH:
  197.                    *buff++=M_INV_COUNTER;
  198.                    *buff++=(TOKEN)arg1;
  199.                 default:
  200.                    *buff++=M_POSITIV_COUNTER;
  201.                    *buff++=(TOKEN)arg1;
  202.               }
  203.              switch(to)
  204.               { case REL_NEQ:
  205.                 case REL_LOW_EQ:
  206.                 case REL_HIGH_EQ:
  207.                    *buff++=M_NOT;
  208.                 case REL_LOW:
  209.                 case REL_HIGH:
  210.                 case REL_EQ:
  211.                 default:
  212.                    break;
  213.               }
  214.              /*}}}  */
  215.              if (arg_token!=END)
  216.               /*{{{  generate jmp and get arg1 back*/
  217.               { if (!jmp_end) jmp_end=buff;
  218.                 buff=generate_jmp(M_JMP_FALSE,buff,jmp_end);
  219.                 *buff++=M_PUSH_INT;
  220.                 *buff++=(TOKEN)arg2;
  221.                 *buff++=M_POP_INT;
  222.                 *buff++=(TOKEN)arg1;
  223.               }
  224.               /*}}}  */
  225.            }
  226.           while (arg_token!=END);
  227.           if (jmp_end)
  228.              generate_jmp(M_JMP_FALSE,jmp_end,buff);
  229.           break;
  230.         }
  231.        /*}}}  */
  232.        /*{{{  testset*/
  233.        case TEST_CHAR_SET:
  234.          *buff++ = M_TEST_CHAR_SET;
  235.          *buff++ =(TOKEN)get_set();
  236.          break;
  237.        /*}}}  */
  238.        /*{{{  testlanguage*/
  239.        case TEST_LANG:
  240.         { *buff++ = M_LANGUAGE;
  241.           if ((to=get_full_token())!=MACRO || ustrlen(tk_string)!=1)
  242.              m_exit(M_NOTEST);
  243.           /*{{{  check valid lg-tag*/
  244.           { char **s;
  245.  
  246.             tk_string[0]=toupper(tk_string[0]);
  247.             for (s=f_c_name;;)
  248.                if (**s==(char)tk_string[0])
  249.                   break;
  250.                else if (**s)
  251.                   s++;
  252.                else
  253.                   m_exit(M_NOTEST);
  254.           }
  255.           /*}}}  */
  256.           *buff++=(TOKEN)tk_string[0];
  257.           break;
  258.         }
  259.        /*}}}  */
  260.        /*{{{  not condition*/
  261.        case NOT:
  262.          begin_parse();
  263.          if (!(buff=l_parse_cond(buff,get_full_token(),False,dummy_base,ret_used)))
  264.             return(0);
  265.          *buff++ = M_NOT;
  266.          end_parse(M_WANTEND);
  267.          break;
  268.        /*}}}  */
  269.        /*{{{  and/or (c[,c...])*/
  270.        case AND:
  271.        case OR: {
  272.          TOKEN jmp= to==AND ? M_JMP_FALSE : M_JMP_TRUE;
  273.          TOKEN *bp;
  274.  
  275.          begin_parse();
  276.          if (!(buff=l_parse_cond(buff,get_full_token(),True,dummy_base,ret_used)))
  277.             return(0);
  278.          bp=buff;
  279.          /*{{{  scan all and-arguments up to )*/
  280.          while ((to=get_full_token())!=END) {
  281.            buff=generate_jmp(jmp,buff,bp);
  282.            if (!(buff=l_parse_cond(buff,to,True,dummy_base,ret_used)))
  283.               return(0);
  284.          }
  285.          /*}}}  */
  286.          if (to!=END)
  287.             m_exit(M_WANTEND);
  288.          /*{{{  backpatch the jumps*/
  289.          generate_jmp(jmp,bp,buff);
  290.          /*}}}  */
  291.          break;
  292.        }
  293.        /*}}}  */
  294.        /*{{{  pre*/
  295.        case PRE: {
  296.          /*{{{  push dummy vars*/
  297.          { int i;
  298.  
  299.            for (i=0;i<dummy_base;i++)
  300.             { *buff++=M_PUSH_INT;
  301.               *buff++=(TOKEN)dummy_var(i);
  302.             }
  303.          }
  304.          /*}}}  */
  305.          if (!(buff=parse_macro(buff,0,ret_used))) return(0);
  306.          /*{{{  pop dummy vars*/
  307.          { int i;
  308.  
  309.            for (i=dummy_base-1;i>=0;i--)
  310.             { *buff++=M_POP_INT;
  311.               *buff++=(TOKEN)dummy_var(i);
  312.             }
  313.          }
  314.          /*}}}  */
  315.          if (!(buff=l_parse_cond(buff,get_full_token(),False,dummy_base,ret_used)))
  316.             return(0);
  317.          break;
  318.        }
  319.        /*}}}  */
  320.        case ERROR: return(0);
  321.        /*{{{  lastmessage*/
  322.        case LASTMES:
  323.         { *buff++ = M_LASTMES;
  324.           if (get_full_token()==NAME)
  325.            /*{{{  look for msg*/
  326.            { int msg_no;
  327.  
  328.              if ((msg_no=name2msg(tk_string))>=0)
  329.               { *buff++=msg_no;
  330.                 break;
  331.               }
  332.            }
  333.            /*}}}  */
  334.           m_exit(M_NOTEST);
  335.         }
  336.        /*}}}  */
  337.        /*{{{  variable: compile it like ``not(counter-0 variable)''*/
  338.        case VARIABLE:
  339.          if (tk_var->size==1)
  340.           { *buff++ = M_NULL_COUNTER;
  341.             *buff++ = (TOKEN) tk_var->no;
  342.             *buff++ = M_NOT;
  343.             break;
  344.           }
  345.          else
  346.             goto term_as_boolean;
  347.        /*}}}  */
  348.        /*{{{  default use it as term*/
  349.        term_as_boolean:
  350.        default:
  351.           if (!(buff=parse_term(to,buff,dummy_var(dummy_base),dummy_base+1,ret_used))) return(0);
  352.           *buff++ = M_NULL_COUNTER;
  353.           *buff++ = (TOKEN) dummy_var(dummy_base);
  354.           *buff++ = M_NOT;
  355.           break;
  356.        /*}}}  */
  357.      }
  358.      return(buff);
  359.    }
  360. }
  361. /*}}}  */
  362.  
  363. public TOKEN *parse_cond(TOKEN *buff,int dummy_base,boolean *ret_used)
  364. {
  365.   return
  366.    ( l_parse_cond
  367.       ( buff,
  368.         name_to_var
  369.          ( get_full_token(),
  370.            0,
  371.            new_vars_enabled
  372.          ),
  373.         False,
  374.         dummy_base,
  375.         ret_used
  376.       )
  377.    );
  378. }
  379. /*}}}  */
  380.