From 89e5c66189202713b317defcf629ff006e559bcc Mon Sep 17 00:00:00 2001 From: "zik.saleeba" Date: Fri, 20 Feb 2009 09:04:45 +0000 Subject: [PATCH] Implemented ellipsis for stdargs and stdarg stack handling git-svn-id: http://picoc.googlecode.com/svn/trunk@95 21eae674-98b7-11dd-bd71-f92a316d2d60 --- Makefile | 2 +- intrinsic.c | 6 +++--- lex.c | 3 ++- parse.c | 31 +++++++++++++++++++++---------- picoc.h | 3 ++- tests/02_printf.c | 2 +- tests/02_printf.expect | 2 +- 7 files changed, 31 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 4211b44..a2ba9e2 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CC=gcc -CFLAGS=-Wall -g #-DDEBUG_HEAP -DDEBUG_LEXER +CFLAGS=-Wall -g #-DDEBUG_LEXER #-DDEBUG_HEAP -DDEBUG_LEXER LIBS=-lm TARGET = picoc diff --git a/intrinsic.c b/intrinsic.c index 5613cd8..cc34e66 100644 --- a/intrinsic.c +++ b/intrinsic.c @@ -23,9 +23,9 @@ struct IntrinsicFunction const char *Prototype; } Intrinsics[] = { - { IntrinsicSayHello, "void sayhello()" }, /* -1 */ - { IntrinsicPrintf, "void printf()" }, /* -2 */ - { IntrinsicPrintInt, "void printint(int)" }, /* -3 */ + { IntrinsicSayHello, "void sayhello()" }, + { IntrinsicPrintf, "void printf(char *, ...)" }, + { IntrinsicPrintInt, "void printint(int)" }, }; void IntrinsicInit(struct Table *GlobalTable) diff --git a/lex.c b/lex.c index 15449f0..58e3317 100644 --- a/lex.c +++ b/lex.c @@ -14,6 +14,7 @@ #define NEXTIS(c,x,y) { if (NextChar == (c)) { Lexer->Pos++; GotToken = (x); } else GotToken = (y); } #define NEXTIS3(c,x,d,y,z) { if (NextChar == (c)) { Lexer->Pos++; GotToken = (x); } else NEXTIS(d,y,z) } #define NEXTIS4(c,x,d,y,e,z,a) { if (NextChar == (c)) { Lexer->Pos++; GotToken = (x); } else NEXTIS3(d,y,e,z,a) } +#define NEXTISEXACTLY3(c,d,y,z) { if (NextChar == (c) && Lexer->Pos[1] == (d)) { Lexer->Pos += 2; GotToken = (y); } else GotToken = (z); } static union AnyValue LexAnyValue; static struct Value LexValue = { TypeVoid, &LexAnyValue, FALSE, FALSE }; @@ -325,7 +326,7 @@ enum LexToken LexScanGetToken(struct LexState *Lexer, struct Value **Value) case '^': GotToken = TokenArithmeticExor; break; case '~': GotToken = TokenUnaryExor; break; case ',': GotToken = TokenComma; break; - case '.': GotToken = TokenDot; break; + case '.': NEXTISEXACTLY3('.', '.', TokenEllipsis, TokenDot); break; case ':': GotToken = TokenColon; break; default: LexFail(Lexer, "illegal character '%c'", ThisChar); break; } diff --git a/parse.c b/parse.c index 4fab440..697602d 100644 --- a/parse.c +++ b/parse.c @@ -43,13 +43,14 @@ void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, const c { if (Parser->Mode == RunModeRun) { - if (ArgCount >= FuncValue->Val->FuncDef.NumParams) + if (ArgCount >= FuncValue->Val->FuncDef.NumParams && !FuncValue->Val->FuncDef.VarArgs) ProgramFail(Parser, "too many arguments to %s()", FuncName); if (FuncValue->Val->FuncDef.ParamType[ArgCount] != Param->Typ) - ProgramFail(Parser, "parameter %d to %s() is the wrong type", ArgCount, FuncName); + ProgramFail(Parser, "parameter %d to %s() is the wrong type", ArgCount+1, FuncName); - ParamArray[ArgCount] = Param; + if (ArgCount < FuncValue->Val->FuncDef.NumParams) + ParamArray[ArgCount] = Param; } ArgCount++; @@ -58,7 +59,7 @@ void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, const c ProgramFail(Parser, "comma expected"); } else - { + { /* end of argument list? */ Token = LexGetToken(Parser, NULL, TRUE); if (!TokenCloseBracket) ProgramFail(Parser, "bad argument"); @@ -78,7 +79,7 @@ void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, const c VariableStackFrameAdd(Parser, FuncValue->Val->FuncDef.Intrinsic ? FuncValue->Val->FuncDef.NumParams : 0); TopStackFrame->NumParams = ArgCount; TopStackFrame->ReturnValue = *Result; - for (Count = 0; Count < ArgCount; Count++) + for (Count = 0; Count < FuncValue->Val->FuncDef.NumParams; Count++) VariableDefine(Parser, FuncValue->Val->FuncDef.ParamName[Count], ParamArray[Count]); if (!ParseStatement(&FuncParser)) @@ -90,7 +91,7 @@ void ParseFunctionCall(struct ParseState *Parser, struct Value **Result, const c VariableStackFramePop(Parser); } else - FuncValue->Val->FuncDef.Intrinsic(*Result, ParamArray); + FuncValue->Val->FuncDef.Intrinsic(*Result, ParamArray, ArgCount); HeapPopStackFrame(); } @@ -450,18 +451,28 @@ struct Value *ParseFunctionDefinition(struct ParseState *Parser, struct ValueTyp FuncValue->Typ = &FunctionType; FuncValue->Val->FuncDef.ReturnType = ReturnType; FuncValue->Val->FuncDef.NumParams = ParamCount; + FuncValue->Val->FuncDef.VarArgs = FALSE; FuncValue->Val->FuncDef.ParamType = (void *)FuncValue->Val + sizeof(struct FuncDef); FuncValue->Val->FuncDef.ParamName = (void *)FuncValue->Val->FuncDef.ParamType + sizeof(struct ValueType *) * ParamCount; FuncValue->Val->FuncDef.Body = *Parser; for (ParamCount = 0; ParamCount < FuncValue->Val->FuncDef.NumParams; ParamCount++) { /* harvest the parameters into the function definition */ - TypeParse(&ParamParser, &ParamType, &ParamIdentifier); - FuncValue->Val->FuncDef.ParamType[ParamCount] = ParamType; - FuncValue->Val->FuncDef.ParamName[ParamCount] = ParamIdentifier; + if (ParamCount == FuncValue->Val->FuncDef.NumParams-1 && LexGetToken(&ParamParser, NULL, FALSE) == TokenEllipsis) + { /* ellipsis at end */ + FuncValue->Val->FuncDef.NumParams--; + FuncValue->Val->FuncDef.VarArgs = TRUE; + break; + } + else + { /* add a parameter */ + TypeParse(&ParamParser, &ParamType, &ParamIdentifier); + FuncValue->Val->FuncDef.ParamType[ParamCount] = ParamType; + FuncValue->Val->FuncDef.ParamName[ParamCount] = ParamIdentifier; + } Token = LexGetToken(&ParamParser, NULL, TRUE); - if (Token != TokenComma && ParamCount != FuncValue->Val->FuncDef.NumParams-1) + if (Token != TokenComma && ParamCount < FuncValue->Val->FuncDef.NumParams-1) ProgramFail(&ParamParser, "comma expected"); } diff --git a/picoc.h b/picoc.h index 4b5c765..ee79ba9 100644 --- a/picoc.h +++ b/picoc.h @@ -49,7 +49,7 @@ enum LexToken TokenOpenBracket, TokenCloseBracket, TokenAssign, TokenPlus, TokenMinus, TokenAsterisk, TokenSlash, TokenEquality, TokenLessThan, TokenGreaterThan, TokenLessEqual, TokenGreaterEqual, - TokenSemicolon, TokenComma, TokenDot, TokenColon, + TokenSemicolon, TokenComma, TokenDot, TokenColon, TokenEllipsis, TokenArrow, TokenAmpersand, TokenLeftBrace, TokenRightBrace, TokenLeftSquareBracket, TokenRightSquareBracket, @@ -126,6 +126,7 @@ struct FuncDef { struct ValueType *ReturnType; /* the return value type */ int NumParams; /* the number of parameters */ + int VarArgs; /* has a variable number of arguments after the explicitly specified ones */ struct ValueType **ParamType; /* array of parameter types */ const char **ParamName; /* array of parameter names */ void (*Intrinsic)(); /* intrinsic call address or NULL */ diff --git a/tests/02_printf.c b/tests/02_printf.c index b1ad67e..5435753 100644 --- a/tests/02_printf.c +++ b/tests/02_printf.c @@ -1 +1 @@ -printf() +printf("Hello world\n"); diff --git a/tests/02_printf.expect b/tests/02_printf.expect index 00a60cb..802992c 100644 --- a/tests/02_printf.expect +++ b/tests/02_printf.expect @@ -1 +1 @@ -IntrinsicPrintf +Hello world