Skip to content
Snippets Groups Projects
Select Git revision
  • nettle_3.1.1_release_20150424
  • master default protected
  • streebog
  • gost28147
  • master-updates
  • ed448
  • shake256
  • curve448
  • ecc-sqrt
  • gosthash94cp
  • cmac64
  • block16-refactor
  • siv-mode
  • cmac-layout
  • delete-des-compat
  • delete-rsa_blind
  • aes-struct-layout
  • release-3.4-fixes
  • struct-layout
  • attribute-deprecated
  • rename-data-symbols
  • nettle_3.5.1_release_20190627
  • nettle_3.5_release_20190626
  • nettle_3.5rc1
  • nettle_3.4.1_release_20181204
  • nettle_3.4.1rc1
  • nettle_3.4_release_20171119
  • nettle_3.4rc2
  • nettle_3.4rc1
  • nettle_3.3_release_20161001
  • nettle_3.2_release_20160128
  • nettle_3.1_release_20150407
  • nettle_3.1rc3
  • nettle_3.1rc2
  • nettle_3.1rc1
  • nettle_3.0_release_20140607
  • nettle_2.7.1_release_20130528
  • nettle_2.7_release_20130424
  • nettle_2.6_release_20130116
  • nettle_2.5_release_20120707
40 results

camellia256-meta.c

Blame
  • Forked from Nettle / nettle
    Source project has a limited visibility.
    lex.c 21.71 KiB
    /*\
    ||| This file a part of Pike, and is copyright by Fredrik Hubinette
    ||| Pike is distributed as GPL (General Public License)
    ||| See the files COPYING and DISCLAIMER for more information.
    \*/
    #include "global.h"
    RCSID("$Id: lex.c,v 1.55 1998/06/07 12:26:51 grubba Exp $");
    #include "language.h"
    #include "array.h"
    #include "lex.h"
    #include "stralloc.h"
    #include "dynamic_buffer.h"
    #include "constants.h"
    #include "hashtable.h"
    #include "stuff.h"
    #include "pike_memory.h"
    #include "interpret.h"
    #include "error.h"
    #include "object.h"
    #include "las.h"
    #include "operators.h"
    #include "opcodes.h"
    #include "builtin_functions.h"
    #include "main.h"
    #include "mapping.h"
    
    #include "pike_macros.h"
    
    #ifdef HAVE_SYS_PARAM_H
    #include <sys/param.h>
    #endif
    
    #include <ctype.h>
    #include <math.h>
    #include <fcntl.h>
    #include <errno.h>
    #include "time_stuff.h"
    
    #define LEXDEBUG 0
    
    #ifdef INSTR_PROFILING
    int last_instruction=0;
    #endif
    
    void exit_lex(void)
    {
    #ifdef DEBUG
      if(p_flag)
      {
        int e;
        fprintf(stderr,"Opcode usage: (opcode, runned, compiled)\n");
        for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++)
        {
          fprintf(stderr,":: %-30s %8ld %8ld\n",
    	      low_get_f_name(e+F_OFFSET,0),
    	      (long)instrs[e].runs,
    	      (long)instrs[e].compiles);
        }
    
    #ifdef INSTR_PROFILING
        for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++)
        {
          int d;
          for(d=0;d<256;d++)
    	if(instrs[e].reruns[d])
    	  fprintf(stderr,"%010ld::%s - %s\n",instrs[e].reruns[d],low_get_f_name(e+F_OFFSET,0),low_get_f_name(d+F_OFFSET,0));
        }
    #endif
      }
    #endif
    }
    
    struct keyword instr_names[]=
    {
    { "!",			F_NOT },	
    { "!=",			F_NE },	
    { "%",			F_MOD },	
    { "%=",			F_MOD_EQ },	
    { "& global",           F_GLOBAL_LVALUE, I_HASARG },
    { "& local",            F_LOCAL_LVALUE, I_HASARG },
    { "&",			F_AND },
    { "&=",			F_AND_EQ },	
    { "*",			F_MULTIPLY },	
    { "*=",			F_MULT_EQ },	
    { "+",			F_ADD },	
    { "++x",		F_INC },	
    { "+=",			F_ADD_EQ },	
    { "-",			F_SUBTRACT },	
    { "--x",		F_DEC },	
    { "-=",			F_SUB_EQ },	
    { "/",			F_DIVIDE },	
    { "/=",			F_DIV_EQ },	
    { "<",			F_LT },	
    { "<<",			F_LSH },	
    { "<<=",		F_LSH_EQ },	
    { "<=",			F_LE },	
    { "==",			F_EQ },	
    { ">",			F_GT },	
    { ">=",			F_GE },	
    { ">>",			F_RSH },	
    { ">>=",		F_RSH_EQ },	
    { "@",			F_PUSH_ARRAY },
    { "^",			F_XOR },
    { "^=",			F_XOR_EQ },	
    { "arg+=1024",		F_PREFIX_1024 },
    { "arg+=256",		F_PREFIX_256 },
    { "arg+=256*X",		F_PREFIX_CHARX256 },
    { "arg+=256*XX",	F_PREFIX_WORDX256 },
    { "arg+=256*XXX",	F_PREFIX_24BITX256 },
    { "arg+=512",		F_PREFIX_512 },
    { "arg+=768",		F_PREFIX_768 },
    { "assign and pop",	F_ASSIGN_AND_POP },
    { "assign global",	F_ASSIGN_GLOBAL, I_HASARG },
    { "assign global and pop",	F_ASSIGN_GLOBAL_AND_POP, I_HASARG },
    { "assign local",       F_ASSIGN_LOCAL, I_HASARG },
    { "assign local and pop",	F_ASSIGN_LOCAL_AND_POP, I_HASARG },
    { "assign",		F_ASSIGN },
    { "break",		F_BREAK },	
    { "case",		F_CASE },	
    { "cast",		F_CAST },	
    { "const-1",		F_CONST_1 },	
    { "constant",           F_CONSTANT, I_HASARG },
    { "continue",		F_CONTINUE },	
    { "copy_value",         F_COPY_VALUE },
    { "default",		F_DEFAULT },	
    { "do-while",		F_DO },	
    { "dumb return",	F_DUMB_RETURN },	
    { "float number",	F_FLOAT },
    { "for",		F_FOR },
    { "global",		F_GLOBAL, I_HASARG },
    { "index",              F_INDEX },
    { "->x",                F_ARROW, I_HASARG },
    { "clear string subtype", F_CLEAR_STRING_SUBTYPE },
    { "arrow string",       F_ARROW_STRING, I_HASARG },
    { "indirect",		F_INDIRECT },
    
    { "branch",             F_BRANCH, I_ISJUMP },
    { "branch non zero",	F_BRANCH_WHEN_NON_ZERO, I_ISJUMP },	
    { "branch if local",	F_BRANCH_IF_LOCAL, I_HASARG },	
    { "branch if !local",	F_BRANCH_IF_NOT_LOCAL, I_HASARG },	
    { "branch if ! local->x",	F_BRANCH_IF_NOT_LOCAL_ARROW, I_HASARG },	
    { "branch when zero",	F_BRANCH_WHEN_ZERO, I_ISJUMP },	
    { "branch if <",	F_BRANCH_WHEN_LT, I_ISJUMP },
    { "branch if >",	F_BRANCH_WHEN_GT, I_ISJUMP },
    { "branch if <=",	F_BRANCH_WHEN_LE, I_ISJUMP },
    { "branch if >=",	F_BRANCH_WHEN_GE, I_ISJUMP },
    { "branch if ==",	F_BRANCH_WHEN_EQ, I_ISJUMP },
    { "branch if !=",	F_BRANCH_WHEN_NE, I_ISJUMP },
    { "branch & pop if zero",	F_BRANCH_AND_POP_WHEN_ZERO, I_ISJUMP },
    { "branch & pop if !zero",	F_BRANCH_AND_POP_WHEN_NON_ZERO, I_ISJUMP },
    { "++Loop",		F_INC_LOOP, I_ISJUMP },	
    { "++Loop!=",		F_INC_NEQ_LOOP, I_ISJUMP },
    { "--Loop",		F_DEC_LOOP, I_ISJUMP },	
    { "--Loop!=",		F_DEC_NEQ_LOOP, I_ISJUMP },
    { "&&",			F_LAND, I_ISJUMP },	
    { "||",			F_LOR, I_ISJUMP },	
    { "==||",               F_EQ_OR, I_ISJUMP },
    { "==&&",               F_EQ_AND, I_ISJUMP },
    { "catch",		F_CATCH, I_ISJUMP },
    { "foreach",		F_FOREACH, I_ISJUMP },
    { "pointer",		F_POINTER, I_ISPOINTER },
    { "data",		F_DATA, I_DATA },
    
    { "local function call",F_CALL_LFUN, I_HASARG },
    { "local function call and pop",F_CALL_LFUN_AND_POP, I_HASARG },
    { "local function",	F_LFUN, I_HASARG },	
    { "local",		F_LOCAL, I_HASARG },	
    { "external",		F_EXTERNAL, I_HASARG },
    { "& external",		F_EXTERNAL_LVALUE, I_HASARG },
    { "LDA",			F_LDA, I_HASARG },
    { "mark & local",	F_MARK_AND_LOCAL, I_HASARG },	
    { "ltosval2",		F_LTOSVAL2 },
    { "lvalue to svalue",	F_LTOSVAL },	
    { "lvalue_list",	F_LVALUE_LIST },	
    { "[ lvalues ]",	F_ARRAY_LVALUE, I_HASARG },	
    { "mark sp-X",          F_MARK_X, I_HASARG },
    { "mark",               F_MARK },
    { "mark mark",          F_MARK2 },
    { "negative number",	F_NEG_NUMBER, I_HASARG },
    { "number",             F_NUMBER, I_HASARG },
    { "pop",		F_POP_VALUE },	
    { "pop_n_elems",        F_POP_N_ELEMS, I_HASARG },
    { "push 0",             F_CONST0 },
    { "push 1",             F_CONST1 },
    { "push 0x7fffffff",    F_BIGNUM },
    { "range",              F_RANGE },
    { "return",		F_RETURN },
    { "return 0",		F_RETURN_0 },
    { "return 1",		F_RETURN_1 },
    { "return local",	F_RETURN_LOCAL, I_HASARG },
    { "sscanf",		F_SSCANF, I_HASARG },	
    { "string",             F_STRING, I_HASARG },
    { "switch",		F_SWITCH, I_HASARG },
    { "unary minus",	F_NEGATE },
    { "while",		F_WHILE },	
    { "x++ and pop",	F_INC_AND_POP },	
    { "x++",		F_POST_INC },	
    { "x-- and pop",	F_DEC_AND_POP },	
    { "x--",		F_POST_DEC },	
    { "|",			F_OR },
    { "|=",			F_OR_EQ },	
    { "~",			F_COMPL },
    { "label",		F_LABEL,1 },
    { "align",		F_ALIGN, I_HASARG },
    { "call",		F_APPLY, I_HASARG },
    { "clear local",	F_CLEAR_LOCAL, I_HASARG },
    { "clear 2 local",	F_CLEAR_2_LOCAL, I_HASARG },
    { "clear 4 local",	F_CLEAR_4_LOCAL, I_HASARG },
    { "++local",		F_INC_LOCAL, I_HASARG },
    { "++local and pop",	F_INC_LOCAL_AND_POP, I_HASARG },
    { "local++",		F_POST_INC_LOCAL, I_HASARG },
    { "--local",		F_DEC_LOCAL, I_HASARG },
    { "--local and pop",	F_DEC_LOCAL_AND_POP, I_HASARG },
    { "local--",		F_POST_DEC_LOCAL, I_HASARG },
    { "sizeof",		F_SIZEOF },
    { "sizeof local",	F_SIZEOF_LOCAL, I_HASARG },
    { "throw(0)",		F_THROW_ZERO },
    { "string index",       F_STRING_INDEX, I_HASARG },
    { "local index",        F_LOCAL_INDEX, I_HASARG },
    { "local local index",  F_LOCAL_LOCAL_INDEX, I_HASARG },
    { "int index",          F_POS_INT_INDEX, I_HASARG },
    { "-int index",         F_NEG_INT_INDEX, I_HASARG },
    { "apply and pop",      F_APPLY_AND_POP, I_HASARG },
    { "2 locals",           F_2_LOCALS, I_HASARG },
    { "byte",               F_BYTE, I_HASARG },
    { "nop",                F_NOP },
    { "add integer",        F_ADD_INT, I_HASARG },
    { "add -integer",       F_ADD_NEG_INT, I_HASARG },
    { "mark & string",      F_MARK_AND_STRING, I_HASARG },
    { "mark & call",        F_MARK_APPLY, I_HASARG },
    { "mark, call & pop",   F_MARK_APPLY_POP, I_HASARG },
    { "apply and return",   F_APPLY_AND_RETURN, I_HASARG },
    { "apply, assign local and pop",   F_APPLY_ASSIGN_LOCAL_AND_POP, I_HASARG },
    { "apply & assign local",   F_APPLY_ASSIGN_LOCAL, I_HASARG },
    { "call lfun & return", F_CALL_LFUN_AND_RETURN, I_HASARG },
    { "call function",      F_CALL_FUNCTION, 0 },
    { "call function & return", F_CALL_FUNCTION_AND_RETURN, 0 },
    { "+= and pop",         F_ADD_TO_AND_POP, 0 },
    { "local=local;",       F_LOCAL_2_LOCAL, I_HASARG },
    { "local=global;",      F_GLOBAL_2_LOCAL, I_HASARG },
    { "global=local;",      F_LOCAL_2_GLOBAL, I_HASARG },
    { "local->x",           F_LOCAL_ARROW, I_HASARG },
    { "global[local]",      F_GLOBAL_LOCAL_INDEX, I_HASARG },
    };
    
    struct instr instrs[F_MAX_INSTR - F_OFFSET];
    
    struct reserved
    {
      struct hash_entry link;
      int token;
    };
    
    void init_lex()
    {
      unsigned int i;
      for(i=0; i<NELEM(instr_names);i++)
      {
        if(instr_names[i].token >= F_MAX_INSTR)
          fatal("Error in instr_names[%u]\n\n",i);
    
        if(instrs[instr_names[i].token - F_OFFSET].name)
          fatal("Duplicate name for %s\n",instr_names[i].word);
    
        instrs[instr_names[i].token - F_OFFSET].name = instr_names[i].word;
        instrs[instr_names[i].token - F_OFFSET].flags=instr_names[i].flags;
      }
    }
    
    char *low_get_f_name(int n,struct program *p)
    {
      static char buf[30];
      
      if (n<F_MAX_OPCODE && instrs[n-F_OFFSET].name)
      {
        return instrs[n-F_OFFSET].name;
      }else if(n >= F_MAX_OPCODE) {
        if(p &&
           (int)p->num_constants > (int)(n-F_MAX_OPCODE) &&
           p->constants[n-F_MAX_OPCODE].type==T_FUNCTION &&
           (p->constants[n-F_MAX_OPCODE].subtype == FUNCTION_BUILTIN) &&
           p->constants[n-F_MAX_OPCODE].u.efun)
        {
          return p->constants[n-F_MAX_OPCODE].u.efun->name->str;
        }else{
          sprintf(buf, "Call efun %d", n - F_MAX_OPCODE);
          return buf;
        }
      }else{
        sprintf(buf, "<OTHER %d>", n);
        return buf;
      }
    }
    
    char *get_f_name(int n)
    {
      static char buf[30];
      if (n<F_MAX_OPCODE && instrs[n-F_OFFSET].name)
      {
        return instrs[n-F_OFFSET].name;
      }else if(n >= F_MAX_OPCODE) {
        if(fp && fp->context.prog &&
           (int)fp->context.prog->num_constants > (int)(n-F_MAX_OPCODE) &&
           fp->context.prog->constants[n-F_MAX_OPCODE].type==T_FUNCTION &&
           fp->context.prog->constants[n-F_MAX_OPCODE].subtype == FUNCTION_BUILTIN &&
           fp->context.prog->constants[n-F_MAX_OPCODE].u.efun)
        {
          return fp->context.prog->constants[n-F_MAX_OPCODE].u.efun->name->str;
        }else{
          sprintf(buf, "Call efun %d", n - F_MAX_OPCODE);
          return buf;
        }
      }else{
        sprintf(buf, "<OTHER %d>", n);
        return buf;
      }
    }
    
    char *get_token_name(int n)
    {
      static char buf[30];
      if (n<F_MAX_INSTR && instrs[n-F_OFFSET].name)
      {
        return instrs[n-F_OFFSET].name;
      }else{
        sprintf(buf, "<OTHER %d>", n);
        return buf;
      }
    }
    
    struct lex lex;
    
    #define LOOK() EXTRACT_UCHAR(lex.pos)
    #define GETC() EXTRACT_UCHAR(lex.pos++)
    #define GOBBLE(c) (LOOK()==c?(lex.pos++,1):0)
    #define SKIPSPACE() do { while(ISSPACE(LOOK()) && LOOK()!='\n') lex.pos++; }while(0)
    #define SKIPWHITE() do { while(ISSPACE(LOOK())) lex.pos++; }while(0)
    #define SKIPUPTO(X) do { while(LOOK()!=(X) && LOOK()) lex.pos++; }while(0)
    
    #define READBUF(X) {				\
      register int C;				\
      buf=lex.pos;					\
      while((C=LOOK()) && (X)) lex.pos++;		\
      len=lex.pos - buf;				\
    }
    
    #define TWO_CHAR(X,Y) ((X)<<8)+(Y)
    #define ISWORD(X) (len==(long)strlen(X) && !MEMCMP(buf,X,strlen(X)))
    
    /*** Lexical analyzing ***/
    
    static int char_const(void)
    {
      int c;
      switch(c=GETC())
      {
        case 0:
          lex.pos--;
          yyerror("Unexpected end of file\n");
          return 0;
          
        case '0': case '1': case '2': case '3':
        case '4': case '5': case '6': case '7':
          c-='0';
          if(LOOK()<'0' || LOOK()>'8') return c;
          c=c*8+(GETC()-'0');
          if(LOOK()<'0' || LOOK()>'8') return c;
          c=c*8+(GETC()-'0');
          return c;
          
        case 'r': return '\r';
        case 'n': return '\n';
        case 't': return '\t';
        case 'b': return '\b';
          
        case '\n':
          lex.current_line++;
          return '\n';
          
          
        case 'x':
          switch(LOOK())
          {
    	default: return c;
    	case '0': case '1': case '2': case '3':
    	case '4': case '5': case '6': case '7':
    	case '8': case '9':
    	  c=GETC()-'0';
    	  break;
    	  
    	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
    	  c=GETC()-'a'+10;
    	  break;
    	  
    	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
    	  c=GETC()-'A'+10;
    	  break;
          }
          switch(LOOK())
          {
    	default: return c;
    	case '0': case '1': case '2': case '3':
    	case '4': case '5': case '6': case '7':
    	case '8': case '9':
    	  c=c*16+GETC()-'0';
    	  break;
    	  
    	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
    	  c=c*16+GETC()-'a'+10;
    	  break;
    	  
    	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
    	  c=c*16+GETC()-'A'+10;
    	  break;
          }
          return c;
        
      }
      return c;
    }
    
    static struct pike_string *readstring(void)
    {
      int c;
      dynamic_buffer tmp;
      initialize_buf(&tmp);
      
      while(1)
      {
        switch(c=GETC())
        {
        case 0:
          lex.pos--;
          yyerror("End of file in string.");
          break;
          
        case '\n':
          lex.current_line++;
          yyerror("Newline in string.");
          break;
          
        case '\\':
          low_my_putchar(char_const(),&tmp);
          continue;
          
        case '"':
          break;
          
        default:
          low_my_putchar(c,&tmp);
          continue;
        }
        break;
      }
      return low_free_buf(&tmp);
    }
    
    int yylex(YYSTYPE *yylval)
    #if LEXDEBUG>4
    {
      int t;
      int yylex2(YYSTYPE *);
      t=yylex2(yylval);
      if(t<256)
      {
        fprintf(stderr,"YYLEX: '%c' (%d) at %s:%d\n",t,t,lex.current_file->str,lex.current_line);
      }else{
        fprintf(stderr,"YYLEX: %s (%d) at %s:%d\n",low_get_f_name(t,0),t,lex.current_file->str,lex.current_line);
      }
      return t;
    }
    
    static int yylex2(YYSTYPE *yylval)
    #endif
    {
      INT32 c,len;
      char *buf;
    
    #ifdef __CHECKER__
      MEMSET((char *)yylval,0,sizeof(YYSTYPE));
    #endif
    #ifdef MALLOC_DEBUG
      check_sfltable();
    #endif
    
      while(1)
      {
        switch(c=GETC())
        {
        case 0:
          lex.pos--;
    #ifdef F_LEX_EOF
          return F_LEX_EOF;
    #else /* !F_LEX_EOF */
          return 0;
    #endif /* F_LEX_EOF */
    
        case '\n':
          lex.current_line++;
          continue;
    
        case '#':
          SKIPSPACE();
          READBUF(C!=' ' && C!='\t' && C!='\n');
    
          switch(len>0?buf[0]:0)
          {
    	char *p;
    	
          case 'l':
    	if(!ISWORD("line")) goto badhash;
    	READBUF(C!=' ' && C!='\t' && C!='\n');
    	
          case '0': case '1': case '2': case '3': case '4':
          case '5': case '6': case '7': case '8': case '9':
    	lex.current_line=atoi(buf)-1;
    	SKIPSPACE();
    	if(GOBBLE('"'))
    	{
    	  struct pike_string *tmp=readstring();
    	  free_string(lex.current_file);
    	  lex.current_file=tmp;
    	}
    	break;
    	
          case 'e':
    	if(ISWORD("error"))
    	{
    	  SKIPSPACE();
    	  READBUF(C!='\n');
    	  yyerror(buf);
    	  break;
    	}
    	goto badhash;
    
          case 'p':
    	if(ISWORD("pragma"))
    	{
    	  SKIPSPACE();
    	  READBUF(C!='\n');
    	  if (strcmp(buf, "all_inline") == 0)
    	  {
    	    lex.pragmas |= ID_INLINE;
    	  }
    	  else if (strcmp(buf, "all_nomask") == 0)
    	  {
    	    lex.pragmas |= ID_NOMASK;
    	  }
    	  break;
    	}
    	
          badhash:
    	if (sizeof(buf) < 1024) {
    	  my_yyerror("Unknown preprocessor directive #%s.",buf);
    	} else {
    	  my_yyerror("Unknown preprocessor directive.");
    	}
    	SKIPUPTO('\n');
    	continue;
          }
          continue;
    
        case ' ':
        case '\t':
          continue;
    
        case '\'':
          switch(c=GETC())
          {
          case 0:
    	lex.pos--;
    	yyerror("Unexpected end of file\n");
    	break;
    
    	case '\\':
    	  c=char_const();
          }
          if(!GOBBLE('\''))
    	yyerror("Unterminated character constant.");
          yylval->number=c;
          return F_NUMBER;
    	
        case '"':
        {
          struct pike_string *s=readstring();
          yylval->n=mkstrnode(s);
          free_string(s);
          return F_STRING;
        }
      
        case ':':
          if(GOBBLE(':')) return F_COLON_COLON;
          return c;
    
        case '.':
          if(GOBBLE('.'))
          {
    	if(GOBBLE('.')) return F_DOT_DOT_DOT;
    	return F_DOT_DOT;
          }
          return c;
      
        case '0':
          if(GOBBLE('x') || GOBBLE('X'))
          {
    	yylval->number=STRTOL(lex.pos, &lex.pos, 16);
    	return F_NUMBER;
          }
      
        case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
        {
          char *p1, *p2;
          double f;
          long l;
          lex.pos--;
          f=my_strtod(lex.pos, &p1);
          l=STRTOL(lex.pos, &p2, 0);
    
          if(p1>p2)
          {
    	lex.pos=p1;
    	yylval->fnum=(FLOAT_TYPE)f;
    	return F_FLOAT;
          }else{
    	lex.pos=p2;
    	yylval->number=l;
    	return F_NUMBER;
          }
      
        case '-':
          if(GOBBLE('=')) return F_SUB_EQ;
          if(GOBBLE('>')) return F_ARROW;
          if(GOBBLE('-')) return F_DEC;
          return '-';
      
        case '+':
          if(GOBBLE('=')) return F_ADD_EQ;
          if(GOBBLE('+')) return F_INC;
          return '+';
      
        case '&':
          if(GOBBLE('=')) return F_AND_EQ;
          if(GOBBLE('&')) return F_LAND;
          return '&';
      
        case '|':
          if(GOBBLE('=')) return F_OR_EQ;
          if(GOBBLE('|')) return F_LOR;
          return '|';
    
        case '^':
          if(GOBBLE('=')) return F_XOR_EQ;
          return '^';
      
        case '*':
          if(GOBBLE('=')) return F_MULT_EQ;
          return '*';
    
        case '%':
          if(GOBBLE('=')) return F_MOD_EQ;
          return '%';
      
        case '/':
          if(GOBBLE('=')) return F_DIV_EQ;
          return '/';
      
        case '=':
          if(GOBBLE('=')) return F_EQ;
          return '=';
      
        case '<':
          if(GOBBLE('<'))
          {
    	if(GOBBLE('=')) return F_LSH_EQ;
    	return F_LSH;
          }
          if(GOBBLE('=')) return F_LE;
          return '<';
      
        case '>':
          if(GOBBLE(')')) return F_MULTISET_END;
          if(GOBBLE('=')) return F_GE;
          if(GOBBLE('>'))
          {
    	if(GOBBLE('=')) return F_RSH_EQ;
    	return F_RSH;
          }
          return '>';
    
        case '!':
          if(GOBBLE('=')) return F_NE;
          return F_NOT;
    
        case '(':
          if(GOBBLE('<')) return F_MULTISET_START;
          return '(';
    
        case ']':
        case '?':
        case ',':
        case '~':
        case '@':
        case ')':
        case '[':
        case '{':
        case ';':
        case '}': return c;
    
        case '`':
        {
          char *tmp;
          int offset=2;
          if(GOBBLE('`')) offset--;
          if(GOBBLE('`')) offset--;
          
          switch(GETC())
          {
          case '+': tmp="```+"; break;
          case '/': tmp="```/"; break;
          case '%': tmp="```%"; break;
          case '*': tmp="```*"; break;
          case '&': tmp="```&"; break;
          case '|': tmp="```|"; break;
          case '^': tmp="```^"; break;
          case '~': tmp="```~"; break;
          case '<':
    	if(GOBBLE('<')) { tmp="```<<"; break; }
    	if(GOBBLE('=')) { tmp="```<="; break; }
    	tmp="```<";
    	break;
    
          case '>':
    	if(GOBBLE('>')) { tmp="```>>"; break; }
    	if(GOBBLE('=')) { tmp="```>="; break; }
    	tmp="```>";
    	break;
    
          case '!':
    	if(GOBBLE('=')) { tmp="```!="; break; }
    	tmp="```!";
    	break;
    
          case '=':
    	if(GOBBLE('=')) { tmp="```=="; break; }
    	tmp="```=";
    	break;
    
          case '(':
    	if(GOBBLE(')')) 
    	{
    	  tmp="```()";
    	  break;
    	}
    	yyerror("Illegal ` identifier.");
    	tmp="``";
    	break;
    	
          case '-':
    	if(GOBBLE('>'))
    	{
    	  tmp="```->";
    	  if(GOBBLE('=')) tmp="```->=";
    	}else{
    	  tmp="```-";
    	}
    	break;
    
          case '[':
    	if(GOBBLE(']'))
    	{
    	  tmp="```[]";
    	  if(GOBBLE('=')) tmp="```[]=";
    	  break;
    	}
    
          default:
    	yyerror("Illegal ` identifier.");
    	lex.pos--;
    	tmp="``";
    	break;
          }
    
          {
    	struct pike_string *s=make_shared_string(tmp+offset);
    	yylval->n=mkstrnode(s);
    	free_string(s);
    	return F_IDENTIFIER;
          }
        }
    
      
        default:
          if(isidchar(c))
          {
    	struct pike_string *s;
    	lex.pos--;
    	READBUF(isidchar(C));
    
    	yylval->number=lex.current_line;
    
    	if(len>1 && len<10)
    	{
    	  switch(TWO_CHAR(buf[0],buf[1]))
    	  {
    	  case TWO_CHAR('a','r'):
    	    if(ISWORD("array")) return F_ARRAY_ID;
    	  break;
    	  case TWO_CHAR('b','r'):
    	    if(ISWORD("break")) return F_BREAK;
    	  break;
    	  case TWO_CHAR('c','a'):
    	    if(ISWORD("case")) return F_CASE;
    	    if(ISWORD("catch")) return F_CATCH;
    	  break;
    	  case TWO_CHAR('c','l'):
    	    if(ISWORD("class")) return F_CLASS;
    	  break;
    	  case TWO_CHAR('c','o'):
    	    if(ISWORD("constant")) return F_CONSTANT;
    	    if(ISWORD("continue")) return F_CONTINUE;
    	  break;
    	  case TWO_CHAR('d','e'):
    	    if(ISWORD("default")) return F_DEFAULT;
    	  break;
    	  case TWO_CHAR('d','o'):
    	    if(ISWORD("do")) return F_DO;
    	  break;
    	  case TWO_CHAR('e','l'):
    	    if(ISWORD("else")) return F_ELSE;
    	  break;
    	  case TWO_CHAR('f','i'):
    	    if(ISWORD("final")) return F_FINAL_ID;
    	  break;
    	  case TWO_CHAR('f','l'):
    	    if(ISWORD("float")) return F_FLOAT_ID;
    	  break;
    	  case TWO_CHAR('f','o'):
    	    if(ISWORD("for")) return F_FOR;
    	    if(ISWORD("foreach")) return F_FOREACH;
    	  break;
    	  case TWO_CHAR('f','u'):
    	    if(ISWORD("function")) return F_FUNCTION_ID;
    	  break;
    	  case TWO_CHAR('g','a'):
    	    if(ISWORD("gauge")) return F_GAUGE;
    	  break;
    	  case TWO_CHAR('i','f'):
    	    if(ISWORD("if")) return F_IF;
    	  break;
    	  case TWO_CHAR('i','m'):
    	    if(ISWORD("import")) return F_IMPORT;
    	  break;
    	  case TWO_CHAR('i','n'):
    	    if(ISWORD("int")) return F_INT_ID;
    	    if(ISWORD("inherit")) return F_INHERIT;
    	    if(ISWORD("inline")) return F_INLINE;
    	  break;
    	  case TWO_CHAR('l','a'):
    	    if(ISWORD("lambda")) return F_LAMBDA;
    	  break;
    	  case TWO_CHAR('l','o'):
    	    if(ISWORD("local")) return F_LOCAL_ID;
    	  break;
    	  case TWO_CHAR('m','a'):
    	    if(ISWORD("mapping")) return F_MAPPING_ID;
    	  break;
    	  case TWO_CHAR('m','i'):
    	    if(ISWORD("mixed")) return F_MIXED_ID;
    	  break;
    	  case TWO_CHAR('m','u'):
    	    if(ISWORD("multiset")) return F_MULTISET_ID;
    	  break;
    	  case TWO_CHAR('n','o'):
    	    if(ISWORD("nomask")) return F_NO_MASK;
    	  break;
    	  case TWO_CHAR('o','b'):
    	    if(ISWORD("object")) return F_OBJECT_ID;
    	  break;
    	  case TWO_CHAR('p','r'):
    	    if(ISWORD("predef")) return F_PREDEF;
    	    if(ISWORD("program")) return F_PROGRAM_ID;
    	    if(ISWORD("private")) return F_PRIVATE;
    	    if(ISWORD("protected")) return F_PROTECTED;
    	    break;
    	  break;
    	  case TWO_CHAR('p','u'):
    	    if(ISWORD("public")) return F_PUBLIC;
    	  break;
    	  case TWO_CHAR('r','e'):
    	    if(ISWORD("return")) return F_RETURN;
    	  break;
    	  case TWO_CHAR('s','s'):
    	    if(ISWORD("sscanf")) return F_SSCANF;
    	  break;
    	  case TWO_CHAR('s','t'):
    	    if(ISWORD("static")) return F_STATIC;
    	    if(ISWORD("string")) return F_STRING_ID;
    	  break;
    	  case TWO_CHAR('s','w'):
    	    if(ISWORD("switch")) return F_SWITCH;
    	  break;
    	  case TWO_CHAR('t','y'):
    	    if(ISWORD("typeof")) return F_TYPEOF;
    	  break;
    	  case TWO_CHAR('v','o'):
    	    if(ISWORD("void")) return F_VOID_ID;
    	  break;
    	  case TWO_CHAR('w','h'):
    	    if(ISWORD("while")) return F_WHILE;
    	  break;
    	  }
    	}
    	{
    	  struct pike_string *tmp=make_shared_binary_string(buf,len);
    	  yylval->n=mkstrnode(tmp);
    	  free_string(tmp);
    	  return F_IDENTIFIER;
    	}
          }else{
    	char buff[100];
    	sprintf(buff, "Illegal character (hex %02x) '%c'", c, c);
    	yyerror(buff);
    	return ' ';
          }
        }
        }
      }
    }