mirror of https://github.com/minexew/Shrine.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1195 lines
26 KiB
1195 lines
26 KiB
CLexFile *LexFilePush(CCmpCtrl *cc) |
|
{//#include file push. |
|
CLexFile *res=CAlloc(sizeof(CLexFile)); |
|
if (res->next=cc->lex_include_stk) |
|
res->depth=res->next->depth+1; |
|
else |
|
res->depth=-1; //Include depth starts with -1. |
|
return cc->lex_include_stk=res; |
|
} |
|
|
|
CLexFile *LexFilePop(CCmpCtrl *cc) |
|
{//#include file pop. |
|
CLexFile *tmpf; |
|
if (tmpf=cc->lex_include_stk) { |
|
if ((cc->lex_include_stk=tmpf->next) || !(cc->flags & CCF_DONT_FREE_BUF)) { |
|
if (tmpf->flags & LFSF_DOC) { |
|
if (tmpf->doc) |
|
DocDel(tmpf->doc); |
|
} else |
|
Free(tmpf->buf);; |
|
} |
|
Free(tmpf->full_name); |
|
Free(tmpf); |
|
} |
|
return cc->lex_include_stk; |
|
} |
|
|
|
CCmpCtrl *CmpCtrlNew(U8 *buf=NULL,I64 flags=0,U8 *filename=NULL) |
|
{//MAlloc and Init CCmpCtrl. |
|
//Frees buf in $LK,"CmpCtrlDel",A="MN:CmpCtrlDel"$ unless $LK,"CCF_DONT_FREE_BUF",A="MN:CCF_DONT_FREE_BUF"$ flag is set. |
|
//FileName is for error reporting. If files are #included, |
|
//new names are used. See $LK,"Psalmody CmpCtrlNew",A="FF:::/Apps/Psalmody/PsalmodyFile.HC,CmpCtrlNew"$. |
|
CCmpCtrl *cc=CAlloc(sizeof(CCmpCtrl)); |
|
CLexFile *tmpf; |
|
QueInit(cc); |
|
cc->flags=flags; |
|
cc->opts=1<<OPTf_WARN_UNUSED_VAR|1<<OPTf_WARN_HEADER_MISMATCH; |
|
cc->htc.hash_mask=HTG_TYPE_MASK-HTT_IMPORT_SYS_SYM; |
|
cc->htc.define_hash_table=cc->htc.hash_table_lst= |
|
cc->htc.glbl_hash_table=cc->htc.local_hash_table=Fs->hash_table; |
|
if (flags&CCF_KEEP_AT_SIGN) |
|
cc->char_bmp_alpha_numeric=char_bmp_alpha_numeric_no_at; |
|
else |
|
cc->char_bmp_alpha_numeric=char_bmp_alpha_numeric; |
|
tmpf=LexFilePush(cc); |
|
QueInit(&cc->next_stream_blk); |
|
if (filename) |
|
tmpf->full_name=FileNameAbs(filename); |
|
else |
|
tmpf->full_name=StrNew(blkdev.tmp_filename); |
|
if (flags & CCF_PMT) |
|
buf=CAlloc(8); |
|
tmpf->buf=tmpf->buf_ptr=tmpf->line_start=cc->cur_buf_ptr=buf; |
|
tmpf->line_num=1; |
|
return cc; |
|
} |
|
|
|
U0 CmpCtrlDel(CCmpCtrl *cc) |
|
{//Free CCmpCtrl. |
|
while (LexFilePop(cc)); |
|
LinkedLstDel(cc->lex_prs_stk); |
|
LinkedLstDel(cc->htc.next); |
|
Free(cc->ps); |
|
Free(cc->cur_str); |
|
Free(cc->cur_help_idx); |
|
Free(cc->dollar_buf); |
|
Free(cc); |
|
} |
|
|
|
I64 CmpCtrlSize(CCmpCtrl *cc) |
|
{//Mem size of CCmpCtrl and its members. |
|
CLexFile *tmpf=cc->lex_include_stk; |
|
I64 res=0; |
|
while (tmpf) { |
|
if (tmpf->next || !(cc->flags & CCF_DONT_FREE_BUF)) { |
|
if (tmpf->flags & LFSF_DOC) { |
|
if (tmpf->doc) |
|
res+=DocSize(tmpf->doc); |
|
} else |
|
res+=MSize2(tmpf->buf); |
|
} |
|
res+=MSize2(tmpf->full_name); |
|
res+=MSize2(tmpf); |
|
tmpf=tmpf->next; |
|
} |
|
res+=MSize2(cc->cur_str); |
|
res+=MSize2(cc); |
|
return res; |
|
} |
|
|
|
U32 lex_zeros=0; |
|
|
|
Bool LexDollar(CCmpCtrl *cc,CDoc *doc,CDocEntry *doc_e) |
|
{ |
|
U8 *st; |
|
if (cc->flags&CCF_IN_QUOTES) { |
|
Free(cc->dollar_buf); |
|
st=Doc2PlainText(doc,doc_e); |
|
cc->dollar_buf=MStrPrint("$$%$$Q$$",st); |
|
cc->dollar_cnt=2; |
|
Free(st); |
|
return TRUE; |
|
} else |
|
return FALSE; |
|
} |
|
|
|
I64 LexGetChar(CCmpCtrl *cc) |
|
{//Get one char from stream. Allow put-back one. |
|
U8 *ptr,*src; |
|
CLexFile *tmpf; |
|
CDoc *doc; |
|
CDocEntry *doc_e; |
|
if (!Btr(&cc->flags,CCf_USE_LAST_U16)) { |
|
lgc_start1: |
|
if (!(src=cc->cur_buf_ptr++)) { |
|
cc->cur_buf_ptr=NULL; |
|
goto lgc_here; |
|
} |
|
switch [cc->last_U16=*src++] { |
|
case 0: |
|
lgc_here: |
|
tmpf=cc->lex_include_stk; |
|
if (tmpf->flags & LFSF_DOC) { |
|
doc=tmpf->doc; |
|
doc_e=tmpf->cur_entry; |
|
doc_e=doc_e->next; |
|
lgc_start2: |
|
if (doc_e!=doc) { |
|
tmpf->cur_entry=doc_e; |
|
switch [doc_e->type_u8] { |
|
case DOCT_TEXT: |
|
if (doc_e->de_flags & ~(DOCEF_TAG|DOCEF_DEFINE|DOCEF_TAG_CB| |
|
DOCG_BL_IV_UL|DOCEF_WORD_WRAP|DOCEF_HIGHLIGHT| |
|
DOCEF_SKIP|DOCEF_FILTER_SKIP) && |
|
LexDollar(cc,doc,doc_e) && *(src=cc->dollar_buf)) { |
|
tmpf->line_num=doc_e->y+1; |
|
tmpf->buf_ptr=cc->cur_buf_ptr=src; |
|
} else if (*(src=doc_e->tag)) |
|
tmpf->buf_ptr=cc->cur_buf_ptr=src; |
|
else { |
|
doc_e=doc_e->next; |
|
goto lgc_start2; |
|
} |
|
break; |
|
case DOCT_NEW_LINE: |
|
tmpf->buf_ptr=cc->cur_buf_ptr=&lex_zeros; |
|
tmpf->line_start=doc_e->next; |
|
tmpf->line_num=doc_e->y+2;//+1 because NEW_LINE is on prev line |
|
//+1 because doc y starts at zero |
|
cmp.compiled_lines++; |
|
cc->last_U16='\n'; |
|
goto lgc_done; |
|
case DOCT_TAB: |
|
tmpf->buf_ptr=cc->cur_buf_ptr=&lex_zeros; |
|
tmpf->line_num=doc_e->y+1; |
|
cc->last_U16='\t'; |
|
goto lgc_done; |
|
case DOCT_INS_BIN: |
|
tmpf->buf_ptr=cc->cur_buf_ptr=&lex_zeros; |
|
tmpf->line_num=doc_e->y+1; |
|
Free(cc->cur_str); |
|
cc->cur_str=NULL; |
|
cc->cur_str_len=0; |
|
if (doc_e->bin_data) { |
|
ptr=MAlloc(doc_e->bin_data->size); |
|
if (doc_e->bin_data->data) |
|
MemCpy(ptr,doc_e->bin_data->data,doc_e->bin_data->size); |
|
cc->cur_str=ptr; |
|
cc->cur_str_len=doc_e->bin_data->size; |
|
} |
|
cc->last_U16=TK_INS_BIN; |
|
goto lgc_done; |
|
case DOCT_INS_BIN_SIZE: |
|
tmpf->buf_ptr=cc->cur_buf_ptr=&lex_zeros; |
|
if (doc_e->bin_data) |
|
cc->cur_i64=doc_e->bin_data->size; |
|
else |
|
cc->cur_i64=0; |
|
tmpf->line_num=doc_e->y+1; |
|
cc->last_U16=TK_INS_BIN_SIZE; |
|
goto lgc_done; |
|
case DOCT_SHIFTED_Y: |
|
if (LexDollar(cc,doc,doc_e) && *(src=cc->dollar_buf)) { |
|
tmpf->line_num=doc_e->y+1; |
|
tmpf->buf_ptr=cc->cur_buf_ptr=src; |
|
} else { |
|
tmpf->buf_ptr=cc->cur_buf_ptr=&lex_zeros; |
|
tmpf->line_num=doc_e->y+1; |
|
if (doc_e->attr<0) |
|
cc->last_U16=TK_SUPERSCRIPT; |
|
else if (doc_e->attr>0) |
|
cc->last_U16=TK_SUBSCRIPT; |
|
else |
|
cc->last_U16=TK_NORMALSCRIPT; |
|
goto lgc_done; |
|
} |
|
break; |
|
case DOCT_MARKER: |
|
case DOCT_CURSOR: |
|
doc_e=doc_e->next; |
|
goto lgc_start2; |
|
case 0xFF: //nobound switch |
|
default: |
|
if (LexDollar(cc,doc,doc_e) && *(src=cc->dollar_buf)) { |
|
tmpf->line_num=doc_e->y+1; |
|
tmpf->buf_ptr=cc->cur_buf_ptr=src; |
|
} else { |
|
doc_e=doc_e->next; |
|
goto lgc_start2; |
|
} |
|
} |
|
} |
|
if (doc_e!=doc) |
|
goto lgc_start1; |
|
tmpf->cur_entry=doc->head.last; //When take next, will still be end. |
|
} |
|
tmpf=cc->lex_include_stk; |
|
if (tmpf->next) { |
|
tmpf=LexFilePop(cc); |
|
cc->cur_buf_ptr=tmpf->buf_ptr; |
|
cc->flags&=~CCF_USE_LAST_U16; |
|
if (!(cc->last_U16=tmpf->last_U16)) |
|
goto lgc_start1; |
|
} else { |
|
if (cc->flags & CCF_PMT) { |
|
Free(tmpf->buf); |
|
ptr=CmdLinePmt; |
|
if (StrCmp(ptr,"\n") && !cc->pmt_line++ && !StrCmp(ptr,"?\n") && |
|
cc->flags & CCF_QUESTION_HELP) { |
|
Free(ptr); |
|
ptr=StrNew("Help;;\n"); |
|
} |
|
tmpf->buf=tmpf->buf_ptr=tmpf->line_start=cc->cur_buf_ptr=ptr; |
|
goto lgc_start1; |
|
} else { |
|
if (src) |
|
cc->cur_buf_ptr=src-1; |
|
cc->last_U16=TK_EOF; |
|
} |
|
} |
|
break; |
|
case CH_CURSOR: |
|
goto lgc_start1; |
|
case '\n': |
|
tmpf=cc->lex_include_stk; |
|
if (!(tmpf->flags & LFSF_DOC)) { |
|
tmpf->line_num++; |
|
cmp.compiled_lines++; |
|
tmpf->line_start=src; |
|
} |
|
break; |
|
case 0xFF: //nobound switch |
|
} |
|
lgc_done: |
|
if (cc->last_U16==CH_SHIFT_SPACE) |
|
cc->last_U16=CH_SPACE; |
|
if (cc->opts & OPTF_ECHO && |
|
cc->last_U16<256 && Bt(char_bmp_printable,cc->last_U16)) |
|
'' cc->last_U16; |
|
} |
|
return cc->last_U16; |
|
} |
|
|
|
U0 LexSkipEol(CCmpCtrl *cc) |
|
{//$LK,"LexGetChar",A="MN:LexGetChar"$ to NULL until end-of-line. |
|
I64 ch; |
|
do ch=$WW,0$LexGetChar(cc); |
|
while (Bt(char_bmp_non_eol,ch)); |
|
} |
|
|
|
U8 *LexFirstRem(CCmpCtrl *cc,U8 *marker,I64 _len=NULL) |
|
{//$LK,"LexGetChar",A="MN:LexGetChar"$() chars making str until marker. |
|
U8 *res,*ptr; |
|
CQueVectU8 *tmpv=QueVectU8New; |
|
I64 i,len=0; |
|
while (TRUE) { |
|
i=LexGetChar(cc); |
|
if (!i||StrOcc(marker,i)) |
|
break; |
|
QueVectU8Put(tmpv,len++,i); |
|
} |
|
if (i) |
|
Bts(&cc->flags,CCf_USE_LAST_U16); |
|
res=ptr=MAlloc(len+1); |
|
for (i=0;i<len;i++) |
|
*ptr++=QueVectU8Get(tmpv,i); |
|
*ptr=0; |
|
QueVectU8Del(tmpv); |
|
if (_len) *_len=len; |
|
return res; |
|
} |
|
|
|
U0 LexIncludeStr(CCmpCtrl *cc,U8 *abs_filename,U8 *src,Bool actual_file) |
|
{ |
|
LexBackupLastChar(cc); |
|
CLexFile *tmpf=LexFilePush(cc); |
|
if (actual_file) |
|
tmpf->full_name=StrNew(abs_filename); |
|
else |
|
tmpf->full_name=StrNew(blkdev.tmp_filename); |
|
tmpf->line_num=1; |
|
tmpf->buf=tmpf->buf_ptr=tmpf->line_start=cc->cur_buf_ptr=src; |
|
} |
|
|
|
CDoc *LexDocRead(U8 *abs_filename,I64 flags) |
|
{ |
|
CDoc *doc=DocNew(abs_filename); |
|
U8 *src; |
|
I64 size=0; |
|
doc->flags|=flags; |
|
src=FileRead(abs_filename,&size); |
|
if (!src || !size) { |
|
Free(src); |
|
src=CAlloc(1); |
|
size=0; |
|
} |
|
DocLoad(doc,src,size); |
|
Free(src); |
|
return doc; |
|
} |
|
|
|
I64 cmp_type_flags_src_code[(DOCT_TYPES_NUM+63)/64]={ |
|
1<<DOCT_TEXT|1<<DOCT_TAB|1<<DOCT_INS_BIN|1<<DOCT_INS_BIN_SIZE}; |
|
|
|
U0 LexAttachDoc(CCmpCtrl *cc,CLexFile *tmpf=NULL, |
|
CDoc *doc=NULL,U8 *abs_filename=NULL,CDocEntry *doc_e=NULL,I64 col=0) |
|
{//Start lexing doc. Give either doc or abs_filename. |
|
if (!doc) |
|
doc=LexDocRead(abs_filename,DOCF_DBL_DOLLARS); |
|
if (!tmpf) { |
|
LexBackupLastChar(cc); |
|
tmpf=LexFilePush(cc); |
|
} |
|
if (!doc_e) |
|
doc_e=doc->head.next; |
|
tmpf->full_name=StrNew(doc->filename.name); |
|
tmpf->doc=doc; |
|
while (doc_e!=doc) { |
|
if (Bt(cmp_type_flags_src_code,doc_e->type_u8)) |
|
break; |
|
doc_e=doc_e->next; |
|
col=doc_e->min_col; |
|
} |
|
if (doc_e!=doc) { |
|
col=ClampI64(col,doc_e->min_col,doc_e->max_col); |
|
tmpf->line_start=doc_e; |
|
tmpf->buf=NULL; |
|
tmpf->line_num=doc_e->y+1; |
|
if (doc_e->type_u8==DOCT_TEXT) { |
|
tmpf->cur_entry=doc_e; |
|
tmpf->buf_ptr=doc_e->tag; |
|
} else { |
|
tmpf->cur_entry=doc_e->last; //TODO: might be problem at begin of file |
|
tmpf->buf_ptr=&lex_zeros; |
|
} |
|
tmpf->flags=LFSF_DOC; |
|
} else {//TODO: DocDel(doc)? |
|
col=0; |
|
tmpf->buf=tmpf->buf_ptr=tmpf->line_start=CAlloc(1); |
|
tmpf->line_num=1; |
|
tmpf->flags=0; |
|
} |
|
cc->cur_buf_ptr=tmpf->buf_ptr+col; |
|
tmpf->last_U16=0; |
|
} |
|
|
|
I64 LexInStr(CCmpCtrl *cc,U8 *buf,I64 size,Bool *done) |
|
{ |
|
I64 i=0,j,k,ch; |
|
*done=TRUE; |
|
while (i<size-1) { |
|
ch=LexGetChar(cc); |
|
if (!ch || ch=='"') { |
|
buf[i++]=0; |
|
return i; |
|
} else if (ch=='\\') { |
|
switch (ch=LexGetChar(cc)) { |
|
case '0': |
|
buf[i++]=0; |
|
break; |
|
case '\'': |
|
buf[i++]='\''; |
|
break; |
|
case '\`': |
|
buf[i++]='\`'; |
|
break; |
|
case '\\': |
|
buf[i++]='\\'; |
|
break; |
|
case '"': |
|
buf[i++]='"'; |
|
break; |
|
case 'd': |
|
buf[i++]='$$'; |
|
break; |
|
case 'n': |
|
buf[i++]='\n'; |
|
break; |
|
case 'r': |
|
buf[i++]='\r'; |
|
break; |
|
case 't': |
|
buf[i++]='\t'; |
|
break; |
|
case 'x': |
|
case 'X': |
|
j=0; |
|
for (k=0;k<2;k++) { |
|
ch=ToUpper(LexGetChar(cc)); |
|
if (Bt(char_bmp_hex_numeric,ch)) { |
|
if (ch<='9') |
|
j=j<<4+ch-'0'; |
|
else |
|
j=j<<4+ch-'A'+10; |
|
} else { |
|
cc->flags|=CCF_USE_LAST_U16; |
|
break; |
|
} |
|
} |
|
buf[i++]=j; |
|
break; |
|
default: |
|
cc->flags|=CCF_USE_LAST_U16; |
|
buf[i++]='\\'; |
|
} |
|
} else if (ch=='$$') { |
|
buf[i++]='$$'; |
|
if (cc->dollar_cnt) |
|
cc->dollar_cnt--; |
|
else if (LexGetChar(cc)!='$$') { |
|
cc->dollar_cnt=1; |
|
cc->flags|=CCF_USE_LAST_U16; |
|
} |
|
} else |
|
buf[i++]=ch; |
|
} |
|
*done=FALSE; |
|
return i; |
|
} |
|
|
|
I64 Lex(CCmpCtrl *cc) |
|
{//Fetch next token. |
|
I64 i,j,k,l,ch; |
|
CHash *tmph; |
|
Bool str_done,in_str,neg_e; |
|
U8 *fbuf,*buf2,*buf3,buf[STR_LEN]; |
|
cc->last_line_num=cc->lex_include_stk->line_num; |
|
while (TRUE) { |
|
lex_cont: |
|
switch [ch=LexGetChar(cc)] { |
|
case 0: |
|
return cc->token=TK_EOF; |
|
case TK_SUPERSCRIPT: |
|
ch='>'; |
|
goto lex_ident; |
|
case TK_SUBSCRIPT: |
|
ch='<'; |
|
goto lex_ident; |
|
case TK_NORMALSCRIPT: |
|
ch='='; |
|
goto lex_ident; |
|
case '@': |
|
if (cc->flags&CCF_KEEP_AT_SIGN) { |
|
cc->token=ch; |
|
goto lex_end; |
|
} |
|
case 'A'...'Z': |
|
case 'a'...'z': |
|
case '_': |
|
case 128...255: |
|
lex_ident: |
|
i=0; |
|
buf[i++]=ch; |
|
while (TRUE) { |
|
if (i>=STR_LEN) |
|
LexExcept(cc,"Ident limited to STR_LEN chars at "); |
|
else if (!(ch=LexGetChar(cc))) |
|
break; |
|
else if (Bt(cc->char_bmp_alpha_numeric,ch)) |
|
buf[i++]=ch; |
|
else if (ch==TK_SUPERSCRIPT) |
|
buf[i++]='>'; |
|
else if (ch==TK_SUBSCRIPT) |
|
buf[i++]='<'; |
|
else if (ch==TK_NORMALSCRIPT) |
|
buf[i++]='='; |
|
else { |
|
cc->flags|=CCF_USE_LAST_U16; |
|
break; |
|
} |
|
} |
|
buf[i++]=0; |
|
tmph=NULL; |
|
if (cc->htc.local_var_lst) |
|
cc->local_var_entry=MemberFind(buf,cc->htc.local_var_lst); |
|
else |
|
cc->local_var_entry=NULL; |
|
if (!cc->local_var_entry && cc->htc.hash_table_lst) |
|
tmph=HashFind(buf,cc->htc.hash_table_lst,cc->htc.hash_mask); |
|
if (tmph) |
|
j=tmph->type; |
|
else |
|
j=0; |
|
if (j & HTT_DEFINE_STR && !(cc->flags & CCF_NO_DEFINES)) { |
|
LexIncludeStr(cc, |
|
tmph->str,StrNew(tmph(CHashDefineStr *)->data),FALSE); |
|
cc->lex_include_stk->flags|=LFSF_DEFINE; |
|
} else { |
|
cc->hash_entry=tmph; |
|
Free(cc->cur_str); |
|
cc->cur_str=StrNew(buf); |
|
cc->cur_str_len=i; |
|
cc->token=TK_IDENT; |
|
goto lex_end; |
|
} |
|
break; |
|
case '0'...'9': |
|
i=ch-'0'; |
|
ch=ToUpper(LexGetChar(cc)); |
|
if (ch=='X') { |
|
while (TRUE) { |
|
ch=ToUpper(LexGetChar(cc)); |
|
if (Bt(char_bmp_hex_numeric,ch)) { |
|
if (ch<='9') |
|
i=i<<4+ch-'0'; |
|
else |
|
i=i<<4+ch-'A'+10; |
|
} else { |
|
cc->cur_i64=i; |
|
cc->flags|=CCF_USE_LAST_U16; |
|
cc->token=TK_I64; |
|
goto lex_end; |
|
} |
|
} |
|
} else if (ch=='B') { |
|
while (TRUE) { |
|
ch=LexGetChar(cc); |
|
if (ch=='0') |
|
i=i<<1; |
|
else if (ch=='1') |
|
i=i<<1+1; |
|
else { |
|
cc->cur_i64=i; |
|
cc->flags|=CCF_USE_LAST_U16; |
|
cc->token=TK_I64; |
|
goto lex_end; |
|
} |
|
} |
|
} |
|
while (TRUE) { |
|
if (Bt(char_bmp_dec_numeric,ch)) |
|
i=i*10+ch-'0'; |
|
else { |
|
if (ch=='.' || ch=='e' || ch=='E') break; |
|
lex_is_int: |
|
cc->cur_i64=i; |
|
cc->flags|=CCF_USE_LAST_U16; |
|
cc->token=TK_I64; |
|
goto lex_end; |
|
} |
|
ch=LexGetChar(cc); |
|
} |
|
if (ch=='.') { |
|
ch=LexGetChar(cc); |
|
if (ch=='.') { |
|
cc->flags|=CCF_LAST_WAS_DOT; |
|
goto lex_is_int; |
|
} |
|
} |
|
lex_float_start: |
|
k=0; |
|
while (TRUE) { |
|
if (Bt(char_bmp_dec_numeric,ch)) { |
|
i=i*10+ch-'0'; |
|
k++; |
|
} else { |
|
if (ch=='e' || ch=='E') |
|
break; |
|
cc->cur_f64=i*Pow10I64(-k); |
|
cc->flags|=CCF_USE_LAST_U16; |
|
cc->token=TK_F64; |
|
goto lex_end; |
|
} |
|
ch=LexGetChar(cc); |
|
} |
|
ch=LexGetChar(cc); |
|
neg_e=FALSE; |
|
if (ch=='-') { |
|
neg_e=TRUE; |
|
ch=LexGetChar(cc); |
|
} |
|
j=0; |
|
while (TRUE) { |
|
if (Bt(char_bmp_dec_numeric,ch)) |
|
j=j*10+ch-'0'; |
|
else { |
|
if (neg_e) |
|
cc->cur_f64=i*Pow10I64(-j-k); |
|
else |
|
cc->cur_f64=i*Pow10I64(j-k); |
|
cc->flags|=CCF_USE_LAST_U16; |
|
cc->token=TK_F64; |
|
goto lex_end; |
|
} |
|
ch=LexGetChar(cc); |
|
} |
|
break; |
|
case '"': |
|
cc->flags|=CCF_IN_QUOTES; |
|
buf2=NULL; |
|
i=0; |
|
do { |
|
j=LexInStr(cc,buf,STR_LEN,&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(cc->cur_str); |
|
cc->cur_str=MAlloc(i); |
|
MemCpy(cc->cur_str,buf2,i); |
|
Free(buf2); |
|
cc->cur_str_len=i; |
|
cc->flags&=~CCF_IN_QUOTES; |
|
cc->token=TK_STR; |
|
goto lex_end; |
|
case '\'': |
|
if (cc->flags&CCF_NO_CHAR_CONST) |
|
break; |
|
k=0; |
|
for (j=0;j<8;j++) { |
|
if (!(ch=LexGetChar(cc)) || ch=='\'') |
|
break; |
|
if (ch=='\\') { |
|
switch (ch=LexGetChar(cc)) { |
|
case '0': k.u8[j]=0; break; |
|
case '\'': k.u8[j]='\''; break; |
|
case '\`': k.u8[j]='\`'; break; |
|
case '"': k.u8[j]='"'; break; |
|
case '\\': k.u8[j]='\\'; break; |
|
case 'd': k.u8[j]='$$'; break; |
|
case 'n': k.u8[j]='\n'; break; |
|
case 'r': k.u8[j]='\r'; break; |
|
case 't': k.u8[j]='\t'; break; |
|
case 'x': |
|
case 'X': |
|
i=0; |
|
for (l=0;l<2;l++) { |
|
ch=ToUpper(LexGetChar(cc)); |
|
if (Bt(char_bmp_hex_numeric,ch)) { |
|
if (ch<='9') |
|
i=i<<4+ch-'0'; |
|
else |
|
i=i<<4+ch-'A'+10; |
|
} else { |
|
cc->flags|=CCF_USE_LAST_U16; |
|
break; |
|
} |
|
} |
|
k.u8[j]=i; |
|
break; |
|
default: |
|
k.u8[j]='\\'; |
|
cc->flags|=CCF_USE_LAST_U16; |
|
} |
|
} else if (ch=='$$') { |
|
ch=LexGetChar(cc); |
|
k.u8[j]='$$'; |
|
if (ch!='$$') |
|
cc->flags|=CCF_USE_LAST_U16; |
|
} else |
|
k.u8[j]=ch; |
|
} |
|
if (ch!='\'' && (ch=LexGetChar(cc)) && ch!='\'') |
|
LexExcept(cc,"Char const limited to 8 chars at "); |
|
cc->cur_i64=k; |
|
cc->token=TK_CHAR_CONST; |
|
goto lex_end; |
|
case '#': |
|
if (cc->flags&CCF_KEEP_SIGN_NUM) { |
|
cc->token=ch; |
|
goto lex_end; |
|
} |
|
if (Lex(cc)!=TK_IDENT) //skip '#' |
|
goto lex_end; |
|
if (!(tmph=cc->hash_entry)) |
|
goto lex_end; |
|
if (!(tmph->type & HTT_KEYWORD)) |
|
goto lex_end; |
|
switch (i=tmph(CHashGeneric *)->user_data0) { |
|
case KW_INCLUDE: |
|
if (Lex(cc)!=TK_STR) |
|
goto lex_end; |
|
fbuf=ExtDft(cc->cur_str,"HC.Z"); |
|
buf2=FileNameAbs(fbuf); |
|
Free(fbuf); |
|
if (Bt(&sys_run_level,RLf_DOC)) |
|
LexAttachDoc(cc,,,buf2); |
|
else |
|
LexIncludeStr(cc,buf2,FileRead(buf2),TRUE); |
|
Free(buf2); |
|
break; |
|
case KW_DEFINE: |
|
cc->flags|=CCF_NO_DEFINES; |
|
if (Lex(cc)==TK_IDENT) { |
|
tmph=CAlloc(sizeof(CHashDefineStr)); |
|
tmph->str=cc->cur_str; |
|
cc->cur_str=0; |
|
tmph->type=HTT_DEFINE_STR; |
|
HashSrcFileSet(cc,tmph); |
|
|
|
do ch=LexGetChar(cc); //skip space between define name and start |
|
while (Bt(char_bmp_non_eol_white_space,ch)); |
|
|
|
i=j=0; |
|
buf2=NULL; |
|
if (ch) { |
|
in_str=FALSE; |
|
do { |
|
if (ch=='\\') { |
|
if (ch=LexGetChar(cc)) { |
|
if (ch!='\r' && ch!='\n') { |
|
buf[j++]='\\'; |
|
buf[j++]=ch; |
|
} else if (ch=='\r' && LexGetChar(cc)!='\n') |
|
cc->flags|=CCF_USE_LAST_U16; |
|
} else { |
|
buf[j++]='\\'; |
|
break; |
|
} |
|
} else if (ch!='\n') { |
|
if (ch=='\"') |
|
in_str=!in_str; |
|
buf[j++]=ch; |
|
} else |
|
break; |
|
while (ch=LexGetChar(cc)) { |
|
if (ch=='/') { |
|
ch=LexGetChar(cc); |
|
if (ch=='/' && !in_str) { |
|
do ch=LexGetChar(cc); |
|
while (Bt(char_bmp_non_eol,ch)); |
|
break; |
|
} else { |
|
buf[j++]='/'; |
|
cc->flags|=CCF_USE_LAST_U16; |
|
} |
|
} else if (ch=='\\') { |
|
if (ch=LexGetChar(cc)) { |
|
if (ch=='\"') { |
|
buf[j++]='\\'; |
|
buf[j++]=ch; |
|
} else { |
|
cc->flags|=CCF_USE_LAST_U16; |
|
ch='\\'; |
|
break; |
|
} |
|
} |
|
} else if (Bt(char_bmp_non_eol,ch)) { |
|
if (ch=='\"') |
|
in_str=!in_str; |
|
buf[j++]=ch; |
|
} else |
|
break; |
|
if (j>=STR_LEN-4) {//Spot for ['\'][ch],[ch],[0] |
|
buf[j++]=0; |
|
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-1; |
|
j=0; |
|
} |
|
} |
|
} while (ch=='\\'); |
|
} |
|
buf[j++]=0; |
|
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); |
|
} |
|
tmph(CHashDefineStr *)->data=buf2; |
|
tmph(CHashDefineStr *)->cnt=-1; |
|
HashAdd(tmph,cc->htc.define_hash_table); |
|
} |
|
cc->flags&=~CCF_NO_DEFINES; |
|
break; |
|
case KW_ELSE: |
|
if (cc->flags & CCF_IN_IF) { |
|
cc->token=TK_ELSE; |
|
goto lex_end; |
|
} |
|
lex_else: |
|
j=1; |
|
do { |
|
if (ch=LexGetChar(cc)) { |
|
if (ch=='#') { |
|
if (!Lex(cc)) |
|
goto lex_end; |
|
i=PrsKeyWord(cc); |
|
if (i==KW_IF || i==KW_IFDEF || i==KW_IFNDEF || |
|
i==KW_IFAOT || i==KW_IFJIT) |
|
j++; |
|
else if (i==KW_ENDIF) |
|
j--; |
|
} |
|
} else { |
|
cc->token=TK_EOF; |
|
goto lex_end; |
|
} |
|
} while (j); |
|
break; |
|
|
|
case KW_IF: |
|
if (cc->flags & CCF_IN_IF) { |
|
cc->token=TK_IF; |
|
goto lex_end; |
|
} |
|
lex_if: |
|
cc->flags|=CCF_IN_IF; |
|
if (!Lex(cc)) { |
|
cc->flags&=~CCF_IN_IF; |
|
goto lex_end; |
|
} |
|
if (LexExpression(cc)) { |
|
cc->flags&=~CCF_IN_IF; |
|
switch (cc->token) { |
|
case TK_IF: goto lex_if; |
|
case TK_IFDEF: goto lex_ifdef; |
|
case TK_IFNDEF: goto lex_ifndef; |
|
case TK_IFAOT: goto lex_ifaot; |
|
case TK_IFJIT: goto lex_ifjit; |
|
case TK_ELSE: goto lex_else; |
|
case TK_ENDIF: goto lex_cont; |
|
default: goto lex_end; |
|
} |
|
} else { |
|
cc->flags&=~CCF_IN_IF; |
|
if (cc->token!=TK_ENDIF && cc->token!=TK_ELSE) { |
|
if (cc->token==TK_IF || cc->token==TK_IFDEF || |
|
cc->token==TK_IFNDEF || cc->token==TK_IFAOT || |
|
cc->token==TK_IFJIT) |
|
j=2; |
|
else |
|
j=1; |
|
do { |
|
if (ch=LexGetChar(cc)) { |
|
if (ch=='#') { |
|
if (!Lex(cc)) |
|
goto lex_end; |
|
i=PrsKeyWord(cc); |
|
if (i==KW_IF || i==KW_IFDEF || i==KW_IFNDEF || |
|
i==KW_IFAOT || i==KW_IFJIT) |
|
j++; |
|
else if (i==KW_ENDIF) |
|
j--; |
|
else if (i==KW_ELSE && j==1) |
|
break; |
|
} |
|
} else { |
|
cc->token=TK_EOF; |
|
goto lex_end; |
|
} |
|
} while (j); |
|
} |
|
} |
|
break; |
|
case KW_IFDEF: |
|
if (cc->flags & CCF_IN_IF) { |
|
cc->token=TK_IFDEF; |
|
goto lex_end; |
|
} |
|
lex_ifdef: |
|
cc->flags|=CCF_NO_DEFINES; |
|
if (!Lex(cc)) { |
|
cc->flags&=~CCF_NO_DEFINES; |
|
goto lex_end; |
|
} |
|
cc->flags&=~CCF_NO_DEFINES; |
|
if (cc->token!=TK_IDENT) |
|
goto lex_end; |
|
if (cc->hash_entry) |
|
goto lex_cont; |
|
j=1; |
|
do { |
|
if (ch=LexGetChar(cc)) { |
|
if (ch=='#') { |
|
if (!Lex(cc)) |
|
goto lex_end; |
|
i=PrsKeyWord(cc); |
|
if (i==KW_IF || i==KW_IFDEF || i==KW_IFNDEF || |
|
i==KW_IFAOT || i==KW_IFJIT) |
|
j++; |
|
else if (i==KW_ENDIF) |
|
j--; |
|
else if (i==KW_ELSE && j==1) |
|
break; |
|
} |
|
} else { |
|
cc->token=TK_EOF; |
|
goto lex_end; |
|
} |
|
} while (j); |
|
break; |
|
case KW_IFNDEF: |
|
if (cc->flags & CCF_IN_IF) { |
|
cc->token=TK_IFNDEF; |
|
goto lex_end; |
|
} |
|
lex_ifndef: |
|
cc->flags|=CCF_NO_DEFINES; |
|
if (!Lex(cc)) { |
|
cc->flags&=~CCF_NO_DEFINES; |
|
goto lex_end; |
|
} |
|
cc->flags&=~CCF_NO_DEFINES; |
|
if (cc->token!=TK_IDENT) |
|
goto lex_end; |
|
if (!cc->hash_entry) |
|
goto lex_cont; |
|
j=1; |
|
do { |
|
if (ch=LexGetChar(cc)) { |
|
if (ch=='#') { |
|
if (!Lex(cc)) |
|
goto lex_end; |
|
i=PrsKeyWord(cc); |
|
if (i==KW_IF || i==KW_IFDEF || i==KW_IFNDEF || |
|
i==KW_IFAOT || i==KW_IFJIT) |
|
j++; |
|
else if (i==KW_ENDIF) |
|
j--; |
|
else if (i==KW_ELSE && j==1) |
|
break; |
|
} |
|
} else { |
|
cc->token=TK_EOF; |
|
goto lex_end; |
|
} |
|
} while (j); |
|
break; |
|
case KW_IFAOT: |
|
if (cc->flags & CCF_IN_IF) { |
|
cc->token=TK_IFAOT; |
|
goto lex_end; |
|
} |
|
lex_ifaot: |
|
if (cc->flags & CCF_AOT_COMPILE) |
|
goto lex_cont; |
|
j=1; |
|
do { |
|
if (ch=LexGetChar(cc)) { |
|
if (ch=='#') { |
|
if (!Lex(cc)) |
|
goto lex_end; |
|
i=PrsKeyWord(cc); |
|
if (i==KW_IF || i==KW_IFDEF || i==KW_IFNDEF || |
|
i==KW_IFAOT || i==KW_IFJIT) |
|
j++; |
|
else if (i==KW_ENDIF) |
|
j--; |
|
else if (i==KW_ELSE && j==1) |
|
break; |
|
} |
|
} else { |
|
cc->token=TK_EOF; |
|
goto lex_end; |
|
} |
|
} while (j); |
|
break; |
|
case KW_IFJIT: |
|
if (cc->flags & CCF_IN_IF) { |
|
cc->token=TK_IFAOT; |
|
goto lex_end; |
|
} |
|
lex_ifjit: |
|
if (!(cc->flags & CCF_AOT_COMPILE)) |
|
goto lex_cont; |
|
j=1; |
|
do { |
|
if (ch=LexGetChar(cc)) { |
|
if (ch=='#') { |
|
if (!Lex(cc)) |
|
goto lex_end; |
|
i=PrsKeyWord(cc); |
|
if (i==KW_IF || i==KW_IFDEF || i==KW_IFNDEF || |
|
i==KW_IFAOT || i==KW_IFJIT) |
|
j++; |
|
else if (i==KW_ENDIF) |
|
j--; |
|
else if (i==KW_ELSE && j==1) |
|
break; |
|
} |
|
} else { |
|
cc->token=TK_EOF; |
|
goto lex_end; |
|
} |
|
} while (j); |
|
break; |
|
case KW_ENDIF: |
|
if (cc->flags & CCF_IN_IF) { |
|
cc->token=TK_ENDIF; |
|
goto lex_end; |
|
} |
|
break; |
|
case KW_ASSERT: |
|
if (!Lex(cc)) |
|
goto lex_end; |
|
if (!LexExpression(cc)) |
|
LexWarn(cc,"Assert Failed "); |
|
goto lex_end; |
|
case KW_EXE: |
|
if (!Lex(cc)) |
|
goto lex_end; |
|
PrsStreamBlk(cc); |
|
goto lex_end; |
|
case KW_HELP_INDEX: |
|
if (Lex(cc)!=TK_STR) |
|
goto lex_end; |
|
Free(cc->cur_help_idx); |
|
cc->cur_help_idx=LexExtStr(cc,,FALSE); |
|
break; |
|
case KW_HELP_FILE: |
|
if (Lex(cc)!=TK_STR) |
|
goto lex_end; |
|
tmph=CAlloc(sizeof(CHashSrcSym)); |
|
fbuf=ExtDft(cc->cur_str,"DD.Z"); |
|
tmph->str=FileNameAbs(fbuf); |
|
Free(fbuf); |
|
tmph->type=HTT_HELP_FILE|HTF_PUBLIC; |
|
HashSrcFileSet(cc,tmph); |
|
HashAdd(tmph,cc->htc.glbl_hash_table); |
|
break; |
|
} |
|
break; |
|
case '\n': |
|
if (!(cc->flags&CCF_KEEP_NEW_LINES)) |
|
break; //else fall through |
|
case TK_INS_BIN: |
|
case TK_INS_BIN_SIZE: |
|
cc->token=ch; |
|
goto lex_end; |
|
case '.': |
|
if (cc->flags&CCF_KEEP_DOT) { |
|
cc->token=ch; |
|
goto lex_end; |
|
} |
|
if (cc->flags&CCF_LAST_WAS_DOT) { |
|
cc->flags&=~CCF_LAST_WAS_DOT; |
|
goto lex_dot_dot; |
|
} |
|
ch=LexGetChar(cc); |
|
if ('0'<=ch<='9') { |
|
i=0; |
|
goto lex_float_start; |
|
} else if (ch=='.') { |
|
lex_dot_dot: |
|
cc->token=TK_DOT_DOT; |
|
if (LexGetChar(cc)=='.') |
|
cc->token=TK_ELLIPSIS; |
|
else |
|
cc->flags|=CCF_USE_LAST_U16; |
|
goto lex_end; |
|
} |
|
cc->flags|=CCF_USE_LAST_U16; |
|
cc->token='.'; |
|
goto lex_end; |
|
case '!': |
|
case '$$'...'&': |
|
case '('...'-': |
|
case '/': |
|
case ':'...'?': |
|
case '[': |
|
case ']'...'^': |
|
case '{'...'~': |
|
case '`': |
|
if (!(i=cmp.dual_U16_tokens1[ch])) { |
|
if (ch=='$$') { |
|
ch=LexGetChar(cc); |
|
if (ch=='$$') { |
|
cc->token='$$'; |
|
goto lex_end; |
|
} else if (ch) { |
|
do ch=LexGetChar(cc); |
|
while (ch && ch!='$$'); |
|
if (!ch) { |
|
cc->token=TK_EOF; |
|
goto lex_end; |
|
} else |
|
goto lex_cont; |
|
} else { |
|
cc->flags|=CCF_USE_LAST_U16; |
|
cc->token='$$'; |
|
goto lex_end; |
|
} |
|
} else { |
|
cc->token=ch; |
|
goto lex_end; |
|
} |
|
} else { |
|
j=LexGetChar(cc); |
|
if (i.u16[0]==j) { |
|
i>>=16; |
|
if (!i) {// "/*" |
|
j=1; |
|
do { |
|
if (!(ch=LexGetChar(cc))) |
|
return cc->token=TK_EOF; |
|
lex_check_comment: |
|
if (ch=='*') { |
|
if (!(ch=LexGetChar(cc))) |
|
return cc->token=TK_EOF; |
|
if (ch=='/') |
|
j--; |
|
else |
|
goto lex_check_comment; |
|
} else if (ch=='/') { |
|
if (!(ch=LexGetChar(cc))) |
|
return cc->token=TK_EOF; |
|
if (ch=='*') |
|
j++; |
|
else |
|
goto lex_check_comment; |
|
} |
|
} while (j); |
|
goto lex_cont; |
|
} else { |
|
cc->token=i; |
|
goto lex_end; |
|
} |
|
} |
|
if (i=cmp.dual_U16_tokens2[ch]) { |
|
if (i.u16[0]==j) { |
|
i>>=16; |
|
if (!i) {// "//" |
|
LexSkipEol(cc); |
|
if (cc->flags&CCF_KEEP_NEW_LINES) { |
|
cc->token='\n'; |
|
goto lex_end; |
|
} else |
|
goto lex_cont; |
|
} else { |
|
if (i==TK_SHL || i==TK_SHR) { |
|
j=LexGetChar(cc); |
|
if (j=='=') { |
|
if (i==TK_SHL) |
|
i=TK_SHL_EQU; |
|
else |
|
i=TK_SHR_EQU; |
|
} else |
|
cc->flags|=CCF_USE_LAST_U16; |
|
} |
|
cc->token=i; |
|
goto lex_end; |
|
} |
|
} |
|
if (i=cmp.dual_U16_tokens3[ch]) { |
|
if (i.u16[0]==j) { |
|
cc->token=i.u16[1]; |
|
goto lex_end; |
|
} |
|
} |
|
} |
|
cc->flags|=CCF_USE_LAST_U16; |
|
cc->token=ch; |
|
goto lex_end; |
|
} |
|
case TK_TKS_NUM: |
|
break; |
|
} |
|
} |
|
lex_end: |
|
LexGetChar(cc); //Do this so WAS_NEW_LINE is right |
|
cc->flags|=CCF_USE_LAST_U16; |
|
return cc->token; |
|
}
|
|
|