Added printf() and variants to stdio
git-svn-id: http://picoc.googlecode.com/svn/trunk@424 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
8bd5cfa054
commit
40e338b823
83
clibrary.c
83
clibrary.c
|
@ -1,10 +1,5 @@
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
|
|
||||||
struct OutputStream CStdOut;
|
|
||||||
|
|
||||||
static int TRUEValue = 1;
|
|
||||||
static int ZeroValue = 0;
|
|
||||||
|
|
||||||
/* initialise a library */
|
/* initialise a library */
|
||||||
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[])
|
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[])
|
||||||
{
|
{
|
||||||
|
@ -16,8 +11,6 @@ void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct Libr
|
||||||
void *Tokens;
|
void *Tokens;
|
||||||
const char *IntrinsicName = TableStrRegister("c library");
|
const char *IntrinsicName = TableStrRegister("c library");
|
||||||
|
|
||||||
CStdOut.Putch = &PlatformPutc;
|
|
||||||
|
|
||||||
for (Count = 0; (*FuncList)[Count].Prototype != NULL; Count++)
|
for (Count = 0; (*FuncList)[Count].Prototype != NULL; Count++)
|
||||||
{
|
{
|
||||||
Tokens = LexAnalyse(IntrinsicName, (*FuncList)[Count].Prototype, strlen((char *)(*FuncList)[Count].Prototype), NULL);
|
Tokens = LexAnalyse(IntrinsicName, (*FuncList)[Count].Prototype, strlen((char *)(*FuncList)[Count].Prototype), NULL);
|
||||||
|
@ -29,6 +22,53 @@ void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct Libr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* print a type to a stream without using printf/sprintf */
|
||||||
|
void PrintType(struct ValueType *Typ, IOFILE *Stream)
|
||||||
|
{
|
||||||
|
switch (Typ->Base)
|
||||||
|
{
|
||||||
|
case TypeVoid: PrintStr("void", Stream); break;
|
||||||
|
case TypeInt: PrintStr("int", Stream); break;
|
||||||
|
case TypeShort: PrintStr("short", Stream); break;
|
||||||
|
case TypeChar: PrintStr("char", Stream); break;
|
||||||
|
case TypeLong: PrintStr("long", Stream); break;
|
||||||
|
case TypeUnsignedInt: PrintStr("unsigned int", Stream); break;
|
||||||
|
case TypeUnsignedShort: PrintStr("unsigned short", Stream); break;
|
||||||
|
case TypeUnsignedLong: PrintStr("unsigned long", Stream); break;
|
||||||
|
#ifndef NO_FP
|
||||||
|
case TypeFP: PrintStr("double", Stream); break;
|
||||||
|
#endif
|
||||||
|
case TypeFunction: PrintStr("function", Stream); break;
|
||||||
|
case TypeMacro: PrintStr("macro", Stream); break;
|
||||||
|
case TypePointer: if (Typ->FromType) PrintType(Typ->FromType, Stream); PrintCh('*', Stream); break;
|
||||||
|
case TypeArray: PrintType(Typ->FromType, Stream); PrintCh('[', Stream); if (Typ->ArraySize != 0) PrintSimpleInt(Typ->ArraySize, Stream); PrintCh(']', Stream); break;
|
||||||
|
case TypeStruct: PrintStr("struct ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
||||||
|
case TypeUnion: PrintStr("union ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
||||||
|
case TypeEnum: PrintStr("enum ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
||||||
|
case Type_Type: PrintStr("type ", Stream); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef BUILTIN_MINI_STDLIB
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a simplified standard library for small embedded systems. It doesn't require
|
||||||
|
* a system stdio library to operate.
|
||||||
|
*
|
||||||
|
* A more complete standard library for larger computers is in the library_XXX.c files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct OutputStream CStdOut;
|
||||||
|
|
||||||
|
static int TRUEValue = 1;
|
||||||
|
static int ZeroValue = 0;
|
||||||
|
|
||||||
|
void BasicIOInit()
|
||||||
|
{
|
||||||
|
CStdOut.Putch = &PlatformPutc;
|
||||||
|
}
|
||||||
|
|
||||||
/* initialise the C library */
|
/* initialise the C library */
|
||||||
void CLibraryInit()
|
void CLibraryInit()
|
||||||
{
|
{
|
||||||
|
@ -148,33 +188,6 @@ void PrintFP(double Num, struct OutputStream *Stream)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* print a type to a stream without using printf/sprintf */
|
|
||||||
void PrintType(struct ValueType *Typ, struct OutputStream *Stream)
|
|
||||||
{
|
|
||||||
switch (Typ->Base)
|
|
||||||
{
|
|
||||||
case TypeVoid: PrintStr("void", Stream); break;
|
|
||||||
case TypeInt: PrintStr("int", Stream); break;
|
|
||||||
case TypeShort: PrintStr("short", Stream); break;
|
|
||||||
case TypeChar: PrintStr("char", Stream); break;
|
|
||||||
case TypeLong: PrintStr("long", Stream); break;
|
|
||||||
case TypeUnsignedInt: PrintStr("unsigned int", Stream); break;
|
|
||||||
case TypeUnsignedShort: PrintStr("unsigned short", Stream); break;
|
|
||||||
case TypeUnsignedLong: PrintStr("unsigned long", Stream); break;
|
|
||||||
#ifndef NO_FP
|
|
||||||
case TypeFP: PrintStr("double", Stream); break;
|
|
||||||
#endif
|
|
||||||
case TypeFunction: PrintStr("function", Stream); break;
|
|
||||||
case TypeMacro: PrintStr("macro", Stream); break;
|
|
||||||
case TypePointer: if (Typ->FromType) PrintType(Typ->FromType, Stream); PrintCh('*', Stream); break;
|
|
||||||
case TypeArray: PrintType(Typ->FromType, Stream); PrintCh('[', Stream); if (Typ->ArraySize != 0) PrintInt(Typ->ArraySize, 0, FALSE, FALSE, Stream); PrintCh(']', Stream); break;
|
|
||||||
case TypeStruct: PrintStr("struct ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
|
||||||
case TypeUnion: PrintStr("union ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
|
||||||
case TypeEnum: PrintStr("enum ", Stream); PrintStr(Typ->Identifier, Stream); break;
|
|
||||||
case Type_Type: PrintStr("type ", Stream); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* intrinsic functions made available to the language */
|
/* intrinsic functions made available to the language */
|
||||||
void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs, struct OutputStream *Stream)
|
void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs, struct OutputStream *Stream)
|
||||||
{
|
{
|
||||||
|
@ -626,3 +639,5 @@ struct LibraryFunction CLibrary[] =
|
||||||
#endif
|
#endif
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif /* BUILTIN_MINI_STDLIB */
|
||||||
|
|
|
@ -40,7 +40,7 @@ void IncludeFile(char *FileName)
|
||||||
if (LInclude->SetupFunction != NULL)
|
if (LInclude->SetupFunction != NULL)
|
||||||
(*LInclude->SetupFunction)();
|
(*LInclude->SetupFunction)();
|
||||||
|
|
||||||
/* parse the setup C source code - may define types etc. */
|
/* run an extra startup function if there is one */
|
||||||
if (LInclude->SetupCSource != NULL)
|
if (LInclude->SetupCSource != NULL)
|
||||||
Parse(FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE);
|
Parse(FileName, LInclude->SetupCSource, strlen(LInclude->SetupCSource), TRUE);
|
||||||
|
|
||||||
|
|
281
library_stdio.c
281
library_stdio.c
|
@ -1,13 +1,172 @@
|
||||||
/* stdio.h library */
|
/* stdio.h library */
|
||||||
|
#include <errno.h>
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
|
|
||||||
#ifndef NO_HASH_INCLUDE
|
#ifndef BUILTIN_MINI_STDLIB
|
||||||
|
|
||||||
|
#define MAX_FORMAT 80
|
||||||
|
|
||||||
|
FILE *CStdOut;
|
||||||
|
|
||||||
static int EOFValue = EOF;
|
static int EOFValue = EOF;
|
||||||
static int SEEK_SETValue = SEEK_SET;
|
static int SEEK_SETValue = SEEK_SET;
|
||||||
static int SEEK_CURValue = SEEK_CUR;
|
static int SEEK_CURValue = SEEK_CUR;
|
||||||
static int SEEK_ENDValue = SEEK_END;
|
static int SEEK_ENDValue = SEEK_END;
|
||||||
|
static int BUFSIZValue = BUFSIZ;
|
||||||
|
static int FILENAME_MAXValue = FILENAME_MAX;
|
||||||
|
static int _IOFBFValue = _IOFBF;
|
||||||
|
static int _IOLBFValue = _IOLBF;
|
||||||
|
static int _IONBFValue = _IONBF;
|
||||||
|
static int L_tmpnamValue = L_tmpnam;
|
||||||
|
static int GETS_MAXValue = 255; /* arbitrary maximum size of a gets() file */
|
||||||
|
|
||||||
|
struct StdVararg
|
||||||
|
{
|
||||||
|
struct Value **Param;
|
||||||
|
int NumArgs;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void BasicIOInit()
|
||||||
|
{
|
||||||
|
CStdOut = stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *Format, struct StdVararg *Args)
|
||||||
|
{
|
||||||
|
struct Value **ArgPos = Args->Param;
|
||||||
|
int ArgCount = 0;
|
||||||
|
char *FPos = Format;
|
||||||
|
char OneFormatBuf[MAX_FORMAT+1];
|
||||||
|
int OneFormatCount;
|
||||||
|
struct ValueType *ShowType;
|
||||||
|
int TotalCharsPrinted = 0;
|
||||||
|
|
||||||
|
while (*FPos != '\0')
|
||||||
|
{
|
||||||
|
if (*FPos == '%')
|
||||||
|
{
|
||||||
|
/* work out what type we're printing */
|
||||||
|
FPos++;
|
||||||
|
ShowType = NULL;
|
||||||
|
OneFormatBuf[OneFormatCount] = '%';
|
||||||
|
OneFormatCount = 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
switch (*FPos)
|
||||||
|
{
|
||||||
|
case 'd': case 'i': ShowType = &IntType; break; /* integer decimal */
|
||||||
|
case 'o': case 'u': case 'x': case 'X': ShowType = &UnsignedIntType; break; /* integer base conversions */
|
||||||
|
case 'e': case 'E': ShowType = &FPType; break; /* double, exponent form */
|
||||||
|
case 'f': case 'F': ShowType = &FPType; break; /* double, fixed-point */
|
||||||
|
case 'g': case 'G': ShowType = &FPType; break; /* double, flexible format */
|
||||||
|
case 'a': case 'A': ShowType = &UnsignedIntType; break; /* hexadecimal, 0x- format */
|
||||||
|
case 'c': ShowType = &UnsignedIntType; break; /* character */
|
||||||
|
case 's': ShowType = CharPtrType; break; /* string */
|
||||||
|
case 'p': ShowType = VoidPtrType; break; /* pointer */
|
||||||
|
case 'n': ShowType = &VoidType; break; /* number of characters written */
|
||||||
|
case 'm': ShowType = &VoidType; break; /* strerror(errno) */
|
||||||
|
case '%': ShowType = &VoidType; break; /* just a '%' character */
|
||||||
|
case '\0': ShowType = &VoidType; break; /* end of format string */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy one character of format across to the OneFormatBuf */
|
||||||
|
OneFormatBuf[OneFormatCount] = *FPos;
|
||||||
|
OneFormatCount++;
|
||||||
|
|
||||||
|
/* do special actions depending on the conversion type */
|
||||||
|
if (ShowType == &VoidType)
|
||||||
|
{
|
||||||
|
switch (*FPos)
|
||||||
|
{
|
||||||
|
case 'm': fputs(strerror(errno), Stream); break;
|
||||||
|
case '%': fputc(*FPos, Stream); break;
|
||||||
|
case '\0': OneFormatBuf[OneFormatCount] = '\0'; fputc(*FPos, Stream); break;
|
||||||
|
case 'n':
|
||||||
|
if ((*ArgPos)->Typ->Base == TypeArray && (*ArgPos)->Typ->FromType->Base == TypeInt)
|
||||||
|
*(int *)(*ArgPos)->Val->Integer = TotalCharsPrinted;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (ShowType == NULL && OneFormatCount < MAX_FORMAT);
|
||||||
|
|
||||||
|
if (ShowType != &VoidType)
|
||||||
|
{
|
||||||
|
if (ArgCount >= Args->NumArgs)
|
||||||
|
fputs("XXX", Stream);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* null-terminate the buffer */
|
||||||
|
OneFormatBuf[OneFormatCount] = '\0';
|
||||||
|
|
||||||
|
if (ShowType == &IntType)
|
||||||
|
{
|
||||||
|
/* show a signed integer */
|
||||||
|
if (IS_INTEGER_NUMERIC(*ArgPos))
|
||||||
|
fprintf(Stream, OneFormatBuf, ExpressionCoerceInteger(*ArgPos));
|
||||||
|
else
|
||||||
|
fputs("XXX", Stream);
|
||||||
|
}
|
||||||
|
else if (ShowType == &UnsignedIntType)
|
||||||
|
{
|
||||||
|
/* show an unsigned integer */
|
||||||
|
if (IS_INTEGER_NUMERIC(*ArgPos))
|
||||||
|
fprintf(Stream, OneFormatBuf, ExpressionCoerceUnsignedInteger(*ArgPos));
|
||||||
|
else
|
||||||
|
fputs("XXX", Stream);
|
||||||
|
}
|
||||||
|
else if (ShowType == &FPType)
|
||||||
|
{
|
||||||
|
/* show a floating point number */
|
||||||
|
if (IS_FP(*ArgPos))
|
||||||
|
fprintf(Stream, OneFormatBuf, ExpressionCoerceFP(*ArgPos));
|
||||||
|
else
|
||||||
|
fputs("XXX", Stream);
|
||||||
|
}
|
||||||
|
else if (ShowType == CharPtrType)
|
||||||
|
{
|
||||||
|
if ((*ArgPos)->Typ->Base == TypePointer)
|
||||||
|
fprintf(Stream, OneFormatBuf, (*ArgPos)->Val->NativePointer);
|
||||||
|
|
||||||
|
else if ((*ArgPos)->Typ->Base == TypeArray && (*ArgPos)->Typ->FromType->Base == TypeChar)
|
||||||
|
fprintf(Stream, OneFormatBuf, &(*ArgPos)->Val->ArrayMem[0]);
|
||||||
|
|
||||||
|
else
|
||||||
|
fputs("XXX", Stream);
|
||||||
|
}
|
||||||
|
else if (ShowType == VoidPtrType)
|
||||||
|
{
|
||||||
|
if ((*ArgPos)->Typ->Base == TypePointer)
|
||||||
|
fprintf(Stream, OneFormatBuf, (*ArgPos)->Val->NativePointer);
|
||||||
|
|
||||||
|
else if ((*ArgPos)->Typ->Base == TypeArray)
|
||||||
|
fprintf(Stream, OneFormatBuf, &(*ArgPos)->Val->ArrayMem[0]);
|
||||||
|
|
||||||
|
else
|
||||||
|
fputs("XXX", Stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArgPos++;
|
||||||
|
ArgCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* just output a normal character */
|
||||||
|
putc(*FPos, Stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TotalCharsPrinted;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StdioBaseSprintf(struct ParseState *Parser, char *Str, int MaxStrSize, char *Format, struct StdVararg *Args)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void StdioFopen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
void StdioFopen(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
{
|
{
|
||||||
|
@ -154,9 +313,76 @@ void StdioPuts(struct ParseState *Parser, struct Value *ReturnValue, struct Valu
|
||||||
ReturnValue->Val->Integer = puts(Param[0]->Val->NativePointer);
|
ReturnValue->Val->Integer = puts(Param[0]->Val->NativePointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StdioGets(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
ReturnValue->Val->NativePointer = fgets(Param[0]->Val->NativePointer, GETS_MAXValue, stdin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioGetchar(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
ReturnValue->Val->Integer = getchar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
struct StdVararg PrintfArgs;
|
||||||
|
|
||||||
|
PrintfArgs.Param = Param+1;
|
||||||
|
PrintfArgs.NumArgs = NumArgs;
|
||||||
|
ReturnValue->Val->Integer = StdioBasePrintf(Parser, stdout, Param[0]->Val->NativePointer, &PrintfArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioVprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
ReturnValue->Val->Integer = StdioBasePrintf(Parser, stdout, Param[0]->Val->NativePointer, Param[1]->Val->NativePointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioFprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
struct StdVararg PrintfArgs;
|
||||||
|
|
||||||
|
PrintfArgs.Param = Param+1;
|
||||||
|
PrintfArgs.NumArgs = NumArgs;
|
||||||
|
ReturnValue->Val->Integer = StdioBasePrintf(Parser, Param[0]->Val->NativePointer, Param[1]->Val->NativePointer, &PrintfArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioVfprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
ReturnValue->Val->Integer = StdioBasePrintf(Parser, Param[0]->Val->NativePointer, Param[1]->Val->NativePointer, Param[2]->Val->NativePointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioSprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
struct StdVararg PrintfArgs;
|
||||||
|
|
||||||
|
PrintfArgs.Param = Param+2;
|
||||||
|
PrintfArgs.NumArgs = NumArgs;
|
||||||
|
ReturnValue->Val->Integer = StdioBaseSprintf(Parser, Param[0]->Val->NativePointer, -1, Param[1]->Val->NativePointer, &PrintfArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioSnprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
struct StdVararg PrintfArgs;
|
||||||
|
|
||||||
|
PrintfArgs.Param = Param+3;
|
||||||
|
PrintfArgs.NumArgs = NumArgs;
|
||||||
|
ReturnValue->Val->Integer = StdioBaseSprintf(Parser, Param[0]->Val->NativePointer, Param[1]->Val->Integer, Param[2]->Val->NativePointer, &PrintfArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioVsprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
ReturnValue->Val->Integer = StdioBaseSprintf(Parser, Param[0]->Val->NativePointer, -1, Param[1]->Val->NativePointer, Param[2]->Val->NativePointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StdioVsnprintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
||||||
|
{
|
||||||
|
ReturnValue->Val->Integer = StdioBaseSprintf(Parser, Param[0]->Val->NativePointer, Param[1]->Val->Integer, Param[2]->Val->NativePointer, Param[3]->Val->NativePointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char StdioDefs[] = "\
|
const char StdioDefs[] = "\
|
||||||
typedef struct FILEStruct FILE; \
|
typedef struct __FILEStruct FILE; \
|
||||||
|
typedef struct __va_listStruct va_list; \
|
||||||
";
|
";
|
||||||
|
|
||||||
struct LibraryFunction StdioFunctions[] =
|
struct LibraryFunction StdioFunctions[] =
|
||||||
|
@ -193,28 +419,67 @@ struct LibraryFunction StdioFunctions[] =
|
||||||
{ StdioSetvbuf, "void setvbuf(FILE *, char *, int, int);" },
|
{ StdioSetvbuf, "void setvbuf(FILE *, char *, int, int);" },
|
||||||
{ StdioUngetc, "int ungetc(int, FILE *);" },
|
{ StdioUngetc, "int ungetc(int, FILE *);" },
|
||||||
{ StdioPuts, "int puts(char *);" },
|
{ StdioPuts, "int puts(char *);" },
|
||||||
|
{ StdioPrintf, "void printf(char *, ...);" },
|
||||||
|
{ StdioSprintf, "char *sprintf(char *, char *, ...);" },
|
||||||
|
{ StdioGets, "char *gets(char *);" },
|
||||||
|
{ StdioGetchar, "int getchar();" },
|
||||||
|
{ StdioGetchar, "int printf(char *format, ...);" },
|
||||||
|
{ StdioGetchar, "int fprintf(FILE *stream, char *format, ...);" },
|
||||||
|
{ StdioGetchar, "int sprintf(char *str, char *format, ...);" },
|
||||||
|
{ StdioGetchar, "int snprintf(char *str, size_t size, char *format, ...);" },
|
||||||
|
{ StdioGetchar, "int vprintf(const char *format, va_list ap);" },
|
||||||
|
{ StdioGetchar, "int vfprintf(FILE *stream, char *format, va_list ap);" },
|
||||||
|
{ StdioGetchar, "int vsprintf(char *str, char *format, va_list ap);" },
|
||||||
|
{ StdioGetchar, "int vsnprintf(char *str, size_t size, char *format, va_list ap);" },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
void StdioSetupFunc(void)
|
void StdioSetupFunc(void)
|
||||||
{
|
{
|
||||||
/* make a "struct FILEStruct" which is the same size as a native FILE structure */
|
/* make a "struct __FILEStruct" which is the same size as a native FILE structure */
|
||||||
TypeCreateOpaqueStruct(NULL, TableStrRegister("FILEStruct"), sizeof(FILE));
|
TypeCreateOpaqueStruct(NULL, TableStrRegister("__FILEStruct"), sizeof(FILE));
|
||||||
|
|
||||||
|
/* make a "struct __va_listStruct" which is the same size as our struct StdVararg */
|
||||||
|
TypeCreateOpaqueStruct(NULL, TableStrRegister("__va_listStruct"), sizeof(FILE));
|
||||||
|
|
||||||
/* define EOF equal to the system EOF */
|
/* define EOF equal to the system EOF */
|
||||||
VariableDefinePlatformVar(NULL, "EOF", &IntType, (union AnyValue *)&EOFValue, FALSE);
|
VariableDefinePlatformVar(NULL, "EOF", &IntType, (union AnyValue *)&EOFValue, FALSE);
|
||||||
VariableDefinePlatformVar(NULL, "SEEK_SET", &IntType, (union AnyValue *)&SEEK_SETValue, FALSE);
|
VariableDefinePlatformVar(NULL, "SEEK_SET", &IntType, (union AnyValue *)&SEEK_SETValue, FALSE);
|
||||||
VariableDefinePlatformVar(NULL, "SEEK_CUR", &IntType, (union AnyValue *)&SEEK_CURValue, FALSE);
|
VariableDefinePlatformVar(NULL, "SEEK_CUR", &IntType, (union AnyValue *)&SEEK_CURValue, FALSE);
|
||||||
VariableDefinePlatformVar(NULL, "SEEK_END", &IntType, (union AnyValue *)&SEEK_ENDValue, FALSE);
|
VariableDefinePlatformVar(NULL, "SEEK_END", &IntType, (union AnyValue *)&SEEK_ENDValue, FALSE);
|
||||||
|
VariableDefinePlatformVar(NULL, "BUFSIZ", &IntType, (union AnyValue *)&BUFSIZValue, FALSE);
|
||||||
|
VariableDefinePlatformVar(NULL, "FILENAME_MAX", &IntType, (union AnyValue *)&FILENAME_MAXValue, FALSE);
|
||||||
|
VariableDefinePlatformVar(NULL, "_IOFBF", &IntType, (union AnyValue *)&_IOFBFValue, FALSE);
|
||||||
|
VariableDefinePlatformVar(NULL, "_IOLBF", &IntType, (union AnyValue *)&_IOLBFValue, FALSE);
|
||||||
|
VariableDefinePlatformVar(NULL, "_IONBF", &IntType, (union AnyValue *)&_IONBFValue, FALSE);
|
||||||
|
VariableDefinePlatformVar(NULL, "L_tmpnam", &IntType, (union AnyValue *)&L_tmpnamValue, FALSE);
|
||||||
|
VariableDefinePlatformVar(NULL, "GETS_MAX", &IntType, (union AnyValue *)&GETS_MAXValue, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* NO_HASH_INCLUDE */
|
void PrintCh(char OutCh, FILE *Stream)
|
||||||
|
{
|
||||||
|
putc(OutCh, Stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintSimpleInt(long Num, FILE *Stream)
|
||||||
|
{
|
||||||
|
fprintf(Stream, "%ld", Num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintStr(const char *Str, FILE *Stream)
|
||||||
|
{
|
||||||
|
fputs(Str, Stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintFP(double Num, FILE *Stream)
|
||||||
|
{
|
||||||
|
fprintf(Stream, "%f", Num);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !BUILTIN_MINI_STDLIB */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
vprintf used to print to the standard output stream
|
|
||||||
fprintf, vfprintf used to print to a file
|
|
||||||
snprintf, vsprintf, vsnprintf used to print to a char array (C string)
|
|
||||||
scanf, vscanf used to input from the standard input stream
|
scanf, vscanf used to input from the standard input stream
|
||||||
fscanf, vfscanf used to input from a file
|
fscanf, vfscanf used to input from a file
|
||||||
sscanf, vsscanf used to input from a char array (e.g., a C string)
|
sscanf, vsscanf used to input from a char array (e.g., a C string)
|
||||||
|
|
|
@ -15,18 +15,11 @@ void Clineno (struct ParseState *Parser, struct Value *ReturnValue, struct Value
|
||||||
ReturnValue->Val->Integer = Parser->Line;
|
ReturnValue->Val->Integer = Parser->Line;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cerrormsg (struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs)
|
|
||||||
{
|
|
||||||
PlatformErrorPrefix(Parser);
|
|
||||||
LibPrintf(Parser, ReturnValue, Param, NumArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* list of all library functions and their prototypes */
|
/* list of all library functions and their prototypes */
|
||||||
struct LibraryFunction PlatformLibrary[] =
|
struct LibraryFunction PlatformLibrary[] =
|
||||||
{
|
{
|
||||||
{ Ctest, "void test(int);" },
|
{ Ctest, "void test(int);" },
|
||||||
{ Clineno, "int lineno();" },
|
{ Clineno, "int lineno();" },
|
||||||
{ Cerrormsg, "void errorprintf(char *,...);" },
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
3
picoc.c
3
picoc.c
|
@ -3,13 +3,16 @@
|
||||||
/* initialise everything */
|
/* initialise everything */
|
||||||
void Initialise()
|
void Initialise()
|
||||||
{
|
{
|
||||||
|
BasicIOInit();
|
||||||
HeapInit();
|
HeapInit();
|
||||||
TableInit();
|
TableInit();
|
||||||
VariableInit();
|
VariableInit();
|
||||||
LexInit();
|
LexInit();
|
||||||
TypeInit();
|
TypeInit();
|
||||||
|
#ifdef BUILTIN_MINI_STDLIB
|
||||||
LibraryInit(&GlobalTable, "c library", &CLibrary);
|
LibraryInit(&GlobalTable, "c library", &CLibrary);
|
||||||
CLibraryInit();
|
CLibraryInit();
|
||||||
|
#endif
|
||||||
PlatformLibraryInit();
|
PlatformLibraryInit();
|
||||||
LibraryInit(&GlobalTable, "platform library", &PlatformLibrary);
|
LibraryInit(&GlobalTable, "platform library", &PlatformLibrary);
|
||||||
}
|
}
|
||||||
|
|
22
picoc.h
22
picoc.h
|
@ -21,6 +21,13 @@
|
||||||
|
|
||||||
#define GETS_BUF_MAX 256
|
#define GETS_BUF_MAX 256
|
||||||
|
|
||||||
|
/* small processors use a simplified FILE * for stdio, otherwise use the system FILE * */
|
||||||
|
#ifdef BUILTIN_MINI_STDLIB
|
||||||
|
typedef struct OutputStream IOFILE;
|
||||||
|
#else
|
||||||
|
typedef FILE IOFILE;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* coercion of numeric types to other numeric types */
|
/* coercion of numeric types to other numeric types */
|
||||||
#ifndef NO_FP
|
#ifndef NO_FP
|
||||||
#define IS_FP(v) ((v)->Typ->Base == TypeFP)
|
#define IS_FP(v) ((v)->Typ->Base == TypeFP)
|
||||||
|
@ -270,6 +277,7 @@ extern struct Table GlobalTable;
|
||||||
extern struct StackFrame *TopStackFrame;
|
extern struct StackFrame *TopStackFrame;
|
||||||
extern struct ValueType UberType;
|
extern struct ValueType UberType;
|
||||||
extern struct ValueType IntType;
|
extern struct ValueType IntType;
|
||||||
|
extern struct ValueType UnsignedIntType;
|
||||||
extern struct ValueType CharType;
|
extern struct ValueType CharType;
|
||||||
#ifndef NO_FP
|
#ifndef NO_FP
|
||||||
extern struct ValueType FPType;
|
extern struct ValueType FPType;
|
||||||
|
@ -285,7 +293,7 @@ extern char *StrEmpty;
|
||||||
extern struct PointerValue NULLPointer;
|
extern struct PointerValue NULLPointer;
|
||||||
extern struct LibraryFunction CLibrary[];
|
extern struct LibraryFunction CLibrary[];
|
||||||
extern struct LibraryFunction PlatformLibrary[];
|
extern struct LibraryFunction PlatformLibrary[];
|
||||||
extern struct OutputStream CStdOut;
|
extern IOFILE *CStdOut;
|
||||||
|
|
||||||
/* table.c */
|
/* table.c */
|
||||||
void TableInit();
|
void TableInit();
|
||||||
|
@ -374,13 +382,15 @@ void VariableStringLiteralDefine(char *Ident, struct Value *Val);
|
||||||
void *VariableDereferencePointer(struct ParseState *Parser, struct Value *PointerValue, struct Value **DerefVal, int *DerefOffset, struct ValueType **DerefType, int *DerefIsLValue);
|
void *VariableDereferencePointer(struct ParseState *Parser, struct Value *PointerValue, struct Value **DerefVal, int *DerefOffset, struct ValueType **DerefType, int *DerefIsLValue);
|
||||||
|
|
||||||
/* clibrary.c */
|
/* clibrary.c */
|
||||||
|
void BasicIOInit();
|
||||||
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]);
|
void LibraryInit(struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction (*FuncList)[]);
|
||||||
void CLibraryInit();
|
void CLibraryInit();
|
||||||
void PrintCh(char OutCh, struct OutputStream *Stream);
|
void PrintCh(char OutCh, IOFILE *Stream);
|
||||||
void PrintInt(long Num, int FieldWidth, int ZeroPad, int LeftJustify, struct OutputStream *Stream);
|
void PrintSimpleInt(long Num, FILE *Stream);
|
||||||
void PrintStr(const char *Str, struct OutputStream *Stream);
|
void PrintInt(long Num, int FieldWidth, int ZeroPad, int LeftJustify, IOFILE *Stream);
|
||||||
void PrintFP(double Num, struct OutputStream *Stream);
|
void PrintStr(const char *Str, IOFILE *Stream);
|
||||||
void PrintType(struct ValueType *Typ, struct OutputStream *Stream);
|
void PrintFP(double Num, IOFILE *Stream);
|
||||||
|
void PrintType(struct ValueType *Typ, IOFILE *Stream);
|
||||||
void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs);
|
void LibPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs);
|
||||||
|
|
||||||
/* platform.c */
|
/* platform.c */
|
||||||
|
|
24
platform.c
24
platform.c
|
@ -19,23 +19,23 @@ void PrintSourceTextErrorLine(const char *FileName, const char *SourceText, int
|
||||||
|
|
||||||
/* display the line */
|
/* display the line */
|
||||||
for (CPos = LinePos; *CPos != '\n' && *CPos != '\0'; CPos++)
|
for (CPos = LinePos; *CPos != '\n' && *CPos != '\0'; CPos++)
|
||||||
PrintCh(*CPos, &CStdOut);
|
PrintCh(*CPos, CStdOut);
|
||||||
PrintCh('\n', &CStdOut);
|
PrintCh('\n', CStdOut);
|
||||||
|
|
||||||
/* display the error position */
|
/* display the error position */
|
||||||
for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' && (CCount < CharacterPos || *CPos == ' '); CPos++, CCount++)
|
for (CPos = LinePos, CCount = 0; *CPos != '\n' && *CPos != '\0' && (CCount < CharacterPos || *CPos == ' '); CPos++, CCount++)
|
||||||
{
|
{
|
||||||
if (*CPos == '\t')
|
if (*CPos == '\t')
|
||||||
PrintCh('\t', &CStdOut);
|
PrintCh('\t', CStdOut);
|
||||||
else
|
else
|
||||||
PrintCh(' ', &CStdOut);
|
PrintCh(' ', CStdOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* assume we're in interactive mode - try to make the arrow match up with the input text */
|
/* assume we're in interactive mode - try to make the arrow match up with the input text */
|
||||||
for (CCount = 0; CCount < CharacterPos + strlen(INTERACTIVE_PROMPT_STATEMENT); CCount++)
|
for (CCount = 0; CCount < CharacterPos + strlen(INTERACTIVE_PROMPT_STATEMENT); CCount++)
|
||||||
PrintCh(' ', &CStdOut);
|
PrintCh(' ', CStdOut);
|
||||||
}
|
}
|
||||||
PlatformPrintf("^\n%s:%d: ", FileName, Line, CharacterPos);
|
PlatformPrintf("^\n%s:%d: ", FileName, Line, CharacterPos);
|
||||||
|
|
||||||
|
@ -122,18 +122,18 @@ void PlatformVPrintf(const char *Format, va_list Args)
|
||||||
FPos++;
|
FPos++;
|
||||||
switch (*FPos)
|
switch (*FPos)
|
||||||
{
|
{
|
||||||
case 's': PrintStr(va_arg(Args, char *), &CStdOut); break;
|
case 's': PrintStr(va_arg(Args, char *), CStdOut); break;
|
||||||
case 'd': PrintInt(va_arg(Args, int), 0, FALSE, FALSE, &CStdOut); break;
|
case 'd': PrintSimpleInt(va_arg(Args, int), CStdOut); break;
|
||||||
case 'c': PrintCh(va_arg(Args, int), &CStdOut); break;
|
case 'c': PrintCh(va_arg(Args, int), CStdOut); break;
|
||||||
case 't': PrintType(va_arg(Args, struct ValueType *), &CStdOut); break;
|
case 't': PrintType(va_arg(Args, struct ValueType *), CStdOut); break;
|
||||||
#ifndef NO_FP
|
#ifndef NO_FP
|
||||||
case 'f': PrintFP(va_arg(Args, double), &CStdOut); break;
|
case 'f': PrintFP(va_arg(Args, double), CStdOut); break;
|
||||||
#endif
|
#endif
|
||||||
case '%': PrintCh('%', &CStdOut); break;
|
case '%': PrintCh('%', CStdOut); break;
|
||||||
case '\0': FPos--; break;
|
case '\0': FPos--; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PrintCh(*FPos, &CStdOut);
|
PrintCh(*FPos, CStdOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ extern jmp_buf ExitBuf;
|
||||||
# include <setjmp.h>
|
# include <setjmp.h>
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
# define assert(x)
|
# define assert(x)
|
||||||
|
# define BUILTIN_MINI_STDLIB
|
||||||
# undef BIG_ENDIAN
|
# undef BIG_ENDIAN
|
||||||
# undef FANCY_ERROR_REPORTING
|
# undef FANCY_ERROR_REPORTING
|
||||||
|
|
||||||
|
@ -103,10 +104,12 @@ extern jmp_buf ExitBuf;
|
||||||
# define NO_CALLOC
|
# define NO_CALLOC
|
||||||
# define NO_REALLOC
|
# define NO_REALLOC
|
||||||
# define BROKEN_FLOAT_CASTS
|
# define BROKEN_FLOAT_CASTS
|
||||||
|
# define BUILTIN_MINI_STDLIB
|
||||||
# else
|
# else
|
||||||
# ifdef UMON_HOST
|
# ifdef UMON_HOST
|
||||||
# define HEAP_SIZE (128*1024) /* space for the heap and the stack */
|
# define HEAP_SIZE (128*1024) /* space for the heap and the stack */
|
||||||
# define NO_FP
|
# define NO_FP
|
||||||
|
# define BUILTIN_MINI_STDLIB
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
|
|
Loading…
Reference in a new issue