
//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