Page 1 of 1

Lair of LoseThos the Troll. No feeding

Posted: Fri Dec 12, 2008 5:45 am
by LoseThos
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.

Re: How to handle certain interrupts?

Posted: Fri Dec 12, 2008 5:57 am
by M-Saunders
LoseThos wrote:I keep telling you guys to write your own tools.
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!

M

Re: How to handle certain interrupts?

Posted: Fri Dec 12, 2008 6:01 am
by LoseThos
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?

Posted: Fri Dec 12, 2008 6:06 am
by JamesM
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.
How about, You write your own tools, I will do whatever I want. How does that sound?

Re: How to handle certain interrupts?

Posted: Fri Dec 12, 2008 6:10 am
by LoseThos
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:

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