From fd391690b93e6ca5d4291ca7e456d499f288b27d Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 17 Jun 2023 15:08:03 +0200 Subject: [PATCH] Add .cpp mode and namespace/using --- oscar64/CompilationUnits.cpp | 4 +- oscar64/Compiler.cpp | 22 +- oscar64/CompilerTypes.h | 3 + oscar64/Declaration.cpp | 38 +++- oscar64/Declaration.h | 25 ++- oscar64/Errors.h | 1 + oscar64/GlobalAnalyzer.cpp | 12 +- oscar64/InterCodeGenerator.cpp | 27 +-- oscar64/Parser.cpp | 354 ++++++++++++++++++++++++--------- oscar64/Parser.h | 9 +- oscar64/Scanner.cpp | 16 +- oscar64/Scanner.h | 6 + oscar64/oscar64.cpp | 13 ++ 13 files changed, 395 insertions(+), 135 deletions(-) diff --git a/oscar64/CompilationUnits.cpp b/oscar64/CompilationUnits.cpp index 60f8e8a..11e381f 100644 --- a/oscar64/CompilationUnits.cpp +++ b/oscar64/CompilationUnits.cpp @@ -12,8 +12,8 @@ CompilationUnits::CompilationUnits(Errors * errors) { mCompilationUnits = nullptr; mPendingUnits = nullptr; - mScope = new DeclarationScope(nullptr); - mRuntimeScope = new DeclarationScope(nullptr); + mScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); + mRuntimeScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); mStartup = nullptr; for (int i = 0; i < 256; i++) diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 2cb4b03..de6cb89 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -145,6 +145,10 @@ bool Compiler::ParseSource(void) for (int i = 0; i < mDefines.Size(); i++) scanner->AddMacro(mDefines[i].mIdent, mDefines[i].mValue); + scanner->mCompilerOptions = mCompilerOptions; + + scanner->NextToken(); + Parser* parser = new Parser(mErrors, scanner, mCompilationUnits); parser->mCompilerOptions = mCompilerOptions; @@ -1161,25 +1165,25 @@ bool Compiler::WriteDbjFile(const char* filename) { case DT_TYPE_INTEGER: if (dec->mFlags & DTF_SIGNED) - fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"int\"}", dec->mIdent ? dec->mIdent->mString : "", i, dec->mSize); + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"int\"}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize); else - fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"uint\"}", dec->mIdent ? dec->mIdent->mString : "", i, dec->mSize); + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"uint\"}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize); break; case DT_TYPE_FLOAT: - fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"float\"}", dec->mIdent ? dec->mIdent->mString : "", i, dec->mSize); + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"float\"}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize); break; case DT_TYPE_BOOL: - fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"bool\"}", dec->mIdent ? dec->mIdent->mString : "", i, dec->mSize); + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"bool\"}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize); break; case DT_TYPE_ARRAY: - fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"array\", \"eid\": %d}", dec->mIdent ? dec->mIdent->mString : "", i, dec->mSize, types.IndexOrPush(dec->mBase)); + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"array\", \"eid\": %d}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize, types.IndexOrPush(dec->mBase)); break; case DT_TYPE_POINTER: - fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"ptr\", eid: %d}", dec->mIdent ? dec->mIdent->mString : "", i, dec->mSize, types.IndexOrPush(dec->mBase)); + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"ptr\", eid: %d}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize, types.IndexOrPush(dec->mBase)); break; case DT_TYPE_ENUM: { - fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"enum\",\"members\": [\n", dec->mIdent ? dec->mIdent->mString : "", i, dec->mSize); + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"enum\",\"members\": [\n", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize); bool tfirst = true; Declaration* mdec = dec->mParams; while (mdec) @@ -1201,7 +1205,7 @@ bool Compiler::WriteDbjFile(const char* filename) break; case DT_TYPE_STRUCT: { - fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"struct\",\"members\": [\n", dec->mIdent ? dec->mIdent->mString : "", i, dec->mSize); + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"struct\",\"members\": [\n", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize); bool tfirst = true; Declaration* mdec = dec->mParams; while (mdec) @@ -1218,7 +1222,7 @@ bool Compiler::WriteDbjFile(const char* filename) } break; default: - fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d}", dec->mIdent ? dec->mIdent->mString : "", i, dec->mSize); + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize); } } diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index 25cafb0..9d8436e 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -34,6 +34,9 @@ static const uint64 COPT_VERBOSE3 = 1ULL << 50; static const uint64 COPT_DEBUGINFO = 1ULL << 51; +static const uint64 COPT_CPLUSPLUS = 1ULL << 52; + + static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 0964a8e..7f81eb8 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1,8 +1,10 @@ #include "Declaration.h" -DeclarationScope::DeclarationScope(DeclarationScope* parent) +DeclarationScope::DeclarationScope(DeclarationScope* parent, ScopeLevel level, const Ident* name) { mParent = parent; + mLevel = level; + mName = name; mHashSize = 0; mHashFill = 0; mHash = nullptr; @@ -13,6 +15,25 @@ DeclarationScope::~DeclarationScope(void) delete[] mHash; } +const Ident* DeclarationScope::Mangle(const Ident* ident) const +{ + if (mName) + { + char buffer[200]; + strcpy_s(buffer, mName->mString); + strcat_s(buffer, "::"); + strcat_s(buffer, ident->mString); + return Ident::Unique(buffer); + } + else + return ident; +} + +void DeclarationScope::UseScope(DeclarationScope* scope) +{ + mUsed.Push(scope); +} + Declaration * DeclarationScope::Insert(const Ident* ident, Declaration* dec) { if (!mHash) @@ -79,6 +100,13 @@ Declaration* DeclarationScope::Lookup(const Ident* ident) } } + for (int i = 0; i < mUsed.Size(); i++) + { + Declaration* dec = mUsed[i]->Lookup(ident); + if (dec) + return dec; + } + return mParent ? mParent->Lookup(ident) : nullptr; } @@ -602,7 +630,8 @@ Expression* Expression::ConstantFold(Errors * errors) } Declaration::Declaration(const Location& loc, DecType type) - : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), + : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), + mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mConst(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), @@ -632,6 +661,7 @@ Declaration* Declaration::Clone(void) ndec->mScope = mScope; ndec->mParams = mParams; ndec->mIdent = mIdent; + ndec->mQualIdent = mQualIdent; ndec->mValue = mValue; ndec->mVarIndex = mVarIndex; ndec->mLinkerObject = mLinkerObject; @@ -689,6 +719,7 @@ Declaration* Declaration::ToStriped(int stripe) ndec->mStripe = stripe; ndec->mFlags = mFlags; ndec->mIdent = mIdent; + ndec->mQualIdent = mQualIdent; if (mType == DT_ELEMENT) ndec->mBase = mBase->ToStriped(stripe); @@ -697,7 +728,7 @@ Declaration* Declaration::ToStriped(int stripe) if (mType == DT_TYPE_STRUCT) { - ndec->mScope = new DeclarationScope(nullptr); + ndec->mScope = new DeclarationScope(nullptr, mScope->mLevel); Declaration * p = mParams; Declaration* prev = nullptr; while (p) @@ -743,6 +774,7 @@ Declaration* Declaration::ToConstType(void) ndec->mScope = mScope; ndec->mParams = mParams; ndec->mIdent = mIdent; + ndec->mQualIdent = mQualIdent; mConst = ndec; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 1841df5..842f3fa 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -45,7 +45,8 @@ enum DecType DT_LABEL, DT_VARIABLE_REF, DT_FUNCTION_REF, - DT_LABEL_REF + DT_LABEL_REF, + DT_NAMESPACE, }; // TypeFlags @@ -96,17 +97,34 @@ static const uint64 DTF_VAR_ALIASING = (1ULL << 48); class Declaration; +enum ScopeLevel +{ + SLEVEL_GLOBAL, + SLEVEL_STATIC, + SLEVEL_NAMESPACE, + SLEVEL_CLASS, + SLEVEL_FUNCTION, + SLEVEL_LOCAL +}; + class DeclarationScope { public: - DeclarationScope(DeclarationScope * parent); + DeclarationScope(DeclarationScope * parent, ScopeLevel level, const Ident * name = nullptr); ~DeclarationScope(void); + const Ident* Mangle(const Ident* ident) const; + Declaration* Insert(const Ident* ident, Declaration* dec); Declaration* Lookup(const Ident* ident); void End(const Location & loc); + void UseScope(DeclarationScope* scope); + + ScopeLevel mLevel; + const Ident * mName; + DeclarationScope* mParent; protected: struct Entry @@ -116,6 +134,7 @@ protected: }; Entry * mHash; int mHashSize, mHashFill; + ExpandingArray mUsed; }; enum ExpressionType @@ -199,7 +218,7 @@ public: int64 mInteger, mMinValue, mMaxValue; double mNumber; uint64 mFlags, mCompilerOptions; - const Ident * mIdent; + const Ident * mIdent, * mQualIdent; LinkerSection * mSection; const uint8 * mData; LinkerObject * mLinkerObject; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index a7d33ac..f824e15 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -69,6 +69,7 @@ enum ErrorID ERRR_USE_OF_UNINITIALIZED_VARIABLE, ERRR_STRIPE_REQUIRES_FIXED_SIZE_ARRAY, ERRR_CANNOT_FIND_BANK_OF_EXPRESSION, + ERRO_NOT_A_NAMESPACE, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 9f3519f..b51e40a 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -40,21 +40,21 @@ void GlobalAnalyzer::DumpCallGraph(void) for (int j = 0; j < decs.Size(); j++) { if (decs[j]->mType == DT_CONST_FUNCTION) - printf("CALL %s[%d, %08llx] -> %d -> %s[%d, %08llx]\n", from->mIdent->mString, from->mComplexity, from->mFlags, calls[j], decs[j]->mIdent->mString, decs[j]->mComplexity, decs[j]->mFlags); + printf("CALL %s[%d, %08llx] -> %d -> %s[%d, %08llx]\n", from->mQualIdent->mString, from->mComplexity, from->mFlags, calls[j], decs[j]->mQualIdent->mString, decs[j]->mComplexity, decs[j]->mFlags); else - printf("CALL %s[%d, %08llx] -> %d\n", from->mIdent->mString, from->mComplexity, from->mFlags, calls[j]); + printf("CALL %s[%d, %08llx] -> %d\n", from->mQualIdent->mString, from->mComplexity, from->mFlags, calls[j]); } } else { - printf("LEAF %d -> %s[%d, %08llx]\n", from->mCallers.Size(), from->mIdent->mString, from->mComplexity, from->mFlags ); + printf("LEAF %d -> %s[%d, %08llx]\n", from->mCallers.Size(), from->mQualIdent->mString, from->mComplexity, from->mFlags ); } } for (int i = 0; i < mGlobalVariables.Size(); i++) { Declaration* var = mGlobalVariables[i]; - printf("VAR %s[%d, %08llx, %d]\n", var->mIdent->mString, var->mSize, var->mFlags, var->mUseCount); + printf("VAR %s[%d, %08llx, %d]\n", var->mQualIdent->mString, var->mSize, var->mFlags, var->mUseCount); } } @@ -445,7 +445,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) Analyze(exp, dec, false); } else - mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mIdent); + mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent); dec->mFlags &= ~DTF_FUNC_ANALYZING; } @@ -662,7 +662,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo { procDec->mFlags &= ~DTF_FUNC_INTRSAVE; if (procDec->mFlags & DTF_INTERRUPT) - mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent); + mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mQualIdent); } if (!(GetProcFlags(ldec) & DTF_FUNC_PURE)) procDec->mFlags &= ~DTF_FUNC_PURE; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 08a0bd3..e1a024e 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -376,8 +376,8 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* InterVariable * var = new InterVariable(); var->mOffset = 0; var->mSize = dec->mSize; - var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_DATA, dec->mAlignment); - var->mIdent = dec->mIdent; + var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment); + var->mIdent = dec->mQualIdent; Declaration* decb = dec->mBase; while (decb && decb->mType == DT_TYPE_ARRAY) @@ -437,7 +437,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex Declaration* dec = exp->mDecValue; - dec->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_NATIVE_CODE); + dec->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_NATIVE_CODE); uint8* d = dec->mLinkerObject->AddSpace(osize); @@ -485,7 +485,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex dec->mLinkerObject->AddReference(ref); } else - mErrors->Error(aexp->mLocation, EERR_ASM_INVALD_OPERAND, "Undefined immediate operand", aexp->mBase->mIdent); + mErrors->Error(aexp->mLocation, EERR_ASM_INVALD_OPERAND, "Undefined immediate operand", aexp->mBase->mQualIdent); } else if (aexp->mType == DT_VARIABLE_REF) { @@ -730,7 +730,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex if (aexp->mBase->mBase) d[offset] = uint8(aexp->mOffset + aexp->mBase->mInteger - offset - 1); else - mErrors->Error(aexp->mLocation, EERR_ASM_INVALD_OPERAND, "Undefined immediate operand", aexp->mBase->mIdent); + mErrors->Error(aexp->mLocation, EERR_ASM_INVALD_OPERAND, "Undefined immediate operand", aexp->mBase->mQualIdent); } else d[offset] = uint8(aexp->mInteger - offset - 1); @@ -884,6 +884,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro ains->mConst.mOperandSize = pdec->mSize; vdec->mSize = ains->mConst.mOperandSize; vdec->mIdent = pdec->mIdent; + vdec->mQualIdent = pdec->mQualIdent; } else { @@ -1177,12 +1178,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* dec->mVarIndex = proc->mModule->mGlobalVars.Size(); InterVariable* var = new InterVariable(); var->mIndex = dec->mVarIndex; - var->mIdent = dec->mIdent; + var->mIdent = dec->mQualIdent; var->mOffset = 0; var->mSize = dec->mSize; if ((dec->mFlags & DTF_VAR_ALIASING) || dec->mBase->mType == DT_TYPE_ARRAY) var->mAliased = true; - var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_DATA, dec->mAlignment); + var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment); dec->mLinkerObject = var->mLinkerObject; var->mLinkerObject->AddData(dec->mData, dec->mSize); proc->mModule->mGlobalVars.Push(var); @@ -1209,9 +1210,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* var->mSize = dec->mSize; if (dec->mFlags & DTF_VAR_ALIASING) var->mAliased = true; - var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_DATA, dec->mAlignment); + var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment); dec->mLinkerObject = var->mLinkerObject; - var->mIdent = dec->mIdent; + var->mIdent = dec->mQualIdent; dec->mVarIndex = proc->mModule->mGlobalVars.Size(); var->mIndex = dec->mVarIndex; proc->mModule->mGlobalVars.Push(var); @@ -2229,7 +2230,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && (exp->mLeft->mDecValue->mFlags & DTF_INTRINSIC)) { Declaration* decf = exp->mLeft->mDecValue; - const Ident * iname = decf->mIdent; + const Ident * iname = decf->mQualIdent; if (!strcmp(iname->mString, "fabs")) { @@ -3657,7 +3658,7 @@ void InterCodeGenerator::BuildInitializer(InterCodeModule * mod, uint8* dp, int var->mSize = dec->mSize; if (dec->mFlags & DTF_VAR_ALIASING) var->mAliased = true; - var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_DATA, dec->mAlignment); + var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment); dec->mLinkerObject = var->mLinkerObject; var->mLinkerObject->AddData(dec->mData, dec->mSize); mod->mGlobalVars.Push(var); @@ -3756,7 +3757,7 @@ void InterCodeGenerator::TranslateLogic(Declaration* procType, InterCodeProcedur InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod, Expression* exp, Declaration * dec) { - InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mIdent, mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_BYTE_CODE)); + InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mQualIdent, mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_BYTE_CODE)); uint64 outerCompilerOptions = mCompilerOptions; mCompilerOptions = dec->mCompilerOptions; @@ -3845,7 +3846,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod TranslateExpression(dec->mBase, proc, exitBlock, exp, nullptr, nullptr, nullptr); } else - mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mIdent->mString); + mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent->mString); InterInstruction * ins = new InterInstruction(exp ? exp->mEndLocation : dec->mLocation, IC_RETURN); exitBlock->Append(ins); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index adbbd49..d255906 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -6,7 +6,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUnits) : mErrors(errors), mScanner(scanner), mCompilationUnits(compilationUnits) { - mGlobals = new DeclarationScope(compilationUnits->mScope); + mGlobals = new DeclarationScope(compilationUnits->mScope, SLEVEL_STATIC); mScope = mGlobals; mCodeSection = compilationUnits->mSectionCode; @@ -63,7 +63,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (!dec->mIdent || !dec->mScope) { dec->mIdent = structName; - dec->mScope = new DeclarationScope(nullptr); + dec->mQualIdent = mScope->Mangle(structName); + dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); } if (mScanner->mToken == TK_OPEN_BRACE) @@ -72,7 +73,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) Declaration* mlast = nullptr; for (;;) { - Declaration* mdec = ParseDeclaration(false, false); + Declaration* mdec = ParseDeclaration(nullptr, false, false); int offset = dec->mSize; if (dt == DT_TYPE_UNION) @@ -265,6 +266,7 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) ndec->mScope = dec->mScope; ndec->mParams = dec->mParams; ndec->mIdent = dec->mIdent; + ndec->mQualIdent = dec->mQualIdent; dec = ndec; } mScanner->NextToken(); @@ -286,12 +288,13 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) dec = new Declaration(mScanner->mLocation, DT_TYPE_ENUM); dec->mFlags = flags; dec->mSize = 1; - dec->mScope = new DeclarationScope(nullptr); + dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); mScanner->NextToken(); if (mScanner->mToken == TK_IDENT) { dec->mIdent = mScanner->mTokenIdent; + dec->mQualIdent = mScope->Mangle(dec->mIdent); if (mScope->Insert(dec->mIdent, dec)) mErrors->Error(dec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate name", dec->mIdent); @@ -314,6 +317,7 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) if (mScanner->mToken == TK_IDENT) { cdec->mIdent = mScanner->mTokenIdent; + cdec->mQualIdent = mScope->Mangle(cdec->mIdent); if (mScope->Insert(cdec->mIdent, cdec) != nullptr) mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate declaration", mScanner->mTokenIdent->mString); mScanner->NextToken(); @@ -441,6 +445,7 @@ Declaration* Parser::ParsePostfixDeclaration(void) { dec = new Declaration(mScanner->mLocation, DT_VARIABLE); dec->mIdent = mScanner->mTokenIdent; + dec->mQualIdent = mScope->Mangle(dec->mIdent); dec->mSection = mBSSection; dec->mBase = nullptr; mScanner->NextToken(); @@ -1005,87 +1010,126 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) return exp; } -Declaration* Parser::ParseDeclaration(bool variable, bool expression) +Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression) { bool definingType = false; uint64 storageFlags = 0, typeFlags = 0; + Declaration* bdec; - if (mScanner->mToken == TK_TYPEDEF) + if (pdec) { - definingType = true; - variable = false; - mScanner->NextToken(); + bdec = pdec; } else { - for (;;) + if (mScanner->mToken == TK_TYPEDEF) { - if (mScanner->mToken == TK_STATIC) + definingType = true; + variable = false; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_USING) + { + mScanner->NextToken(); + if (ConsumeTokenIf(TK_NAMESPACE)) { - storageFlags |= DTF_STATIC; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_EXTERN) - { - storageFlags |= DTF_EXTERN; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_ZEROPAGE) - { - storageFlags |= DTF_ZEROPAGE; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_STRIPED) - { - storageFlags |= DTF_STRIPED; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_NOINLINE) - { - storageFlags |= DTF_PREVENT_INLINE; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_INLINE) - { - storageFlags |= DTF_REQUEST_INLINE; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_EXPORT) - { - storageFlags |= DTF_EXPORT; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_DYNSTACK) - { - storageFlags |= DTF_DYNSTACK; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_FASTCALL) - { - storageFlags |= DTF_FASTCALL; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_NATIVE) - { - storageFlags |= DTF_NATIVE; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_INTERRUPT) - { - storageFlags |= DTF_INTERRUPT | DTF_NATIVE; - mScanner->NextToken(); - } - else if (mScanner->mToken == TK_HWINTERRUPT) - { - storageFlags |= DTF_INTERRUPT | DTF_HWINTERRUPT | DTF_NATIVE; - mScanner->NextToken(); + Declaration* dec = ParseQualIdent(); + if (dec) + { + if (dec->mType == DT_NAMESPACE) + { + mScope->UseScope(dec->mScope); + } + else + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a class or namespace"); + } + + return dec; } else - break; - } - } + { + Declaration* dec = ParseQualIdent(); + if (dec) + { + Declaration* pdec = mScope->Insert(dec->mIdent, dec); + if (pdec && pdec != dec) + mErrors->Error(dec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate declaration", dec->mIdent); + } - Declaration* bdec = ParseBaseTypeDeclaration(typeFlags); + return dec; + } + } + else + { + for (;;) + { + if (mScanner->mToken == TK_STATIC) + { + storageFlags |= DTF_STATIC; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_EXTERN) + { + storageFlags |= DTF_EXTERN; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_ZEROPAGE) + { + storageFlags |= DTF_ZEROPAGE; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_STRIPED) + { + storageFlags |= DTF_STRIPED; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_NOINLINE) + { + storageFlags |= DTF_PREVENT_INLINE; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_INLINE) + { + storageFlags |= DTF_REQUEST_INLINE; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_EXPORT) + { + storageFlags |= DTF_EXPORT; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_DYNSTACK) + { + storageFlags |= DTF_DYNSTACK; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_FASTCALL) + { + storageFlags |= DTF_FASTCALL; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_NATIVE) + { + storageFlags |= DTF_NATIVE; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_INTERRUPT) + { + storageFlags |= DTF_INTERRUPT | DTF_NATIVE; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_HWINTERRUPT) + { + storageFlags |= DTF_INTERRUPT | DTF_HWINTERRUPT | DTF_NATIVE; + mScanner->NextToken(); + } + else + break; + } + } + + bdec = ParseBaseTypeDeclaration(typeFlags); + } Declaration* rdec = nullptr, * ldec = nullptr; @@ -1155,9 +1199,9 @@ Declaration* Parser::ParseDeclaration(bool variable, bool expression) mErrors->Error(ndec->mLocation, ERRR_INVALID_STORAGE_TYPE, "Invalid storage type", ndec->mIdent); } - if (mGlobals == mScope && !(storageFlags & DTF_STATIC)) + if (mScope->mLevel < SLEVEL_FUNCTION && !(storageFlags & DTF_STATIC)) { - pdec = mCompilationUnits->mScope->Insert(ndec->mIdent, ndec); + pdec = mCompilationUnits->mScope->Insert(ndec->mQualIdent, ndec); Declaration * ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec); if (ldec && ldec != pdec) @@ -1183,7 +1227,10 @@ Declaration* Parser::ParseDeclaration(bool variable, bool expression) while (npdec && ppdec) { if (npdec->mIdent) + { ppdec->mIdent = npdec->mIdent; + ppdec->mQualIdent = npdec->mQualIdent; + } npdec = npdec->mNext; ppdec = ppdec->mNext; } @@ -1236,7 +1283,7 @@ Declaration* Parser::ParseDeclaration(bool variable, bool expression) } } - if (mGlobals == mScope || (ndec->mFlags & DTF_STATIC)) + if (mScope->mLevel < SLEVEL_FUNCTION || (ndec->mFlags & DTF_STATIC)) { ndec->mFlags |= DTF_GLOBAL; ndec->mVarIndex = -1; @@ -1316,12 +1363,12 @@ Declaration* Parser::ParseDeclaration(bool variable, bool expression) return rdec; } -Expression* Parser::ParseDeclarationExpression(void) +Expression* Parser::ParseDeclarationExpression(Declaration * pdec) { Declaration* dec; Expression* exp = nullptr, * rexp = nullptr; - dec = ParseDeclaration(true, true); + dec = ParseDeclaration(pdec, true, true); if (dec->mType == DT_ANON && dec->mNext == 0) { exp = new Expression(dec->mLocation, EX_TYPE); @@ -1366,6 +1413,44 @@ Expression* Parser::ParseDeclarationExpression(void) return exp; } +Declaration* Parser::ParseQualIdent(void) +{ + Declaration* dec = mScope->Lookup(mScanner->mTokenIdent); + if (dec) + { + mScanner->NextToken(); + while (ConsumeTokenIf(TK_COLCOLON)) + { + if (mScanner->mToken == TK_IDENT) + { + if (dec->mType == DT_NAMESPACE) + { + Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent); + + if (ndec) + dec = ndec; + else + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown identifier", mScanner->mTokenIdent); + } + else + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a class or namespace"); + + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + + mScanner->NextToken(); + } + } + else + { + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown identifier", mScanner->mTokenIdent); + mScanner->NextToken(); + } + + return dec; +} + Expression* Parser::ParseSimpleExpression(void) { Declaration* dec; @@ -1390,7 +1475,7 @@ Expression* Parser::ParseSimpleExpression(void) case TK_STATIC: case TK_AUTO: case TK_STRIPED: - exp = ParseDeclarationExpression(); + exp = ParseDeclarationExpression(nullptr); break; case TK_CHARACTER: dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); @@ -1538,7 +1623,7 @@ Expression* Parser::ParseSimpleExpression(void) mScanner->NextToken(); break; case TK_IDENT: - dec = mScope->Lookup(mScanner->mTokenIdent); + dec = ParseQualIdent(); if (dec) { if (dec->mType == DT_CONST_INTEGER || dec->mType == DT_CONST_FLOAT || dec->mType == DT_CONST_FUNCTION || dec->mType == DT_CONST_ASSEMBLER || dec->mType == DT_LABEL || dec->mType == DT_LABEL_REF) @@ -1547,7 +1632,6 @@ Expression* Parser::ParseSimpleExpression(void) exp->mDecValue = dec; exp->mDecType = dec->mBase; exp->mConst = true; - mScanner->NextToken(); } else if (dec->mType == DT_VARIABLE || dec->mType == DT_ARGUMENT) { @@ -1571,24 +1655,16 @@ Expression* Parser::ParseSimpleExpression(void) exp->mDecValue = dec; exp->mDecType = dec->mBase; } - - mScanner->NextToken(); } else if (dec->mType <= DT_TYPE_FUNCTION) { - exp = ParseDeclarationExpression(); + exp = ParseDeclarationExpression(dec); } else { mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid identifier", mScanner->mTokenIdent); - mScanner->NextToken(); } } - else - { - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown identifier", mScanner->mTokenIdent); - mScanner->NextToken(); - } break; case TK_SIZEOF: @@ -2159,7 +2235,7 @@ Expression* Parser::ParseListExpression(void) Expression* Parser::ParseFunction(Declaration * dec) { - DeclarationScope* scope = new DeclarationScope(mScope); + DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_FUNCTION); mScope = scope; Declaration* pdec = dec->mParams; @@ -2191,7 +2267,7 @@ Expression* Parser::ParseStatement(void) if (mScanner->mToken == TK_OPEN_BRACE) { - DeclarationScope* scope = new DeclarationScope(mScope); + DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_LOCAL); mScope = scope; mScanner->NextToken(); @@ -2256,7 +2332,7 @@ Expression* Parser::ParseStatement(void) { mScanner->NextToken(); - DeclarationScope* scope = new DeclarationScope(mScope); + DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_LOCAL); mScope = scope; exp = new Expression(mScanner->mLocation, EX_WHILE); @@ -2284,7 +2360,7 @@ Expression* Parser::ParseStatement(void) mScanner->NextToken(); if (mScanner->mToken == TK_OPEN_PARENTHESIS) { - DeclarationScope* scope = new DeclarationScope(mScope); + DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_LOCAL); mScope = scope; mScanner->NextToken(); @@ -2725,6 +2801,7 @@ Expression* Parser::ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset) exp = new Expression(mScanner->mLocation, EX_CONSTANT); dec = new Declaration(mScanner->mLocation, DT_LABEL); dec->mIdent = mScanner->mTokenIdent; + dec->mQualIdent = mScanner->mTokenIdent; exp->mDecType = TheUnsignedIntTypeDeclaration; mScope->Insert(dec->mIdent, dec); } @@ -2772,6 +2849,7 @@ Expression* Parser::ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset) { Declaration* ndec = new Declaration(mScanner->mLocation, DT_LABEL); ndec->mIdent = exp->mDecValue->mIdent; + ndec->mQualIdent = exp->mDecValue->mQualIdent; ndec->mBase = exp->mDecValue; ndec->mInteger = 0; exp->mDecValue = ndec; @@ -3017,6 +3095,7 @@ void Parser::AddAssemblerRegister(const Ident* ident, int value) { Declaration* decaccu = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); decaccu->mIdent = ident; + decaccu->mQualIdent = ident; decaccu->mBase = TheUnsignedIntTypeDeclaration; decaccu->mSize = 2; decaccu->mInteger = value; @@ -3025,7 +3104,7 @@ void Parser::AddAssemblerRegister(const Ident* ident, int value) Expression* Parser::ParseAssembler(void) { - DeclarationScope* scope = new DeclarationScope(mScope); + DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_LOCAL); mScope = scope; mScanner->SetAssemblerMode(true); @@ -3044,6 +3123,7 @@ Expression* Parser::ParseAssembler(void) Declaration* decaccu = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); decaccu->mIdent = Ident::Unique("accu"); + decaccu->mQualIdent = decaccu->mIdent; decaccu->mBase = TheUnsignedIntTypeDeclaration; decaccu->mSize = 2; decaccu->mInteger = BC_REG_ACCU; @@ -3095,6 +3175,7 @@ Expression* Parser::ParseAssembler(void) dec = new Declaration(mScanner->mLocation, DT_LABEL); dec->mIdent = label; + dec->mQualIdent = dec->mIdent; dec->mValue = ilast; dec->mInteger = offset; dec->mBase = vdasm; @@ -4105,6 +4186,84 @@ void Parser::ParsePragma(void) mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Invalid pragma directive"); } +void Parser::ParseNamespace(void) +{ + if (mScanner->mToken == TK_IDENT) + { + const Ident* ident = mScanner->mTokenIdent; + + mScanner->NextToken(); + + if (mScanner->mToken == TK_OPEN_BRACE) + { + Declaration* ns = mScope->Lookup(ident); + if (ns) + { + if (ns->mType != DT_NAMESPACE) + { + mErrors->Error(mScanner->mLocation, ERRO_NOT_A_NAMESPACE, "Not a namespace", ident); + ns = nullptr; + } + } + + if (!ns) + { + ns = new Declaration(mScanner->mLocation, DT_NAMESPACE); + mScope->Insert(ident, ns); + ns->mScope = new DeclarationScope(mScope, SLEVEL_NAMESPACE, ident); + } + + mScanner->NextToken(); + + DeclarationScope* outerScope = mScope; + mScope = ns->mScope; + + while (mScanner->mToken != TK_EOF && mScanner->mToken != TK_CLOSE_BRACE) + { + if (mScanner->mToken == TK_PREP_PRAGMA) + { + mScanner->NextToken(); + ParsePragma(); + } + else if (mScanner->mToken == TK_SEMICOLON) + mScanner->NextToken(); + else if (mScanner->mToken == TK_NAMESPACE) + { + mScanner->NextToken(); + ParseNamespace(); + } + else + ParseDeclaration(nullptr, true, false); + } + + ConsumeToken(TK_CLOSE_BRACE); + + mScope = outerScope; + } + else + { + ConsumeToken(TK_ASSIGN); + Declaration* dec = ParseQualIdent(); + if (dec) + { + if (dec->mType == DT_NAMESPACE) + { + Declaration* ns = mScope->Insert(ident, dec); + if (ns) + mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition", ident); + } + else + mErrors->Error(mScanner->mLocation, ERRO_NOT_A_NAMESPACE, "Not a namespace", ident); + } + ConsumeToken(TK_SEMICOLON); + } + } + else + { + // Annonymous namespace + } +} + void Parser::Parse(void) { mLocalIndex = 0; @@ -4144,7 +4303,12 @@ void Parser::Parse(void) } else if (mScanner->mToken == TK_SEMICOLON) mScanner->NextToken(); + else if (mScanner->mToken == TK_NAMESPACE) + { + mScanner->NextToken(); + ParseNamespace(); + } else - ParseDeclaration(true, false); + ParseDeclaration(nullptr, true, false); } } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index b228a64..406bede 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -13,6 +13,7 @@ public: DeclarationScope * mGlobals, * mScope; int mLocalIndex; CompilationUnits * mCompilationUnits; + Declaration * mNamespace; LinkerSection * mCodeSection, * mDataSection, * mBSSection; @@ -33,15 +34,17 @@ protected: uint8* ParseStringLiteral(int msize); + void ParseNamespace(void); + void ParsePragma(void); Declaration* ParseBaseTypeDeclaration(uint64 flags); - Declaration* ParseDeclaration(bool variable, bool expression); + Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression); Declaration* ParseStructDeclaration(uint64 flags, DecType dt); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); Expression* ParseInitExpression(Declaration* dtype); - Expression* ParseDeclarationExpression(void); + Expression* ParseDeclarationExpression(Declaration* pdec); Declaration* ParsePostfixDeclaration(void); Declaration* ReverseDeclaration(Declaration* odec, Declaration* bdec); @@ -56,6 +59,8 @@ protected: void AddAssemblerRegister(const Ident* ident, int value); + Declaration* ParseQualIdent(void); + Expression* ParseStatement(void); Expression* ParseSwitchStatement(void); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 0d52f79..c5467f1 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -148,7 +148,11 @@ const char* TokenNames[] = "'#repeat'", "'#until'", "'#embed'", - "'##'" + "'##'", + + "'namespace'", + "'using'", + "'::'" }; @@ -311,7 +315,6 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) mToken = TK_NONE; NextChar(); - NextToken(); assert(sizeof(TokenNames) == NUM_TOKENS * sizeof(char*)); } @@ -1088,6 +1091,11 @@ void Scanner::NextRawToken(void) case ':': mToken = TK_COLON; NextChar(); + if (mTokenChar == ':' && (mCompilerOptions & COPT_CPLUSPLUS)) + { + mToken = TK_COLCOLON; + NextChar(); + } break; case '?': mToken = TK_QUESTIONMARK; @@ -1379,6 +1387,10 @@ void Scanner::NextRawToken(void) mToken = TK_STRIPED; else if (!strcmp(tkident, "__dynstack")) mToken = TK_DYNSTACK; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "namespace")) + mToken = TK_NAMESPACE; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "using")) + mToken = TK_USING; else { mToken = TK_IDENT; diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index f06a530..b150d14 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -149,6 +149,10 @@ enum Token TK_PREP_CONCAT, + TK_NAMESPACE, + TK_USING, + TK_COLCOLON, + NUM_TOKENS }; @@ -231,6 +235,8 @@ public: bool mAssemblerMode; bool mPreprocessorMode; + uint64 mCompilerOptions; + void AddMacro(const Ident* ident, const char* value); protected: void NextRawToken(void); diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index e11ab2e..1ad5bb6 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -237,6 +237,11 @@ int main2(int argc, const char** argv) { compiler->mCompilerOptions |= COPT_EXTENDED_ZERO_PAGE; } + else if (arg[1] == 'p' && arg[2] == 'p') + { + compiler->mCompilerOptions |= COPT_CPLUSPLUS; + compiler->AddDefine(Ident::Unique("__cplusplus"), "1"); + } else compiler->mErrors->Error(loc, EERR_COMMAND_LINE, "Invalid command line argument", arg); } @@ -244,6 +249,14 @@ int main2(int argc, const char** argv) { if (!targetPath[0]) strcpy_s(targetPath, argv[i]); + + int n = strlen(argv[i]); + if (n > 4 && argv[i][n - 4] == '.' && argv[i][n - 3] == 'c' && argv[i][n - 2] == 'p' && argv[i][n - 1] == 'p') + { + compiler->mCompilerOptions |= COPT_CPLUSPLUS; + compiler->AddDefine(Ident::Unique("__cplusplus"), "1"); + } + compiler->mCompilationUnits->AddUnit(loc, argv[i], nullptr); } }