/* creates various system-dependent definitions */ void StdioSetupFunc(void) { struct LibraryFunction *plib; plib = &StdioFunctions; plib[ 0].Func = StdioSprintf ; plib[ 1].Func = StdioPuts ; plib[ 2].Func = StdioGets ; plib[ 3].Func = StdioCls ; plib[ 4].Func = StdioFopen ; plib[ 5].Func = StdioFreopen ; plib[ 6].Func = StdioFclose ; plib[ 7].Func = StdioFread ; plib[ 8].Func = StdioFwrite ; plib[ 9].Func = StdioFgetc ; plib[10].Func = StdioFgetc ; plib[11].Func = StdioFgets ; plib[12].Func = StdioFputc ; plib[13].Func = StdioFputs ; plib[14].Func = StdioFeof ; plib[15].Func = StdioFtell ; plib[16].Func = StdioFseek ; plib[17].Func = StdioPrintf ; struct ValueType *StructFileType; struct ValueType *FilePtrType; /* make a "struct __FILEStruct" which is the same size as a native FILE structure */ StructFileType = TypeCreateOpaqueStruct(NULL, TableStrRegister("__FILEStruct"), sizeof(FILE)); /* get a FILE * type */ FilePtrType = TypeGetMatching(NULL, StructFileType, TypePointer, 0, StrEmpty, TRUE); /* 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 */ VariableDefinePlatformVar(NULL, "EOF", &IntType, (union AnyValue *)&EOFValue, FALSE); VariableDefinePlatformVar(NULL, "SEEK_SET", &IntType, (union AnyValue *)&SEEK_SETValue, FALSE); VariableDefinePlatformVar(NULL, "SEEK_CUR", &IntType, (union AnyValue *)&SEEK_CURValue, 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); /* define NULL*/ if (!VariableDefined(TableStrRegister("NULL"))) VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); }
/* initialise the lexer */ void LexInit() { int Count; for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) ReservedWords[Count].SharedWord = TableStrRegister(ReservedWords[Count].Word); }
/* register a new build-in include file */ void IncludeRegister(Picoc *pc, const char *IncludeName, void (*SetupFunction)(Picoc *pc), struct LibraryFunction *FuncList, const char *SetupCSource){ struct IncludeLibrary *NewLib = HeapAllocMem(pc, sizeof(struct IncludeLibrary)); NewLib->IncludeName = TableStrRegister(pc, IncludeName); NewLib->SetupFunction = SetupFunction; NewLib->FuncList = FuncList; NewLib->SetupCSource = SetupCSource; NewLib->NextLib = pc->IncludeLibList; pc->IncludeLibList = NewLib; }
/* deallocate */ void LexCleanup(Picoc *pc) { int Count; LexInteractiveClear(pc, NULL); for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) TableDelete(pc, &pc->ReservedWordTable, TableStrRegister(pc, ReservedWords[Count].Word)); }
/* define a variable. Ident must be registered. If it's a redefinition from the same declaration don't throw an error */ struct Value *VariableDefineButIgnoreIdentical(struct ParseState *Parser, char *Ident, struct ValueType *Typ, int IsStatic, int *FirstVisit) { struct Value *ExistingValue; const char *DeclFileName; int DeclLine; int DeclColumn; if (IsStatic) { char MangledName[LINEBUFFER_MAX]; char *MNPos = &MangledName[0]; char *MNEnd = &MangledName[LINEBUFFER_MAX-1]; const char *RegisteredMangledName; /* make the mangled static name (avoiding using sprintf() to minimise library impact) */ memset((void *)&MangledName, '\0', sizeof(MangledName)); *MNPos++ = '/'; strncpy(MNPos, (char *)Parser->FileName, MNEnd - MNPos); MNPos += strlen(MNPos); if (TopStackFrame != NULL) { /* we're inside a function */ if (MNEnd - MNPos > 0) *MNPos++ = '/'; strncpy(MNPos, (char *)TopStackFrame->FuncName, MNEnd - MNPos); MNPos += strlen(MNPos); } if (MNEnd - MNPos > 0) *MNPos++ = '/'; strncpy(MNPos, Ident, MNEnd - MNPos); RegisteredMangledName = TableStrRegister(MangledName); /* is this static already defined? */ if (!TableGet(&GlobalTable, RegisteredMangledName, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn)) { /* define the mangled-named static variable store in the global scope */ ExistingValue = VariableAllocValueFromType(Parser, Typ, TRUE, NULL, TRUE); TableSet(&GlobalTable, (char *)RegisteredMangledName, ExistingValue, (char *)Parser->FileName, Parser->Line, Parser->CharacterPos); *FirstVisit = TRUE; } /* static variable exists in the global scope - now make a mirroring variable in our own scope with the short name */ VariableDefinePlatformVar(Parser, Ident, ExistingValue->Typ, ExistingValue->Val, TRUE); return ExistingValue; } else { if (Parser->Line != 0 && TableGet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, &ExistingValue, &DeclFileName, &DeclLine, &DeclColumn) && DeclFileName == Parser->FileName && DeclLine == Parser->Line && DeclColumn == Parser->CharacterPos) return ExistingValue; else return VariableDefine(Parser, Ident, NULL, Typ, TRUE); } }
/* make a new temporary name. takes a static buffer of char [7] as a parameter. should be initialised to "XX0000" * where XX can be any characters */ char *PlatformMakeTempName(char *TempNameBuffer) { int CPos = 5; while (CPos > 1) { if (TempNameBuffer[CPos] < '9') { TempNameBuffer[CPos]++; return TableStrRegister(TempNameBuffer); } else { TempNameBuffer[CPos] = '0'; CPos--; } } return TableStrRegister(TempNameBuffer); }
/* global initialisation for libraries */ void LibraryInit(Picoc *pc) { /* define the version number macro */ pc->VersionString = TableStrRegister(pc, PICOC_VERSION); VariableDefinePlatformVar(pc, NULL, "PICOC_VERSION", pc->CharPtrType, (union AnyValue *)&pc->VersionString, FALSE); /* define endian-ness macros */ BigEndian = ((*(char*)&__ENDIAN_CHECK__) == 0); LittleEndian = ((*(char*)&__ENDIAN_CHECK__) == 1); VariableDefinePlatformVar(pc, NULL, "BIG_ENDIAN", &pc->IntType, (union AnyValue *)&BigEndian, FALSE); VariableDefinePlatformVar(pc, NULL, "LITTLE_ENDIAN", &pc->IntType, (union AnyValue *)&LittleEndian, FALSE); }
/* creates various system-dependent definitions */ void UnistdSetupFunc(void) { /* define NULL */ if (!VariableDefined(TableStrRegister("NULL"))) VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); /* define optarg and friends */ VariableDefinePlatformVar(NULL, "optarg", CharPtrType, (union AnyValue *)&optarg, TRUE); VariableDefinePlatformVar(NULL, "optind", &IntType, (union AnyValue *)&optind, TRUE); VariableDefinePlatformVar(NULL, "opterr", &IntType, (union AnyValue *)&opterr, TRUE); VariableDefinePlatformVar(NULL, "optopt", &IntType, (union AnyValue *)&optopt, TRUE); }
/* creates various system-dependent definitions */ void StdTimeSetupFunc(void) { /* make a "struct tm" which is the same size as a native tm structure */ TypeCreateOpaqueStruct(NULL, TableStrRegister("tm"), sizeof(struct tm)); /* define CLK_PER_SEC etc. */ VariableDefinePlatformVar(NULL, "CLOCKS_PER_SEC", &IntType, (union AnyValue *)&CLOCKS_PER_SECValue, FALSE); #ifdef CLK_PER_SEC VariableDefinePlatformVar(NULL, "CLK_PER_SEC", &IntType, (union AnyValue *)&CLK_PER_SECValue, FALSE); #endif #ifdef CLK_TCK VariableDefinePlatformVar(NULL, "CLK_TCK", &IntType, (union AnyValue *)&CLK_TCKValue, FALSE); #endif }
/** * creates various system-dependent definitions * * We retain values like stdout, stdin and stderr in this * function to avoid having to invent "FilePtrType" for * rotables. */ void StdioSetupFunc(void) { struct ValueType *StructFileType; struct ValueType *FilePtrType; /* make a "struct __FILEStruct" which is the same size as a native FILE structure */ StructFileType = TypeCreateOpaqueStruct(NULL, TableStrRegister("__FILEStruct"), sizeof(FILE)); /* get a FILE * type */ FilePtrType = TypeGetMatching(NULL, StructFileType, TypePointer, 0, StrEmpty, TRUE); /* make a "struct __va_listStruct" which is the same size as our struct StdVararg */ TypeCreateOpaqueStruct(NULL, TableStrRegister("__va_listStruct"), sizeof(FILE)); /* define stdin, stdout and stderr */ VariableDefinePlatformVar(NULL, "stdin", FilePtrType, (union AnyValue *)&stdinValue, FALSE); VariableDefinePlatformVar(NULL, "stdout", FilePtrType, (union AnyValue *)&stdoutValue, FALSE); VariableDefinePlatformVar(NULL, "stderr", FilePtrType, (union AnyValue *)&stderrValue, FALSE); /* define NULL, TRUE and FALSE */ if (!VariableDefined(TableStrRegister("NULL"))) VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); }
void PicocCallMain(int argc, char **argv) { /* check if the program wants arguments */ struct Value *FuncValue = NULL; if (!VariableDefined(TableStrRegister("main"))) ProgramFail(NULL, "main() no esta definido"); VariableGet(NULL, TableStrRegister("main"), &FuncValue); if (FuncValue->Typ->Base != TypeFunction) ProgramFail(NULL, "main no es una funcion - no puedo llamarla"); if (FuncValue->Val->FuncDef.NumParams != 0) { /* define the arguments */ VariableDefinePlatformVar(NULL, "__argc", &IntType, (union AnyValue *)&argc, FALSE); VariableDefinePlatformVar(NULL, "__argv", CharPtrPtrType, (union AnyValue *)&argv, FALSE); } if (FuncValue->Val->FuncDef.ReturnType == &VoidType) { if (FuncValue->Val->FuncDef.NumParams == 0) PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE, TRUE, FALSE); else PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE, TRUE, FALSE); } else { VariableDefinePlatformVar(NULL, "__exit_value", &IntType, (union AnyValue *)&PicocExitValue, TRUE); if (FuncValue->Val->FuncDef.NumParams == 0) PicocParse("startup", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE, TRUE, FALSE); else PicocParse("startup", CALL_MAIN_WITH_ARGS_RETURN_INT, strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), TRUE, TRUE, FALSE); } }
/* creates various system-dependent definitions */ void StdioSetupFunc(Picoc *pc) { struct ValueType *StructFileType; struct ValueType *FilePtrType; /* make a "struct __FILEStruct" which is the same size as a native FILE structure */ StructFileType = TypeCreateOpaqueStruct(pc, NULL, TableStrRegister(pc, "__FILEStruct"), sizeof(FILE)); /* get a FILE * type */ FilePtrType = TypeGetMatching(pc, NULL, StructFileType, TypePointer, 0, pc->StrEmpty, TRUE); /* make a "struct __va_listStruct" which is the same size as our struct StdVararg */ TypeCreateOpaqueStruct(pc, NULL, TableStrRegister(pc, "__va_listStruct"), sizeof(FILE)); /* define EOF equal to the system EOF */ VariableDefinePlatformVar(pc, NULL, "EOF", &pc->IntType, (union AnyValue *)&EOFValue, FALSE); VariableDefinePlatformVar(pc, NULL, "SEEK_SET", &pc->IntType, (union AnyValue *)&SEEK_SETValue, FALSE); VariableDefinePlatformVar(pc, NULL, "SEEK_CUR", &pc->IntType, (union AnyValue *)&SEEK_CURValue, FALSE); VariableDefinePlatformVar(pc, NULL, "SEEK_END", &pc->IntType, (union AnyValue *)&SEEK_ENDValue, FALSE); VariableDefinePlatformVar(pc, NULL, "BUFSIZ", &pc->IntType, (union AnyValue *)&BUFSIZValue, FALSE); VariableDefinePlatformVar(pc, NULL, "FILENAME_MAX", &pc->IntType, (union AnyValue *)&FILENAME_MAXValue, FALSE); VariableDefinePlatformVar(pc, NULL, "_IOFBF", &pc->IntType, (union AnyValue *)&_IOFBFValue, FALSE); VariableDefinePlatformVar(pc, NULL, "_IOLBF", &pc->IntType, (union AnyValue *)&_IOLBFValue, FALSE); VariableDefinePlatformVar(pc, NULL, "_IONBF", &pc->IntType, (union AnyValue *)&_IONBFValue, FALSE); VariableDefinePlatformVar(pc, NULL, "L_tmpnam", &pc->IntType, (union AnyValue *)&L_tmpnamValue, FALSE); VariableDefinePlatformVar(pc, NULL, "GETS_MAX", &pc->IntType, (union AnyValue *)&GETS_MAXValue, FALSE); /* define stdin, stdout and stderr */ VariableDefinePlatformVar(pc, NULL, "stdin", FilePtrType, (union AnyValue *)&stdinValue, FALSE); VariableDefinePlatformVar(pc, NULL, "stdout", FilePtrType, (union AnyValue *)&stdoutValue, FALSE); VariableDefinePlatformVar(pc, NULL, "stderr", FilePtrType, (union AnyValue *)&stderrValue, FALSE); /* define NULL, TRUE and FALSE */ if (!VariableDefined(pc, TableStrRegister(pc, "NULL"))) VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&Stdio_ZeroValue, FALSE); }
void PicocCallMain(Picoc *pc, int argc, char **argv) { /* check if the program wants arguments */ struct Value *FuncValue = NULL; if (!VariableDefined(pc, TableStrRegister(pc, "main"))) ProgramFailNoParser(pc, "main() is not defined"); VariableGet(pc, NULL, TableStrRegister(pc, "main"), &FuncValue); if (FuncValue->Typ->Base != TypeFunction) ProgramFailNoParser(pc, "main is not a function - can't call it"); if (FuncValue->Val->FuncDef.NumParams != 0) { /* define the arguments */ VariableDefinePlatformVar(pc, NULL, "__argc", &pc->IntType, (union AnyValue *)&argc, FALSE); VariableDefinePlatformVar(pc, NULL, "__argv", pc->CharPtrPtrType, (union AnyValue *)&argv, FALSE); } if (FuncValue->Val->FuncDef.ReturnType == &pc->VoidType) { if (FuncValue->Val->FuncDef.NumParams == 0) PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_VOID, strlen(CALL_MAIN_NO_ARGS_RETURN_VOID), TRUE, TRUE, FALSE, TRUE); else PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_VOID, strlen(CALL_MAIN_WITH_ARGS_RETURN_VOID), TRUE, TRUE, FALSE, TRUE); } else { VariableDefinePlatformVar(pc, NULL, "__exit_value", &pc->IntType, (union AnyValue *)&pc->PicocExitValue, TRUE); if (FuncValue->Val->FuncDef.NumParams == 0) PicocParse(pc, "startup", CALL_MAIN_NO_ARGS_RETURN_INT, strlen(CALL_MAIN_NO_ARGS_RETURN_INT), TRUE, TRUE, FALSE, TRUE); else PicocParse(pc, "startup", CALL_MAIN_WITH_ARGS_RETURN_INT, strlen(CALL_MAIN_WITH_ARGS_RETURN_INT), TRUE, TRUE, FALSE, TRUE); } }
/* initialise the lexer */ void LexInit(Picoc *pc) { int Count; TableInitTable(&pc->ReservedWordTable, &pc->ReservedWordHashTable[0], sizeof(ReservedWords) / sizeof(struct ReservedWord) * 2, TRUE); for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) { TableSet(pc, &pc->ReservedWordTable, TableStrRegister(pc, ReservedWords[Count].Word), (struct Value *)&ReservedWords[Count], NULL, 0, 0); } pc->LexValue.Typ = NULL; pc->LexValue.Val = &pc->LexAnyValue; pc->LexValue.LValueFrom = FALSE; pc->LexValue.ValOnHeap = FALSE; pc->LexValue.ValOnStack = FALSE; pc->LexValue.AnyValOnHeap = FALSE; pc->LexValue.IsLValue = FALSE; }
/* add a library */ void LibraryAdd(Picoc *pc, struct Table *GlobalTable, const char *LibraryName, struct LibraryFunction *FuncList) { struct ParseState Parser; int Count; char *Identifier; struct ValueType *ReturnType; struct Value *NewValue; void *Tokens; char *IntrinsicName = TableStrRegister(pc, "c library"); /* read all the library definitions */ for (Count = 0; FuncList[Count].Prototype != NULL; Count++) { Tokens = LexAnalyse(pc, IntrinsicName, FuncList[Count].Prototype, strlen((char *)FuncList[Count].Prototype), NULL); LexInitParser(&Parser, pc, FuncList[Count].Prototype, Tokens, IntrinsicName, TRUE, FALSE); TypeParse(&Parser, &ReturnType, &Identifier, NULL); NewValue = ParseFunctionDefinition(&Parser, ReturnType, Identifier); NewValue->Val->FuncDef.Intrinsic = FuncList[Count].Func; HeapFreeMem(pc, Tokens); } }
/* quick scan a source file for definitions */ void PicocParse(Picoc *pc, const char *FileName, const char *Source, int SourceLen, int RunIt, int CleanupNow, int CleanupSource, int EnableDebugger) { struct ParseState Parser; enum ParseResult Ok; struct CleanupTokenNode *NewCleanupNode; char *RegFileName = TableStrRegister(pc, FileName); void *Tokens = LexAnalyse(pc, RegFileName, Source, SourceLen, NULL); /* allocate a cleanup node so we can clean up the tokens later */ if (!CleanupNow) { NewCleanupNode = (struct CleanupTokenNode *) HeapCallocMem(pc, sizeof(struct CleanupTokenNode)); if (NewCleanupNode == NULL) ProgramFailNoParser(pc, "out of memory"); NewCleanupNode->Tokens = Tokens; if (CleanupSource) NewCleanupNode->SourceText = Source; else NewCleanupNode->SourceText = NULL; NewCleanupNode->Next = pc->CleanupTokenList; pc->CleanupTokenList = NewCleanupNode; } /* do the parsing */ LexInitParser(&Parser, pc, Source, Tokens, RegFileName, RunIt, EnableDebugger); do { Ok = ParseStatement(&Parser, TRUE); } while (Ok == ParseResultOk); if (Ok == ParseResultError) ProgramFail(&Parser, "parse error"); /* clean up */ if (CleanupNow) HeapFreeMem(pc, Tokens); }
/* define a global variable shared with a platform global. Ident will be registered */ void VariableDefinePlatformVar(struct ParseState *Parser, char *Ident, struct ValueType *Typ, union AnyValue *FromValue, int IsWritable) { struct Value *SomeValue = VariableAllocValueAndData(NULL, 0, IsWritable, NULL, TRUE); SomeValue->Typ = Typ; SomeValue->Val = FromValue; if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, TableStrRegister(Ident), SomeValue, Parser ? Parser->FileName : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) ProgramFail(Parser, "'%s' is already defined", Ident); }
/* creates various system-dependent definitions */ void StringSetupFunc(Picoc *pc) { /* define NULL */ if (!VariableDefined(pc, TableStrRegister(pc, "NULL"))) VariableDefinePlatformVar(pc, NULL, "NULL", &pc->IntType, (union AnyValue *)&String_ZeroValue, FALSE); }
/* creates various system-dependent definitions */ void StringSetupFunc(void) { /* define NULL */ if (!VariableDefined(TableStrRegister("NULL"))) VariableDefinePlatformVar(NULL, "NULL", &IntType, (union AnyValue *)&ZeroValue, FALSE); }
/* initialise the shared string system */ void TableInit() { TableInitTable(&StringTable, &StringHashTable[0], STRING_TABLE_SIZE, TRUE); StrEmpty = TableStrRegister(""); }
/* initialise the shared string system */ void TableInit(Picoc *pc){ TableInitTable(&pc->StringTable, &pc->StringHashTable[0], STRING_TABLE_SIZE, TRUE); pc->StrEmpty = TableStrRegister(pc, ""); }