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 CmpCtrlDel unless CCF_DONT_FREE_BUF flag is set. //FileName is for error reporting. If files are #included, //new names are used. See Psalmody 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) {//LexGetChar to NULL until end-of-line. I64 ch; do ch=LexGetChar(cc); while (Bt(char_bmp_non_eol,ch)); } U8 *LexFirstRem(CCmpCtrl *cc,U8 *marker,I64 _len=NULL) {//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 (!Bt(&cc->opts, OPTf_DECIMAL_ONLY)) { 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; }