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

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #include <ctype.h>
  4. #include <sys/types.h>
  5. #include <limits.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <signal.h>
  10. #include <stdio.h>
  11.  
  12. #define SCANNER_C
  13.  
  14. #include "keybind.h"
  15.  
  16. #include <h/rcformat.h>
  17. #include <h/envvar_str.h>
  18. #include <lib/ori_rc_lib.h>
  19. #include <lib/ori_add_lib.h>
  20. /*}}}  */
  21.  
  22. /*{{{  typedefs*/
  23. typedef struct { int line,col,input;boolean nl; } t_read_data;
  24. /*}}}  */
  25. /*{{{  variable declarations*/
  26. /*{{{  stack for filed-folds*/
  27. private t_read_data po_stack[OCL_FILE_DEPTH+1];
  28. private LOC_FILE file_stack[OCL_FILE_DEPTH+1];
  29. private unsigned char *name_stack[OCL_FILE_DEPTH+1];
  30. private int f_s_ptr=0;
  31. /*}}}  */
  32. /*{{{  reading-stuff*/
  33. private t_read_data read_data={ 1,0,EOF,False };
  34. /*}}}  */
  35. private boolean err_marked;
  36. public boolean err_pos_out=False;
  37. /*{{{  return-vars for the scanner*/
  38. public unsigned char tk_char;
  39. public KEYNAME *tk_key;
  40. public OP_LIST *tk_operation;
  41. public VARS_LIST const *tk_var;
  42. public int tk_val;
  43. public unsigned char tk_string[NAME_LG];
  44. public TOKEN tk_macro[OCL_CODE_LEN];
  45. /*}}}  */
  46. /*{{{  tables*/
  47. public unsigned char const undef[]="(undef)";
  48. public VARS_LIST const *var_list=0;
  49. public int repeat_var;
  50. public int return_var;
  51. public int rel_op_var;
  52. public OP_LIST new_op= { (unsigned char*)undef,False,True,0,0,0,0,0 };
  53. public unsigned char *source;
  54. /*}}}  */
  55. /*{{{  if-using stuff*/
  56. /*{{{  type TAG_LIST*/
  57. typedef struct TAG_LIST
  58.  { unsigned char const *tag;
  59.    boolean malloced;
  60.    const struct TAG_LIST *next;
  61.  } TAG_LIST;
  62. /*}}}  */
  63. private int missing_gnisu=0;
  64. private TAG_LIST *tag_list=0;
  65. /*}}}  */
  66. /*}}}  */
  67.  
  68. /*{{{  error_po*/
  69. public void error_po(void)
  70. {
  71.   if (err_pos_out)
  72.    { int i=0;
  73.      
  74.      if (!err_marked)
  75.       { if (verbose_level>0)
  76.            fprintf(stderr,"\n");
  77.         for (;i<=f_s_ptr;i++)
  78.            fprintf
  79.             ( stderr,
  80.               F_ERRORPO,
  81.               (i?name_stack[i]:source),
  82.               (i==f_s_ptr?read_data.line:po_stack[i].line-1)
  83.             );
  84.         fprintf(stderr,F_ERRY,read_data.col);
  85.       }
  86.      err_marked=True;
  87.    }
  88. }
  89. /*}}}  */
  90. /*{{{  create an operation entry*/
  91. public void creat_op(unsigned char *name,boolean mode,int lg,TOKEN *code,int place,boolean ret_used,int args)
  92. { OP_LIST *op;
  93.  
  94.   /*{{{  new node to list*/
  95.   op=kbd_malloc(sizeof(OP_LIST));
  96.   op->next=new_op.next;
  97.   new_op.next=op;
  98.   /*}}}  */
  99.   /*{{{  name to node*/
  100.   op->op_name=kbd_malloc(ustrlen(name)+1);
  101.   ustrcpy(op->op_name,name);
  102.   /*}}}  */
  103.   op->args=args;
  104.   op->length=lg;
  105.   op->def=mode;
  106.   op->place=place;
  107.   op->ret_used=ret_used;
  108.   /*{{{  code to node*/
  109.   op->ops=kbd_malloc((1+lg)*sizeof(TOKEN));
  110.   memcpy(op->ops,code,lg*sizeof(int));
  111.   /*}}}  */
  112.   /*{{{  verbose-handling*/
  113.   if (verbose_level>0)
  114.      if (place<0)
  115.        fprintf(stderr,F_OPERATION,name,args,lg);
  116.      else
  117.        fprintf(stderr,F_BELONGS,name,args);
  118.   /*}}}  */
  119. }
  120. /*}}}  */
  121. /*{{{  undeclare a operation*/
  122. public void free_op(unsigned char *name)
  123. { OP_LIST *op;
  124.  
  125.   /*{{{  set op to list entry, if given*/
  126.   op= &new_op;
  127.   while (op && ustrcmp(op->op_name,name)) op=op->next;
  128.   /*}}}  */
  129.   if (op)
  130.    { OP_LIST *on;
  131.  
  132.      kbd_free(op->op_name);
  133.      kbd_free(op->ops);
  134.      on=op->next;
  135.      if (on)
  136.       { *op= *on;
  137.         kbd_free(on);
  138.       }
  139.      else
  140.         op->op_name=(unsigned char*)undef;
  141.    }
  142.  
  143. }
  144. /*}}}  */
  145. /*{{{  create an variable entry*/
  146. public int creat_var(unsigned char *name,int size,int no)
  147. { VARS_LIST *vp;
  148.  
  149.   /*{{{  maybe get new variable number*/
  150.   if (no<0)
  151.    { no=var_count;
  152.      var_count+=size;
  153.    }
  154.   /*}}}  */
  155.   /*{{{  new node to list*/
  156.   vp=kbd_malloc(sizeof(VARS_LIST));
  157.   vp->next=var_list;
  158.   var_list=vp;
  159.   /*}}}  */
  160.   /*{{{  name to node*/
  161.   vp->var_name=(unsigned char const*)mstrcpy(name);
  162.   /*}}}  */
  163.   if (commenting && !dest_mac)
  164.    /*{{{  comment this var in rc file*/
  165.    { char x[NAME_LG*2];
  166.      char *xp;
  167.  
  168.      sprintf(xp=x,"%d=%s",no,name);
  169.      rc_put_c(RC_COMMENT,rc.fp);
  170.      do rc_put_c(*xp,rc.fp); while (*xp++);
  171.    }
  172.    /*}}}  */
  173.   vp->no=no;
  174.   vp->size=size;
  175.  
  176.   return(no);
  177. }
  178. /*}}}  */
  179. /*{{{  undeclare a variable*/
  180. public void free_var(unsigned char const*const name)
  181. { VARS_LIST *vp;
  182.  
  183.   /*{{{  set vp to list entry, if given*/
  184.   for
  185.    ( vp=(VARS_LIST*)var_list
  186.    ; vp && ustrcmp(vp->var_name,name)
  187.    ; vp=(VARS_LIST*)vp->next
  188.    );
  189.   /*}}}  */
  190.   if (vp)
  191.    /*{{{  remove the var from the list*/
  192.    { VARS_LIST const *vn;
  193.  
  194.      kbd_free((char*)vp->var_name);
  195.      vn=vp->next;
  196.      if (vn)
  197.       /*{{{  trailling copy nodes and free a node*/
  198.       { *vp= *vn;
  199.         kbd_free((char*)vn);
  200.       }
  201.       /*}}}  */
  202.      else
  203.         vp->var_name=undef;
  204.    }
  205.    /*}}}  */
  206. }
  207. /*}}}  */
  208. /*{{{  init_vars*/
  209. public void init_vars(int no_dummy)
  210. { int i;
  211.  
  212.   /*{{{  std-vars, maybe added to rc-file*/
  213.   var_scr_w=     creat_var((unsigned char*)SCR_W,1,-1);
  214.   var_off_w=     creat_var((unsigned char*)SCR_W_O,1,-1);
  215.   var_scr_h=     creat_var((unsigned char*)SCR_H,1,-1);
  216.   var_off_h=     creat_var((unsigned char*)SCR_H_O,1,-1);
  217.   var_cur_lev=   creat_var((unsigned char*)CURSOR_LEVEL,1,-1);
  218.   var_ocl_arg=   creat_var((unsigned char*)OCL_ARG_RECORD_V,DIM_OCL_CMD_OPTS,-1);
  219.                  creat_var((unsigned char*)OCL_ARG_V,1,var_ocl_arg);
  220.   var_file_no=   creat_var((unsigned char*)F_N_VAR,1,-1);
  221.   var_us_buff=   creat_var((unsigned char*)U_B_VAR,1,-1);
  222.   var_cu_buff=   creat_var((unsigned char*)C_B_VAR,1,-1);
  223.   var_cu_b_id=   creat_var((unsigned char*)C_BI_VAR,1,-1);
  224.   var_m_edit=    creat_var((unsigned char*)M_B_VAR,1,-1);
  225.   var_mod_beh=   creat_var((unsigned char*)M_O_VAR,1,-1);
  226.   var_key_count= creat_var((unsigned char*)K_C_VAR,1,-1);
  227.   var_kill_count=creat_var((unsigned char*)KI_C_VAR,1,-1);
  228.   var_move_count=creat_var((unsigned char*)M_C_VAR,1,-1);
  229.   var_path=      creat_var((unsigned char*)VAR_PATH_SEP,1,-1);
  230.   var_m_x=       creat_var((unsigned char*)MOUSE_X,1,-1);
  231.   var_m_y=       creat_var((unsigned char*)MOUSE_Y,1,-1);
  232.   var_m_gy=      creat_var((unsigned char*)MOUSE_G,1,-1);
  233.   var_m_out=     creat_var((unsigned char*)MOUSE_O,1,-1);
  234.   var_m_but=     creat_var((unsigned char*)MOUSE_B,1,-1);
  235.   var_m_buff=    creat_var((unsigned char*)MOUSE_W,1,-1);
  236.   var_dired=     creat_var((unsigned char*)DIRED_VAR,1,-1);
  237.   var_force_sh=  creat_var((unsigned char*)FORCE_SH,1,-1);
  238.   /*}}}  */
  239.   repeat_var=creat_var((unsigned char*)"(repeat)",1,-1);
  240.   return_var=creat_var((unsigned char*)"(return)",1,-1);
  241.   rel_op_var=creat_var((unsigned char*)"(rel_op)",1,-1);
  242.   for (i=0;i<no_dummy;dummy_var(i++));
  243.   def_ocl_args(ocl_std_args);
  244. # ifdef OS_VARS
  245.      OS_VARS
  246. # endif
  247. }
  248. /*}}}  */
  249. /*{{{  use_tag*/
  250. public void use_tag(unsigned char const * const tag, boolean const m)
  251. { TAG_LIST *tp;
  252.  
  253.   tp=kbd_malloc(sizeof(TAG_LIST));
  254.   tp->next=tag_list;
  255.   tag_list=tp;
  256.   tp->tag=(tp->malloced=m)
  257.             ? tp->tag=(unsigned char const*)mstrcpy(tag)
  258.             : tag;
  259.  
  260. }
  261. /*}}}  */
  262. /*{{{  default_using*/
  263. public void default_using(void)
  264. {
  265.   if (ustrcmp(m_name,(unsigned char*)NO_MOUSE))
  266.    { use_it((unsigned char*)"MOUSY");
  267.      use_it(m_name);
  268.    }
  269.   OS_USINGS
  270. }
  271. /*}}}  */
  272. /*{{{  read a character from input, count lines (with look-ahead)*/
  273. #define raw_read_in() (read_data.input=getc(in.fp))
  274. #define in_line_read_in() (read_data.col++,raw_read_in())
  275. private void read_in(void)
  276. {
  277.   if (read_data.nl)
  278.    { read_data.line++;
  279.      read_data.col=0;
  280.    }
  281.   else
  282.      read_data.col++;
  283.   switch (raw_read_in())
  284.    { case '\n':
  285.         read_data.nl=True;
  286.         break;
  287.      case '\t':
  288.         m_error_po(M_TAB);
  289.      default:
  290.         read_data.nl=False;
  291.    }
  292. }
  293. /*}}}  */
  294. /*{{{  init_scan*/
  295. public int ctrl_c[O_NOP];
  296.  
  297. public void init_scan (void)
  298. { int i;
  299.  
  300.   read_in();
  301.   for (i=0;i<O_NOP;i++)
  302.      ctrl_c[i]=0;
  303.   for (i=0;i<32;i++)
  304.    { char c;
  305.  
  306.      c=CTRL_CHARS[i];
  307.      ctrl_c[c]=i;
  308.      if (isupper(c))
  309.         ctrl_c[tolower(c)]=i;
  310.      if (islower(c))
  311.         ctrl_c[toupper(c)]=i;
  312.    }
  313.   ctrl_c['?']=127;
  314.   ctrl_c[HZ_TILDE]='~';
  315. }
  316. /*}}}  */
  317. /*{{{  get token*/
  318. /*{{{  enum scan_class*/
  319. typedef enum
  320.  {
  321.    /*{{{  basic bit coded scan parts*/
  322.    char_scan=        1<<1,
  323.    key_scan=        1<<2,
  324.    ctrl_scan=        1<<3,
  325.    file_scan=        1<<4,
  326.    keyword_scan=    1<<5,
  327.    opcode_scan=        1<<6,
  328.    number_scan=        1<<7,
  329.    ref_id_scan=        1<<8,
  330.    operation_scan=    1<<9,
  331.    var_scan=        1<<10,
  332.    lang_scan=        1<<11,
  333.    opp_scan=        1<<12,
  334.    skip_file_scan=    1<<13,
  335.    /*}}}  */
  336.    /*{{{  complex scan types*/
  337.    filename_scanning=    file_scan,
  338.    full_scanning=    (   char_scan
  339.                  | keyword_scan
  340.                  | opcode_scan
  341.                  | number_scan
  342.                  | operation_scan
  343.                  | var_scan
  344.                  | lang_scan
  345.                ),
  346.    char_or_key_scanning=(   char_scan
  347.                  | keyword_scan
  348.                ),
  349.    single_scanning=    ( char_scan ),
  350.    name_scanning=    ( char_scan ),
  351.    number_scanning=    ( number_scan ),
  352.    key_scanning=    (   char_scan
  353.                  | key_scan
  354.                ),
  355.    skip_scanning=    (   char_scan
  356.                  | skip_file_scan
  357.                           | ctrl_scan
  358.                ),
  359.    skip_c_or_k_scanning=(   char_scan
  360.                  | keyword_scan
  361.                  | ctrl_scan
  362.                ),
  363.    ref_id_scanning=    (   number_scan
  364.                  | ref_id_scan
  365.                ),
  366.    /*}}}  */
  367.    dummy_scan
  368.  } scan_class;
  369. /*}}}  */
  370. /*{{{  get a token*/
  371. /*{{{  get a token and handle filed-folds - filed-folds are handled inside*/
  372. /*{{{  get a token from current input-file*/
  373. private tokens get_token_from_file(scan_class type)
  374. {
  375.   unsigned char *s;
  376.  
  377.   err_marked=False;
  378.   /*{{{  skip comments, spaces  ...*/
  379.   for (;;read_in())
  380.    { switch (read_data.input)
  381.       { case '\n':
  382.         case ' ':
  383.            continue;
  384.         default:
  385.            if
  386.             (    read_data.input==';'
  387.               || read_data.input==BEGIN_STANDARD[0]
  388.               || read_data.input==END_STANDARD[0]
  389.             )
  390.             /*{{{  skip comment line*/
  391.             { for (;;)
  392.                { switch (read_data.input)
  393.                   { case '\n':
  394.                     case EOF:
  395.                        read_data.nl=True;
  396.                        break;
  397.                     default:
  398.                        raw_read_in();
  399.                        continue;
  400.                   }
  401.                  break;
  402.                }
  403.               continue;
  404.             }
  405.             /*}}}  */
  406.            else
  407.               break;
  408.       }
  409.      break;
  410.    }
  411.   /*}}}  */
  412.   /*{{{  maybe error if tab*/
  413.   if (read_data.input=='\t' && !(type&ctrl_scan))
  414.      return(ERROR);
  415.   /*}}}  */
  416.   /*{{{  maybe scan char tokens + - ..*/
  417.   if (type&char_scan)
  418.      switch(read_data.input)
  419.       { case EOF:       read_in();return(ENDFILE);
  420.         case '(':       read_in();return(BEGIN);
  421.         case ')':       read_in();return(END);
  422.         case ',':       read_in();return(COMMA);
  423.         case '@':       read_in();return(COMPPRE);
  424.         case '+':       read_in();return(ADD);
  425.         case '-':       read_in();return(MINUS);
  426.         case '*':       read_in();return(MULT);
  427.         case '=':       read_in();return(REL_EQ);
  428.         case '<':
  429.            read_in();
  430.            switch(read_data.input)
  431.             { case '>':    read_in();return(REL_NEQ);
  432.               case '=':    read_in();return(REL_LOW_EQ);
  433.               default:              return(REL_LOW);
  434.             }
  435.         case '>':
  436.            read_in();
  437.            switch (read_data.input)
  438.             { case '=':    read_in();return(REL_HIGH_EQ);
  439.               default:              return(REL_HIGH);
  440.             }
  441.       }
  442.   /*}}}  */
  443.   /*{{{  maybe scan key-codes*/
  444.   if (type&key_scan)
  445.      switch (read_data.input)
  446.       {
  447.         /*{{{  hex-value*/
  448.         case '0':
  449.          { int h=0;
  450.            unsigned char *s=tk_string;
  451.  
  452.            read_in();
  453.            if (read_data.input!='x' && read_data.input!='X')
  454.               m_exit(M_NOHEX);
  455.            read_in();
  456.            *s++='0';
  457.            *s++='x';
  458.            for (;;)
  459.             { switch(read_data.input)
  460.                { case '0': h=h*16;   break;
  461.                  case '1': h=h*16+1; break;
  462.                  case '2': h=h*16+2; break;
  463.                  case '3': h=h*16+3; break;
  464.                  case '4': h=h*16+4; break;
  465.                  case '5': h=h*16+5; break;
  466.                  case '6': h=h*16+6; break;
  467.                  case '7': h=h*16+7; break;
  468.                  case '8': h=h*16+8; break;
  469.                  case '9': h=h*16+9; break;
  470.                  case 'a': h=h*16+10;break;
  471.                  case 'A': h=h*16+10;break;
  472.                  case 'b': h=h*16+11;break;
  473.                  case 'B': h=h*16+11;break;
  474.                  case 'c': h=h*16+12;break;
  475.                  case 'C': h=h*16+12;break;
  476.                  case 'd': h=h*16+13;break;
  477.                  case 'D': h=h*16+13;break;
  478.                  case 'e': h=h*16+14;break;
  479.                  case 'E': h=h*16+14;break;
  480.                  case 'f': h=h*16+15;break;
  481.                  case 'F': h=h*16+15;break;
  482.                  default:  tk_char=h;*s++=' ';*s='\0';return(HEX);
  483.                }
  484.               *s++=read_data.input;
  485.               read_in();
  486.             }
  487.          }
  488.         /*}}}  */
  489.         /*{{{  Meta-handling*/
  490.         case 'M':
  491.          { in_line_read_in();
  492.            if (read_data.input!='-')
  493.               m_exit(M_NOMETA);
  494.            read_in();
  495.            return(META);
  496.          }
  497.         /*}}}  */
  498.         /*{{{  Control-handling*/
  499.         case 'C':
  500.          { in_line_read_in();
  501.            if (read_data.input!='-')
  502.               m_exit(M_NOCNTRL);
  503.            read_in();
  504.            tk_char=ctrl_c[read_data.input];
  505.            read_in();
  506.            return(CHAR);
  507.          }
  508.         /*}}}  */
  509.         /*{{{  Char-handling*/
  510.         case '"':
  511.          { in_line_read_in();
  512.            if (read_data.input<' ' || read_data.input>127)
  513.               m_exit(M_NOCHAR);
  514.            tk_char=read_data.input;
  515.            read_in();
  516.            return(CHAR);
  517.          }
  518.         /*}}}  */
  519.         /*{{{  Alias-handling*/
  520.         case '$':
  521.          { unsigned char *s=tk_string;
  522.  
  523.            /*{{{  read name*/
  524.            in_line_read_in();
  525.            for (;;)
  526.             { switch (read_data.input)
  527.                { case '\n':
  528.                     read_data.nl=True;
  529.                  case ' ':
  530.                  case ')':
  531.                  case EOF:
  532.                     *s='\0';
  533.                     break;
  534.                  default:
  535.                     *s++=read_data.input;
  536.                     in_line_read_in();
  537.                     continue;
  538.                }
  539.               break;
  540.             }
  541.            /*}}}  */
  542.            return(DOLLAR);
  543.          }
  544.         /*}}}  */
  545.         /*{{{  default=error*/
  546.         default :
  547.            m_exit(M_NOCODE);
  548.         /*}}}  */
  549.       }
  550.   /*}}}  */
  551.   if (read_data.input=='\"')
  552.    /*{{{  string-handling*/
  553.     { TOKEN *t=tk_macro;
  554.       unsigned char  *c=tk_string;
  555.  
  556.       in_line_read_in();
  557.       for (;;)
  558.        { if (c>=(tk_string+NAME_LG-1))
  559.             m_exit(M_LONG_MACRO);
  560.          /*{{{  Test auf < ' ' oder EOF*/
  561.          if (read_data.input<' ' || read_data.input==EOF)
  562.             if (!(type&ctrl_scan))
  563.                m_exit(M_FALSEEND);
  564.             else if (read_data.input=='\n')
  565.                break;
  566.          /*}}}  */
  567.          *t++ = (TOKEN) read_data.input;
  568.          *c++ = (unsigned char) read_data.input;
  569.          in_line_read_in();
  570.          switch (read_data.input)
  571.           { case '\n':
  572.                read_data.nl=True;
  573.             case ' ':
  574.             case ')':
  575.             case '"':
  576.             case EOF:
  577.                break;
  578.             default:
  579.                continue;
  580.           }
  581.          break;
  582.        }
  583.       *t= (TOKEN) 0;
  584.       *c= '\0';
  585.       return(MACRO);
  586.     }
  587.    /*}}}  */
  588.   else
  589.    /*{{{  handle identifier*/
  590.    {
  591.      /*{{{  read given identifier*/
  592.      for (s=tk_string;;)
  593.       { switch ((*s++=read_data.input))
  594.          { case '\n':
  595.               read_data.nl=True;
  596.            case ' ':
  597.            case ')':
  598.            case ',':
  599.            case '(':
  600.            case ';':
  601.            case EOF:
  602.               *--s='\0';
  603.               break;
  604.            default:
  605.               in_line_read_in();
  606.               continue;
  607.          }
  608.         break;
  609.       }
  610.      /*}}}  */
  611.      if (type&file_scan)
  612.         return(NAME);
  613.      if (type&keyword_scan)
  614.       /*{{{  search as keyword*/
  615.       { keywords const *k;
  616.  
  617.         if ((k=name2keyword(tk_string)))
  618.            return(k->value);
  619.       }
  620.       /*}}}  */
  621.      if (type&opcode_scan)
  622.       /*{{{  search as opcode*/
  623.         if ((tk_key=name2func(tk_string)))
  624.            return(OPCODE);
  625.       /*}}}  */
  626.      if (type&number_scan)
  627.       /*{{{  is it a number*/
  628.       { s=tk_string;
  629.         while (*s && isdigit(*s)) s++;
  630.         if (!*s)
  631.          { tk_val=atoi((char*)tk_string);
  632.            return(NUMBER);
  633.          }
  634.       }
  635.       /*}}}  */
  636.      if (type&(ref_id_scan|number_scan))
  637.       /*{{{  search as refcard-level*/
  638.       { static struct ref_list
  639.          { struct ref_list *next;
  640.            int no;
  641.            unsigned char name[1];
  642.          } *ref_names=0,*x;
  643.  
  644.         /*{{{  look if already defined*/
  645.         for (x=ref_names,tk_val=1;x;x=x->next)
  646.            if (!ustrcmp(x->name,tk_string))
  647.             { tk_val=x->no;
  648.               return(NUMBER);
  649.             }
  650.            else if (x->no>=tk_val)
  651.               tk_val++;
  652.         /*}}}  */
  653.         if (type&ref_id_scan)
  654.          /*{{{  define new*/
  655.          { x=kbd_malloc(sizeof(struct ref_list)+strlen((char*)tk_string));
  656.            x->no=tk_val;
  657.            ustrcpy(x->name,tk_string);
  658.            x->next=ref_names;
  659.            ref_names=x;
  660.            return(NUMBER);
  661.          }
  662.          /*}}}  */
  663.       }
  664.       /*}}}  */
  665.      if (type&operation_scan)
  666.       /*{{{  search as operation*/
  667.       { for
  668.          ( tk_operation= &new_op;
  669.               tk_operation
  670.            && ustrcmp(tk_operation->op_name,tk_string);
  671.            tk_operation=tk_operation->next
  672.          );
  673.         if (tk_operation) return(OPERATION);
  674.       }
  675.       /*}}}  */
  676.      if (type&var_scan)
  677.       /*{{{  search as variable*/
  678.       { for
  679.          ( tk_var=var_list;
  680.            tk_var && ustrcmp(tk_var->var_name,tk_string);
  681.            tk_var=tk_var->next
  682.          );
  683.         if (tk_var) return(VARIABLE);
  684.       }
  685.       /*}}}  */
  686.      if (type&lang_scan)
  687.       /*{{{  search as language*/
  688.       { unsigned char c=name2lg(tk_string);
  689.  
  690.         if (c)
  691.          { tk_string[0]=c;
  692.            tk_string[1]='\0';
  693.            tk_macro[0]=(TOKEN)c;
  694.            tk_macro[1]=0;
  695.            return(MACRO);
  696.          }
  697.       }
  698.       /*}}}  */
  699.      if (type&opp_scan)
  700.       /*{{{  look for fi/if-using*/
  701.       { if (!ustrcmp(tk_string,fi_name)) return(FI);
  702.         if (!ustrcmp(tk_string,if_u_name)) return(COMPIF);
  703.       }
  704.       /*}}}  */
  705.      return(NAME);
  706.    }
  707.    /*}}}  */
  708. }
  709. /*}}}  */
  710.  
  711. private tokens get_ff_token(scan_class type)
  712. { static tokens push_back=ENDFILE;
  713.   tokens t;
  714.  
  715.   if (push_back!=ENDFILE)
  716.    /*{{{  return old value*/
  717.    { tokens x;
  718.  
  719.      x=push_back;
  720.      push_back=ENDFILE;
  721.      return(x);
  722.    }
  723.    /*}}}  */
  724.   switch ((t=get_token_from_file(type)))
  725.    {
  726.      /*{{{  True/False*/
  727.      case TRUE_SYM:
  728.      case FALSE_SYM:
  729.         tk_val=(t==TRUE_SYM)?1:0;
  730.         return(NUMBER);
  731.      /*}}}  */
  732.      /*{{{  O_CALL_FIX*/
  733.      case OPCODE:
  734.         if (tk_key->num==O_CALL_FIX)
  735.          /*{{{  handle numbered macro-calls*/
  736.          { static KEYNAME x;
  737.            static unsigned char na[NAME_LG];
  738.  
  739.            x.name=na;
  740.            ustrcpy(na,tk_key->name);
  741.            strcat((char*)na," ");
  742.            /*{{{  get correct buffer-place*/
  743.            switch (get_token_from_file(type))
  744.             {
  745.               /*{{{  number*/
  746.               case NUMBER:
  747.                { x.num=O_CALL_FIX+tk_val+1;
  748.                  break;
  749.                }
  750.               /*}}}  */
  751.               /*{{{  defined macro*/
  752.               case OPERATION:
  753.                { if (tk_operation->place)
  754.                   { x.num=O_CALL_FIX+tk_operation->place+1;
  755.                     break;
  756.                   }
  757.                }
  758.               /*}}}  */
  759.               /*{{{  else error*/
  760.               default:
  761.                  m_exit(M_NOADDCOUNTER);
  762.               /*}}}  */
  763.             }
  764.            if (x.num<0)
  765.             { error_po();
  766.               return(ERROR);
  767.             }
  768.            /*}}}  */
  769.            ustrcat(na,tk_string);
  770.            if (x.num>(mac_count+O_EXE_MACRO-2))
  771.               mac_count=x.num-O_EXE_MACRO+2;
  772.            tk_key= &x;
  773.            return(OPCODE);
  774.          }
  775.          /*}}}  */
  776.         else
  777.            return(t);
  778.      /*}}}  */
  779.      /*{{{  ENDFILE -> goto upper level, if any*/
  780.      case ENDFILE:
  781.         if (f_s_ptr)
  782.          {
  783.            /*{{{  verbose message, part 1*/
  784.            if (verbose_level>2)
  785.             { fprintf(stderr,F_EX_FILE_1,name_stack[f_s_ptr]);
  786.               fflush(stderr);
  787.             }
  788.            /*}}}  */
  789.            /*{{{  pop file from stack*/
  790.            clear_file(&in);
  791.            kbd_free(name_stack[f_s_ptr]);
  792.            read_data=po_stack[--f_s_ptr];
  793.            in=file_stack[f_s_ptr];
  794.            /*}}}  */
  795.            /*{{{  verbose message, part 2*/
  796.            if (verbose_level>2)
  797.             { fprintf
  798.                ( stderr,
  799.                  F_EX_FILE_2,
  800.                  f_s_ptr?name_stack[f_s_ptr]:source,
  801.                  read_data.line
  802.                );
  803.               fflush(stderr);
  804.             }
  805.            /*}}}  */
  806.            return(get_ff_token(type));
  807.          }
  808.         else
  809.            return(ENDFILE);
  810.      /*}}}  */
  811.      /*{{{  INCLUDE or lib -> go to lower level*/
  812.      case COMPPRE:
  813.         switch ((t=get_token_from_file(char_or_key_scanning)))
  814.          { case LIB:
  815.               break;
  816.            case NAME:
  817.               if (!ustrcmp(tk_string,include_name))
  818.                  break;
  819.            default:
  820.               push_back=t;
  821.               return(COMPPRE);
  822.          }
  823.      case INCLUDE:
  824.        if (!(type&skip_file_scan))
  825.         { char *path=((t==LIB)?lib_path:CURR_DIR);
  826.  
  827.           /*{{{  check if correct include*/
  828.           if (get_token_from_file(filename_scanning)!=NAME)
  829.              m_exit(M_NOFNAME);
  830.           if (f_s_ptr==OCL_FILE_DEPTH)
  831.            { fprintf(stderr,M_DEPTH);
  832.              return(ERROR);
  833.            }
  834.           /*}}}  */
  835.           /*{{{  verbose handling, part 1*/
  836.           if (verbose_level>2)
  837.            { fprintf
  838.               ( stderr,
  839.                 F_ENT_FILE_1,
  840.                 f_s_ptr?name_stack[f_s_ptr]:source,
  841.                 read_data.line
  842.               );
  843.              fflush(stderr);
  844.            }
  845.           /*}}}  */
  846.           /*{{{  store file-info*/
  847.           po_stack[f_s_ptr]=read_data;
  848.           file_stack[f_s_ptr++]=in;
  849.           name_stack[f_s_ptr]=mstrcpy(tk_string);
  850.           /*}}}  */
  851.           /*{{{  open file*/
  852.           { char pushfile[_POSIX_PATH_MAX];
  853.  
  854.             if (!IS_ROOT((char*)tk_string))
  855.              { for (;;)
  856.                   if(path_file_test(pushfile,&path,(char*)tk_string,""))
  857.                      break;
  858.                   else if (!*path)
  859.                      goto no_include;
  860.              }
  861.             else
  862.                strcpy(pushfile,(char*)tk_string);
  863.  
  864.             if (!open_source(&in,(unsigned char*)pushfile,False))
  865.  
  866.           no_include:
  867.            { in=file_stack[--f_s_ptr];
  868.              fprintf(stderr,F_INCLUDE,tk_string);
  869.              return(ERROR);
  870.            }
  871.           }
  872.           /*}}}  */
  873.           /*{{{  start reading*/
  874.           read_data.line=1;
  875.           read_data.col=0;
  876.           read_data.input=' ';
  877.           read_data.nl=False;
  878.           read_in();
  879.           /*}}}  */
  880.           /*{{{  verbose handling, part 2*/
  881.           if (verbose_level>2)
  882.            { fprintf(stderr,F_ENT_FILE_2,tk_string);
  883.              fflush(stderr);
  884.            }
  885.           /*}}}  */
  886.           return(get_ff_token(type));
  887.         }
  888.      /*}}}  */
  889.      default: return(t);
  890.    }
  891. }
  892. /*}}}  */
  893. /*{{{  tag_handling*/
  894. /*{{{  comment*/
  895. /*
  896.   set=True: the tags in list are set
  897.             return=-1: syntax-error
  898.             return=0:  tag is set
  899.             return=1:  tag was already set
  900.            if the list starts with ``not'', the return-values 1 and o
  901.            are exchanged!
  902.  set=False: look, if one of the listed tags is set
  903.             return=-1: syntax-error
  904.             return=0:  no set tag found
  905.             return=1:  one of the tags is set
  906. */
  907. /*}}}  */
  908. private int tag_handling(boolean set)
  909. {
  910.   boolean found=False;
  911.   boolean reverse=False;
  912.  
  913.   /*{{{  correct begin given?*/
  914.   switch (get_ff_token(char_or_key_scanning))
  915.    { case NOT:
  916.         if (get_ff_token(char_or_key_scanning)!=BEGIN)
  917.      default:
  918.            m_exit(M_OPPTAG);
  919.         reverse=True;
  920.      case BEGIN:
  921.         break;
  922.    }
  923.   /*}}}  */
  924.   for (;;)
  925.    { switch (get_ff_token(name_scanning))
  926.       { case END:
  927.            break;
  928.         case NAME:
  929.          { boolean local_found;
  930.            TAG_LIST *tp;
  931.          
  932.            /*{{{  look for this tag in taglist*/
  933.            /*
  934.            for (local_found=False,tp= &tags;tp;)
  935.            */ for (local_found=False,tp=tag_list;tp;)
  936.               if (ustrcmp(tk_string,tp->tag))
  937.                  tp=(TAG_LIST*)tp->next;
  938.               else
  939.                { local_found=True;
  940.                  break;
  941.                }
  942.            /*}}}  */
  943.            /*{{{  set and tag not in list, tag->list*/
  944.            if (set && !reverse && !local_found)
  945.             { use_tag(tk_string,True);
  946.               if (verbose_level>3)
  947.                  fprintf(stderr,F_USESET,tk_string);
  948.             }
  949.            /*}}}  */
  950.            /*{{{  unset and tag in list, remove tag from list*/
  951.            if (set && reverse && local_found)
  952.             { TAG_LIST *tn;
  953.  
  954.               if (tp->malloced)
  955.                  kbd_free((char*)tp->tag);
  956.               if ((tn=(TAG_LIST*)tp->next))
  957.                { *tp= *tn;
  958.                  kbd_free(tn);
  959.                }
  960.               else
  961.                  tp->tag=undef;
  962.               if (verbose_level>3)
  963.                  fprintf(stderr,F_UNSET,tk_string);
  964.             }
  965.            /*}}}  */
  966.            found |= local_found;
  967.            continue;
  968.          }
  969.         default:
  970.            m_exit(M_OPPTAG);
  971.       }
  972.      break;
  973.    }
  974.   if (reverse) return(found ? 0 : 1); else return(found ? 1 : 0);
  975. }
  976. /*}}}  */
  977.  
  978. private tokens get_token(scan_class type)
  979. {
  980.   tokens t;
  981.   int x;
  982.  
  983.   for (;;)
  984.    { if ((t=get_ff_token(type))==COMPPRE)
  985.       /*{{{  handle opp-statement*/
  986.       switch (t=get_ff_token(char_or_key_scanning))
  987.        {
  988.          /*{{{  if no set tag listed, overread else store number of missing ends*/
  989.          case COMPIF:
  990.           { x=tag_handling(False);
  991.             if (x)
  992.              { missing_gnisu++;
  993.                /*{{{  very_verbose-message*/
  994.                if (verbose_level>3)
  995.                   fprintf
  996.                    ( stderr,
  997.                      F_USECOMP,
  998.                      missing_gnisu,
  999.                      f_s_ptr?name_stack[f_s_ptr]:source,
  1000.                      read_data.line
  1001.                    );
  1002.                /*}}}  */
  1003.              }
  1004.             else
  1005.              /*{{{  overread the block*/
  1006.              { int use_depth;
  1007.  
  1008.                /*{{{  very_verbose-message*/
  1009.                if (verbose_level>3)
  1010.                   fprintf
  1011.                    ( stderr,
  1012.                      F_IGNORING,
  1013.                      missing_gnisu+1,
  1014.                      f_s_ptr?name_stack[f_s_ptr]:source,
  1015.                      read_data.line
  1016.                    );
  1017.                /*}}}  */
  1018.                use_depth=1;
  1019.                t= !ENDFILE;
  1020.                while (use_depth && t!=ENDFILE)
  1021.                 /*{{{  only parse opp-statements if-using/gnisu-fi*/
  1022.                 if ((t=get_ff_token(skip_scanning))==COMPPRE)
  1023.                  { if ((t=get_ff_token(skip_c_or_k_scanning))==COMPIF)
  1024.                     { use_depth++;
  1025.                       /*{{{  very_verbose-message*/
  1026.                       if (verbose_level>4)
  1027.                          fprintf
  1028.                           ( stderr,
  1029.                             F_IGNORING,
  1030.                             missing_gnisu+use_depth,
  1031.                             f_s_ptr?name_stack[f_s_ptr]:source,
  1032.                             read_data.line
  1033.                           );
  1034.                       /*}}}  */
  1035.                     }
  1036.                    else if (t==FI)
  1037.                     { use_depth--;
  1038.                       /*{{{  very_verbose-message*/
  1039.                       if (verbose_level>4)
  1040.                          fprintf
  1041.                           ( stderr,
  1042.                             F_NOAGAIN,
  1043.                             missing_gnisu+1+use_depth,
  1044.                             f_s_ptr?name_stack[f_s_ptr]:source,
  1045.                             read_data.line
  1046.                           );
  1047.                       /*}}}  */
  1048.                     }
  1049.                  }
  1050.                 else if (t==ENDFILE)
  1051.                    break;
  1052.                 /*}}}  */
  1053.                if (t!=ENDFILE)
  1054.                 {
  1055.                   /*{{{  very_verbose-message*/
  1056.                   if (verbose_level>3)
  1057.                      fprintf
  1058.                       ( stderr,
  1059.                         F_AGAIN,
  1060.                         missing_gnisu+1,
  1061.                         f_s_ptr?name_stack[f_s_ptr]:source,
  1062.                         read_data.line
  1063.                       );
  1064.                   /*}}}  */
  1065.                 }
  1066.                else
  1067.                   missing_gnisu++;
  1068.              }
  1069.              /*}}}  */
  1070.             break;
  1071.           }
  1072.          /*}}}  */
  1073.          /*{{{  set tags*/
  1074.          case COMPUSE:
  1075.             tag_handling(True);
  1076.             break;
  1077.          /*}}}  */
  1078.          /*{{{  print the reference*/
  1079.           { unsigned char line[RC_HELP_LEN+2];
  1080.             int lg;
  1081.             unsigned char *s;
  1082.             unsigned char *r;
  1083.             int dump;
  1084.             int no;
  1085.  
  1086.  
  1087.          case STARTREF_NO:
  1088.           /*{{{  get number of ref entry*/
  1089.           { switch (get_ff_token(ref_id_scanning))
  1090.              { case NUMBER:
  1091.                   if (tk_val>0 || t<=RC_CLASS_MAX)
  1092.                    { no=tk_val;
  1093.                      break;
  1094.                    }
  1095.                default:
  1096.                   m_exit(M_OPP);
  1097.              }
  1098.           }
  1099.           /*}}}  */
  1100.          case STARTREF:
  1101.             for (dump=0;;)
  1102.              {
  1103.                /*{{{  read line*/
  1104.                /*{{{  read the line*/
  1105.                s=line;
  1106.                lg=RC_HELP_LEN;
  1107.                if (t!=STARTREF)
  1108.                   lg-=6;
  1109.                /*{{{  maybe add last line char*/
  1110.                if (dump)
  1111.                 { *s++=dump;
  1112.                   lg--;
  1113.                 }
  1114.                /*}}}  */
  1115.                for (;;)
  1116.                 { switch((dump=raw_read_in()))
  1117.                    { case EOF:
  1118.                         return(ERROR);
  1119.                      case '\n':
  1120.                         read_data.line++;
  1121.                         read_data.col=0;
  1122.                         dump=0;
  1123.                         break;
  1124.                      case '\t':
  1125.                         dump=' ';
  1126.                      default:
  1127.                         *s=dump;
  1128.                         if (lg<=0)
  1129.                            break;
  1130.                         lg--;
  1131.                         s++;
  1132.                         continue;
  1133.                    }
  1134.                   break;
  1135.                 }
  1136.                *s='\0';
  1137.                /*}}}  */
  1138.                /*{{{  cut trailing spaces*/
  1139.                r=s=line;
  1140.                while (*r)
  1141.                   if (*r!=' ')
  1142.                      s= ++r;
  1143.                   else
  1144.                      r++;
  1145.                *s='\0';
  1146.                /*}}}  */
  1147.                /*}}}  */
  1148.                /*{{{  if endref line, break from loop*/
  1149.                s=line;
  1150.                while (*s==' ') s++;
  1151.                if (*s=='@' && !ustrcmp(end_ref,s+1))
  1152.                   break;
  1153.                /*}}}  */
  1154.                if (t==STARTREF)
  1155.                 /*{{{  normal refcard line*/
  1156.                 { if (ref.fp)
  1157.                    { fputs((char*)line,ref.fp);
  1158.                      fputc('\n',ref.fp);
  1159.                    }
  1160.                 }
  1161.                 /*}}}  */
  1162.                else
  1163.                 /*{{{  numbered refcard line*/
  1164.                 { if (ref_no.fp)
  1165.                    { char tag[REF_TAG_LG+1];
  1166.  
  1167.                      ref_code_tag(tag,ref_kbd-no);
  1168.                      fprintf
  1169.                       ( ref_no.fp,
  1170.                         ref_format_str("%s"),
  1171.                         tag,
  1172.                         line
  1173.                       );
  1174.                    }
  1175.                 }
  1176.                 /*}}}  */
  1177.              }
  1178.             break;
  1179.           }
  1180.          /*}}}  */
  1181.          /*{{{  line number*/
  1182.          case LINENO:
  1183.             if (get_ff_token(number_scanning)==NUMBER)
  1184.                read_data.line=tk_val;
  1185.             else
  1186.                m_exit(M_OPP);
  1187.             break;
  1188.          /*}}}  */
  1189.          /*{{{  rc-comment*/
  1190.          case COMMENT:
  1191.             if (!dest_mac) rc_put_c(RC_COMMENT,rc.fp);
  1192.             if (read_data.input==' ') read_in();
  1193.             while
  1194.              (     read_data.input
  1195.                 && read_data.input!=EOF
  1196.                 && read_data.input!='\n'
  1197.              )
  1198.              { if (!dest_mac) rc_put_c(read_data.input,rc.fp);
  1199.                read_in();
  1200.              }
  1201.             if (!dest_mac) rc_put_c(0,rc.fp);
  1202.             break;
  1203.          /*}}}  */
  1204.          /*{{{  error*/
  1205.          case OPP_ERROR:
  1206.             error_po();
  1207.             while
  1208.              (    read_data.input
  1209.                && read_data.input!=EOF
  1210.                && read_data.input!='\n'
  1211.              )
  1212.              { fputc(read_data.input,stderr);
  1213.                read_in();
  1214.              }
  1215.             fputc('\n',stderr);
  1216.             return(ERROR);
  1217.          /*}}}  */
  1218.          /*{{{  handle the end of a block*/
  1219.          case FI:
  1220.             if (missing_gnisu)
  1221.              /*{{{  handle the end of a block*/
  1222.              { missing_gnisu--;
  1223.                /*{{{  very_verbose-message*/
  1224.                if (verbose_level>3)
  1225.                   fprintf
  1226.                    ( stderr,
  1227.                      F_USEEND,
  1228.                      missing_gnisu+1,
  1229.                      f_s_ptr?name_stack[f_s_ptr]:source,
  1230.                      read_data.line
  1231.                    );
  1232.                /*}}}  */
  1233.                break;
  1234.              }
  1235.              /*}}}  */
  1236.          /*}}}  */
  1237.          default:
  1238.          /*{{{  wrong opp-statement*/
  1239.            m_exit(t==FI ? M_ENDUSE : M_OPP);
  1240.          /*}}}  */
  1241.        }
  1242.       /*}}}  */
  1243.      else
  1244.         break;
  1245.    }
  1246.   /*{{{  check missing fi*/
  1247.   if (t==ENDFILE && missing_gnisu)
  1248.      m_exit(M_BEGINUSE);
  1249.   /*}}}  */
  1250.   return(t);
  1251. }
  1252. /*}}}  */
  1253.  
  1254. /*{{{  get_full_token*/
  1255. public tokens get_full_token(void)
  1256. {
  1257.   return(get_token(full_scanning));
  1258. }
  1259. /*}}}  */
  1260. /*{{{  get_keycode_token*/
  1261. public tokens get_keycode_token(void)
  1262. {
  1263.   return(get_token(key_scanning));
  1264. }
  1265. /*}}}  */
  1266. /*{{{  get_single_token*/
  1267. public tokens get_single_token(void)
  1268. {
  1269.   return(get_token(single_scanning));
  1270. }
  1271. /*}}}  */
  1272. /*}}}  */
  1273.