/* 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); } }
/* define a variable. Ident must be registered */ struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable) { struct Value *AssignValue; if (InitValue != NULL) AssignValue = VariableAllocValueAndCopy(Parser, InitValue, TopStackFrame == NULL); else AssignValue = VariableAllocValueFromType(Parser, Typ, MakeWritable, NULL, TopStackFrame == NULL); AssignValue->IsLValue = MakeWritable; if (!TableSet((TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable, Ident, AssignValue, Parser ? ((char *)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) ProgramFail(Parser, "'%s' is already defined", Ident); return AssignValue; }
/* define a variable. Ident must be registered */ struct Value *VariableDefine(struct ParseState *Parser, char *Ident, struct Value *InitValue, struct ValueType *Typ, int MakeWritable) { struct Value *AssignValue; short int ScopeLevel = Parser ? Parser->ScopeLevel : -1; //~ fprintf(stderr, "def %s %d\n", Ident, ScopeLevel); if (InitValue != NULL) AssignValue = VariableAllocValueAndCopy(Parser, InitValue, TopStackFrame == NULL); else AssignValue = VariableAllocValueFromType(Parser, Typ, MakeWritable, NULL, TopStackFrame == NULL); AssignValue->IsLValue = MakeWritable; AssignValue->ScopeLevel = ScopeLevel; AssignValue->OutOfScope = 0; struct Table * currentTable = (TopStackFrame == NULL) ? &GlobalTable : &TopStackFrame->LocalTable; struct Value * ExistingValue; if (TableGet(currentTable, Ident, &ExistingValue, NULL, NULL, NULL)) { if (ExistingValue->OutOfScope) { //~ fprintf(stderr, "reusing %s\n", Ident); // not sure how to delete properly, so... // throw the old copy away and hope it's cleaned up at VariableStackFramePop TableDeleteStack(currentTable, Ident); } } if (!TableSet(currentTable, Ident, AssignValue, Parser ? ((char *)Parser->FileName) : NULL, Parser ? Parser->Line : 0, Parser ? Parser->CharacterPos : 0)) ProgramFail(Parser, "'%s' is already defined", Ident); return AssignValue; }