1222 lines
27 KiB
Plaintext
1222 lines
27 KiB
Plaintext
I1 *CmpPmt(BoolU4 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;
|
|
if (double_semicolon) {
|
|
i=StrLen(s);
|
|
result=MAlloc(i+4);
|
|
MemCpy(result,s,i+1);
|
|
i--;
|
|
while (i>=0 && (result[i]==CH_SPACE || result[i]==CH_SHIFT_SPACE || result[i]==CH_TAB))
|
|
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=NewStr(s);
|
|
Free(s);
|
|
return result;
|
|
}
|
|
|
|
LexStruct *LexNew(I1 *buf,U8 flags,I1 *filename)
|
|
{
|
|
LexStruct *lx=MAlloc(sizeof(LexStruct));
|
|
LexFileStruct *tempf=&lx->lfns[0];
|
|
MemSet(lx,0,offset(LexStruct.lfns)+sizeof(LexFileStruct));
|
|
lx->next=lx;
|
|
lx->last=lx;
|
|
lx->flags=flags;
|
|
lx->lag_line_num=1;
|
|
lx->pass_trace_mask=0b100111111;
|
|
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->next_exe_blk;
|
|
lx->last_exe_blk=&lx->next_exe_blk;
|
|
if (!filename)
|
|
tempf->name=NewStr(sys_temp_filename);
|
|
else
|
|
tempf->name=filename;
|
|
if (flags & LF_PROMPT)
|
|
buf=MAllocZ(4);
|
|
tempf->buf=buf;
|
|
tempf->buf_ptr=buf;
|
|
tempf->line_start=buf;
|
|
tempf->line_num=1;
|
|
lx->cur_buf_ptr=buf;
|
|
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-=sizeof(LexFileStruct);
|
|
}
|
|
Free(tempf->name);
|
|
if (!(lx->flags & LF_DONT_FREE_BUFFER))
|
|
Free(tempf->buf);
|
|
Free(lx->ident);
|
|
Free(lx);
|
|
}
|
|
|
|
|
|
void SetSourceFileInfo(LexStruct *lx,SysHashEntry *h)
|
|
{
|
|
LexFileStruct *tempf=lx->cur_lfn;
|
|
h->source_link=MSPrintF("FL:%s,%d",tempf->name,tempf->line_num);
|
|
if (Bt(&lx->flags,LFf_KEEP_PRIVATE))
|
|
h->type|=HTT_PRIVATE;
|
|
if (lx->cur_index)
|
|
h->index=NewStr(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;
|
|
BoolU4 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->display))
|
|
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->flags & LF_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->flags & LF_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->flags & LF_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-=sizeof(LexFileStruct);
|
|
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->flags & LF_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 DelExpression(U1 *code)
|
|
{
|
|
Free(code);
|
|
}
|
|
|
|
|
|
U8 EvalExpression(LexStruct *lx)
|
|
{
|
|
U1 *exp;
|
|
U8 result=0;
|
|
if (!GetExpression(lx,&exp))
|
|
LexSkipEol(lx);
|
|
else {
|
|
result=Call(exp);
|
|
DelExpression(exp);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void LexIncludeStr(LexStruct *lx,I1 *filename,
|
|
I1 *src,BoolU4 actual_file)
|
|
{
|
|
LexFileStruct *tempf;
|
|
LexBackupLastChar(lx);
|
|
tempf=lx->cur_lfn+sizeof(LexFileStruct);
|
|
lx->cur_lfn=tempf;
|
|
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=NewStr(sys_temp_filename);
|
|
tempf->flags=0;
|
|
}
|
|
lx->cur_buf_ptr=src;
|
|
}
|
|
|
|
void LexIncludeLtf(LexStruct *lx,I1 *filename)
|
|
{
|
|
BoolU4 is_null;
|
|
LtfEntry *cl;
|
|
Ltf *l;
|
|
LexFileStruct *tempf;
|
|
|
|
LexBackupLastChar(lx);
|
|
tempf=lx->cur_lfn+sizeof(LexFileStruct);
|
|
lx->cur_lfn=tempf;
|
|
tempf->line_start=&lex_zeros;
|
|
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 (cl->btype==LTFT_TEXT)
|
|
break;
|
|
if (cl->btype==LTFT_TAB)
|
|
break;
|
|
if (cl->btype==LTFT_CR)
|
|
break;
|
|
if (cl->btype==LTFT_INSERT_BINARY)
|
|
break;
|
|
if (cl->btype==LTFT_INSERT_BINARY_TYPE)
|
|
break;
|
|
if (cl->btype==LTFT_INSERT_BINARY_SIZE)
|
|
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->display;
|
|
tempf->buf_ptr=cl->display;
|
|
} 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;
|
|
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));
|
|
}
|
|
|
|
MemberListStruct *FindMember(I1 *st,ClassStruct *c)
|
|
{
|
|
MemberListStruct *ml=c->member_list;
|
|
while (ml) {
|
|
if (!StrCmp(ml->str,st)) {
|
|
ml->use_cnt++;
|
|
return ml;
|
|
}
|
|
ml=ml->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void DelMemberList(ClassStruct *tempc)
|
|
{
|
|
MemberListStruct *tempm,*tempm1;
|
|
tempm=tempc->member_list;
|
|
while (tempm) {
|
|
tempm1=tempm->next;
|
|
Free(tempm->str);
|
|
Free(tempm->fmtstr);
|
|
Free(tempm->fmtdata);
|
|
DelLinkedList(tempm->dim_list);
|
|
if (tempm->flags & MLF_DEFAULT_AVAILABLE &&
|
|
tempm->member_class==sys_internal_types[IT_I1]+sizeof(ClassStruct))
|
|
Free(tempm->default_value);
|
|
Free(tempm);
|
|
tempm=tempm1;
|
|
}
|
|
tempc->size=0;
|
|
tempc->last_in_member_list=&tempc->member_list;
|
|
tempc->member_list=NULL;
|
|
tempc->member_cnt=0;
|
|
tempc->parameter_cnt=0;
|
|
}
|
|
|
|
|
|
I8 LexInStr(LexStruct *lx,
|
|
I1 *buf,I8 size,BoolU4 *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==0x27) // "\'"
|
|
buf[i++]=0x27;
|
|
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;
|
|
BoolU4 str_done;
|
|
I1 *fbuf;
|
|
I1 *buf2,*buf3,buf[LEX_MAX_IDENT];
|
|
lx->lag_line_num=lx->cur_lfn->line_num;
|
|
while (TRUE) {
|
|
lex_cont:
|
|
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_STR_CONST && !(lx->flags & LF_NO_DEFINES))
|
|
LexIncludeStr(lx,
|
|
temph->str,NewStr(temph><(StrConstStruct *)->data),FALSE);
|
|
else {
|
|
lx->hash_entry=temph;
|
|
Free(lx->ident);
|
|
lx->ident=NewStr(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;
|
|
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);
|
|
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==0x27) { // "'"
|
|
ch=LexGetChar(lx);
|
|
if (!ch || ch==0x27) i=0x27;
|
|
else if (ch=='\\') {
|
|
ch=LexGetChar(lx);
|
|
if (ch=='n')
|
|
i=10;
|
|
else if (ch=='r')
|
|
i=13;
|
|
else if (ch=='"')
|
|
i='"';
|
|
else if (ch==0x27)
|
|
i=0x27;
|
|
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!=0x27)
|
|
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->user_data0) {
|
|
case KW_INCLUDE:
|
|
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])
|
|
LexIncludeLtf(lx,fbuf);
|
|
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(StrConstStruct));
|
|
temph->str=lx->ident;
|
|
lx->ident=0;
|
|
temph->use_cnt=0;
|
|
temph->type=HTT_STR_CONST;
|
|
SetSourceFileInfo(lx,temph);
|
|
i=0;
|
|
do ch=LexGetChar(lx);
|
|
while (ch && (ch<=CH_SPACE || ch>0x7E) && ch!=CH_CR);
|
|
if (ch>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>=CH_SHIFT_SPACE && ch<=0x7E || ch==CH_TAB);
|
|
break;
|
|
} else {
|
|
buf[i++]='/';
|
|
lx->flags|=LF_USE_LAST_I1;
|
|
}
|
|
} else if (ch>=CH_SHIFT_SPACE && ch<=0x7E || ch==CH_TAB)
|
|
buf[i++]=ch;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
buf[i++]=0;
|
|
temph><(StrConstStruct *)->data=NewStr(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 lex_end;
|
|
if (lx->hash_entry)
|
|
goto lex_cont;
|
|
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_IFNDEF:
|
|
if (lx->flags & LF_IN_IF) {
|
|
lx->token=TK_IFNDEF;
|
|
goto lex_end;
|
|
}
|
|
lex_ifndef:
|
|
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 lex_end;
|
|
if (!lx->hash_entry)
|
|
goto lex_cont;
|
|
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_ENDIF:
|
|
if (lx->flags & LF_IN_IF) {
|
|
lx->token=TK_ENDIF;
|
|
goto lex_end;
|
|
}
|
|
break;
|
|
case KW_ASSERT:
|
|
if (!Lex(lx))
|
|
goto lex_end;
|
|
if (!Expression(lx))
|
|
PutLexWarning(lx,"ST_ASSERT_FAILED");
|
|
goto lex_end;
|
|
case KW_EXE:
|
|
if (!Lex(lx))
|
|
goto lex_end;
|
|
CallExtNum(EXT_CMP_EXE_BLK,lx);
|
|
goto lex_end;
|
|
case KW_HELP_INDEX:
|
|
if (Lex(lx)!=TK_STR)
|
|
goto lex_end;
|
|
Free(lx->cur_index);
|
|
lx->cur_index=lx->ident;
|
|
lx->ident=NULL;
|
|
break;
|
|
case KW_HELP_FILE:
|
|
if (Lex(lx)!=TK_STR)
|
|
goto lex_end;
|
|
temph=MAllocZ(sizeof(SysHashEntry));
|
|
temph->str=AbsoluteFileName(lx->ident);
|
|
temph->type=HTT_HELP_FILE|HTT_PUBLIC;
|
|
SetSourceFileInfo(lx,temph);
|
|
AddSysHashEntry(temph,lx->hash_table_list);
|
|
break;
|
|
}
|
|
} else if (ch==TK_INSERT_BINARY ||
|
|
ch==TK_INSERT_BINARY_TYPE ||
|
|
ch==TK_INSERT_BINARY_SIZE) {
|
|
lx->token=ch;
|
|
goto lex_end;
|
|
} else if (ch=='.') {
|
|
ch=LexGetChar(lx);
|
|
if (ch>='0' && ch<='9') {
|
|
i=0;
|
|
goto float_start;
|
|
}
|
|
lx->flags|=LF_USE_LAST_I1;
|
|
lx->token='.';
|
|
goto lex_end;
|
|
} else if (ch>=0x21 && ch<=0x7E) {
|
|
i=duel_I1_tokens1[ch];
|
|
if (!i) {
|
|
if (ch=='$$') {
|
|
do ch=LexGetChar(lx);
|
|
while (ch && ch!='$$');
|
|
goto lex_cont;
|
|
} else {
|
|
lx->token=ch;
|
|
goto lex_end;
|
|
}
|
|
} else {
|
|
j=LexGetChar(lx);
|
|
if (i.u1[0]==j) {
|
|
i>>=8;
|
|
if (!i) { // "/*"
|
|
j=1;
|
|
do {
|
|
if (!(ch=LexGetChar(lx)))
|
|
return lx->token=TK_EOF;
|
|
lex_check_comment:
|
|
if (ch=='*') {
|
|
if (!(ch=LexGetChar(lx)))
|
|
return lx->token=TK_EOF;
|
|
if (ch=='/')
|
|
j--;
|
|
else
|
|
goto lex_check_comment;
|
|
} else if (ch=='/') {
|
|
if (!(ch=LexGetChar(lx)))
|
|
return lx->token=TK_EOF;
|
|
if (ch=='*')
|
|
j++;
|
|
else
|
|
goto lex_check_comment;
|
|
}
|
|
} while (j);
|
|
goto lex_cont;
|
|
} else {
|
|
lx->token=i;
|
|
goto lex_end;
|
|
}
|
|
}
|
|
if (i=duel_I1_tokens2[ch]) {
|
|
if (i.u1[0]==j) {
|
|
i>>=8;
|
|
if (!i) { // "//"
|
|
LexSkipEol(lx);
|
|
goto lex_cont;
|
|
} else {
|
|
if (i==TK_SHL || i==TK_SHR) {
|
|
j=LexGetChar(lx);
|
|
if (j=='=') {
|
|
if (i==TK_SHL)
|
|
i=TK_SHL_EQUAL;
|
|
else
|
|
i=TK_SHR_EQUAL;
|
|
} else
|
|
lx->flags|=LF_USE_LAST_I1;
|
|
}
|
|
lx->token=i;
|
|
goto lex_end;
|
|
}
|
|
}
|
|
if (i=duel_I1_tokens3[ch]) {
|
|
if (i.u1[0]==j) {
|
|
lx->token=i.u1[1];
|
|
goto lex_end;
|
|
}
|
|
}
|
|
}
|
|
lx->flags|=LF_USE_LAST_I1;
|
|
lx->token=ch;
|
|
goto lex_end;
|
|
}
|
|
}
|
|
}
|
|
lex_end:
|
|
if (Bt(&lx->flags,LFf_LEX_TRACE))
|
|
LexPutToken(lx);
|
|
return lx->token;
|
|
}
|
|
|
|
I1 *LexExtendStr(LexStruct *lx,U8 *size=NULL)
|
|
{
|
|
U8 len=lx->ident_len,len1,len2;
|
|
I1 *st=lx->ident,*st1,*st2;
|
|
lx->ident=NULL;
|
|
while (lx->token==TK_STR) {
|
|
st1=st;
|
|
len1=len;
|
|
if (Lex(lx)==TK_STR) {
|
|
len2=lx->ident_len;
|
|
st2=lx->ident;
|
|
lx->ident=NULL;
|
|
len=len1+len2-1;
|
|
st=MAlloc(len);
|
|
if (len1>1)
|
|
MemCpy(st,st1,len1-1);
|
|
MemCpy(st+len1-1,st2,len2);
|
|
Free(st1);
|
|
Free(st2);
|
|
}
|
|
}
|
|
if (size)
|
|
*size=len;
|
|
return st;
|
|
}
|
|
|
|
I1 *LexPutLine(LexStruct *lx,I1 *start)
|
|
{
|
|
I1 *ptr;
|
|
if (!start) return;
|
|
if (lx->cur_lfn->flags&LFSF_IS_LTF)
|
|
return CallExtStr("LtfPutLine",start);
|
|
else {
|
|
ptr=start;
|
|
while (*ptr && *ptr!=CH_LINE_FEED && *ptr!=CH_CR)
|
|
PutChar(*ptr++);
|
|
CrLf;
|
|
return (*ptr) ? ptr+1:ptr;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
I8 LexLineNum(LexStruct *lx)
|
|
{
|
|
return lx->cur_lfn->line_num;
|
|
}
|
|
|
|
void LexPutLink(LexStruct *lx)
|
|
{
|
|
if (IsRaw)
|
|
PrintF("%s,%d ",lx->cur_lfn->name,lx->cur_lfn->line_num);
|
|
else {
|
|
PutFileLink(lx->cur_lfn->name,lx->cur_lfn->line_num);
|
|
AdamErr("%s,%d\r",lx->cur_lfn->name,lx->cur_lfn->line_num);
|
|
PutS(" ");
|
|
}
|
|
}
|
|
|
|
void PutLexError(LexStruct *lx,I1 *name=NULL,I1 *msg=NULL)
|
|
{
|
|
PutErr;
|
|
lx->error_cnt++;
|
|
if (!IsRaw)
|
|
AdamErr("Tsk:%08X ",Fs);
|
|
if (name) {
|
|
PutSysText(name);
|
|
if (!IsRaw)
|
|
AdamErr("%S",name);
|
|
}
|
|
if (msg) {
|
|
PutS(msg);
|
|
if (!IsRaw)
|
|
AdamErr("%s\r\n",msg);
|
|
}
|
|
LexPutToken(lx);
|
|
LexPutLink(lx);
|
|
LexPutLine(lx,lx->cur_lfn->line_start);
|
|
}
|
|
|
|
void PutLexWarning(LexStruct *lx,I1 *name=NULL,I1 *msg=NULL)
|
|
{
|
|
PrintFWarn("%S%s",name,msg);
|
|
lx->warning_cnt++;
|
|
LexPutToken(lx);
|
|
LexPutLink(lx);
|
|
LexPutLine(lx,lx->cur_lfn->line_start);
|
|
}
|
|
|
|
void PutAsmError(LexStruct *lx,I1 *name)
|
|
{
|
|
PutLexError(lx,name);
|
|
LexSkipEol(lx);
|
|
Lex(lx);
|
|
}
|
|
|
|
void PutAsmWarning(LexStruct *lx,I1 *name)
|
|
{
|
|
PutLexWarning(lx,name);
|
|
LexSkipEol(lx);
|
|
Lex(lx);
|
|
}
|
|
|
|
void PrsExcept(LexStruct *lx,I1 *name=NULL,I1 *msg=NULL)
|
|
{
|
|
PutLexError(lx,name,msg);
|
|
CallExtNum(EXT_FLUSH_MSGS,NULL);
|
|
throw(EXCEPT_COMPILER,0);
|
|
}
|
|
|
|
|