You might want to make a disassembler first. I keep telling you guys to write your own tools. My disassembler will tell me how many bytes and instruction is and can be called from within the interrupt. I throw an exception, though. That disassembly thing is relatively slow slow. I recommend making the program crash.
That disassembler call is useful for making an IDE when you want to single step, but most of the time you can use the single step flag.
Lair of LoseThos the Troll. No feeding
-
- Member
- Posts: 155
- Joined: Fri Oct 27, 2006 5:11 am
- Location: Oberbayern
- Contact:
Re: How to handle certain interrupts?
Why should anyone listen to what you tell them to do, Terry? What makes you the boss? Were you this arrogant and bigoted before you went into the mental hospital? I know I'm feeding the troll here, but your personality is almost comically bad!LoseThos wrote:I keep telling you guys to write your own tools.
M
MikeOS -- simple, well-documented x86 real-mode OS written in assembly language
http://mikeos.sourceforge.net
http://mikeos.sourceforge.net
Re: How to handle certain interrupts?
Traditionally writing tools and operating systems are discussed together because they are interrelated.
As I like to say, I know how to have fun programming. Discovering the nuances of gcc and qemu is not my idea of fun. Writing tools is fun.
I'm not sure this is the case but my Mom says "Lazy men work the hardest." Write your own tools.
As I like to say, I know how to have fun programming. Discovering the nuances of gcc and qemu is not my idea of fun. Writing tools is fun.
I'm not sure this is the case but my Mom says "Lazy men work the hardest." Write your own tools.
Re: How to handle certain interrupts?
How about, You write your own tools, I will do whatever I want. How does that sound?LoseThos wrote:Traditionally writing tools and operating systems are discussed together because they are interrelated.
As I like to say, I know how to have fun programming. Discovering the nuances of gcc and qemu is not my idea of fun. Writing tools is fun.
I'm not sure this is the case but my Mom says "Lazy men work the hardest." Write your own tools.
Re: How to handle certain interrupts?
You people drive me crazy!
Use my tools, if you like. I use my tools. You can download them from http://www.losethos.com
Here's the expression parser of my compiler:
I wouldn't use my tools if I were you, I'd write my own.
I just wanted to show I'm not bullsh*tting.
Seriously an unoptimized compiler is easy compared to many operating system things. Surprisingly when I added major optimizations, i could hardly tell a difference because the intel chips are so smart that unoptimized code is just as fast, almost.
Use my tools, if you like. I use my tools. You can download them from http://www.losethos.com
Here's the expression parser of my compiler:
Code: Select all
$PJ,"Project: OSMain2.SPZ","/LT/OSMain2/OSMain2.SPZ"$
LTextern CP_PRSPUSH void PrsPush(ParseStack *ps,I8 val);
LTextern CP_PRSPOP I8 PrsPop(ParseStack *ps);
void ParenWarning(LexStruct *lx)
{
if (Bt(&lx->opts,OPTf_PAREN_WARN) &&
!(lx->cur_lfn->flags&LFSF_IS_DEFINE))
PutLexWarn(lx,"ST_UNNECESSARY_PARENTHESIS");
}
#define PRST_UNARY_TERM 0
#define PRST_UNARY_MODIFIERS 1
#define PRST_DEREFERRENCE 2
#define PRST_CHECK_BINARY_OPS 3
BoolI8 PrsParseExpression(LexStruct *lx,I8 *_max_precedence,BoolI1 end_exp)
{
BoolI1 result=TRUE,question_clause=FALSE,
cont_unary,cont_check_binary_ops,is_lower,div_sizeof;
I8 i,j,k,old_flags=lx->flags,old_start_line=lx->expression_start_line,
max_precedence=PREC_NULL,unary_precedence,
left_precedence=PREC_MAX;
IntermediateCode *tempi,*tempi_first=lx->cb.cb_out_ptr,*tempi2;
ClassStruct *tempc,*tempcc;
ParseStack *ps=MAlloc(sizeof(ParseStack));
MemberListStruct *local_var;
ArrayDimStruct *tempad=NULL;
if (!(lx->flags&LF_INSIDE_EXPRESSION))
lx->expression_start_line=lx->start_line_num;
lx->flags|=LF_INSIDE_EXPRESSION;
ps->ptr=0;
PrsPush(ps,0); //terminate
PrsPush(ps,0); //terminate
if (Btr(&lx->flags,Lf_BY_ADDRESS)) {
PrsPush(ps,tempc);
PrsPush(ps,unary_ops_table['&']);
}
try {
do {
unary_precedence=PREC_NULL;
lx->flags&=~(LF_PREINC+LF_PREDEC+LF_POSTINC+LF_POSTDEC+LF_FUNCTION);
do i=PrsUnaryTerm(lx,ps,&local_var,&tempad,&max_precedence,&unary_precedence);
while (i==PRST_UNARY_TERM);
while (i==PRST_UNARY_MODIFIERS)
i=PrsUnaryModifier(lx,ps,&local_var,&tempad,&max_precedence);
if (i==PRST_DEREFERRENCE)
PrsDereferrence(lx,ps);
//Check for binary Ops
do {
i=PrsPop(ps);
tempc=PrsPop(ps);
if (i && i.u1[2]<=PREC_UNARY+PRECF_NON_ASSOCIATIVE) {
tempi=lx->cb.cb_last_out_ptr;
i=i.u2[0];
tempc=tempi->ic_class;
if (Bt(deref_bitmap,i) && tempc->ptr_cnt) {
tempc--;
while (tempc->return_class)
tempc=tempc->return_class;
i=EC_DEREF+PREC_UNARY<<16;
} else {
if (i==EC_ADDRESS) {
if (!(lx->flags & (LF_RAX|LF_ARRAY))) {
j=tempi->ic_opcode;
if (!Bt(deref_bitmap,j))
PrsExcept(lx,"ST_INVALID_LVALUE");
tempi->ic_opcode=EC_NOP;
tempc++;
} else {
if (lx->flags & LF_ARRAY)
tempc++;
}
}
}
CbAddIc(lx,i,0,tempc);
cont_check_binary_ops=TRUE;
} else {
PrsPush(ps,tempc);
PrsPush(ps,i);
i=lx->token;
if (lx->opts&1<<OPTf_STD_C)
k=c_binary_ops_table[i];
else
k=binary_ops_table[i];
switch (k.u2[0]) {
case EC_ADD:
case EC_SUB:
tempi=lx->cb.cb_last_out_ptr;
if (!tempi->ic_class->ptr_cnt &&
tempi->ic_class->sub_type!=IT_DOUBLE) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
break;
case EC_AND_AND:
case EC_OR_OR:
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
break;
case EC_QUESTION:
question_clause=TRUE;
break;
case EC_COLON:
if (!question_clause)
k=0;
else
question_clause=FALSE;
break;
}
if (k.u1[2]==PREC_NULL) {
if (unary_precedence>PREC_UNARY+PRECF_NON_ASSOCIATIVE) {
if (unary_precedence&PRECF_NON_ASSOCIATIVE ||
left_precedence&PRECF_NON_ASSOCIATIVE) {
if (unary_precedence&~PRECF_NON_ASSOCIATIVE<left_precedence&~PRECF_NON_ASSOCIATIVE)
ParenWarning(lx);
} else {
if (unary_precedence&~PRECF_NON_ASSOCIATIVE<=left_precedence&~PRECF_NON_ASSOCIATIVE)
ParenWarning(lx);
}
}
cont_check_binary_ops=FALSE;
cont_unary=FALSE; //DONE
} else {
Lex(lx); //skip op
if (unary_precedence>PREC_UNARY+PRECF_NON_ASSOCIATIVE) {
if (unary_precedence&PRECF_NON_ASSOCIATIVE ||
left_precedence&PRECF_NON_ASSOCIATIVE) {
if (unary_precedence&~PRECF_NON_ASSOCIATIVE<left_precedence&~PRECF_NON_ASSOCIATIVE &&
unary_precedence&~PRECF_NON_ASSOCIATIVE<=k.u1[2]&~PRECF_NON_ASSOCIATIVE)
ParenWarning(lx);
} else {
if (unary_precedence&~PRECF_NON_ASSOCIATIVE<=left_precedence&~PRECF_NON_ASSOCIATIVE &&
unary_precedence&~PRECF_NON_ASSOCIATIVE<=k.u1[2]&~PRECF_NON_ASSOCIATIVE)
ParenWarning(lx);
}
}
if (k.u1[2]>max_precedence)
max_precedence=k.u1[2];
left_precedence=k.u1[2];
if (Bt(assign_bitmap,k.u2[0])) {
tempi=lx->cb.cb_last_out_ptr;
tempc=tempi->ic_class;
j=tempi->ic_opcode;
if (!Bt(deref_bitmap,j))
PrsExcept(lx,"ST_INVALID_LVALUE");
tempi->ic_opcode=EC_NOP;
while (tempc->return_class)
tempc=tempc->return_class;
k.u1[2]=PREC_ASSIGN;
#assert (PREC_ASSIGN==C_PREC_ASSIGN)
}
do {
i=PrsPop(ps); //pop ops of higher prec
tempc=PrsPop(ps);
is_lower=FALSE;
if (i) {
if (k.u1[2]&~PRECF_NON_ASSOCIATIVE==i.u1[2]&~PRECF_NON_ASSOCIATIVE) {
if (!Bt(assign_bitmap,k.u2[0]) ||
!Bt(assign_bitmap,i.u2[0]))
is_lower=TRUE;
} else if (k.u1[2]&~PRECF_NON_ASSOCIATIVE>i.u1[2]&~PRECF_NON_ASSOCIATIVE)
is_lower=TRUE;
}
div_sizeof=FALSE;
if (is_lower) {
switch (i.u2[0]) {
case EC_ADD:
if (tempc->ptr_cnt) {
tempi=lx->cb.cb_last_out_ptr;
if (!tempi->ic_class->ptr_cnt &&
tempi->ic_class->sub_type!=IT_DOUBLE) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
}
break;
case EC_SUB:
if (tempc->ptr_cnt) {
tempi=lx->cb.cb_last_out_ptr;
if (!tempi->ic_class->ptr_cnt &&
tempi->ic_class->sub_type!=IT_DOUBLE) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
} else
div_sizeof=TRUE;
}
break;
case EC_AND_AND:
case EC_OR_OR:
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
break;
case EC_ADD_EQUAL:
case EC_SUB_EQUAL:
if (tempc->ptr_cnt) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
break;
}
CbAddIc(lx,i,0,tempc);
tempi2=lx->cb.cb_last_out_ptr;
if (i.u1[3]&ECF_HAS_PUSH_CMP) {
tempi2->ic_flags|=ICF_POP_CMP;
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_AND_AND,0,sys_internal_types[IT_I8]);
tempi=lx->cb.cb_last_out_ptr;
tempi->ic_flags|=ICF_POP_CMP;
}
if (Bt(cmp_bitmap,k.u2[0]) &&
Bt(cmp_bitmap,i.u2[0]) && !(lx->opts&1<<OPTf_STD_C)) {
tempi2->ic_flags|=ICF_PUSH_CMP;
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_PUSH_CMP,0,tempc);
k.u1[3]|=ECF_HAS_PUSH_CMP;
} else if (k.u2[0]==EC_AND_AND || k.u2[0]==EC_OR_OR)
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
if (div_sizeof) {
tempcc=tempc-1;
if (tempcc->size!=1) {
CbAddIc(lx,EC_IMM,tempcc->size,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_DIV,0,sys_internal_types[IT_I8]);
tempc=sys_internal_types[IT_I8];
}
}
} else {
PrsPush(ps,tempc);
PrsPush(ps,i);
tempi=lx->cb.cb_last_out_ptr;
tempc=tempi->ic_class;
PrsPush(ps,tempc);
PrsPush(ps,k);
cont_check_binary_ops=FALSE;
cont_unary=TRUE;
break;
}
} while (TRUE);
}
}
} while (cont_check_binary_ops);
} while (cont_unary);
while (TRUE) {
i=PrsPop(ps);
tempc=PrsPop(ps);
div_sizeof=FALSE;
switch (i.u2[0]) {
case 0:
goto done3;
case EC_ADD:
if (tempc->ptr_cnt) {
tempi=lx->cb.cb_last_out_ptr;
if (!tempi->ic_class->ptr_cnt &&
tempi->ic_class->sub_type!=IT_DOUBLE) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
}
break;
case EC_SUB:
if (tempc->ptr_cnt) {
tempi=lx->cb.cb_last_out_ptr;
if (tempi->ic_class->sub_type!=IT_DOUBLE) {
if (!tempi->ic_class->ptr_cnt) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
} else
div_sizeof=TRUE;
}
}
break;
case EC_AND_AND:
case EC_OR_OR:
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
break;
case EC_ADD_EQUAL:
case EC_SUB_EQUAL:
if (tempc->ptr_cnt) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
break;
}
CbAddIc(lx,i,0,tempc);
if (i.u1[3]&ECF_HAS_PUSH_CMP) {
tempi=lx->cb.cb_last_out_ptr;
tempi->ic_flags|=ICF_POP_CMP;
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_AND_AND,0,sys_internal_types[IT_I8]);
tempi=lx->cb.cb_last_out_ptr;
tempi->ic_flags|=ICF_POP_CMP;
}
if (div_sizeof) {
tempcc=tempc-1;
if (tempcc->size!=1) {
CbAddIc(lx,EC_IMM,tempcc->size,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_DIV,0,sys_internal_types[IT_I8]);
tempc=sys_internal_types[IT_I8];
}
}
}
done3:
} catch {
if (Fs->except_argc>0) {
if (Fs->except_argv[0]==EXCEPT_COMPILER) {
lx->statement_cnt=0;
lx->braces_cnt=0;
lx->last_indent_level=lx->indent_level=0;
result=FALSE;
Fs->catch_except=TRUE;
}
}
}
Free(ps);
if (end_exp && result)
CbAddIc(lx,EC_END_EXP,0,0);
if (_max_precedence)
*_max_precedence=max_precedence;
lx->flags=lx->flags&~LF_INSIDE_EXPRESSION |
old_flags&LF_INSIDE_EXPRESSION;
lx->expression_start_line=old_start_line;
return result;
}
U8 PrsUnaryTerm(LexStruct *lx,ParseStack *ps,MemberListStruct **local_var,ArrayDimStruct **tempad,
I8 *max_precedence,I8 *unary_precedence)
{
I8 i,*i_ptr,j;
I8 argc_cnt,size;
U8 d;
SysSymHashEntry *tempss;
ClassStruct *tempc,*tempc1,*tempc2;
GlblVarStruct *tempg;
MemberListStruct *tempm;
LexUndefEntry *templu;
CbMiscStruct *tempmc;
IntermediateCode *tempi;
BoolI1 needs_right_paren,is_first_arg,paren_warn;
LexCbStack *templ,*templ1;
*local_var=NULL;
switch (lx->token) {
case TK_INTEGER:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
if (lx->cur_i<0)
CbAddIc(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_U8]);
else
CbAddIc(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_I8]);
Lex(lx);
return PRST_CHECK_BINARY_OPS;
case TK_DOUBLE:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
i_ptr=&lx->cur_d;
CbAddIc(lx,EC_DOUBLE,*i_ptr,sys_internal_types[IT_DOUBLE]);
Lex(lx);
return PRST_CHECK_BINARY_OPS;
case TK_STR:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
d=LexExtendStr(lx,&size);
tempmc=CbMiscNew(lx,CBMT_STR_CONST);
CbAddIc(lx,EC_STR_CONST,tempmc,sys_internal_types[IT_I1]+1);
tempmc->st_len=size;
tempmc->str=d;
lx->flags|=LF_HAS_MISC_DATA;
return PRST_CHECK_BINARY_OPS;
case TK_INSERT_BINARY:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
d=lx->ident;
size=lx->ident_len;
lx->ident=NULL;
Lex(lx);
tempmc=CbMiscNew(lx,CBMT_STR_CONST);
CbAddIc(lx,EC_STR_CONST,tempmc,sys_internal_types[IT_I1]+1);
tempmc->st_len=size;
tempmc->str=d;
lx->flags|=LF_HAS_MISC_DATA;
return PRST_CHECK_BINARY_OPS;
case TK_INSERT_BINARY_TYPE:
case TK_INSERT_BINARY_SIZE:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
CbAddIc(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_U8]);
Lex(lx);
return PRST_CHECK_BINARY_OPS;
case '(':
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
Lex(lx); //Skip (
if (lx->cur_lfn->flags&LFSF_IS_DEFINE ||
*unary_precedence!=PREC_NULL)
paren_warn=FALSE;
else
paren_warn=TRUE;
*unary_precedence=PREC_NULL;
if (!PrsParseExpression(lx,unary_precedence,FALSE))
throw(EXCEPT_COMPILER,2);
if (!paren_warn)
*unary_precedence=PREC_NULL;
else if (*unary_precedence==PREC_TERM)
ParenWarning(lx);
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx); //skip )
lx->flags= lx->flags & ~(LF_ARRAY+LF_FUNCTION) | LF_RAX;
return PRST_UNARY_MODIFIERS;
}
i=unary_ops_table[lx->token];
if (i.u1[2]) {
if (i.u1[2]>*max_precedence)
*max_precedence=i.u1[2];
if (i.u1[2]>*unary_precedence)
*unary_precedence=i.u1[2];
Lex(lx); //Skip op
if (i.u2[0]==EC_ADDRESS && lx->token==TK_IDENT) {
if (tempc=lx->hash_entry) {
if (tempc->s.h.type & HTT_FUNCTION) {
if (!Bt(tempc->flags,Cf_INTERNAL)) {
Lex(lx); //skip fun name
if (Bt(tempc->flags,Cf_EXTERN)) {
if (lx->flags&LF_STATIC_COMPILE)
PrsExcept(lx,"ST_ADDRESS_EXTERN");
else
CbAddIc(lx,EC_IMM,
&tempc->executable_address,sys_internal_types[IT_PTR]);
CbAddIc(lx,EC_DEREF,0,
sys_internal_types[IT_PTR]);
} else {
if (lx->flags&LF_STATIC_COMPILE)
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,
tempc->executable_address,sys_internal_types[IT_PTR]);
else
CbAddIc(lx,EC_IMM,
tempc->executable_address,sys_internal_types[IT_PTR]);
}
return PRST_CHECK_BINARY_OPS;
}
}
}
}
PrsPush(ps,tempc);
PrsPush(ps,i);
return PRST_UNARY_TERM;
}
if (lx->token=='+') {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (PREC_UNARY>*unary_precedence)
*unary_precedence=PREC_UNARY;
Lex(lx);
return PRST_UNARY_TERM;
}
if (lx->token!=TK_IDENT) {
if (lx->token==TK_PLUS_PLUS) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (PREC_UNARY>*unary_precedence)
*unary_precedence=PREC_UNARY;
Lex(lx);
lx->flags|=LF_PREINC;
return PRST_UNARY_TERM;
}
if (lx->token==TK_MINUS_MINUS) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (PREC_UNARY>*unary_precedence)
*unary_precedence=PREC_UNARY;
Lex(lx);
lx->flags|=LF_PREDEC;
return PRST_UNARY_TERM;
}
if (lx->token=='$$') {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
Lex(lx);
if (lx->flags & LF_ASM_EXPRESSIONS) {
lx->absolute_address_cnt++;
if (lx->flags&LF_STATIC_COMPILE)
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,lx->instruction_ptr,sys_internal_types[IT_PTR]);
else
CbAddIc(lx,EC_IMM,lx->instruction_ptr,sys_internal_types[IT_PTR]);
} else
CbAddIc(lx,EC_RIP,0,sys_internal_types[IT_PTR]);
return PRST_CHECK_BINARY_OPS;
}
PrsExcept(lx,"ST_MISSING_EXPRESSION");
}
if (tempm=lx->local_var_entry) {
lx->local_var_entry->use_cnt++;
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
lx->flags&=~(LF_RAX+LF_ARRAY+LF_FUNCTION);
tempc=tempm->member_class+1;
if (tempm->flags & MLF_FUNCTION) {
lx->flags|=LF_FUNCTION;
PrsPush(ps,tempm->return_class);
PrsPush(ps,tempm->arg_cnt);
}
if (tempm->dim.next) {
*tempad=tempm->dim.next;
lx->flags|=LF_ARRAY;
}
if (tempm->flags&MLF_STATIC) {
if (lx->flags&LF_STATIC_COMPILE)
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,tempm->static_data,tempc);
else
CbAddIc(lx,EC_IMM,tempm->static_data,tempc);
} else {
CbAddIc(lx,EC_RBP,0,tempc);
CbAddIc(lx,EC_IMM,tempm->offset,tempc);
CbAddIc(lx,EC_ADD,0,tempc);
}
Lex(lx); //skip var name
*local_var=tempm;
return PRST_UNARY_MODIFIERS;
}
if (!(tempss=lx->hash_entry)) {
if (!(lx->flags & LF_ASM_EXPRESSIONS))
PrsExcept(lx,"ST_INVALID_LVALUE");
tempss=MAllocZ(sizeof(SysSymHashEntry));
tempss->s.h.str=lx->ident;
lx->ident=NULL;
if (*tempss->s.h.str=='@' &&
tempss->s.h.str[1]=='@') {
tempss->s.h.type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_LOCAL;
if (IsReplaceSyms)
ReplaceSysHashEntry(tempss,lx->local_hash_table);
else
AddSysHashEntry(tempss,lx->local_hash_table);
} else {
tempss->s.h.type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_GLBL;
if (IsReplaceSyms)
ReplaceSysHashEntry(tempss,lx->glbl_hash_table);
else
AddSysHashEntry(tempss,lx->glbl_hash_table);
}
}
if (tempss->s.h.type & HTT_SYS_SYMBOL) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
if (!(tempss->s.h.type & HTT_LITERAL) &&
!(tempss->s.h.type & HTT_IMPORT))
lx->absolute_address_cnt++;
if (tempss->s.h.type & (HTT_UNRESOLVED_LOCAL|HTT_UNRESOLVED_GLBL)) {
templu=MAlloc(sizeof(LexUndefEntry));
templu->hash=tempss;
templu->next=lx->undef_hash_entry;
lx->undef_hash_entry=templu;
if (tempss->s.h.type & HTT_UNRESOLVED_LOCAL)
lx->flags|=LF_UNRESOLVED_LOCAL;
else
lx->flags|=LF_UNRESOLVED_GLBL;
CbAddIc(lx,EC_IMM,&tempss->val,sys_internal_types[IT_PTR]);
CbAddIc(lx,EC_DEREF,0,sys_internal_types[IT_PTR]);
} else {
if (lx->flags&LF_STATIC_COMPILE && !(tempss->s.h.type & HTT_LITERAL))
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,tempss->val,sys_internal_types[IT_PTR]);
else
CbAddIc(lx,EC_IMM,tempss->val,sys_internal_types[IT_PTR]);
}
Lex(lx);
return PRST_CHECK_BINARY_OPS;
}
if (tempss->s.h.type & HTT_FUNCTION) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
is_first_arg=TRUE;
Lex(lx); //skip fun name
CbAddIc(lx,EC_NOP,0,0); //record indent_level
CbPush(lx);
templ=lx->cb.cb_next;
lx->cb.cb_next=NULL;
tempc=tempss;
i=tempc->arg_cnt;
tempm=tempc->member_list;
argc_cnt=0;
if (lx->token!='(')
needs_right_paren=FALSE;
else {
Lex(lx);
needs_right_paren=TRUE;
}
while (i--) {
CbInitOutPtrs(&lx->cb);
if (needs_right_paren && !is_first_arg) {
if (lx->token==',')
Lex(lx);
else if (lx->token!=')')
PrsExcept(lx,"ST_EXPECTING_COMMA");
}
if (tempm->flags & MLF_DEFAULT_AVAILABLE &&
(lx->token==')' || lx->token==',' || !needs_right_paren))
CbAddIc(lx,EC_IMM,tempm->default_value,tempm->member_class);
else {
if (tempm->flags&MLF_BY_ADDRESS)
lx->flags|=LF_BY_ADDRESS;
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,3);
else {
CbPush(lx);
CbAddIc(lx,EC_NULL,0,0);
tempi=CmpOptPass012(lx,NULL,FALSE,0);
CbPop(lx);
tempc1=tempi->ic_class;
while (tempc1->return_class)
tempc1=tempc1->return_class;
tempc2=tempm->member_class;
while (tempc2->return_class)
tempc2=tempc2->return_class;
if (tempc2->sub_type==IT_DOUBLE &&
tempc1->sub_type!=IT_DOUBLE)
tempi->ic_flags|=ICF_R_TO_DOUBLE;
else
if (tempc2->sub_type!=IT_DOUBLE &&
tempc1->sub_type==IT_DOUBLE)
tempi->ic_flags|=ICF_R_TO_INT;
}
}
CbAddIc(lx,EC_NULL,0,0);
CbPush(lx);
is_first_arg=FALSE;
tempm=tempm->next;
}
if (tempm && tempm->flags & MLF_DOT_DOT_DOT) {
CbInitOutPtrs(&lx->cb);
CbAddIc(lx,EC_IMM,0,tempm->member_class);
tempi=lx->cb.cb_last_out_ptr;
CbAddIc(lx,EC_NULL,0,0);
CbPush(lx);
if (needs_right_paren) {
if (lx->token!=')') {
do {
if (!is_first_arg) {
if (lx->token==',')
Lex(lx);
else
PrsExcept(lx,"ST_EXPECTING_COMMA");
}
CbInitOutPtrs(&lx->cb);
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,4);
CbAddIc(lx,EC_NULL,0,0);
CbPush(lx);
is_first_arg=FALSE;
argc_cnt++;
} while (lx->token==',');
}
}
tempi->ic_data=argc_cnt++; //++ so add_esp latter works
}
if (needs_right_paren) {
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx);
}
templ1=templ->cb_next;
templ->cb_next=lx->cb.cb_next;
lx->cb.cb_next=templ;
CbPop(lx);
templ=lx->cb.cb_next;
lx->cb.cb_next=templ1;
CbAddIc(lx,EC_CALL_START,tempc,0);
while (templ) {
templ1=templ->cb_next;
CbAppend(lx,templ);
if (!Bt(tempc->flags,Cf_INTERNAL))
lx->cb.cb_last_out_ptr->ic_flags|=ICF_PUSH_RESULT;
templ=templ1;
}
if (Bt(tempc->flags,Cf_INTERNAL))
CbAddIc(lx,tempc->executable_address,0,tempc->return_class);
else if (Bt(tempc->flags,Cf_EXTERN)) {
if (lx->flags&LF_STATIC_COMPILE) {
if (tempc->s.h.type&HTT_IMPORT)
CbAddIc(lx,EC_CALL_IMPORT,tempc,tempc->return_class);
else
CbAddIc(lx,EC_CALL_EXTERN,tempc,tempc->return_class);
} else
CbAddIc(lx,EC_CALL_INDIRECT2,&tempc->executable_address,tempc->return_class);
CbAddIc(lx,EC_ADD_RSP,(argc_cnt+tempc->arg_cnt)<<3,tempc->return_class);
} else {
CbAddIc(lx,EC_CALL,tempc->executable_address,tempc->return_class);
CbAddIc(lx,EC_ADD_RSP,(argc_cnt+tempc->arg_cnt)<<3,tempc->return_class);
}
CbAddIc(lx,EC_CALL_END,tempc,tempc->return_class);
lx->flags=(lx->flags|LF_RAX) & ~(LF_ARRAY|LF_FUNCTION);
return PRST_UNARY_MODIFIERS;
}
if (tempss->s.h.type & HTT_GLBL_VAR) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
tempg=tempss;
tempc=tempg->var_class+1;
lx->flags&=~(LF_RAX|LF_ARRAY|LF_FUNCTION);
if (tempg->dim.next) {
*tempad=tempg->dim.next;
lx->flags|=LF_ARRAY;
}
if (tempg->flags & GVAF_FUNCTION) {
//TODO:Not implemented
lx->flags|=LF_FUNCTION;
}
if (lx->flags&LF_STATIC_COMPILE) {
if (tempg->flags & GVAF_EXTERN) //TODO
PrsExcept(lx,"ST_NOT_IMPLEMENTED");
else {
if (tempg->flags & GVAF_IMPORT)
CbAddIc(lx,EC_ADDRESS_IMPORT,tempg,tempc);
else {
if (tempg->flags&GVAF_DATA_HEAP)
CbAddIc(lx,EC_HEAP_GLBL,tempg->data,tempc);
else
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,tempg->data_address,tempc);
}
}
} else {
if (tempg->flags & GVAF_EXTERN) {
CbAddIc(lx,EC_IMM,&tempg->data_address,tempc);
CbAddIc(lx,EC_DEREF,0,tempc);
} else
CbAddIc(lx,EC_IMM,tempg->data_address,tempc);
}
Lex(lx);
return PRST_UNARY_MODIFIERS;
}
if (!(tempss->s.h.type & HTT_KEYWORD))
PrsExcept(lx,"ST_MISSING_EXPRESSION");
if (tempss><(GenericHashEntry *)->user_data0==KW_SIZEOF) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
Lex(lx); //skip sizeof
j=0;
while (lx->token=='(') {
Lex(lx);
j++;
}
if (lx->token!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_CLASS");
if (tempm=lx->local_var_entry) {
lx->local_var_entry->use_cnt++;
tempc=tempm->member_class;
i=tempc->size*tempm->dim.total_cnt;
} else {
tempc=lx->hash_entry;
if (!tempc || !(tempc->s.h.type & (HTT_CLASS|HTT_INTERNAL_TYPE|HTT_GLBL_VAR|HTT_TYPEDEF)))
PrsExcept(lx,"ST_INVALID_CLASS");
i=tempc->size;
} //TODO: should allow '.member', etc;
if (Lex(lx)=='*') {
while (Lex(lx)=='*');
i=sizeof(void *);
}
CbAddIc(lx,EC_IMM,i,sys_internal_types[IT_I8]);
while (j--) {
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx);
}
return PRST_CHECK_BINARY_OPS;
} else if (tempss><(GenericHashEntry *)->user_data0==KW_OFFSET && !(lx->opts&1<<OPTf_STD_C)) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
Lex(lx); //skip offset
j=0;
while (lx->token=='(') {
Lex(lx);
j++;
}
if (lx->token!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_CLASS");
if (tempm=lx->local_var_entry) {
lx->local_var_entry->use_cnt++;
tempc=tempm->member_class;
} else {
tempc=lx->hash_entry;
if (!tempc || !(tempc->s.h.type & (HTT_CLASS|HTT_GLBL_VAR)))
PrsExcept(lx,"ST_INVALID_CLASS");
else if (tempc->s.h.type & HTT_GLBL_VAR)
tempc=tempc><(GlblVarStruct *)->var_class;
}
if (Lex(lx)!='.')
PrsExcept(lx,"ST_EXPECTING_DOT");
if (Lex(lx)!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_MEMBER");
if (!(tempm=FindMember(lx->ident,tempc)))
PrsExcept(lx,"ST_INVALID_MEMBER");
CbAddIc(lx,EC_IMM,tempm->offset,sys_internal_types[IT_I8]);
Lex(lx);
while (j--) {
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx);
}
return PRST_CHECK_BINARY_OPS;
}
PrsExcept(lx,"ST_MISSING_EXPRESSION");
}
U8 PrsUnaryModifier(LexStruct *lx,ParseStack *ps,MemberListStruct **local_var,ArrayDimStruct **tempad,I8 *max_precedence)
{
I8 i,j;
LexCbStack *templ,*templ2,*templl;
ClassStruct *tempc,*tempc1;
MemberListStruct *tempm;
IntermediateCode *tempi,*tempi1;
ArrayDimStruct *tempad1;
if (lx->flags & LF_ASM_EXPRESSIONS)
return PRST_CHECK_BINARY_OPS;
if (tempm=*local_var) {
if (tempm->flags&MLF_BY_ADDRESS) {
tempi=lx->cb.cb_last_out_ptr;
if (!(lx->flags & (LF_RAX | LF_ARRAY)))
CbAddIc(lx,EC_DEREF+PREC_UNARY<<16,0,tempi->ic_class-1);
else {
tempi->ic_class--;
lx->flags&=~(LF_RAX|LF_ARRAY);
}
}
}
if (lx->token==TK_DEREFERRENCE) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
tempi=lx->cb.cb_last_out_ptr;
if (!(lx->flags & (LF_RAX | LF_ARRAY)))
CbAddIc(lx,EC_DEREF+PREC_UNARY<<16,0,tempi->ic_class-1);
else
tempi->ic_class--;
} else if (lx->token=='.') {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (tempm)
tempm->flags|=MLF_NO_REG_VARIABLE;
}
*local_var=NULL;
if (lx->token=='.' || lx->token==TK_DEREFERRENCE) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
tempi=lx->cb.cb_last_out_ptr;
tempc=tempi->ic_class;
if (!(lx->flags & LF_RAX))
tempc--;
if (!(tempc->s.h.type & HTT_CLASS))
PrsExcept(lx,"ST_INVALID_CLASS");
if (Lex(lx)!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_MEMBER");
if (!(tempm=FindMember(lx->ident,tempc)))
PrsExcept(lx,"ST_INVALID_MEMBER");
Lex(lx); //skip member name
tempc1=tempm->member_class+1;
CbAddIc(lx,EC_IMM,tempm->offset,tempc1);
lx->flags&=~(LF_RAX|LF_ARRAY|LF_FUNCTION);
if (tempm->dim.next) {
*tempad=tempm->dim.next;
lx->flags|=LF_ARRAY;
}
if(tempm->flags & MLF_FUNCTION) {
PrsPush(ps,tempm->return_class);
PrsPush(ps,tempm->arg_cnt);
lx->flags|=LF_FUNCTION;
}
CbAddIc(lx,EC_ADD,0,tempc1);
return PRST_UNARY_MODIFIERS;
}
if (lx->token==TK_CAST) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (Lex(lx)!='(')
PrsExcept(lx,"ST_EXPECTING_LEFT_PAREN");
if (Lex(lx)!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_CLASS");
tempc=lx->hash_entry;
if (!tempc || !(tempc->s.h.type & (HTT_CLASS|HTT_INTERNAL_TYPE)))
PrsExcept(lx,"ST_INVALID_CLASS");
while (Lex(lx)=='*')
tempc++;
if (!(lx->flags&(LF_RAX|LF_ARRAY)))
tempc++;
tempi=lx->cb.cb_last_out_ptr;
tempi->ic_class=tempc;
CbAddIc(lx,EC_TYPECAST,0,tempc);
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx);
return PRST_UNARY_MODIFIERS;
}
if (lx->token=='[') {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
Lex(lx);
tempi=lx->cb.cb_last_out_ptr;
if (!(lx->flags & (LF_ARRAY | LF_RAX))) {
tempc=tempi->ic_class-1;
while (tempc->return_class)
tempc=tempc->return_class;
i=EC_DEREF+PREC_UNARY<<16;
CbAddIc(lx,i,0,tempc);
} else {
tempc=tempi->ic_class;
while (tempc->return_class)
tempc=tempc->return_class;
}
tempc1=tempc-1;
if (tempad1=*tempad) {
CbAddIc(lx,EC_IMM,tempad1->total_cnt*tempc1->size,tempc);
if (*tempad=tempad1->next) {
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,5);
if (lx->token!=']')
PrsExcept(lx,"ST_MISSING_RIGHT_BRACKET");
Lex(lx); //skip ]
tempi1=lx->cb.cb_last_out_ptr;
if (tempi1->ic_class->sub_type==IT_DOUBLE)
tempi1->ic_flags|=ICF_R_TO_INT;
CbAddIc(lx,EC_MUL,0,tempc);
tempi1=lx->cb.cb_last_out_ptr;
tempi1->ic_flags|=ICF_USE_INT;
CbAddIc(lx,EC_ADD,0,tempc);
tempi1=lx->cb.cb_last_out_ptr;
tempi1->ic_flags|=ICF_USE_INT;
lx->flags|=LF_RAX;
return PRST_UNARY_MODIFIERS;
}
} else
CbAddIc(lx,EC_IMM,tempc1->size,tempc);
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,5);
if (lx->token!=']')
PrsExcept(lx,"ST_MISSING_RIGHT_BRACKET");
Lex(lx); //skip ]
tempi1=lx->cb.cb_last_out_ptr;
if (tempi1->ic_class->sub_type==IT_DOUBLE)
tempi1->ic_flags|=ICF_R_TO_INT;
CbAddIc(lx,EC_MUL,0,tempc);
tempi1=lx->cb.cb_last_out_ptr;
tempi1->ic_flags|=ICF_USE_INT;
CbAddIc(lx,EC_ADD,0,tempc);
tempi1=lx->cb.cb_last_out_ptr;
tempi1->ic_flags|=ICF_USE_INT;
lx->flags&=~(LF_RAX|LF_ARRAY);
return PRST_UNARY_MODIFIERS;
}
if (lx->token=='(' && lx->flags & LF_FUNCTION) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
tempi=lx->cb.cb_last_out_ptr;
tempc=tempi->ic_class-1;
if (!(lx->flags & (LF_RAX | LF_ARRAY)))
CbAddIc(lx,EC_DEREF,0,sys_internal_types[IT_PTR]);
else if (!(lx->flags & LF_ARRAY))
tempi->ic_class=tempc;
CbAddIc(lx,EC_SET_RAX,0,sys_internal_types[IT_PTR]);
CbAddIc(lx,EC_NOP1,1,sys_internal_types[IT_PTR]); //balance the books
CbAddIc(lx,EC_CALL_START,0,tempc);
CbAddIc(lx,EC_PUSH_REGS,1<<CREG_RAX,tempc);
i=PrsPop(ps);
tempc=PrsPop(ps);
j=i;
Lex(lx); //skip '('
CbAddIc(lx,EC_NOP,0,0); //record indent_level
CbPush(lx);
templ=lx->cb.cb_next;
lx->cb.cb_next=NULL;
while (i--) {
if (lx->token==',')
Lex(lx);
CbInitOutPtrs(&lx->cb);
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,6);
CbAddIc(lx,EC_NULL,0,0);
CbPush(lx);
}
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx); //skip ')'
templl=templ->cb_next;
templ->cb_next=lx->cb.cb_next;
lx->cb.cb_next=templ;
CbPop(lx);
templ=lx->cb.cb_next;
lx->cb.cb_next=templl;
while (templ) {
templ2=templ->cb_next;
CbAppend(lx,templ);
lx->cb.cb_last_out_ptr->ic_flags|=ICF_PUSH_RESULT;
templ=templ2;
}
CbAddIc(lx,EC_CALL_INDIRECT,j<<3,tempc);
CbAddIc(lx,EC_ADD_RSP,j<<3+8,tempc);
CbAddIc(lx,EC_CALL_END,0,tempc);
lx->flags=(lx->flags | LF_RAX)&~(LF_ARRAY | LF_FUNCTION);
return PRST_UNARY_MODIFIERS;
}
if (lx->token==TK_PLUS_PLUS) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
Lex(lx);
lx->flags|=LF_POSTINC;
return PRST_DEREFERRENCE;
}
if (lx->token==TK_MINUS_MINUS) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
Lex(lx);
lx->flags|=LF_POSTDEC;
return PRST_DEREFERRENCE;
}
return PRST_DEREFERRENCE;
}
U8 PrsDereferrence(LexStruct *lx,ParseStack *ps)
{
I8 i;
ClassStruct *tempc;
IntermediateCode *tempi;
if (lx->flags & LF_FUNCTION) {
ps->ptr--;
tempc=PrsPop(ps);
}
if (lx->flags & (LF_RAX|LF_ARRAY))
return PRST_CHECK_BINARY_OPS;
tempi=lx->cb.cb_last_out_ptr;
tempc=tempi->ic_class-1;
if (lx->flags & LF_PREINC) {
lx->flags&=~LF_PREINC;
i=EC_PP_;
} else if (lx->flags & LF_PREDEC) {
lx->flags&=~LF_PREDEC;
i=EC_MM_;
} else if (lx->flags & LF_POSTINC) {
lx->flags&=~LF_POSTINC;
i=EC__PP;
} else if (lx->flags & LF_POSTDEC) {
lx->flags&=~LF_POSTDEC;
i=EC__MM;
} else
i=EC_DEREF;
while (tempc->return_class)
tempc=tempc->return_class;
CbAddIc(lx,i+PREC_UNARY<<16,0,tempc);
return PRST_CHECK_BINARY_OPS;
}
void *CompileExpression(LexStruct *lx,U8 *type=NULL)
{
void *result;
U8 size;
DbgInfo *dbg=NULL;
IndentInfo *indent=NULL;
BoolI1 old_trace=Btr(&lx->flags,LFf_OPT_TRACE_PRESENT);
CbPush(lx);
CbInitOutPtrs(&lx->cb);
CbAddIc(lx,EC_RETURN_START,0,0);
if (PrsParseExpression(lx,NULL,TRUE)) {
CbAddIc(lx,EC_RETURN_END,0,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_RET,0,0);
CbAddIc(lx,EC_NULL,0,0);
result=CbCompile(lx,NULL,&size,&dbg,&indent,type);
} else
result=NULL;
CbPop(lx);
Free(dbg);
Free(indent);
AssignBit(&lx->flags,LFf_OPT_TRACE_PRESENT,old_trace);
return result;
}
BoolI8 GetExpression(LexStruct *lx,void **ex) //FALSE=no err
{
*ex=CompileExpression(lx);
if (*ex)
return TRUE;
else
return FALSE;
}
I8 Expression(LexStruct *lx) //FALSE=no err
{
I8 result;
void *ex=CompileExpression(lx);
if (ex) {
result=Call(ex);
ExpressionDel(ex);
} else
result=0;
return result;
}
I just wanted to show I'm not bullsh*tting.
Seriously an unoptimized compiler is easy compared to many operating system things. Surprisingly when I added major optimizations, i could hardly tell a difference because the intel chips are so smart that unoptimized code is just as fast, almost.