//Compiler Options
//  Use $LK,"OptOn","MN:OptOn"$() $LK,"OptOff","MN:OptOff"$()
//You might need to do $FG,2$#exe {OptOn();}$FG$

#define OPTf_UNUSED_VAR_WARN        0
#define OPTf_PAREN_WARN                1
#define OPTf_PARSE_TRACE        2
#define OPTf_COMPILE_TRACE        3
#define OPTf_ECHO                4
#define OPTf_OPT_TRACE                5
#define OPTf_LEX_TRACE                6
#define OPTf_EXTERNS_TO_IMPORTS        7
#define OPTf_KEEP_PRIVATE        8
#define OPTf_NO_REG_VAR                9
#define OPTf_STD_C                10

#define OPTF_ECHO                        (1<<OPTf_ECHO)
#define OPTF_PARSE_TRACE                (1<<OPTf_PARSE_TRACE)

#define LFSF_IS_INCLUDED        1
#define LFSF_IS_LTF                2
#define LFSF_IS_DEFINE                4

#define LFSf_IS_INCLUDED        0
#define LFSf_IS_LTF                1
#define LFSf_IS_DEFINE                2

class LexFileStruct
{
 I1 *buf;
 I1 *buf_ptr;
 I8 line_num,flags;
 I1 *name;
 I1 *line_start;
 Ltf *l;
 LtfEntry *cur_entry;
 I1 last_I1,pad[7];
};

class LexUndefEntry
{
 LexUndefEntry *next;
 SysSymHashEntry *hash;
};

#define ICF_R_TO_DOUBLE                        0x0000000001
#define ICF_R_TO_INT                        0x0000000002
#define ICF_P1_TO_DOUBLE                0x0000000004
#define ICF_P1_TO_INT                        0x0000000008
#define ICF_P2_TO_DOUBLE                0x0000000010
#define ICF_P2_TO_INT                        0x0000000020
#define ICF_P3_TO_DOUBLE                0x0000000040
#define ICF_P3_TO_INT                        0x0000000080
#define ICF_USE_DOUBLE                        0x0000000100
#define ICF_USE_UNSIGNED                0x0000000200
#define ICF_USE_INT                        0x0000000400 //highest priority
#define ICF_NO_DEPEND_RESULT                0x0000000800
#define ICF_CODE_FINAL                        0x0000001000
#define ICF_NOT_ADDRESS                        0x0000002000
#define ICF_SHORT_JMP                        0x0000004000
#define ICF_P1_FIRST                        0x0000008000
#define ICF_PUSH_RESULT                        0x0000010000
#define ICF_TRACE                        0x0000020000
#define ICF_R_WAS_STK                        0x0000040000
#define ICF_P1_WAS_STK                        0x0000080000
#define ICF_P2_WAS_STK                        0x0000100000
#define ICF_P3_WAS_STK                        0x0000200000
#define ICF_PUSH_CMP                        0x0000400000 //for 50<i<j<=100 expressions
#define ICF_POP_CMP                        0x0000800000 //for 50<i<j<=100 expressions
#define ICF_RCX_CMP                        0x0001000000 //for 50<i<j<=100 expressions
#define ICF_RCX_CMP2                        0x0002000000 //for 50<i<j<=100 expressions
#define ICF_DEPEND_RESULT                0x0004000000
#define ICF_SWAP                        0x0008000000
#define ICf_DONT_PUSH_FLOAT0                28
#define ICF_DONT_PUSH_FLOAT0                0x0010000000
#define ICF_DONT_PUSH_FLOAT1                0x0020000000
#define ICF_DONT_PUSH_FLOAT2                0x0040000000
#define ICF_DONT_PUSH_FLOAT3                0x0080000000
#define ICf_DONT_POP_FLOAT0                32
#define ICF_DONT_POP_FLOAT0                0x0100000000
#define ICF_DONT_POP_FLOAT1                0x0200000000
#define ICF_DONT_POP_FLOAT2                0x0400000000
#define ICF_DONT_POP_FLOAT3                0x0800000000
#define ICF_ALTERNATE_TEMPLATE                0x1000000000
#define ICF_NO_CVT_MASK                        0xFFFFFFFF00
#define IC_BODY_SIZE        64

#define ECF_HAS_PUSH_CMP                0x01 //for 50<i<j<=100 expressions


class IcArg
{
 U1 type,ptype;
 U2 reg; //low is reg, high is index_reg+scale<<6
 I8 disp;
};

class IntermediateCode
{//dup copys  $LK,"IC_CODE","FF:::/LT/OSMain/OSDefs.ASZ,IC_CODE"$
 U2 ic_opcode;
 U2 ic_precedence;
 U2 ic_cnt;
 U2 ic_last_cnt;

 U8 ic_flags;
 I8 ic_data;


 ClassStruct *ic_class;

 U4 ic_line;
 U1 ic_indent_level,pad1;
 U2 ic_start_line_offset;
 IcArg p1,p2,p3,r;

 U1 *ic_ext_body;
 U1 ic_body[IC_BODY_SIZE-7*sizeof(void *)];

//the following form a union with IC_BODY
 ClassStruct *original_class;
 ClassStruct *p1c,*p2c,*p3c;
 IntermediateCode *p1t,*p2t,*p3t;
};

#assert IC_BODY_SIZE>7*sizeof(void *)

class ParseStack
{//dup code $LK,"CP_PRSPUSH","FF:::/LT/OSMain2/Compiler/CmpAsm.ASZ,CP_PRSPUSH"$
 U8 ptr;
 I8 stk[255];
};

#define CB_IC_CNT 511
class CodeBlk
{
 CodeBlk *next;
 IntermediateCode data[CB_IC_CNT];
};

#define CBMT_LABEL                0
#define CBMT_GOTO_LABEL                1
#define CBMT_STR_CONST                2
#define CBMT_JMP_TABLE                3

#define CBMF_USED                1
#define CBMF_POP_CMP                2

class CbMiscStruct
{
 CbMiscStruct *next,*forward;
 I1 *str;
 U4 type,flags;
 U1 *address;
 U8 st_len;
 U1 **jmp_table;
};

#define IEF_OP_SIZE16                1
#define IEF_OP_SIZE32                2
#define IEF_DONT_SWITCH_MODES        4
#define IEF_PLUS_OPCODE                8
#define IEF_DEFAULT                16
#define IEF_NO_REX                32
#define IEF_40_REX                64
#define IEF_48_REX                128

#define SV_REGISTER        8
#define SV_NONE                9
class InstructionEntry
{
 U1 ins_entry_num; //This entry num in opcode hash entry
 U1 opcode_cnt;
 U1 opcode[4];
 U1 flags,slash_value,opcode_modifier;
 U1 arg1,arg2;
 U1 pad[5];
};

class OpcodeHashEntry
{
 SysHashEntry h;
 U1 instruction_entry_cnt;
 U1 pad[7];
 InstructionEntry ins[1];
};

#define ASM_CODE_BLK_BITS 16
#define ASM_CODE_BLK_SIZE (1<<ASM_CODE_BLK_BITS)

class AsmCodeBlk
{
 AsmCodeBlk *next;
 U1 body[ASM_CODE_BLK_SIZE];
};

class AsmArgStruct
{
 I8 seg,size,reg1,reg2;
 I8 imm;
 I8 scale;
 I8 absolute_address_cnt;
 BoolI1 indirect,imm_or_off_present,just_seg,pad[5];
 LexUndefEntry *undef_local,*undef_glbl;
 U1 *exp;
};

class AsmUnresolvedRef
{
 AsmUnresolvedRef *next;
 I8 type,line_num;
 U1 *exp;
 U8 ip,rel_ip;
 I1 *str;  //Only for import glbls
 LexUndefEntry *undef_hash;
 BoolI1 U1_avail;
 BoolI1 literal;  //Only for import glbls
};

#define EIE_REL_EXPORT                0
#define EIE_LIT_EXPORT                1
#define EIE_REL_U1                2
#define EIE_LIT_U1                3
#define EIE_REL_U2                4
#define EIE_LIT_U2                5
#define EIE_REL_U4                6
#define EIE_LIT_U4                7
#define EIE_REL_U8                8
#define EIE_LIT_U8                9
#define EIE_MAIN                16
#define EIE_ABSOLUTE_ADDRESS        32
#define EIE_END                        0xFF

class ExeImportExportStruct
{
 ExeImportExportStruct *next,*last;
 I8 ip;
 I1 *str;
 U1 type;
};

class ExeAbsoluteAddressStruct
{
 ExeAbsoluteAddressStruct *next;
 I8 ip;
 U1 type;
};

class ExeStruct
{
 U1 *code;
 I8 code_U1s;
 ExeImportExportStruct *next_ie,*last_ie;
 ExeAbsoluteAddressStruct *absolutes;
};


#define OM_NO 0
#define OM_R  1 // Not used
#define OM_CB 2
#define OM_CW 3
#define OM_CD 4
#define OM_CP 5
#define OM_IB 6
#define OM_IW 7
#define OM_ID 8
#define OM_RB 9
#define OM_RW 10
#define OM_RD 11

#define ARGT_NO                0
#define ARGT_REL8        1
#define ARGT_REL16        2
#define ARGT_REL32        3

#define ARGT_UIMM8        4
#define ARGT_UIMM16        5
#define ARGT_UIMM32        6
#define ARGT_UIMM64        7

#define ARGT_R8                8
#define ARGT_R16        9
#define ARGT_R32        10
#define ARGT_R64        11

#define ARGT_IMM8        12
#define ARGT_IMM16        13
#define ARGT_IMM32        14
#define ARGT_IMM64        15

#define ARGT_RM8        16
#define ARGT_RM16        17
#define ARGT_RM32        18
#define ARGT_RM64        19

#define ARGT_M8                20 // Not used, needed for LEA, etc
#define ARGT_M16        21 // Not used
#define ARGT_M32        22 // Not used
#define ARGT_M1616        23 // Not used

#define ARGT_M1632        24 // Not used
#define ARGT_M16N32        25 // Not used
#define ARGT_M16N16        26 // Not used
#define ARGT_M32N32        27 // Not used

#define ARGT_MOFFS8        28
#define ARGT_MOFFS16        29
#define ARGT_MOFFS32        30
#define ARGT_MOFFS64        31

#define ARGT_AL                32
#define ARGT_AX                33
#define ARGT_EAX        34
#define ARGT_RAX        35

#define ARGT_CL                36
#define ARGT_DX                37

#define ARGT_SREG        39

#define ARGT_SS                40
#define ARGT_DS                41
#define ARGT_ES                42
#define ARGT_FS                43

#define ARGT_GS                44
#define ARGT_CS                45

#define TK_EOF                        0
#define TK_IDENT                2
#define TK_STR                        3
#define TK_INTEGER                6
#define TK_DOUBLE                7

#define TK_PLUS_PLUS                11
#define TK_MINUS_MINUS                14
#define TK_DEREFERRENCE                15
#define TK_DOUBLE_COLON         16

#define TK_SHL                        17
#define TK_SHR                         18

#define TK_EQUAL_EQUAL                19
#define TK_NOT_EQUAL                20
#define TK_LESS_EQUAL                21
#define TK_GREATER_EQUAL        22

#define TK_AND_AND                23
#define TK_OR_OR                24
#define TK_XOR_XOR                25

#define TK_SHL_EQUAL                0x80
#define TK_SHR_EQUAL                0x81
#define TK_MUL_EQUAL                0x82
#define TK_DIV_EQUAL                0x83
#define TK_AND_EQUAL                0x84
#define TK_OR_EQUAL                0x85
#define TK_XOR_EQUAL                0x86
#define TK_ADD_EQUAL                0x87
#define TK_SUB_EQUAL                0x88
#define TK_CAST                        0x89
#define TK_IF                        0x8A
#define TK_IFDEF                0x8B
#define TK_IFNDEF                0x8C
#define TK_ENDIF                0x8D
#define TK_ELSE                        0x8E
#define TK_MOD_EQUAL                0x8F
#define TK_DOT_DOT                0x90
#define TK_DOT_DOT_DOT                0x91
#define TK_INSERT_BINARY        0x92
#define TK_INSERT_BINARY_TYPE        0x93
#define TK_INSERT_BINARY_SIZE        0x94

#define TK_NUM_TK                0x95

//Lex flags
#define LF_EXPECTING_HEX        1
#define LF_PROMPT                2
#define LF_DONT_FREE_BUFFER        4
#define LF_NO_DEFINES                8
#define LF_IN_IF                16
#define LF_JUST_LOAD                32

#define LFf_OPT_TRACE_PRESENT        6
#define LF_NOT_CONSTANT                0x0000008000
#define LF_NO_REG_OPT                0x0000010000
#define LF_IN_QUOTES                0x0000020000
#define LF_EXE_BLK                0x0000040000
#define LF_HAS_MISC_DATA        0x0000080000
#define LF_STR2                        0x0000100000
#define LF_ASM_EXPRESSIONS        0x0000200000
#define LF_UNRESOLVED_LOCAL        0x0000400000
#define LF_UNRESOLVED_GLBL        0x0000800000
#define LF_FUNCTION                0x0001000000
#define LF_POSTINC                0x0002000000
#define LF_POSTDEC                0x0004000000
#define LF_PREINC                0x0008000000
#define LF_PREDEC                0x0010000000
#define LF_ARRAY                0x0020000000
#define LF_RAX                        0x0040000000
#define LF_USE_LAST_I1                0x0080000000
#define LF_UNSIGNED                0x0100000000
#define LF_LAST_WAS_DOT                0x0200000000
#define LF_INSIDE_EXPRESSION        0x0400000000
#define LF_STATIC_COMPILE        0x0800000000
#define LF_BY_ADDRESS                0x1000000000
#define Lf_BY_ADDRESS                36
#define LF_NO_ABSOLUTES                0x2000000000

#define LEX_MAX_IDENT                134

#define LFN_CNT                8
#define LFN_STACK_CNT        32

#define ACSF_IN_STRUCT                1

class AsmCtrlStruct
{
 SysHashTable *local_hash,*glbl_hash;
 I8 ip,flags;        //instruction ptr
 AsmArgStruct arg1,arg2;
 AsmCodeBlk *code;
 I8 num_code_U1s;
 AsmUnresolvedRef *local_unresolved,*glbl_unresolved;
 ExeAbsoluteAddressStruct *absolutes;
 I8 display_col,last_ip;
 I1 *last_label,*last_line_listed;
 LexFileStruct *last_lfn;
 I8 seg_size;
 BoolI1 has_locals,list;
};

class ExeBlkStruct
{
 ExeBlkStruct *next,*last;
 U1 *body;
};

class LexCbStack
{
 LexCbStack                *cb_next;
 CodeBlk                 *cb_out_first;
 CodeBlk                 *cb_out_last;
 IntermediateCode         *cb_out_end;
 IntermediateCode         *cb_out_ptr;
 IntermediateCode         *cb_last_out_ptr;
 CodeBlk                 *cb_in_first;
 IntermediateCode         *cb_in_end;
 IntermediateCode         *cb_in_ptr;
 CbMiscStruct                 *cb_misc_list,*cb_misc_list_end;
};

#define NUM_REGS        16

public class LexStruct
{
 LexStruct *next,*last;
 I8        token;
 U8        flags;
 I8        cur_i;
 double cur_d;
 I1        *ident;
 I8        ident_len;
 I1        *cur_index;
 I8        last_I1,last_indent_level,last_line_num,start_line_num,indent_line_offset;
 I8        braces_cnt;
 I8        statement_cnt;
 I8        indent_level,expression_start_line;
 I8        instruction_ptr;  //For asm
 SysHashTable         *define_hash_table;
 SysHashTable         *local_hash_table;
 SysHashTable         *glbl_hash_table;
 U8 hash_mask;
 SysHashTable         *hash_table_list;
 GenericHashEntry *hash_entry;
 U8 absolute_address_cnt;
 LexUndefEntry  *undef_hash_entry;
 ClassStruct           *local_var_list;
 MemberListStruct *local_var_entry;
 CbMiscStruct        *leave_label;
 I1 *cur_buf_ptr;
 LexFileStruct *cur_lfn;
 I8 stack_ptr;
 ExeBlkStruct *next_exe_blk,*last_exe_blk;
 ExeStruct *exe_struct;
 U8 opts;
 U8 pass_trace_mask;
 U8 error_cnt,warning_cnt;
 I8 float_template_cnt;
 LexCbStack cb;
 AsmCtrlStruct *a;

 U0 end_of_zeroed_members;
 LexFileStruct lfns[LFN_CNT];
 LexFileStruct stack[LFN_STACK_CNT];
};




$PJ,"Project: OSMain2.SPZ","/LT/OSMain2/OSMain2.SPZ"$
I1 *CmpPmt(BoolI1 double_semicolon=FALSE)
{
 I8 i;
 I1 *s,*result;

 for (i=Fs->answers_displayed-1;i>=0;i--) {
     if (Fs->answers_types[i]==IT_DOUBLE)
         PrintF("ansd%d=%15.7g=%15e\r\n",i,
             Fs->double_answers[i],Fs->double_answers[i]);
     else
         PrintF("ans%d=0x%016X=%d\r\n",i,
             Fs->answers[i],Fs->answers[i]);
 }
 s=CurDir;
 PutS(s);
 Free(s);
 PutChar('>');
 s=MGetS(GETSF_CTRLQ_EXIT);
 if (double_semicolon) {
     i=StrLen(s);
     result=MAlloc(i+4);
     MemCpy(result,s,i+1);
     i--;
     while (i>=0 && Bt(white_space_bitmap,result[i]))
         i--;
     i++;
     if (i>0 && result[i-1]==';')
         result[i++]=';'; //The Lex goes one beyond
     result[i++]=13;//#define goes to <cr>
     result[i++]=10;
     result[i]=0;
 } else
     result=StrNew(s);
 Free(s);
 return result;
}

LexStruct *LexNew(I1 *buf,U8 flags,I1 *filename=NULL)
{
 LexStruct *lx=MAlloc(sizeof(LexStruct));
 LexFileStruct *tempf=&lx->lfns[0];
 MemSet(lx,0,offset(LexStruct.end_of_zeroed_members)+sizeof(LexFileStruct));
 lx->next=lx->last=lx;
 lx->flags=flags;
 lx->opts=1<<OPTf_UNUSED_VAR_WARN;
 lx->start_line_num=lx->last_line_num=1;
 lx->pass_trace_mask=0b1001111101;
 lx->hash_mask=HTT_ALL;
 lx->hash_table_list=Fs->hash_table;
 lx->define_hash_table=Fs->hash_table;
 lx->cur_lfn=tempf;
 lx->next_exe_blk=lx->last_exe_blk=&lx->next_exe_blk;
 if (!filename)
     tempf->name=StrNew(sys_temp_filename);
 else
     tempf->name=filename;
 if (flags & LF_PROMPT)
     buf=MAllocZ(4);
 tempf->buf=tempf->buf_ptr=tempf->line_start=lx->cur_buf_ptr=buf;
 tempf->line_num=1;
 return lx;
}

void LexDel(LexStruct *lx)
{
 LexFileStruct *tempf=lx->cur_lfn;
 Ltf *l;

 while (tempf!=&lx->lfns[0]) {
     if (l=tempf->l)
         CallExtNum(EXT_LTF_DEL,l);
     Free(tempf->buf);
     Free(tempf->name);
     tempf--;
 }
 Free(tempf->name);
 if (!(lx->flags & LF_DONT_FREE_BUFFER))
     Free(tempf->buf);
 Free(lx->ident);
 Free(lx);
}

U8 LexSize(LexStruct *lx)
{
 U8 result=0;
 LexFileStruct *tempf=lx->cur_lfn;
 Ltf *l;
 while (tempf!=&lx->lfns[0]) {
     if (l=tempf->l)
         result+=CallExtNum(EXT_LTF_SIZE,l);
     result+=MSize2(tempf->buf);
     result+=MSize2(tempf->name);
     tempf--;
 }
 result+=MSize2(tempf->name);
 if (!(lx->flags & LF_DONT_FREE_BUFFER))
     result+=MSize2(tempf->buf);
 result+=MSize2(lx->ident);
 result+=MSize2(lx);
 return result;
}

void SetSourceFileInfo(LexStruct *lx,SrcSymHashEntry *h)
{
 LexFileStruct *tempf=lx->cur_lfn;
 h->source_link=MSPrintF("FL:%s,%d",tempf->name,tempf->line_num);
 if (Bt(&lx->opts,OPTf_KEEP_PRIVATE))
     h->h.type|=HTT_PRIVATE;
 if (lx->cur_index)
     h->index=StrNew(lx->cur_index);
 else
     h->index=NULL;
}

void LexPutToken(LexStruct *lx)
{
 PutChar('"');
 if (lx->token==TK_IDENT || lx->token==TK_STR)
     PutS(lx->ident);
 else if (lx->token==TK_INTEGER)
     cout "INT:",lx->cur_i;
 else if (lx->token==TK_DOUBLE)
     cout "DBL:",lx->cur_d;
 else if (lx->token>=CH_SHIFT_SPACE && lx->token<=0x7E)
     PutChar(lx->token);
 else {
     cout "T:",lx->token;
 }
 PutS("\" ");
}

U4 lex_zeros=0,lex_line_feed=0x000A;

void LexBackupLastChar(LexStruct *lx)
{
 LexFileStruct *tempf=lx->cur_lfn;
 tempf->buf_ptr=lx->cur_buf_ptr;
 if (lx->flags & LF_USE_LAST_I1) {
     tempf->last_I1=lx->last_I1;
     lx->flags&=~LF_USE_LAST_I1;
 } else
     tempf->last_I1=0;
}

U8 LexGetChar(LexStruct *lx)
{
 U1 *src;
 LexFileStruct *tempf,*tempf1;
 BoolI1 cont;
 U8 result;
 Ltf *l;
 LtfEntry *cl;
 U1 *ptr;
 if (lx->flags & LF_USE_LAST_I1) {
     lx->flags&=~LF_USE_LAST_I1;
     if (lx->last_I1==CH_SHIFT_SPACE)
         return CH_SPACE;
     else
         return lx->last_I1;
 }
 do {
lex_getchar_start:

     src=lx->cur_buf_ptr++;
     switch (lx->last_I1=result=*src++) {
         case 0:
             tempf=lx->cur_lfn;
             if (tempf->flags & LFSF_IS_LTF) {
                 l=tempf->l;
                 cl=tempf->cur_entry;
                 cl=cl->next;
                 while (cl!=l) {
                     cont=FALSE;
                     tempf->cur_entry=cl;
                     switch (cl->btype) {
                         case LTFT_TEXT:
                             if (*(src=cl->tag))
                                 tempf->buf=tempf->buf_ptr=lx->cur_buf_ptr=src;
                             else {
                                 cont=TRUE;
                                 cl=cl->next;
                             }
                             break;
                         case LTFT_CR:
                             src=&lex_line_feed;
                             tempf->buf=tempf->buf_ptr=lx->cur_buf_ptr=src;

                             tempf->line_start=cl->next;
                             tempf->line_num=cl->y+2;        //+1 because CR is on previous
line, +1 because l y starts at zero
                             compiled_lines++;
                             if (lx->opts & OPTF_ECHO)
                                 CrLf;
                             lx->last_I1=CH_CR;
                             return CH_CR;
                         case LTFT_TAB:
                             src=&lex_zeros;
                             tempf->buf=tempf->buf_ptr=lx->cur_buf_ptr=src;

                             tempf->line_num=cl->y+1;
                             if (lx->opts & OPTF_ECHO)
                                 PutChar(CH_TAB);
                             lx->last_I1=CH_TAB;
                             return CH_TAB;
                         case LTFT_PAGE_BREAK:
                             src=&lex_zeros;
                             tempf->buf=tempf->buf_ptr=lx->cur_buf_ptr=src;

                             tempf->line_num=cl->y+2;        //TODO: should be a page down
                             if (lx->opts & OPTF_ECHO)
                                 PutChar(CH_FORM_FEED);
                             lx->last_I1=CH_FORM_FEED;
                             return CH_FORM_FEED;
                         case LTFT_INSERT_BINARY:
                             src=&lex_zeros;
                             tempf->buf=tempf->buf_ptr=lx->cur_buf_ptr=src;

                             tempf->line_num=cl->y+1;
                             Free(lx->ident);
                             lx->ident=NULL;
                             lx->ident_len=0;
                             if (cl->bin_data) {
                                 ptr=MAlloc(cl->bin_data->size);
                                 if (cl->bin_data->data)
                                     MemCpy(ptr,cl->bin_data->data,cl->bin_data->size);
                                 lx->ident=ptr;
                                 lx->ident_len=cl->bin_data->size;
                             }
                             lx->last_I1=TK_INSERT_BINARY;
                             return TK_INSERT_BINARY;
                         case LTFT_INSERT_BINARY_TYPE:
                             src=&lex_zeros;
                             tempf->buf=tempf->buf_ptr=lx->cur_buf_ptr=src;

                             if (cl->bin_data)
                                 lx->cur_i=cl->bin_data->type;
                             else
                                 lx->cur_i=0;
                             tempf->line_num=cl->y+1;
                             lx->last_I1=TK_INSERT_BINARY_TYPE;
                             return TK_INSERT_BINARY_TYPE;
                         case LTFT_INSERT_BINARY_SIZE:
                             src=&lex_zeros;
                             tempf->buf=tempf->buf_ptr=lx->cur_buf_ptr=src;

                             if (cl->bin_data)
                                 lx->cur_i=cl->bin_data->size;
                             else
                                 lx->cur_i=0;
                             tempf->line_num=cl->y+1;
                             lx->last_I1=TK_INSERT_BINARY_SIZE;
                             return TK_INSERT_BINARY_SIZE;
                         default:
                             cont=TRUE;
                             cl=cl->next;
                     }
                     if (!cont) break;
                 }
                 if (cl==l) {
                     CallExtNum(EXT_LTF_DEL,l);
                     tempf->l=tempf->buf=NULL;
                     Free(tempf->name);
                     tempf->name=NULL;
                     goto here;
                 }
             } else {
here:
                 tempf=lx->cur_lfn;
                 if (tempf!=&lx->lfns[0]) {
                     Free(tempf->name);
                     tempf->name=NULL;
                     Free(tempf->buf);
                     tempf->buf=NULL;
                     tempf1=tempf;
                     lx->cur_lfn=--tempf;
                     lx->cur_buf_ptr=tempf->buf_ptr;
                     if (lx->last_I1=tempf->last_I1) {
                         lx->flags&=~LF_USE_LAST_I1;
                         if (lx->last_I1==CH_SHIFT_SPACE)
                             return CH_SPACE;
                         else
                             return lx->last_I1;
                     } else
                         lx->flags&=~LF_USE_LAST_I1;
                 } else {
                     if (lx->flags & LF_PROMPT) {
                         Free(tempf->buf);
                         lx->cur_buf_ptr=tempf->line_start=
                             tempf->buf_ptr=tempf->buf=CmpPmt(TRUE);
                     } else {
                         lx->last_I1=TK_EOF;
                         lx->cur_buf_ptr=src-1;
                         return TK_EOF;
                     }
                 }
             }
             break;
         case CH_CURSOR:
         case CH_FORM_FEED:
             goto lex_getchar_start;
         case CH_LINE_FEED:
             tempf=lx->cur_lfn;
             if (tempf->flags & LFSF_IS_LTF)
                 if (result==CH_SHIFT_SPACE)
                     return CH_SPACE;
                 else
                     return result;
             else {
                 tempf->line_num++;
                 compiled_lines++;
                 tempf->line_start=src;
             }
         default:
             if (lx->opts & OPTF_ECHO)
                 PutChar(result);
             if (result==CH_SHIFT_SPACE)
                 return CH_SPACE;
             else
                 return result;
     }
 } while (TRUE);
}

void LexSkipEol(LexStruct *lx)
{
 U1 ch;
 do ch=LexGetChar(lx);
 while (ch && ch!=CH_CR && ch!=CH_LINE_FEED);
}

void ExpressionDel(U1 *code)
{
 Free(code);
}


U8 EvalExpression(LexStruct *lx)
{
 U1 *exp;
 U8 result=0;
 if (!GetExpression(lx,&exp))
     LexSkipEol(lx);
 else {
     result=Call(exp);
     ExpressionDel(exp);
 }
 return result;
}

void LexIncludeStr(LexStruct *lx,I1 *filename,
 I1 *src,BoolI1 actual_file)
{
 LexFileStruct *tempf;
 LexBackupLastChar(lx);
 tempf=++lx->cur_lfn;
 tempf->buf=src;
 tempf->buf_ptr=src;
 tempf->line_num=1;
 tempf->line_start=src;
 tempf->last_I1=0;
 if (actual_file) {
     tempf->name=AbsoluteFileName(filename);
     tempf->flags=LFSF_IS_INCLUDED;
 } else {
     tempf->name=StrNew(sys_temp_filename);
     tempf->flags=0;
 }
 lx->cur_buf_ptr=src;
}

I8 ltf_stop_btypes[1]=
{
1<<LTFT_TEXT|
1<<LTFT_TAB|
1<<LTFT_INSERT_BINARY|
1<<LTFT_INSERT_BINARY_TYPE|
1<<LTFT_INSERT_BINARY_SIZE
};


void LexIncludeLtf(LexStruct *lx,I1 *filename,Ltf *_l)
{ //If ltf==null load
 BoolI1 is_null;
 LtfEntry *cl;
 LexFileStruct *tempf;
 Ltf *l;

 LexBackupLastChar(lx);
 tempf=++lx->cur_lfn;
 tempf->line_start=&lex_zeros;
 if (_l)
     l=_l;
 else {
     if (ext[EXT_LTF_READ])
         l=CallExtNum(EXT_LTF_READ,filename,LTFF_DOUBLE_DOLLARS+LTFF_NO_PICWORDS);
     else
         throw(EXCEPT_COMPILER,1);  //This should never happen
 }
 tempf->l=l;
 cl=l->dummy.next;
 while (cl!=l) {
     if (Bt(ltf_stop_btypes,cl->btype))
         break;
     cl=cl->next;
 }
 if (cl!=l) {
     tempf->line_start=cl;
     tempf->line_num=cl->y+1;
     if (cl->btype==LTFT_TEXT) {
         tempf->cur_entry=cl;
         tempf->buf=cl->tag;
         tempf->buf_ptr=cl->tag;
     } else {
         tempf->cur_entry=cl->last;  //TODO might be problem at begining of file
         tempf->buf=&lex_zeros;
         tempf->buf_ptr=&lex_zeros;
     }
     is_null=FALSE;
 } else
     is_null=TRUE;
 if (!filename)
     tempf->name=StrNew(sys_temp_filename);
 else
     tempf->name=AbsoluteFileName(filename);
 if (is_null) {
//    LtfDel(lx); TODO
     tempf->flags=LFSF_IS_INCLUDED;
     tempf->buf=MAllocZ(1);
     tempf->buf_ptr=&lex_zeros;
     tempf->line_num=1;
 } else
     tempf->flags=LFSF_IS_INCLUDED|LFSF_IS_LTF;
 tempf->last_I1=0;
 lx->cur_buf_ptr=tempf->buf_ptr;
}

void LexPush(LexStruct *lx)
{
 LexFileStruct *tempf=lx->cur_lfn,
     *tempf1=&lx->stack[lx->stack_ptr++];
 if (lx->stack_ptr>=LFN_STACK_CNT)
     PrsExcept(lx,"ST_LEX_STACK_OVERFLOW");
 LexBackupLastChar(lx);
 if (tempf->last_I1)
     lx->flags|=LF_USE_LAST_I1;
 MemCpy(tempf1,tempf,sizeof(LexFileStruct));
}

void LexPop(LexStruct *lx)
{
 LexFileStruct *tempf=lx->cur_lfn,
     *tempf1=&lx->stack[--lx->stack_ptr];
 lx->cur_buf_ptr=tempf1->buf_ptr;
 if (lx->last_I1=tempf1->last_I1)
     lx->flags|=LF_USE_LAST_I1;
 else
     lx->flags&=~LF_USE_LAST_I1;
 MemCpy(tempf,tempf1,sizeof(LexFileStruct));
}

I8 MemberMetaData(I1 *st,MemberListStruct *ml)
{
 MemberListMeta *meta=ml->meta;
 while (meta) {
     if (!StrCmp(meta->str,st))
         return meta->user_data;
     meta=meta->next;
 }
 return 0;
}

MemberListMeta *FindMemberMeta(I1 *st,MemberListStruct *ml)
{
 MemberListMeta *meta=ml->meta;
 while (meta) {
     if (!StrCmp(meta->str,st))
         return meta;
     meta=meta->next;
 }
 return NULL;
}

MemberListStruct *FindMember(I1 *st,ClassStruct *c)
{
 MemberListStruct *ml=c->member_list;
 while (ml) {
     if (!StrCmp(ml->str,st))
         return ml;
     ml=ml->next;
 }
 return NULL;
}

void MemberListDel(ClassStruct *tempc)
{
 MemberListStruct *tempm,*tempm1;
 MemberListMeta *temp_meta,*temp_meta1;
 tempm=tempc->member_list;
 while (tempm) {
     tempm1=tempm->next;
     Free(tempm->str);
     LinkedListDel(tempm->dim_list);
     if (tempm->flags & MLF_DEFAULT_AVAILABLE &&
             tempm->member_class==sys_internal_types[IT_I1]+1)
         Free(tempm->default_value);
     temp_meta=tempm->meta;
     while (temp_meta) {
         temp_meta1=temp_meta->next;
         Free(temp_meta->str);
         if (temp_meta->flags&MLMF_IS_STR)
             Free(temp_meta->user_data);
         Free(temp_meta);
         temp_meta=temp_meta1;
     }
     Free(tempm);
     tempm=tempm1;
 }
 tempc->size=0;
 tempc->last_in_member_list=&tempc->member_list;
 tempc->member_list=NULL;
 tempc->member_cnt=0;
 tempc->arg_cnt=0;
}

U8 MemberListSize(ClassStruct *tempc)
{
 U8 result=0;
 MemberListStruct *tempm;
 MemberListMeta *temp_meta;
 tempm=tempc->member_list;
 while (tempm) {
     result+=MSize2(tempm->str);
     result+=LinkedListSize(tempm->dim_list);
     if (tempm->flags & MLF_DEFAULT_AVAILABLE &&
             tempm->member_class==sys_internal_types[IT_I1]+1)
         result+=MSize2(tempm->default_value);
     temp_meta=tempm->meta;
     while (temp_meta) {
         result+=MSize2(temp_meta->str);
         if (temp_meta->flags&MLMF_IS_STR)
             result+=MSize2(temp_meta->user_data);
         result+=MSize2(temp_meta);
         temp_meta=temp_meta->next;
     }
     result+=MSize2(tempm);
     tempm=tempm->next;
 }
 return result;
}


I8 LexInStr(LexStruct *lx,
 I1 *buf,I8 size,BoolI1 *done)
{
 I8 i=0,j,ch;
 *done=TRUE;
 while (i<size-1) {
     ch=LexGetChar(lx);
     if (!ch || ch=='"') {
         buf[i++]=0;
         return i;
     } else if (ch=='\\') {
         ch=LexGetChar(lx);
         if (ch=='n')
             buf[i++]=CH_LINE_FEED;
         else if (ch=='r')
             buf[i++]=CH_CR;
         else if (ch=='"')
             buf[i++]='"';
         else if (ch=='\'')
             buf[i++]='\'';
         else if (ch=='\`')
             buf[i++]='\`';
         else if (ch=='\\')
             buf[i++]='\\';
         else if (ch=='t')
             buf[i++]=CH_TAB;
         else if (ch=='x') {
             j=0;
             while (TRUE) {
                 ch=ToUpper(LexGetChar(lx));
                 if (Bt(hex_numeric_bitmap,ch)) {
             if (ch<='9')
                 j=j<<4+ch-'0';
             else
                 j=j<<4+ch-'A'+10;
                 } else
             break;
             }
             buf[i++]=j;
             lx->flags|=LF_USE_LAST_I1;
         } else if (ch>='0' && ch<='7') {
             j=ch-'0';
             do {
                 ch=LexGetChar(lx);
                 if (ch>='0' && ch<='7')
             j=j<<3+ch-'0';
             } while (ch>='0' && ch<='7');
             buf[i++]=j;
             lx->flags|=LF_USE_LAST_I1;
         } else {
             lx->flags|=LF_USE_LAST_I1;
             buf[i++]='\\';
         }
     } else if (ch=='$$') {
         ch=LexGetChar(lx);
         buf[i++]='$$';
         if (ch!='$$')
             lx->flags|=LF_USE_LAST_I1;
     } else
         buf[i++]=ch;
 }
 *done=FALSE;
 return i;
}

I8 Lex(LexStruct *lx)
{
 U8 ch;
 I8 i,j,k;
 double d;
 SysHashEntry *temph;
 BoolI1 str_done;
 I1 *fbuf;
 I1 *buf2,*buf3,buf[LEX_MAX_IDENT];
 lx->last_indent_level=lx->indent_level;
 lx->last_line_num=lx->cur_lfn->line_num;
 while (TRUE) {
lex_cont:
     lx->start_line_num=lx->cur_lfn->line_num;
     if (!(ch=LexGetChar(lx)))
         return lx->token=TK_EOF;
     if (Bt(alpha_bitmap,ch)) {
         i=0;
         buf[i++]=ch;
         do {
             if (i>=LEX_MAX_IDENT-1)
                 break;
             else {
                 if (!(ch=LexGetChar(lx)))
                     break;
                 else {
                     if (Bt(alpha_numeric_bitmap,ch))
                         buf[i++]=ch;
                     else {
                         lx->flags|=LF_USE_LAST_I1;
                         break;
                     }
                 }
             }
         } while (TRUE);
         buf[i++]=0;
         temph=NULL;
         if (lx->local_var_list) {
             lx->local_var_entry=FindMember(buf,
                     lx->local_var_list);
         } else
             lx->local_var_entry=NULL;
         if (!lx->local_var_entry && lx->hash_table_list)
             temph=FindHashEntry(buf,
                     lx->hash_table_list,lx->hash_mask);
         if (temph)
             j=temph->type;
         else
             j=0;
         if (j & HTT_DEFINE_STR && !(lx->flags & LF_NO_DEFINES)) {
             LexIncludeStr(lx,
                 temph->str,StrNew(temph><(DefineStrHashEntry *)->data),FALSE);
             lx->cur_lfn->flags|=LFSF_IS_DEFINE;
         } else {
             if (j & HTT_INTERNAL_TYPE) {
                 if (lx->flags&LF_UNSIGNED) {
                     if (!(temph><(ClassStruct *)->sub_type&1))
                         temph=sys_internal_types[temph><(ClassStruct *)->sub_type+1];
                     lx->flags&=~LF_UNSIGNED;
                 }
             } else if (j&HTT_KEYWORD && temph><(GenericHashEntry *)->user_data0==KW_UNSIGNED
&& lx->opts&1<<OPTf_STD_C) {
                 lx->flags|=LF_UNSIGNED;
                 goto lex_cont;
             }
             lx->hash_entry=temph;
             Free(lx->ident);
             lx->ident=StrNew(buf);
             lx->ident_len=i;
             lx->token=TK_IDENT;
             goto lex_end;
         }
     } else if (Bt(dec_numeric_bitmap,ch)) {
         i=ch-'0';
         ch=LexGetChar(lx);
         if (ch=='X' || ch=='x') {
             while (TRUE) {
                 ch=ToUpper(LexGetChar(lx));
                 if (Bt(hex_numeric_bitmap,ch)) {
                     if (ch<='9')
                         i=i<<4+ch-'0';
                     else
                         i=i<<4+ch-'A'+10;
                 } else {
                     lx->cur_i=i;
                     lx->flags|=LF_USE_LAST_I1;
                     lx->token=TK_INTEGER;
                     goto lex_end;
                 }
             }
         }
         if (ch=='B' || ch=='b') {
             while (TRUE) {
                 ch=LexGetChar(lx);
                 if (ch=='0')
                     i=i<<1;
                 else if (ch=='1')
                     i=i<<1+1;
                 else {
                     lx->cur_i=i;
                     lx->flags|=LF_USE_LAST_I1;
                     lx->token=TK_INTEGER;
                     goto lex_end;
                 }
             }
         }
         while (TRUE) {
             if (Bt(dec_numeric_bitmap,ch))
                 i=i*10+ch-'0';
             else {
                 if (ch=='.' || ch=='e' || ch=='E') break;
is_int:
                 lx->cur_i=i;
                 lx->flags|=LF_USE_LAST_I1;
                 lx->token=TK_INTEGER;
                 goto lex_end;
             }
             ch=LexGetChar(lx);
         }
         if (ch=='.') {
             ch=LexGetChar(lx);
             if (ch=='.') {
                 lx->flags|=LF_LAST_WAS_DOT;
                 goto is_int;
             }
         }
float_start:
         //TODO:back-up for cases where i overflows
         // (people should use 'e', so might not be worth it)
         j=0;
         k=0;
         while (TRUE) {
             //TODO: maybe replace with log2 and insert bit field
             if (Bt(dec_numeric_bitmap,ch)) {
                 j=j*10+ch-'0';
                 k++;
             } else {
                 d=i+j*Pow10(-k);
                 if (ch=='e' || ch=='E') break;
                 lx->cur_d=d;
                 lx->flags|=LF_USE_LAST_I1;
                 lx->token=TK_DOUBLE;
                 goto lex_end;
             }
             ch=LexGetChar(lx);
         }
         ch=LexGetChar(lx);
         k=1;
         if (ch=='-') {
             k=-1;
             ch=LexGetChar(lx);
         }
         j=0;
         while (TRUE) {
             //TODO: maybe replace with log2 and insert bit field
             if (Bt(dec_numeric_bitmap,ch))
                 j=j*10+ch-'0';
             else {
                 d*=Pow10(j*k);
                 lx->cur_d=d;
                 lx->flags|=LF_USE_LAST_I1;
                 lx->token=TK_DOUBLE;
                 goto lex_end;
             }
             ch=LexGetChar(lx);
         }
     } else if (ch=='"') {
         lx->flags|=LF_IN_QUOTES;
         buf2=NULL;
         i=0;
         do {
             j=LexInStr(lx,buf,LEX_MAX_IDENT,&str_done);
             buf3=MAlloc(i+j);
             if (buf2) {
                 MemCpy(buf3,buf2,i);
                 Free(buf2);
                 buf2=buf3;
                 MemCpy(buf2+i,buf,j);
             } else {
                 buf2=buf3;
                 MemCpy(buf2,buf,j);
             }
             i+=j;
         } while (!str_done);
         Free(lx->ident);
         lx->ident=MAlloc(i);
         MemCpy(lx->ident,buf2,i);
         Free(buf2);
         lx->ident_len=i;
         lx->flags&=~LF_IN_QUOTES;
         lx->token=TK_STR;
         goto lex_end;
     } else if (ch=='\'') {
         ch=LexGetChar(lx);
         if (!ch || ch=='\'') i='\'';
         else if (ch=='\\') {
             ch=LexGetChar(lx);
             if (ch=='n')
                 i=10;
             else if (ch=='r')
                 i=13;
             else if (ch=='"')
                 i='"';
             else if (ch=='\'')
                 i='\'';
             else if (ch=='\`')
                 i='\`';
             else if (ch=='\\')
                 i='\\';
             else if (ch=='t')
                 i=9;
             else if (ch=='x') {
                 i=0;
                 while (TRUE) {
                     ch=ToUpper(LexGetChar(lx));
                     if (Bt(hex_numeric_bitmap,ch)) {
                         if (ch<='9')
                             i=i<<4+ch-'0';
                         else
                             i=i<<4+ch-'A'+10;
                     } else
                         break;
                 }
                 lx->flags|=LF_USE_LAST_I1;
             } else if (ch>='0' && ch<='7') {
                 i=ch-'0';
                 do {
                     ch=LexGetChar(lx);
                     if (ch>='0' && ch<='7')
                         i=i<<3+ch-'0';
                 } while (ch>='0' && ch<='7');
                 lx->flags|=LF_USE_LAST_I1;
             } else {
                 lx->flags|=LF_USE_LAST_I1;
                 i='\\';
             }
         } else if (ch=='$$') {
             ch=LexGetChar(lx);
             i='$$';
             if (ch!='$$')
                 lx->flags|=LF_USE_LAST_I1;
         } else
             i=ch;
         ch=LexGetChar(lx);
         if (ch!='\'')
             lx->flags|=LF_USE_LAST_I1;
         lx->cur_i=i;
         lx->token=TK_INTEGER;
         goto lex_end;
     } else if (ch=='#') {
         if (Lex(lx)!=TK_IDENT)         //skip '#'
             goto lex_end;
         if (!(temph=lx->hash_entry))
             goto lex_end;
         if (!(temph->type & HTT_KEYWORD))
             goto lex_end;
         switch (i=temph><(GenericHashEntry *)->user_data0) {
             case KW_INCLUDE:
             case KW_INCLUDE_TEXT:
                 if (Lex(lx)!=TK_STR)
                     goto lex_end;
                 if (lx->flags & LF_ASM_EXPRESSIONS)
                     fbuf=DefaultExtension(lx->ident,"ASZ");
                 else if (Fs==adam_tss)
                     fbuf=DefaultExtension(lx->ident,"APZ");
                 else
                     fbuf=DefaultExtension(lx->ident,"CPZ");
                 if (ext[EXT_LTF_READ] && i==KW_INCLUDE)
                     LexIncludeLtf(lx,fbuf,NULL);
                 else
                     LexIncludeStr(lx,fbuf,ReadTextFile(fbuf),TRUE);
                 Free(fbuf);
                 break;
             case KW_DEFINE:
                 lx->flags|=LF_NO_DEFINES;
                 if (Lex(lx)==TK_IDENT) {
                     temph=MAllocZ(sizeof(DefineStrHashEntry));
                     temph->str=lx->ident;
                     lx->ident=0;
                     temph->type=HTT_DEFINE_STR;
                     SetSourceFileInfo(lx,temph);
                     i=0;
                     do ch=LexGetChar(lx);
                     while (ch && !(CH_SPACE<ch<=0x7E) && ch!=CH_CR);
                     if (CH_SPACE<ch<=0x7E || ch==CH_CR) {
                         if (ch!=CH_CR)
                             buf[i++]=ch;
                         while (i<LEX_MAX_IDENT-1) {
                             ch=LexGetChar(lx);
                             if (ch=='/') {
                                 ch=LexGetChar(lx);
                                 if (ch=='/') {
                                     do ch=LexGetChar(lx);
                                     while (CH_SHIFT_SPACE<=ch<=0x7E || ch==CH_TAB);
                                     break;
                                 } else {
                                     buf[i++]='/';
                                     lx->flags|=LF_USE_LAST_I1;
                                 }
                             } else if (CH_SHIFT_SPACE<=ch<=0x7E || ch==CH_TAB)
                                 buf[i++]=ch;
                             else
                                 break;
                         }
                     }
                     buf[i++]=0;
                     temph><(DefineStrHashEntry *)->data=StrNew(buf);
                     AddSysHashEntry(temph,lx->define_hash_table);
                 }
                 lx->flags&=~LF_NO_DEFINES;
                 break;
             case KW_ELSE:
                 if (lx->flags & LF_IN_IF) {
                     lx->token=TK_ELSE;
                     goto lex_end;
                 }
lex_else:
                 j=1;
                 do {
                     if (ch=LexGetChar(lx)) {
                         if (ch=='#') {
                             if (!Lex(lx))
                                 goto lex_end;
                             i=CmpKeyWord(lx);
                             if (i==KW_IF || i==KW_IFDEF || i==KW_IFNDEF)
                                 j++;
                             else if (i==KW_ENDIF)
                                 j--;
                         }
                     } else {
                         lx->token=TK_EOF;
                         goto lex_end;
                     }
                 } while (j);
                 break;
             case KW_IF:
                 if (lx->flags & LF_IN_IF) {
                     lx->token=TK_IF;
                     goto lex_end;
                 }
lex_if:
                 lx->flags|=LF_IN_IF;
                 if (!Lex(lx)) {
                     lx->flags&=~LF_IN_IF;
                     goto lex_end;
                 }
                 if (Expression(lx)) {
                     lx->flags&=~LF_IN_IF;
                     if (lx->token==TK_IF)
                         goto lex_if;
                     else if (lx->token==TK_IFDEF)
                         goto lex_ifdef;
                     else if (lx->token==TK_IFNDEF)
                         goto lex_ifndef;
                     else if (lx->token==TK_ELSE)
                         goto lex_else;
                     else if (lx->token==TK_ENDIF)
                         goto lex_cont;
                     else
                         goto lex_end;
                 } else {
                     lx->flags&=~LF_IN_IF;
                     if (lx->token!=TK_ENDIF && lx->token!=TK_ELSE) {
                         if (lx->token==TK_IF || lx->token==KW_IFDEF || lx->token==KW_IFNDEF)
                             j=2;
                         else
                             j=1;
                         do {
                             if (ch=LexGetChar(lx)) {
                                 if (ch=='#') {
                                     if (!Lex(lx))
                                         goto lex_end;
                                     i=CmpKeyWord(lx);
                                     if (i==KW_IF || i==KW_IFDEF || i==KW_IFNDEF)
                                         j++;
                                     else if (i==KW_ENDIF)
                                         j--;
                                     else if (i==KW_ELSE && j==1)
                                         break;
                                 }
                             } else {
                                 lx->token=TK_EOF;
                                 goto lex_end;
                             }
                         } while (j);
                     }
                 }
                 break;
             case KW_IFDEF:
                 if (lx->flags & LF_IN_IF) {
                     lx->token=TK_IFDEF;
                     goto lex_end;
                 }
lex_ifdef:
                 lx->flags|=LF_NO_DEFINES;
                 if (!Lex(lx)) {
                     lx->flags&=~LF_NO_DEFINES;
                     goto lex_end;
                 }
                 lx->flags&=~LF_NO_DEFINES;
                 if (lx->token!=TK_IDENT)
                     goto