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

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7.  
  8. #define PARSEMAC_C
  9.  
  10. #include "keybind.h"
  11. #include <lib/ori_add_lib.h>
  12. /*}}}  */
  13.  
  14. /*{{{  variables*/
  15. private boolean op_recursiv = False;
  16. /*}}}  */
  17.  
  18. /*{{{  parse_macro*/
  19. /*{{{  get_arg_terms*/
  20. private TOKEN *get_arg_terms(TOKEN *buff,int args,int dummy_base,boolean *ret_used)
  21. { int i;
  22.  
  23.   begin_parse();
  24.   for (i=0;i<args;i++)
  25.    { tokens token;
  26.  
  27.      if ((token=get_full_token())!=DEFAULT)
  28.         if (!(buff=parse_term(token,buff,ocl_arg_var(i),dummy_base,ret_used)))
  29.            return(0);
  30.    }
  31.   end_parse(M_WANTEND);
  32.   return(buff);
  33. }
  34. /*}}}  */
  35.  
  36. public TOKEN *parse_macro(TOKEN *buff,int dummy_base,boolean *ret_used)
  37. {
  38.   tokens token;
  39.   tokens to;
  40.  
  41.   begin_parse();
  42.   do {
  43.     check_length(buff);
  44.     token=get_full_token();
  45.     switch (token) {
  46.       /*{{{  repeat*/
  47.       case REPEAT:
  48.        { boolean r_end_used=False;
  49.          TOKEN *call,*test,*ex;
  50.  
  51.          /*{{{  save old and get current repeat value*/
  52.          *buff++=M_PUSH_INT;
  53.          *buff++=repeat_var;
  54.          if (!(buff=parse_term(get_full_token(),buff,repeat_var,dummy_base,ret_used)))
  55.             return(0);
  56.          /*}}}  */
  57.          /*{{{  call the repeated block, prepare the exit-statements*/
  58.          call=buff;
  59.          buff=generate_jmp(M_CALL,call,call);
  60.          *buff++=M_POP_INT;
  61.          *buff++=repeat_var;
  62.          *buff++=M_END_MACRO;
  63.          /*}}}  */
  64.          /*{{{  handle the test*/
  65.          test=buff;
  66.          *buff++=M_POSITIV_COUNTER;
  67.          *buff++=repeat_var;
  68.          ex=buff;
  69.          buff=generate_jmp(M_JMP_FALSE,ex,ex);
  70.          *buff++=M_ADD_COUNTER;
  71.          *buff++=repeat_var;
  72.          *buff++= -1;
  73.          /*}}}  */
  74.          /*{{{  code the block*/
  75.          if (!(buff=parse_macro(buff,dummy_base,&r_end_used))) return(0);
  76.          buff=generate_jmp(M_JMP,buff,test);
  77.          generate_jmp(M_JMP_FALSE,ex,buff);
  78.          /*}}}  */
  79.          if (r_end_used)
  80.           /*{{{  pop the adress for exit-handling*/
  81.           { *ret_used=True;
  82.             generate_jmp(M_CALL,call,test);
  83.             /*{{{  pop the adress (don't execute the M_END_MACRO!)*/
  84.             *buff++=M_POP_INT;
  85.             *buff++=repeat_var;
  86.             /*}}}  */
  87.           }
  88.           /*}}}  */
  89.          else
  90.           /*{{{  call test -> jmp test*/
  91.             generate_jmp(M_JMP,call,test);
  92.           /*}}}  */
  93.          /*{{{  restore old loop counter*/
  94.          *buff++=M_POP_INT;
  95.          *buff++=repeat_var;
  96.          /*}}}  */
  97.          break;
  98.        }
  99.       /*}}}  */
  100.       /*{{{  local*/
  101.       case LOC:
  102.        {
  103.          /*{{{  comments*/
  104.          /* macros, using return-from-macro must be called via subroutine-call,
  105.           * to guarantee the proper stack-handling. In this case
  106.           *    M_PUSH_INT var1
  107.           *      :
  108.           *    M_PUSH_INT varn
  109.           *    M_CALL x
  110.           *    M_JMP  e
  111.           *  x macro
  112.           *    M_END_MACRO
  113.           *  e M_POP_INT varn
  114.           *      :
  115.           *    M_POP_INT var1
  116.           * is generated instead of
  117.           *    M_PUSH_INT var1
  118.           *      :
  119.           *    M_PUSH_INT varn
  120.           *    macro
  121.           *    M_POP_INT varn
  122.           *      :
  123.           *    M_POP_INT var1
  124.           */
  125.          /*}}}  */
  126.        
  127.          int l_vars[int_dummy_vars];
  128.          int l_vars_c;
  129.          tokens next;
  130.        
  131.          begin_parse();
  132.          /*{{{  list of vars*/
  133.          l_vars_c=0;
  134.          while ((next=name_to_var(get_full_token(),1,new_vars_enabled))!=END)
  135.             if (next==VARIABLE)
  136.              /*{{{  already defined var*/
  137.              { *buff++ = M_PUSH_INT;
  138.                *buff++ = (TOKEN) (l_vars[l_vars_c++]=tk_var->no);
  139.              }
  140.              /*}}}  */
  141.             else
  142.                m_exit(M_NOVAR);
  143.          /*}}}  */
  144.          /*{{{  parse_statement, maybe handle call/jmp*/
  145.          { TOKEN *jump,*block,*call;
  146.            boolean l_ret_used=False;
  147.  
  148.            buff=generate_jmp(M_CALL,call=buff,buff);
  149.            /*{{{  pop all local vars*/
  150.            { int v_x=l_vars_c;
  151.  
  152.              while (v_x>0) { *buff++ = M_POP_INT;*buff++ = l_vars[--v_x]; }
  153.            }
  154.            /*}}}  */
  155.            buff=generate_jmp(M_JMP,jump=buff,call);
  156.            generate_jmp(M_CALL,call,block=buff);
  157.            if (!(buff=parse_macro(buff,dummy_base,&l_ret_used))) return(0);
  158.            if (l_ret_used)
  159.             /*{{{  internal macro used return-from-macro -> subroutine-call*/
  160.             { *buff++ =M_END_MACRO;
  161.               generate_jmp(M_JMP,jump,buff);
  162.             }
  163.             /*}}}  */
  164.            else
  165.             /*{{{  normal code, delete call/jmp*/
  166.             { while (call!=block) *call++=O_NOP;
  167.               /*{{{  pop all local vars*/
  168.               { int v_x=l_vars_c;
  169.  
  170.                 while (v_x>0) { *buff++ = M_POP_INT;*buff++ = l_vars[--v_x]; }
  171.               }
  172.               /*}}}  */
  173.             }
  174.             /*}}}  */
  175.          }
  176.          /*}}}  */
  177.          break;
  178.        }
  179.       /*}}}  */
  180.       /*{{{  while*/
  181.       case WHILE:
  182.        { TOKEN *whilestart,*jmpad;
  183.        
  184.          if (!(jmpad=parse_cond(whilestart=buff,dummy_base,ret_used))) return(0);
  185.          buff=generate_jmp(M_JMP_FALSE,jmpad,jmpad);
  186.          if (!(buff=parse_macro(buff,dummy_base,ret_used))) return(0);
  187.          buff=generate_jmp(M_JMP,buff,whilestart);
  188.          generate_jmp(M_JMP_FALSE,jmpad,buff);
  189.          break;
  190.        }
  191.       /*}}}  */
  192.       /*{{{  do*/
  193.       case DO: {
  194.         TOKEN *dostart=buff;
  195.  
  196.         if (!(buff=parse_macro(buff,dummy_base,ret_used)))
  197.            return(0);
  198.         /*{{{  read the while*/
  199.         if ((to=get_full_token())!=WHILE)
  200.            m_exit(M_NOWHILE);
  201.         /*}}}  */
  202.         if (!(buff=parse_cond(buff,dummy_base,ret_used)))
  203.            return(0);
  204.         buff=generate_jmp(M_JMP_TRUE,buff,dostart);
  205.         break;
  206.       }
  207.       /*}}}  */
  208.       /*{{{  case*/
  209.       case CASE: {
  210.         TOKEN *defaultjmp=0,*condptr;
  211.  
  212.         token=get_full_token();
  213.         do
  214.          { switch (token)
  215.             { default:
  216.                  m_exit(M_NOESAC);
  217.               case ESAC:
  218.                  break;
  219.               /*{{{  BEGIN -> cond macro*/
  220.               case BEGIN: {
  221.                 if (!(condptr=parse_cond(buff,dummy_base,ret_used)))
  222.                    return(0);
  223.                 buff=generate_jmp(M_JMP_FALSE,condptr,condptr);
  224.                 if (!(buff=parse_macro(buff,dummy_base,ret_used)))
  225.                    return(0);
  226.                 if (defaultjmp)
  227.                    buff=generate_jmp(M_JMP,buff,defaultjmp);
  228.                 else
  229.                    buff=generate_jmp(M_JMP,defaultjmp=buff,buff);
  230.                 generate_jmp(M_JMP_FALSE,condptr,buff);
  231.                 end_parse(M_CASEEND);
  232.                 token=get_full_token();
  233.                 break;
  234.               }
  235.               /*}}}  */
  236.               /*{{{  DEFAULT*/
  237.               case DEFAULT:
  238.                 if (!(buff=parse_macro(buff,dummy_base,ret_used))) return(0);
  239.                 token=get_full_token();
  240.                 break;
  241.               /*}}}  */
  242.             }
  243.          }
  244.         while (token!=ESAC);
  245.         if (defaultjmp)
  246.            generate_jmp(M_JMP,defaultjmp,buff);
  247.         break;
  248.       }
  249.       /*}}}  */
  250.       /*{{{  if*/
  251.       case IF: {
  252.         TOKEN *jmpadr,*endtrue;
  253.  
  254.         if (!(jmpadr=parse_cond(buff,dummy_base,ret_used)))
  255.            return(0);
  256.         buff=generate_jmp(M_JMP_FALSE,jmpadr,jmpadr);
  257.         if (!(endtrue=parse_macro(buff,dummy_base,ret_used)))
  258.            return(0);
  259.         token=get_full_token();
  260.         switch (token)
  261.          { default:
  262.               m_exit(M_NOELSEFI);
  263.            /*{{{  if else fi*/
  264.            case ELSE:
  265.              buff=generate_jmp(M_JMP,endtrue,endtrue);
  266.              generate_jmp(M_JMP_FALSE,jmpadr,buff);
  267.              if (!(buff=parse_macro(buff,dummy_base,ret_used)))
  268.                 return(0);
  269.              generate_jmp(M_JMP,endtrue,buff);
  270.              if ((to=get_full_token())!=FI)
  271.                  m_exit(M_NOFI);
  272.              break;
  273.            /*}}}  */
  274.            /*{{{  if fi*/
  275.            case FI:
  276.              generate_jmp(M_JMP_FALSE,jmpadr,endtrue);
  277.              buff=endtrue;
  278.              break;
  279.            /*}}}  */
  280.          }
  281.         break;
  282.       }
  283.       /*}}}  */
  284.       /*{{{  return- value- from-macro*/
  285.       case RETVAL: {
  286.         int result=dummy_var(dummy_base);
  287.  
  288.         if (!(buff=parse_term(name_to_var(get_full_token(),1,new_vars_enabled),buff,result,dummy_base+1,ret_used)))
  289.            return(0);
  290.         *buff++ = M_PUSH_INT;
  291.         *buff++ = (TOKEN)result;
  292.         *buff++ = M_POP_INT;
  293.         *buff++ = (TOKEN)return_var;
  294.       }
  295.       case RETURN:
  296.         *ret_used=True;
  297.         *buff++ = M_END_MACRO;
  298.         break;
  299.       /*}}}  */
  300.       /*{{{  simple commands, which are not allowed on keyboard!*/
  301.       case POP_DELBUFF: *buff++=M_POP_DELBUF;break;
  302.       case SCROFF: *buff++=M_SCREEN_OFF;break;
  303.       case SCRON: *buff++=M_SCREEN_ON;break;
  304.       case RESTORE_LAYOUT: *buff++=M_LAYOUT;*buff++=1;break;
  305.       case SAVE_LAYOUT:*buff++=M_LAYOUT;*buff++=0;break;
  306.       /*}}}  */
  307.       /*{{{  set/reset-user-mode*/
  308.       case SET_U_M_N:
  309.       case SET_U_M:
  310.       case RESET_U_M: {
  311.         int i=used_modes-1;
  312.         tokens user_token=token;
  313.         boolean d=False;
  314.  
  315.         if ((token=get_full_token())!=NAME)
  316.            i= -1;
  317.         while (i>=0)
  318.            if (!ustrcmp(tk_string,modenames[i]))
  319.               break;
  320.            else
  321.               i--;
  322.         if (i<0)
  323.            m_exit(M_UMNAME);
  324.         if (user_token==SET_U_M_N)
  325.          { to=name_to_var(get_full_token(),1,new_vars_enabled);
  326.            if (to!=VARIABLE)
  327.             { if (!(buff=parse_term(to,buff,dummy_var(dummy_base),dummy_base+1,ret_used))) return(0);
  328.               d=True;
  329.             }
  330.          }
  331.         *buff++ = (user_token==SET_U_M)   ? M_SET_USER_MODE:
  332.                   (user_token==SET_U_M_N) ? M_SET_USER_MODE_NUMB :
  333.                                             M_RESET_USER_MODE;
  334.         *buff++ = (TOKEN) i;
  335.         if (user_token==SET_U_M_N)
  336.            *buff++=(TOKEN)(d?dummy_var(dummy_base):tk_var->no);
  337.         break;
  338.       }
  339.       /*}}}  */
  340.       /*{{{  set-counter*/
  341.       case SET_COUNTER:
  342.        { int no,size,dest,ind;
  343.  
  344.          /*{{{  get destination*/
  345.          switch (name_to_var(get_full_token(),0,new_vars_enabled))
  346.           {
  347.             case VARIABLE:
  348.                if ((size=tk_var->size)==1)
  349.                 /*{{{  single var*/
  350.                 { no=tk_var->no;
  351.                   size=1;
  352.                   break;
  353.                 }
  354.                 /*}}}  */
  355.                else
  356.                 /*{{{  array var*/
  357.                 { begin_parse();
  358.                   dest=tk_var->no;
  359.                   ind=dummy_var(dummy_base++);
  360.                   if (!(buff=parse_term(get_full_token(),buff,ind,dummy_base,ret_used))) return(0);
  361.                   no=dummy_var(dummy_base++);
  362.                   end_parse(M_WANTEND);
  363.                   break;
  364.                 }
  365.                 /*}}}  */
  366.             default:
  367.                m_exit(M_NOVAR);
  368.           }
  369.          /*}}}  */
  370.          if (!(buff=parse_term(get_full_token(),buff,no,dummy_base,ret_used))) return(0);
  371.          if (size>1)
  372.           /*{{{  move result to field*/
  373.           { *buff++=M_PUSH_INT;
  374.             *buff++=(TOKEN)no;
  375.             *buff++=M_POP_INT_X;
  376.             *buff++=(TOKEN)dest;
  377.             *buff++=(TOKEN)ind;
  378.           }
  379.           /*}}}  */
  380.          break;
  381.        }
  382.       /*}}}  */
  383.       /*{{{  history*/
  384.       case HISTORY:
  385.        { histories h;
  386.  
  387.          *buff++=M_HISTORY;
  388.          if ((h=name_to_history(get_full_token(),False))==unknown_history)
  389.             m_exit(M_NOHISTORY);
  390.          else
  391.             *buff++=(TOKEN) h;
  392.          break;
  393.        }
  394.       /*}}}  */
  395.       /*{{{  repeated term commands with ()*/
  396.       case LOAD:
  397.        { boolean in;
  398.          tokens to;
  399.  
  400.          /*{{{  get (, and maybe the leading not*/
  401.          switch (get_full_token())
  402.           { case BEGIN:
  403.                in=True;
  404.                break;
  405.             case NOT:
  406.                if (get_full_token()==BEGIN)
  407.                 { in=False;
  408.                   break;
  409.                 }
  410.             default:
  411.                m_exit(M_WANTBEGIN);
  412.           }
  413.          /*}}}  */
  414.          while ((to=get_full_token())!=END)
  415.           { if (!(buff=parse_term(to,buff,dummy_var(dummy_base),dummy_base+1,ret_used)))
  416.                return(0);
  417.             *buff++=M_LOAD_MAC;
  418.             *buff++=(TOKEN)in;
  419.             *buff++=dummy_var(dummy_base);
  420.           }
  421.          break;
  422.        }
  423.       /*}}}  */
  424.       /*{{{  commands with one term argument*/
  425.       case INSERT_ASCII:
  426.       case ECHO_B:
  427.       case HISTORY_GET:
  428.       case SET_CURSOR:
  429.       case SHOW_CURSOR:
  430.       case COUNTER:
  431.       case HELP_SET:
  432.       case GOTO_BUFFER:
  433.       case GOTO_BUFFER_ID:
  434.       case GOTO_COUNTER:
  435.       case GOTO_MARK:
  436.       case GOTO_Y:
  437.        { boolean d=False;
  438.          histories h;
  439.  
  440.          /*{{{  maybe get history argument for HISTORY_GET*/
  441.          if (token==HISTORY_GET)
  442.           /*{{{  get history list*/
  443.           { if ((h=name_to_history(get_full_token(),False))==unknown_history)
  444.                m_exit(M_NOHISTORY);
  445.           }
  446.           /*}}}  */
  447.          else
  448.             h=unknown_history;
  449.          /*}}}  */
  450.          /*{{{  get variable or eval term*/
  451.          to=name_to_var(get_full_token(),0,new_vars_enabled);
  452.          /*{{{  maybe handle msg*/
  453.          if (token==INSERT_ASCII && to==NAME)
  454.           { int msgid;
  455.  
  456.             msgid=name2msg(tk_string);
  457.             if (msgid>=0)
  458.              { *buff++ = M_PROMPT;
  459.                *buff++ = -3;
  460.                *buff++ = -msgid;
  461.                *buff++ = M_END_MACRO;
  462.                break;
  463.              }
  464.           }
  465.          /*}}}  */
  466.          if (to!=VARIABLE || tk_var->size!=1)
  467.           { if (!(buff=parse_term(to,buff,dummy_var(dummy_base),dummy_base+1,ret_used))) return(0);
  468.             d=True;
  469.           }
  470.          /*}}}  */
  471.          /*{{{  put command*/
  472.          if (token==GOTO_Y)
  473.           { *buff++ = O_GOTO_LINE;*buff++ = M_INT_STRING; }
  474.          else if (token==GOTO_BUFFER)
  475.           { *buff++=M_GO_BUFFER;*buff++=0; }
  476.          else if (token==GOTO_BUFFER_ID)
  477.           { *buff++=M_GO_BUFFER;*buff++=1; }
  478.          else
  479.           { *buff++ = (token==GOTO_COUNTER)? M_GO_COUNTER_X_POS :
  480.                       (token==INSERT_ASCII)? M_ASCII :
  481.                       (token==HELP_SET)    ? M_SHOW_HELP :
  482.                       (token==SHOW_CURSOR) ? M_SHOW_CURSOR :
  483.                       (token==SET_CURSOR)  ? O_FLUSH :
  484.                       (token==HISTORY_GET) ? M_GET_HISTORY :
  485.                       (token==GOTO_MARK)   ? M_GOTO_MARK :
  486.                       (token==ECHO_B)      ? M_ECHO_I :
  487.                                              M_INT_STRING;
  488.           }
  489.          /*}}}  */
  490.          /*{{{  maybe write history argument for HISTORY_GET*/
  491.          if (h!=unknown_history) *buff++ = (TOKEN)h;
  492.          /*}}}  */
  493.          /*{{{  put var/term arg*/
  494.          *buff++=(TOKEN)(d?dummy_var(dummy_base):tk_var->no);
  495.          if (token==GOTO_Y) *buff++ = O_RETURN;
  496.          /*}}}  */
  497.          break;
  498.        }
  499.       /*}}}  */
  500.       /*{{{  commands with two term argument*/
  501.       case CHANGE_FOLD:
  502.        { int n1;
  503.          int n2;
  504.  
  505.          /*{{{  get term 1*/
  506.          to=name_to_var(get_full_token(),0,new_vars_enabled);
  507.          if (to!=VARIABLE || tk_var->size!=1)
  508.           { if (!(buff=parse_term(to,buff,n1=dummy_var(dummy_base),dummy_base+1,ret_used))) return(0);
  509.           }
  510.          else
  511.             n1=tk_var->no;
  512.          /*}}}  */
  513.          /*{{{  get term 2*/
  514.          to=name_to_var(get_full_token(),0,new_vars_enabled);
  515.          if (to!=VARIABLE || tk_var->size!=1)
  516.           { if (!(buff=parse_term(to,buff,n2=dummy_var(dummy_base),dummy_base+1,ret_used))) return(0);
  517.           }
  518.          else
  519.             n2=tk_var->no;
  520.          /*}}}  */
  521.          *buff++=M_CHANGE_FOLD;
  522.          *buff++=(TOKEN)n1;
  523.          *buff++=(TOKEN)n2;
  524.          break;
  525.        }
  526.       /*}}}  */
  527.       /*{{{  commands with prompts*/
  528.       case EXITCODE:
  529.        /*{{{  M_FINISH*/
  530.          *buff++ = M_FINISH;
  531.          if (!(buff=put_var(buff))) return(0);
  532.          goto prompt_command_tail;
  533.        /*}}}  */
  534.       case HISTORY_EDIT:
  535.       case HISTORY_EDIT_F:
  536.       case HISTORY_EDIT_L:
  537.        /*{{{  M_EDIT_HISTORY*/
  538.        { histories h;
  539.  
  540.          *buff++ = M_EDIT_HISTORY;
  541.          *buff++ = (token==HISTORY_EDIT)?0:(token==HISTORY_EDIT_L)?1:2;
  542.          if ((h=name_to_history(get_full_token(),False))==unknown_history)
  543.             m_exit(M_NOHISTORY);
  544.          *buff++=(TOKEN)h;
  545.          goto prompt_command_tail;
  546.        }
  547.        /*}}}  */
  548.       case MENU:
  549.        /*{{{  M_MENU*/
  550.          *buff++ = M_MENU;
  551.          if (!(buff=put_var(buff))) return(0);
  552.          goto prompt_command_tail;
  553.        /*}}}  */
  554.       case HELP_W:
  555.        /*{{{  M_WRITE_HELP*/
  556.          *buff++ = M_WRITE_HELP;
  557.          if (!(buff=put_var(buff))) return(0);
  558.          if (!(buff=put_var(buff))) return(0);
  559.          goto prompt_command_tail;
  560.        /*}}}  */
  561.       case ECHO_P:
  562.        /*{{{  M_ECHO_P*/
  563.          *buff++=M_ECHO_P;
  564.          goto prompt_command_tail;
  565.        /*}}}  */
  566.       case MESSAGE:
  567.        /*{{{  M_PROMPT -2*/
  568.          *buff++ = M_PROMPT;
  569.          *buff++ = -2;
  570.          goto prompt_command_tail;
  571.        /*}}}  */
  572.       case PROMPT:
  573.        /*{{{  M_PROMPT -1*/
  574.          *buff++ = M_PROMPT;
  575.          *buff++ = -1;
  576.          goto prompt_command_tail;
  577.        /*}}}  */
  578.       case PROMPT_CHAR:
  579.        /*{{{  M_PROMPT_C*/
  580.          *buff++ = M_PROMPT_C;
  581.          if (!(buff=put_var(buff))) return(0);
  582.          goto prompt_command_tail;
  583.        /*}}}  */
  584.       case PROMPT_COUNTER:
  585.        /*{{{  M_PROMPT var*/
  586.          *buff++ = M_PROMPT;
  587.          if (!(buff=put_var(buff))) return(0);
  588.          goto prompt_command_tail;
  589.        /*}}}  */
  590.       case GETENV:
  591.        /*{{{  M_ENV_CMD 1*/
  592.          *buff++ = M_ENV_CMD;
  593.          *buff++ = (TOKEN)1;
  594.          goto prompt_command_tail;
  595.        /*}}}  */
  596.  
  597.       prompt_command_tail:
  598.         if (!(buff=get_message(buff))) {
  599.           fprintf(stderr,M_NOPROMPT);
  600.           return(0);
  601.         }
  602.         *buff++ = M_END_MACRO;
  603.         break;
  604.       /*}}}  */
  605.       /*{{{  defset*/
  606.       case DEFSET:
  607.          buff=parse_set_macro(buff);
  608.          break;
  609.       /*}}}  */
  610.       /*{{{  message-exit/exit*/
  611.       case MES_EXIT:
  612.       case EXIT: {
  613.          *buff++ = M_EXIT;
  614.          if (token==MES_EXIT && !(buff=get_message(buff))) {
  615.            fprintf(stderr,M_NOMESSAGE);
  616.            return(0);
  617.          }
  618.          *buff++ = M_END_MACRO;
  619.          break;
  620.       }
  621.       /*}}}  */
  622.       /*{{{  opcode*/
  623.       case OPCODE:
  624.         if (tk_key->num!=O_NOP)
  625.            if ((*buff++=tk_key->num)==O_FLUSH)
  626.               *buff++=var_cur_lev;
  627.         break;
  628.       /*}}}  */
  629.       /*{{{  macrostring*/
  630.       case MACRO: {
  631.         TOKEN *x=tk_macro;
  632.  
  633.         check_length(buff+ustrlen(tk_string));
  634.         while (*x) *buff++ = *x++;
  635.         break;
  636.       }
  637.       /*}}}  */
  638.       /*{{{  previosly defined operation*/
  639.       case OPERATION:
  640.       {
  641.         /*{{{  comments*/
  642.         /* macros, using return-from-macro must be called via subroutine-call,
  643.          * to guarantee  the  proper  semantics.  The  return should abort the
  644.          * called macro and not the current one. In this case
  645.          *    M_CALL x
  646.          *    M_JMP  e
  647.          *  x macro
  648.          *    M_END_MACRO
  649.          *  e
  650.          * is generated.
  651.          */
  652.         /*}}}  */
  653.  
  654.         TOKEN *x=tk_operation->ops;
  655.         int lg=tk_operation->length;
  656.         TOKEN *call_ad,*jmp_ad=0;
  657.         boolean o_ret_used=tk_operation->ret_used;
  658.  
  659.         /*{{{  maybe handle arguments*/
  660.         if
  661.          (    tk_operation->args
  662.            && !(buff=get_arg_terms(buff,tk_operation->args,dummy_base,ret_used))
  663.          )
  664.            return(0);
  665.         /*}}}  */
  666.         /*{{{  maybe subroutine handling*/
  667.         if (o_ret_used)
  668.          { call_ad=buff;
  669.            jmp_ad=buff=generate_jmp(M_CALL,buff,buff);
  670.            buff=generate_jmp(M_JMP,buff,buff);
  671.            generate_jmp(M_CALL,call_ad,buff);
  672.          }
  673.         /*}}}  */
  674.         check_length(buff+lg);
  675.         /*{{{  copy the macro*/
  676.         while (lg--) *buff++ = *x++;
  677.         /*}}}  */
  678.         /*{{{  maybe subroutine handling*/
  679.         if (o_ret_used)
  680.          { *buff++ = M_END_MACRO;
  681.            generate_jmp(M_JMP,jmp_ad,buff);
  682.          }
  683.         /*}}}  */
  684.         break;
  685.       }
  686.       /*}}}  */
  687.       /*{{{  automacro/abortmacro/promptmacros/knb/view*/
  688.       case DEFAUTOSAVE:
  689.       case DEFQUIT:
  690.       case DEFU1:
  691.       case DEFU2:
  692.       case B_CHG_MAC:
  693.       case VMAC:
  694.       case KNBM:
  695.       case PRO_IN:
  696.       case PRO_OUT:
  697.       case DEFAB:
  698.       case DEFAUTO: {
  699.         int x= token==DEFAUTOSAVE?salarm_macro:
  700.               (token==DEFQUIT?squit_macro:
  701.               (token==DEFU1?susr1_macro:
  702.               (token==DEFU2?susr2_macro:
  703.               (token==DEFAB?abort_macro:
  704.               (token==PRO_IN?pin_macro:
  705.               (token==PRO_OUT?pout_macro:
  706.               (token==KNBM?knb_macro:
  707.               (token==VMAC?vm_no:
  708.               (token==B_CHG_MAC?bc_mac:
  709.                       auto_macro)))))))));
  710.  
  711.         if (x) *buff++=O_EXE_MACRO+x;
  712.         break;
  713.       }
  714.       /*}}}  */
  715.       case END: break;
  716.       /*{{{  rekursiv on my own*/
  717.       case NAME:
  718.         op_recursiv=True;
  719.         if (!ustrcmp(op_def_name,tk_string)) {
  720.  
  721.           /*{{{  maybe handle arguments*/
  722.           if
  723.            (    op_def_args
  724.              && !(buff=get_arg_terms(buff,op_def_args,dummy_base,ret_used))
  725.            )
  726.              return(0);
  727.           /*}}}  */
  728.           buff=generate_jmp(M_CALL,buff,m_def);
  729.           break;
  730.         }
  731.       /*}}}  */
  732.       /*{{{  default=error*/
  733.       default:
  734.          m_exit(M_NOMSTRING);
  735.       /*}}}  */
  736.     }
  737.   }
  738.   while (token!=END);
  739.   if (!do_opt) *ret_used=True;
  740.   return(buff);
  741. }
  742. /*}}}  */
  743. /*{{{  opt_parse_macro*/
  744. public TOKEN *opt_parse_macro
  745.                ( TOKEN *buff,
  746.                  int args,
  747.                  boolean *ret_used,
  748.                  boolean end_it,
  749.                  boolean rc_string_gen,
  750.                  boolean fix_args
  751.                )
  752. { TOKEN *x;
  753.   TOKEN *arg_call;
  754.   TOKEN *called_block;
  755.  
  756.   x=buff;
  757.   op_recursiv=False;
  758.   if (args)
  759.    /*{{{  push old local vars and get new values*/
  760.    { int i=args;
  761.  
  762.      /*{{{  push old locs ans get new values*/
  763.      while (i--)
  764.       { *x++=M_PUSH_INT;
  765.         *x++=(TOKEN)ocl_loc_var(i);
  766.         *x++=M_PUSH_INT;
  767.         *x++=(TOKEN)ocl_arg_var(i);
  768.         *x++=M_POP_INT;
  769.         *x++=(TOKEN)ocl_loc_var(i);
  770.       }
  771.      /*}}}  */
  772.      x=generate_jmp(M_CALL,arg_call=x,x);
  773.      /*{{{  get old loc values back*/
  774.      i=0;
  775.      while (i<args)
  776.       { *x++=M_POP_INT;
  777.         *x++=ocl_loc_var(i);
  778.         i++;
  779.       }
  780.      /*}}}  */
  781.      *x++=M_END_MACRO;
  782.      generate_jmp(M_CALL,arg_call,x);
  783.      called_block=x;
  784.    }
  785.    /*}}}  */
  786.   if (!(x=parse_macro(x,0,ret_used))) return(0);
  787.   if (do_opt)
  788.    { if (!*ret_used && !op_recursiv && args)
  789.       /*{{{  don't use M_CALL to execute the body, pop locs now*/
  790.       { generate_jmp(M_JMP,arg_call,called_block);
  791.         /*{{{  generate new pops*/
  792.         { int i=0;
  793.  
  794.           while (i<args)
  795.            { *x++=M_POP_INT;
  796.              *x++=ocl_loc_var(i);
  797.              i++;
  798.            }
  799.         }
  800.         /*}}}  */
  801.       }
  802.       /*}}}  */
  803.      if (op_recursiv)
  804.       /*{{{  M_END_MACRO must be used,otherwise recursion won't work*/
  805.       { *ret_used=True;
  806.         *x++=M_END_MACRO;
  807.       }
  808.       /*}}}  */
  809.      else if (end_it)
  810.       /*{{{  simuale the M_END_MACRO, the optimizer can handle this*/
  811.         *x++=M_END_MACRO;
  812.       /*}}}  */
  813.      x=opt_mac(buff,x,False,rc_string_gen,fix_args);
  814.      /*{{{  maybe delete simulated M_END_MACRO*/
  815.      if (!op_recursiv && end_it && x>buff && *(x-1)==M_END_MACRO)
  816.         x--;
  817.      /*}}}  */
  818.    }
  819.   return(x);
  820. }
  821. /*}}}  */
  822.