/* create a system struct which has no user-visible members */ struct ValueType *TypeCreateOpaqueStruct(struct ParseState *Parser, const char *StructName, int Size) { struct ValueType *Typ = TypeGetMatching(Parser, &UberType, TypeStruct, 0, StructName, FALSE); /* create the (empty) table */ Typ->Members = VariableAlloc(Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE); Typ->Members->HashTable = (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table)); TableInitTable(Typ->Members, (struct TableEntry **)((char *)Typ->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE); Typ->Sizeof = Size; return Typ; }
/* add a stack frame when doing a function call */ void VariableStackFrameAdd(struct ParseState *Parser, const char *FuncName, int NumParams) { struct StackFrame *NewFrame; HeapPushStackFrame(); NewFrame = HeapAllocStack(sizeof(struct StackFrame) + sizeof(struct Value *) * NumParams); if (NewFrame == NULL) ProgramFail(Parser, "out of memory"); ParserCopy(&NewFrame->ReturnParser, Parser); NewFrame->FuncName = FuncName; NewFrame->Parameter = (NumParams > 0) ? ((void *)((char *)NewFrame + sizeof(struct StackFrame))) : NULL; TableInitTable(&NewFrame->LocalTable, &NewFrame->LocalHashTable[0], LOCAL_TABLE_SIZE, FALSE); NewFrame->PreviousStackFrame = TopStackFrame; TopStackFrame = NewFrame; }
/* 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; }
/* initialise the debugger by clearing the breakpoint table */ void DebugInit() { TableInitTable(&BreakpointTable, &BreakpointHashTable[0], BREAKPOINT_TABLE_SIZE, TRUE); BreakpointCount = 0; }
/* parse a struct or union declaration */ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsStruct) { struct Value *LexValue; struct ValueType *MemberType; char *MemberIdentifier; char *StructIdentifier; struct Value *MemberValue; enum LexToken Token; int AlignBoundary; Token = LexGetToken(Parser, &LexValue, FALSE); if (Token == TokenIdentifier) { LexGetToken(Parser, &LexValue, TRUE); StructIdentifier = LexValue->Val->Identifier; Token = LexGetToken(Parser, NULL, FALSE); } else { static char TempNameBuf[7] = "^s0000"; StructIdentifier = PlatformMakeTempName(TempNameBuf); } *Typ = TypeGetMatching(Parser, &UberType, IsStruct ? TypeStruct : TypeUnion, 0, StructIdentifier, Token != TokenLeftBrace); Token = LexGetToken(Parser, NULL, FALSE); if (Token != TokenLeftBrace) { /* use the already defined structure */ if ((*Typ)->Members == NULL) ProgramFail(Parser, "la estructura '%s' no esta definida en este ambito", LexValue->Val->Identifier); return; } if (TopStackFrame != NULL) ProgramFail(Parser, "las estructuras/uniones solo pueden definirse en un ambito global"); LexGetToken(Parser, NULL, TRUE); (*Typ)->Members = VariableAlloc(Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE); (*Typ)->Members->HashTable = (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)); TableInitTable((*Typ)->Members, (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE); do { TypeParse(Parser, &MemberType, &MemberIdentifier, NULL); if (MemberType == NULL || MemberIdentifier == NULL) ProgramFail(Parser, "tipo invalido en estructura"); MemberValue = VariableAllocValueAndData(Parser, sizeof(int), FALSE, NULL, TRUE); MemberValue->Typ = MemberType; if (IsStruct) { /* allocate this member's location in the struct */ AlignBoundary = MemberValue->Typ->AlignBytes; if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) (*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1)); MemberValue->Val->Integer = (*Typ)->Sizeof; (*Typ)->Sizeof += TypeSizeValue(MemberValue, TRUE); } else { /* union members always start at 0, make sure it's big enough to hold the largest member */ MemberValue->Val->Integer = 0; if (MemberValue->Typ->Sizeof > (*Typ)->Sizeof) (*Typ)->Sizeof = TypeSizeValue(MemberValue, TRUE); } /* make sure to align to the size of the largest member's alignment */ if ((*Typ)->AlignBytes < MemberValue->Typ->AlignBytes) (*Typ)->AlignBytes = MemberValue->Typ->AlignBytes; /* define it */ if (!TableSet((*Typ)->Members, MemberIdentifier, MemberValue, Parser->FileName, Parser->Line, Parser->CharacterPos)) ProgramFail(Parser, "el miembro '%s' ya esta definido", &MemberIdentifier); if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) ProgramFail(Parser, "se esperaba un punto y coma"); } while (LexGetToken(Parser, NULL, FALSE) != TokenRightBrace); /* now align the structure to the size of its largest member's alignment */ AlignBoundary = (*Typ)->AlignBytes; if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) (*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1)); LexGetToken(Parser, NULL, TRUE); }
/* parse a struct or union declaration */ void TypeParseStruct(struct ParseState *Parser, struct ValueType **Typ, int IsStruct){ struct Value *LexValue; struct ValueType *MemberType; char *MemberIdentifier; char *StructIdentifier; struct Value *MemberValue; enum LexToken Token; int AlignBoundary; Picoc *pc = Parser->pc; Token = LexGetToken(Parser, &LexValue, FALSE); if (Token == TokenIdentifier){ LexGetToken(Parser, &LexValue, TRUE); StructIdentifier = LexValue->Val->Identifier; Token = LexGetToken(Parser, NULL, FALSE); }else{ static char TempNameBuf[7] = "^s0000"; StructIdentifier = PlatformMakeTempName(pc, TempNameBuf); } *Typ = TypeGetMatching(pc, Parser, &Parser->pc->UberType, IsStruct ? TypeStruct : TypeUnion, 0, StructIdentifier, TRUE); if (Token == TokenLeftBrace && (*Typ)->Members) ProgramFail(Parser, "data type '%t' is already defined", *Typ); Token = LexGetToken(Parser, NULL, FALSE); if (Token != TokenLeftBrace){ /* use the already defined structure */ #if 0 if ((*Typ)->Members == NULL) ProgramFail(Parser, "structure '%s' isn't defined", LexValue->Val->Identifier); #endif return; } if (pc->TopStackFrame != NULL) ProgramFail(Parser, "struct/union definitions can only be globals"); LexGetToken(Parser, NULL, TRUE); (*Typ)->Members = VariableAlloc(pc, Parser, sizeof(struct Table) + STRUCT_TABLE_SIZE * sizeof(struct TableEntry), TRUE); (*Typ)->Members->HashTable = (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)); TableInitTable((*Typ)->Members, (struct TableEntry **)((char *)(*Typ)->Members + sizeof(struct Table)), STRUCT_TABLE_SIZE, TRUE); do { TypeParse(Parser, &MemberType, &MemberIdentifier, NULL); if (!MemberType || !MemberIdentifier) ProgramFail(Parser, "invalid type in struct"); MemberValue = VariableAllocValueAndData(pc, Parser, sizeof(int), FALSE, NULL, TRUE); MemberValue->Typ = MemberType; if (IsStruct){ /* allocate this member's location in the struct */ AlignBoundary = MemberValue->Typ->AlignBytes; if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) (*Typ)->Sizeof += AlignBoundary - ((*Typ)->Sizeof & (AlignBoundary-1)); MemberValue->Val->Integer = (*Typ)->Sizeof; (*Typ)->Sizeof += TypeSizeValue(MemberValue, TRUE); }else{ /* union members always start at 0, make sure it's big enough to hold the largest member */ MemberValue->Val->Integer = 0; if ((*Typ)->Sizeof < MemberValue->Typ->Sizeof ) (*Typ)->Sizeof = TypeSizeValue(MemberValue, TRUE); } /* make sure to align to the size of the largest member's alignment */ if ((*Typ)->AlignBytes < MemberValue->Typ->AlignBytes) (*Typ)->AlignBytes = MemberValue->Typ->AlignBytes; /* define it */ if (!TableSet(pc, (*Typ)->Members, MemberIdentifier, MemberValue, Parser->FileName, Parser->Line, Parser->CharacterPos)) ProgramFail(Parser, "member '%s' already defined", &MemberIdentifier); if (LexGetToken(Parser, NULL, TRUE) != TokenSemicolon) ProgramFail(Parser, "semicolon expected"); } while (LexGetToken(Parser, NULL, FALSE) != TokenRightBrace); /* now align the structure to the size of its largest member's alignment */ AlignBoundary = (*Typ)->AlignBytes; if (((*Typ)->Sizeof & (AlignBoundary-1)) != 0) (*Typ)->Sizeof += AlignBoundary-((*Typ)->Sizeof & (AlignBoundary-1)); LexGetToken(Parser, NULL, TRUE); }
/* initialise the shared string system */ void TableInit(Picoc *pc){ TableInitTable(&pc->StringTable, &pc->StringHashTable[0], STRING_TABLE_SIZE, TRUE); pc->StrEmpty = TableStrRegister(pc, ""); }
/* initialise the shared string system */ void TableInit() { TableInitTable(&StringTable, &StringHashTable[0], STRING_TABLE_SIZE, TRUE); StrEmpty = TableStrRegister(""); }
/* initialise the variable system */ void VariableInit(void) { TableInitTable(&GlobalTable, &GlobalHashTable[0], GLOBAL_TABLE_SIZE, TRUE); TableInitTable(&StringLiteralTable, &StringLiteralHashTable[0], STRING_LITERAL_TABLE_SIZE, TRUE); TopStackFrame = NULL; }
/* initialize the debugger by clearing the breakpoint table */ void DebugInit(Picoc *pc) { TableInitTable(&pc->BreakpointTable, &pc->BreakpointHashTable[0], BREAKPOINT_TABLE_SIZE, true); pc->BreakpointCount = 0; }