File *Parser::GetIncludedFile(sym_t preprocessor, const char *line, FILE **outf, bool& in_compiler_dir) { bool quoted = true; CC_STRING ifpath, itoken, iline; File *retval = NULL; iline = ExpandLine(intab, true, line, errmsg); if(!errmsg.isnull()) goto done; itoken = GetIncludeFileName(iline, quoted); iline.clear(); if( itoken.isnull() ) { errmsg.Format("Invalid include preprocessor: %s", pline.from.c_str()); goto done; } if(!rtc->get_include_file_path(itoken, GetCurrentFileName(), quoted, preprocessor == SSID_SHARP_INCLUDE_NEXT, ifpath, &in_compiler_dir)) { errmsg.Format("Cannot find include file \"%s\"", itoken.c_str()); goto done; } RealFile *file; pline.to = pline.from; file = new RealFile; file->SetFileName(ifpath); retval = file; *outf = NULL; if(has_dep_file() && ! in_compiler_dir) AddDependency(" ", ifpath.c_str()); done: return retval; }
/*------------------------------* * Paste n characters to a line * *------------------------------*/ BOOL PasteChars(LONG x, struct line_node *line, LONG length, const char *characters, struct UserAction *buffer, struct InstData *data) { ENTER(); if(line->line.Styles != NULL) { if(*line->line.Styles != EOS) { ULONG c = 0; while(*(line->line.Styles+c) <= x+1) c += 2; while(*(line->line.Styles+c) != EOS) { *(line->line.Styles+c) += length; c += 2; } } } if(line->line.Colors != NULL) { if(*line->line.Colors != 0xffff) { ULONG c = 0; while(*(line->line.Colors+c) <= x+1) c += 2; while(*(line->line.Colors+c) != 0xffff) { *(line->line.Colors+c) += length; c += 2; } } } if((*((long *)line->line.Contents-1))-4 < (LONG)(line->line.Length + length + 1)) { if(ExpandLine(line, length, data) == FALSE) { RETURN(FALSE); return(FALSE); } } UpdateChange(x, line, length, characters, buffer, data); RETURN(TRUE); return(TRUE); }
/* PreprocessLine() is the "preprocessor". * 1. the line is tokenized with Tokenize(), Token_Count set * 2. (text) macros are expanded by ExpandLine() * 3. "preprocessor" directives are executed */ int PreprocessLine( char *line, struct asm_tok tokenarray[] ) /***********************************************************/ { int i; /* v2.11: GetTextLine() removed - this is now done in ProcessFile() */ /* v2.08: moved here from GetTextLine() */ ModuleInfo.CurrComment = NULL; /* v2.06: moved here from Tokenize() */ ModuleInfo.line_flags = 0; /* Token_Count is the number of tokens scanned */ Token_Count = Tokenize( line, 0, tokenarray, TOK_DEFAULT ); #ifdef DEBUG_OUT cntppl0++; if ( ModuleInfo.GeneratedCode ) DebugMsg1(("PreprocessLine: >%s<\n", line )); else DebugMsg1(("PreprocessLine(%s): >%s< cmt=%s\n", GetTopSrcName(), line, ModuleInfo.CurrComment ? ModuleInfo.CurrComment : "" )); #endif #if REMOVECOMENT == 0 if ( Token_Count == 0 && ( CurrIfState == BLOCK_ACTIVE || ModuleInfo.listif ) ) LstWriteSrcLine(); #endif if ( Token_Count == 0 ) return( 0 ); #ifdef DEBUG_OUT /* option -np, skip preprocessor? */ if ( Options.skip_preprocessor ) return( Token_Count ); #endif /* CurrIfState != BLOCK_ACTIVE && Token_Count == 1 | 3 may happen * if a conditional assembly directive has been detected by Tokenize(). * However, it's important NOT to expand then */ if ( CurrIfState == BLOCK_ACTIVE ) { if ( ( tokenarray[Token_Count].bytval & TF3_EXPANSION ? ExpandText( line, tokenarray, TRUE ) : ExpandLine( line, tokenarray ) ) < NOT_ERROR ) return( 0 ); } DebugCmd( cntppl1++ ); i = 0; if ( Token_Count > 2 && ( tokenarray[1].token == T_COLON || tokenarray[1].token == T_DBL_COLON ) ) i = 2; /* handle "preprocessor" directives: * IF, ELSE, ENDIF, ... * FOR, REPEAT, WHILE, ... * PURGE * INCLUDE * since v2.05, error directives are no longer handled here! */ if ( tokenarray[i].token == T_DIRECTIVE && tokenarray[i].dirtype <= DRT_INCLUDE ) { /* if i != 0, then a code label is located before the directive */ if ( i > 1 ) { if ( ERROR == WriteCodeLabel( line, tokenarray ) ) return( 0 ); } directive_tab[tokenarray[i].dirtype]( i, tokenarray ); return( 0 ); } /* handle preprocessor directives which need a label */ if ( tokenarray[0].token == T_ID && tokenarray[1].token == T_DIRECTIVE ) { struct asym *sym; switch ( tokenarray[1].dirtype ) { case DRT_EQU: /* * EQU is a special case: * If an EQU directive defines a text equate * it MUST be handled HERE and 0 must be returned to the caller. * This will prevent further processing, nothing will be stored * if FASTPASS is on. * Since one cannot decide whether EQU defines a text equate or * a number before it has scanned its argument, we'll have to * handle it in ANY case and if it defines a number, the line * must be stored and, if -EP is set, written to stdout. */ if ( sym = CreateConstant( tokenarray ) ) { if ( sym->state != SYM_TMACRO ) { #if FASTPASS if ( StoreState ) FStoreLine( 0 ); #endif if ( Options.preprocessor_stdout == TRUE ) WritePreprocessedLine( line ); } /* v2.03: LstWrite() must be called AFTER StoreLine()! */ if ( ModuleInfo.list == TRUE ) { LstWrite( sym->state == SYM_INTERNAL ? LSTTYPE_EQUATE : LSTTYPE_TMACRO, 0, sym ); } } return( 0 ); case DRT_MACRO: case DRT_CATSTR: /* CATSTR + TEXTEQU directives */ case DRT_SUBSTR: directive_tab[tokenarray[1].dirtype]( 1, tokenarray ); return( 0 ); } } DebugCmd( cntppl2++ ); return( Token_Count ); }
/************************************************************************ * Function: BYTE GFXTransition(SHORT left, SHORT top, SHORT right, * SHORT bottom, GFX_TRANSITION_TYPE type, * DWORD srcpageaddr, DWORD destpageaddr, * WORD delay_ms, WORD param1, WORD param2) * * Overview: This function saves the parameters to be used and marks the * transition to be pending which is executed when * GFXExecutePendingTransition() is called * * Input: left -> left x coordinate * top -> top y coordinate * right -> right x coordinate * bottom -> bottom y coordinate * type -> Transition type * srcpageaddr -> Source page address for the transition * destpageaddr -> Destination page address for the transition * delay_ms -> Delay in milli seconds between redraws in the * screen while executing the transition * param1 -> Transition-type specific parameter * param2 -> Transition-type specific parameter * * Output: 0 -> Transition executed successfully * -1 -> Transition not executed * ************************************************************************/ BYTE GFXTransition(SHORT left, SHORT top, SHORT right, SHORT bottom, GFX_TRANSITION_TYPE type, DWORD srcpageaddr, DWORD destpageaddr, WORD delay_ms, WORD param1, WORD param2) { BYTE retval = 0; SHORT width, height; if(left > right) { return (-1); /* Don't draw */ } if(top > bottom) { return (-1); /* Don't draw */ } left = (left < 0) ? 0: (left > GetMaxX()) ? GetMaxX(): left; top = (top < 0) ? 0: (top > GetMaxY()) ? GetMaxY(): top; right = (right < 0) ? 0: (right > GetMaxX()) ? GetMaxX(): right; bottom = (bottom < 0) ? 0: (bottom > GetMaxY())? GetMaxY(): bottom; #if (DISP_ORIENTATION == 0) || (DISP_ORIENTATION == 180) width = right - left + 1; height = bottom - top + 1; #elif (DISP_ORIENTATION == 90) || (DISP_ORIENTATION == 270) height = right - left + 1; width = bottom - top + 1; #endif #if (DISP_ORIENTATION == 90) bottom = DISP_VER_RESOLUTION - left; left = top; right = left + width; top = bottom - height; #elif (DISP_ORIENTATION == 180) right = DISP_HOR_RESOLUTION - left; bottom = DISP_VER_RESOLUTION - top; left = right - width; top = bottom - height; #elif (DISP_ORIENTATION == 270) right = DISP_HOR_RESOLUTION - top; top = left; bottom = top + height; left = right - width; #endif Startx = left; Starty = top; Width = width; Height = height; _delay_ms = delay_ms; _srcpageaddr = srcpageaddr; _destpageaddr = destpageaddr; _param1 = param1; _param2 = param2; switch(type) { case EXPANDING_RECTANGLE: ExpandRectangle(); break; case CONTRACTING_RECTANGLE: ContractRectangle(); break; case SLIDE: SlideRectangle(); break; case PUSH: PushRectangle(); break; case EXPANDING_LINE: ExpandLine(); break; case CONTRACTING_LINE: ContractLine(); break; default: PlainCopyRectangle(); retval = 0xFF; break; }; return (retval); }
bool Parser::SM_Run() { FILE *out_fp = included_files.top()->ofile; const char *pos; TRI_STATE result = TSV_0; const char *output = pline.from.c_str(); sym_t preprocessor; CC_STRING expanded_line; do { pos = pline.parsed.c_str(); preprocessor = GetPreprocessor(pos, &pos); if(preprocessor != pline.pp_id || (pline.content != -1 && pline.content + pline.parsed.c_str() != pos) ) { fprintf(stderr, "%s:%zu\n", dv_current_file, dv_current_line); fprintf(stderr, " (%d) %s\n", pline.content, pline.parsed.c_str()); fprintf(stderr, " %d vs %d\n", preprocessor, pline.pp_id); exit(1); } } while(0); pos = pline.parsed.c_str() + pline.content; dv_current_file = GetCurrentFileName().c_str(); dv_current_line = GetCurrentLineNumber(); // GDB_TRAP2(strstr(dv_current_file,"makeint.h"), (dv_current_line==30)); // GDB_TRAP2(strstr(dv_current_file,"/usr/include/features.h"), dv_current_line==131); switch(pline.pp_id) { case SSID_SHARP_IF: if( superior_conditional_value(true) != TSV_0 ) result = (TRI_STATE) Compute(pos); goto handle_if_branch; case SSID_SHARP_IFNDEF: if( superior_conditional_value(true) != TSV_0 ) result = (TRI_STATE) CheckSymbolDefined(pos, true, NULL); goto handle_if_branch; case SSID_SHARP_IFDEF: if( superior_conditional_value(true) != TSV_0 ) result = (TRI_STATE) CheckSymbolDefined(pos, false, NULL); handle_if_branch: if( result == TSV_X ) { if( gvar_preprocess_mode ) { if(errmsg.isnull()) errmsg = "Error on processing conditional"; goto done; } } conditionals.push(new CConditionalChain()); upper_chain()->enter_if(result); upper_chain()->filename = dv_current_file; upper_chain()->line = dv_current_line; if(eval_current_conditional() != TSV_X) output = NULL; included_files.top()->add_if(result); break; case SSID_SHARP_ELIF: if( superior_conditional_value(false) == TSV_0 ) { included_files.top()->add_elif(false); goto done; } if( upper_chain()->has_true() ) { upper_chain()->enter_elif(TSV_0); included_files.top()->add_elif(false); goto done; } result = (TRI_STATE) Compute(pos); if( gvar_preprocess_mode && result == TSV_X) goto done; /* * Transformation on the condition of: * * 1) #if 0 * #elif X --> #if X * * 2) #elif X * #elif 1 --> #else */ if( eval_current_conditional() == TSV_0 ) { if(result == TSV_X) { pline.to = do_elif(1); output = pline.to.c_str(); } else output = NULL; } else { if(result == TSV_1) { pline.to = do_elif(2); output = pline.to.c_str(); } else if(result == TSV_0) output = NULL; } upper_chain()->enter_elif(result); included_files.top()->add_elif(result); break; case SSID_SHARP_ELSE: if( superior_conditional_value(false) == TSV_0 ) { included_files.top()->add_else(false); goto done; } result = upper_chain()->enter_else(); included_files.top()->add_else(result); if( eval_current_conditional() != TSV_X ) output = NULL; break; case SSID_SHARP_ENDIF: included_files.top()->add_endif(); CConditionalChain *c; if( ! upper_chain()->keep_endif() ) output = NULL; if( conditionals.size() == 0 ) { errmsg = "Unmatched #endif"; goto done; } conditionals.pop(c); delete c; break; default: if(eval_current_conditional() == TSV_0) goto done; if(eval_current_conditional() == TSV_X) goto print_and_exit; switch(pline.pp_id) { case SSID_SHARP_DEFINE: if(!do_define(pos)) goto error_out; break; case SSID_SHARP_UNDEF: handle_undef(intab, pos); break; case SSID_SHARP_INCLUDE: case SSID_SHARP_INCLUDE_NEXT: if( gvar_preprocess_mode ) do_include(pline.pp_id, pos, &output); break; default: if(gvar_expand_macros) { pos = pline.parsed.c_str(); expanded_line = ExpandLine(intab, false, pos, errmsg); if(!errmsg.isnull()) goto error_out; if(included_files.size() == 1) { expanded_line += '\n'; output = expanded_line.c_str(); } } } } print_and_exit: if( out_fp != NULL && output != NULL ) fprintf(out_fp, "%s", output); done: pline.comment_start = -1; if(gvar_preprocess_mode && GetError()) { IncludedFile *tmp; CC_STRING pmsg, ts; while(included_files.size() > 0) { included_files.pop(tmp); ts.Format(" %s:%u\n", tmp->ifile->name.c_str(), tmp->ifile->line); pmsg += ts; } if( !pmsg.isnull() ) { errmsg = pmsg + errmsg; } } return gvar_preprocess_mode ? (GetError() == NULL) : true; error_out: return false; }
int Parser::Compute(const char *line) { static const char opp[] = { '<', '=', '>', 'X'}; enum { STAT_INIT, STAT_OPR1, STAT_OPR2, STAT_OPND, STAT_DEFINED, /* defined */ STAT_DEFINED1, /* defined( */ STAT_DEFINED2, /* defined(X */ } state; CC_STACK<sym_t> opr_stack; CC_STACK<SynToken> opnd_stack; sym_t last_opr = SSID_SHARP; SynToken last_token; char sign; const char *symbol = NULL; LOG_VERB dml = LOGV_DEBUG; CC_STRING expansion; if(!gvar_preprocess_mode) { /* * Keep `#if 0' blocks which are usually user comments. */ char *copied_line = strdup(line); const char *first = strtok(copied_line, " \t"); int ignore = 0; /* Simple code and work properly in most cases */ if(first && first[0] == '0') ignore = 1; free(copied_line); if(ignore) return TSV_X; } expansion = ExpandLine(intab, false, line, errmsg); if( !errmsg.isnull() ) { return TSV_X; } ReadReq req(expansion.c_str()); SynToken& token = req.token; opr_stack.push(SSID_SHARP); log(dml, "PUSH OPR: #\n"); sign = 0; state = STAT_OPR1; while(1) { sym_t opr; const char *last_pos = req.cp; int ret; ret = ReadToken(intab, &req, false); if( ret == 0 ) break; else if( ret < 0 ) goto error; if( token.attr == SynToken::TA_CHAR ) token.attr = SynToken::TA_INT; if( sign != 0 ) { if(token.attr != SynToken::TA_UINT && token.id != SSID_DEFINED) { errmsg.Format("%s following %c", TR(intab,token.id), sign); goto error; } if(sign == '-') { token.attr = SynToken::TA_INT; token.i32_val = -token.i32_val; } sign = 0; } else if( (token.id == SSID_ADDITION || token.id == SSID_SUBTRACTION) && CheckPrevOperator(last_opr)) { sign = token.id == SSID_ADDITION ? '+' : '-'; goto next; } switch(state) { case STAT_INIT: if(IsOperator(token.id)) state = STAT_OPR1; else if(token.id == SSID_DEFINED) state = STAT_DEFINED; else if(token.attr == SynToken::TA_IDENT) state = STAT_OPND; break; case STAT_OPND: if(IsOperator(token.id)) state = STAT_OPR1; else { errmsg = "Adjacent operands"; goto error; } break; case STAT_OPR1: if(IsOperator(token.id)) state = STAT_OPR2; else if(token.id == SSID_DEFINED) state = STAT_DEFINED; else state= STAT_INIT; break; case STAT_OPR2: if(IsOperator(token.id)) { } else if(token.id == SSID_DEFINED) state = STAT_DEFINED; else state = STAT_INIT; break; case STAT_DEFINED: if(token.id == SSID_LEFT_PARENTHESIS) state = STAT_DEFINED1; else if(token.attr == SynToken::TA_IDENT) { CheckSymbolDefined(last_pos, false, &token); if(!errmsg.isnull()) goto error; state = STAT_INIT; } break; case STAT_DEFINED1: if(token.attr == SynToken::TA_IDENT) { state = STAT_DEFINED2; symbol = last_pos; } else { errmsg = "Syntax error: "; goto error; } break; case STAT_DEFINED2: if(token.id == SSID_RIGHT_PARENTHESIS) { CheckSymbolDefined(symbol, false, &token); if(!errmsg.isnull()) goto error; state = STAT_INIT; opnd_stack.push(token); opr = token.id; goto next; } else { errmsg = "Unmatched ("; goto error; } break; } if(state == STAT_DEFINED || state == STAT_DEFINED1 || state == STAT_DEFINED2) goto next; if( token.id == SynToken::TA_UINT || token.id == SynToken::TA_INT ) log(dml, "Current: %u\n", token.u32_val); else log(dml, "Current: %s\n", TR(intab,token.id)); // log(dml, "OPR Stack: \n", opr_stack); // log(dml, "OPND Stack: \n", opnd_stack); opr = token.id; if( IsOperator(opr) ) { sym_t opr0; int result; again: opr0 = opr_stack.top(); result = intab->opMat.Compare(opr0, opr); log(dml, "Compare: %s %c %s\n", TR(intab,opr0),opp[1+result],TR(intab,opr)); switch(result) { case _EQ: opr_stack.pop(opr0); break; case _GT: opr_stack.pop(opr0); if( ! CalculateOnStackTop(opr0, opnd_stack, opr_stack) ) { goto error; } goto again; case _LT: opr_stack.push(opr); break; case _XX: errmsg.Format("Cannot compare \"%s\" and \"%s\"", TR(intab,opr0), TR(intab,opr)); log(LOGV_ERROR, "*ERROR* %s\n", errmsg.c_str()); goto error; } } else { opnd_stack.push(token); } next: last_opr = opr; } do { sym_t opr0; int result; if( ! opr_stack.pop(opr0) ) goto error; result = intab->opMat.Compare(opr0, SSID_SHARP); log(dml, "Compare: %s %c #\n", TR(intab,opr0),opp[result]); switch(result) { case _EQ: break; case _GT: if( ! CalculateOnStackTop(opr0, opnd_stack, opr_stack) ) { goto error; } break; default: log(LOGV_ERROR, "%s:%u: Bad expression\n", __func__, __LINE__); errmsg = "[1] Bad expression"; goto error; } } while( opr_stack.size() != 0 ); if( opnd_stack.size() != 1 ) { log(LOGV_ERROR, "%s:%u: Bad expression\n", __func__, __LINE__); errmsg = "[2] Bad expression"; goto error; } if( opnd_stack.top().attr == SynToken::TA_IDENT ) { if( gvar_preprocess_mode ) { return TSV_0; } return TSV_X; } log(dml, "Numberic Value: %u\n", opnd_stack.top().i32_val);; return !!opnd_stack.top().i32_val; error: log(LOGV_ERROR, "*Error* %s\n", errmsg.c_str()); return gvar_preprocess_mode ? TSV_0 : TSV_X; }