void FASTCALL DisposeStringList(STRLIST **plist) { STRLIST *list=*plist, *next; if(list) while((next=list->next)!=NULL) { ssFree(list->string); ssFree(list); list = next; } *plist = NULL; }
void FASTCALL FreeBanks() { BANK *next; while(banks) { next = banks->next; ssFree(banks->buffer); ssFree(banks->label); ssFree(banks); banks = next; } }
void FreeFixoffs(FIXOFFS **pfix) { FIXOFFS *fix=*pfix,*iNext; if(fix) { while(fix) { iNext = fix->prev; ssFree(fix->filename); ssFree(fix); fix = iNext; } *pfix = NULL; } }
void FASTCALL ReleaseIfDef() { IFDEF *ifdef; if(curScript->ifdefTrack) { ifdef = curScript->ifdefTrack->prev; ssFree(curScript->ifdefTrack); curScript->ifdefTrack = ifdef; } }
BOOL FASTCALL IncBin(char *filename, S32 maxsize) { U8 *buffer; S32 len,bankspace; if(PRECOMPILING) return TRUE; if(maxsize==0x10000) maxsize = maxsize; if((buffer=LoadFile(DIR_SCRIPT,filename,&len))==NULL) { error(ERR_OPENFILE_IN, filename); return FALSE; } bankspace = GetBankSpace(); if(maxsize != -1) { if(len > maxsize) { error(ERR_INCBINSIZE,filename,len,maxsize); len = maxsize; } } else maxsize = len; if(len > bankspace) { error(ERR_INCBINSIZEBANK,filename,len,bankspace); maxsize = bankspace; len = bankspace; } BankWrite(buffer,(S32)len); BankSeekFwd(maxsize-len); ssFree(buffer); return TRUE; }
BOOL FASTCALL comProc_VarDeclare(U16 flags, S16 *brackCnt) { int cast,arraySize,elementsSize,braceCnt; S32 offset=-1,elementsEnd; S32 num; U16 varflags = 0; char *label=NULL; VAR *castvar=NULL; VAR *var=NULL,*pvar; BOOL VARSET, SEEKED = FALSE; if(!STRCMP(szTemp,"typedef")) { varflags |= VARFLAG_TYPECAST; GetNextWord(); } if(!STRCMP(szTemp,"shared")) { varflags |= VARFLAG_SHARED; GetNextWord(); } if((cast=IsVarCast(szTemp,&castvar))==VARCAST_NULL) { if(varflags&VARFLAG_TYPECAST) { error(ERR_NOTTYPECAST,szTemp); return TRUE; } return FALSE; } if(curVar&&(curVar->flags&VARFLAG_TYPECAST)) varflags |= VARFLAG_TYPECAST; for(;;) { if(!IsStringLabel(GetNextWord())) { error(ERR_BADLABEL,szTemp); sprintf(szTemp, "invlabel_%04X", invlabel++); } else { if(PRECOMPILING && IsLabelUsed(szTemp,curVar?curVar->childVars:vars)) sprintf(szTemp, "invlabel_%04X", invlabel++); } label = strdup(szTemp); if(PeekNextWord()[0]==':') { GetNextWord(); if(IsStrNum(GetNextWord())) { offset = ConfirmWord(StrToInt(szTemp)); varflags |= VARFLAG_FIXED; } else error(ERR_INTEXP); VARSET = TRUE; } else { if(varflags&VARFLAG_TYPECAST) VARSET = TRUE; else if(!curBank) fatal(FTL_VARNOTROMBANK); if(cast == VARCAST_STRUCT && !(varflags & VARFLAG_TYPECAST) && !PRECOMPILING) { offset = GetBankOffset(); VARSET = TRUE; } else VARSET = FALSE; } if(PRECOMPILING) { var = AddVariable(label, cast, castvar, varflags, offset); if(varflags&VARFLAG_TYPECAST) { if(curVar) { var->offset = VarSize(curVar); } } } else { var = FindVariable(curVar?curVar->childVars:(varflags&VARFLAG_TYPECAST)?typedefs:vars, label); if(!(var->flags&VARFLAG_TYPECAST) && (!(var->flags&VARFLAG_DEFCASTED) || cast!=VARCAST_STRUCT) && (var->offset==-1)) SetVarOffsets(var,GetBankOffset(),FALSE); } if(castvar) { var->size = castvar->size; } arraySize = 0; if(PeekNextWord()[0]=='[') { GetNextWord(); if(PeekNextWord()[0]==']') { arraySize=-1;//autosize GetNextWord(); } else { /* if(IsStrNum(szTemp)) { if(((var->flags&VARFLAG_TYPECAST) && PRECOMPILING) || (!(var->flags&VARFLAG_TYPECAST))) { arraySize = ConfirmWord(StrToInt(szTemp)); var->arraySize = arraySize; } } else error(ERR_INTEXP); */ CompileImmediateInteger(0, &num, -1, 0); if(((var->flags&VARFLAG_TYPECAST) && PRECOMPILING) || (!(var->flags&VARFLAG_TYPECAST))) { arraySize = ConfirmWord(num); var->arraySize = arraySize; } if(GetNextWord()[0]!=']') error(ERR_ARRAYENDEXP,szTemp); } } if(!(var->flags&VARFLAG_DEFCASTED) && (cast==VARCAST_STRUCT)) { SetCurVar(var); GetCode(flags|CF_BRACEOK|CF_GETNEXTWORD, brackCnt); ReleaseCurVar(); } else { if(PeekNextWord()[0]=='=') { GetNextWord(); if(var->flags&VARFLAG_TYPECAST) { error(ERR_VARCASTASSIGN,label); SeekPastBraceBlock(); } else if(curBank->type==BANKTYPE_RAM) { error(ERR_VARDECLAREINRAM); SeekPastBraceBlock(); } else { elementsSize = 0; elementsEnd = (GetBankOffset()-curBank->org) + ((arraySize==-1)? var->size:var->size*arraySize); if(GetNextWord()[0]=='{') { if(!arraySize) { error(ERR_NOTARRAY,var->label); } braceCnt = 1; GetNextWord(); } else braceCnt = 0; do { braceCnt = CompileVarBody(flags,brackCnt, var, &elementsSize, braceCnt, cast); } while(braceCnt); if(!PRECOMPILING) { if(arraySize==-1) { arraySize=elementsSize/VarSize(var); SEEKED = TRUE; } else { if(elementsSize>VarSize(var)) error(ERR_ELEMENTSTOOLARGE,var->label,elementsSize-VarSize(var)); BankSeek(elementsEnd); SEEKED = TRUE; } var->arraySize = arraySize; } } } else { if(((var->flags&VARFLAG_TYPECAST) && PRECOMPILING) || (!(var->flags&VARFLAG_TYPECAST) && !PRECOMPILING && !VARSET)) { if(arraySize==-1) arraySize = 1; if(arraySize!=0) var->arraySize = arraySize; if(!PRECOMPILING) { BankSeekFwd(VarSize(var)); SEEKED = TRUE; } } } if(((var->flags&VARFLAG_TYPECAST) && PRECOMPILING) || (!(var->flags&VARFLAG_TYPECAST) && !PRECOMPILING)) { // adjust all the var sizes for structs arraySize = VarSize(var); pvar = var->parent; while(pvar) { pvar->size += arraySize; pvar = pvar->parent; } } } if(!(var->flags&VARFLAG_TYPECAST) && (cast==VARCAST_STRUCT)) SetVarOffsets(var,offset,FALSE); // removed 2004-05-22, if problems occurs, check if(!SEEKED && (var->flags&(VARFLAG_TYPECAST|VARFLAG_DEFCASTED))==VARFLAG_DEFCASTED && (cast==VARCAST_STRUCT)) { CheckCurBank(); if((var->flags&VARFLAG_TYPECAST) || !PRECOMPILING) BankSeekFwd(VarSize(var)); } ssFree(label); if(PeekNextWord()[0]!=',') break; GetNextWord(); } return TRUE; }
// preprocessor directives BOOL FASTCALL comProc_Preprocess(U16 flags, S16 *brackCnt) { BOOL PREP_OK=FALSE; int code; S32 index; char *label,*enumClass; if(*szTemp != '#') { if(!STRCMP(szTemp,"enum")) { if(IsStringLabel(GetNextWord())) { enumClass = strdup(szTemp); GetNextWord(); } else enumClass = NULL; if(szTemp[0]!='{') { ssFree(enumClass); error(ERR_ENUMBRACK); SkipLine(FALSE); return TRUE; } GetNextWord(); index = 0; while(szTemp[0]!='}') { label = strdup(szTemp); if(GetNextWord()[0]=='=') { if(!IsStrNum(GetNextWord())) { error(ERR_INTEXP); } else { index = ConfirmWord(StrToInt(szTemp)); } if(*szTemp!='}' && *szTemp!=',') GetNextWord(); } AddEnum(enumClass,label,index++); ssFree(label); if(szTemp[0]!=',') break; GetNextWord(); } if(szTemp[0]!='}') { error(ERR_ENUMBRACK); SkipLine(FALSE); return TRUE; } ssFree(enumClass); return TRUE; } return FALSE; } switch(code = StrInPrep(GetNextWord(),szPreprocess)) { /**********************************************************************/ case PREPROCESS_SETPAD: if(InFalseIfDef()) break; if(GetNextWord()[0]=='"') { if(!DoString()) { error(ERR_INTEXP); } else { strncpy(szPadding,szString,sizeof(szPadding)-1); szPadding[sizeof(szPadding)-1] = '\0'; } } else if(IsStrNum(szTemp)) { index = StrToInt(szTemp); szPadding[0] = ConfirmChar(index); szPadding[1] = '\0'; PREP_OK = TRUE; } else error(ERR_INTEXP); break; /*--------------------------------------------------------------------*/ case PREPROCESS_ALIGN: if(InFalseIfDef()) break; if(IsStrNum(GetNextWord())) { index = StrToInt(szTemp); AlignCode(ConfirmWord(index)); PREP_OK = TRUE; } else error(ERR_INTEXP); break; /**********************************************************************/ case PREPROCESS_INCLUDE: if(InFalseIfDef()) break; if(GetNextWord()[0]=='"' && DoStringDirect()) { if(CompileScript(szString,NULL,NULL)) PREP_OK = TRUE; break; } error(ERR_STRINGEXP); break; /*--------------------------------------------------------------------*/ case PREPROCESS_INCBIN: // "filename"[,maxsize] if(InFalseIfDef()) break; if(GetNextWord()[0]=='"' && DoStringDirect()) { index = -1; if(PeekNextWord()[0]==',') { GetNextWord(); if(IsStrNum(GetNextWord())) { index = ConfirmWord(StrToInt(szTemp)); } else { error(ERR_INTEXP); PREP_OK = FALSE; } } if(IncBin(szString,index)) PREP_OK = TRUE; break; } error(ERR_STRINGEXP); break; /*--------------------------------------------------------------------*/ case PREPROCESS_USEPATH: // "pathname" if(InFalseIfDef()) break; if(GetNextWord()[0]=='"' && DoStringDirect()) { if(PRECOMPILING && !AddDirList(&includeDirList, szString)) { error(ERR_ADDINGPATH,szString); } PREP_OK = TRUE; break; } error(ERR_STRINGEXP); break; /**********************************************************************/ case PREPROCESS_DEFINE: if(InFalseIfDef()) break; USE_DEFS = FALSE; AddDefine(GetNextWord(),NULL); USE_DEFS = TRUE; PREP_OK = TRUE; break; /*--------------------------------------------------------------------*/ case PREPROCESS_UNDEF: if(InFalseIfDef()) break; USE_DEFS = FALSE; if(!DelDefine(GetNextWord())) error(ERR_UNDEFINE,szTemp); USE_DEFS = TRUE; PREP_OK = TRUE; break; /*--------------------------------------------------------------------*/ case PREPROCESS_IFDEF: if(InFalseIfDef()) break; USE_DEFS = FALSE; EnterIfDef(FindDefine(defList,GetNextWord())!=NULL); USE_DEFS = TRUE; PREP_OK = TRUE; break; /*--------------------------------------------------------------------*/ case PREPROCESS_IFNDEF: if(InFalseIfDef()) break; USE_DEFS = FALSE; EnterIfDef(FindDefine(defList,GetNextWord())==NULL); USE_DEFS = TRUE; PREP_OK = TRUE; break; /*--------------------------------------------------------------------*/ case PREPROCESS_ELSE: if(!curScript->ifdefTrack || curScript->ifdefTrack->ELSE) { error(ERR_PREPELSEUNEXP); } else { curScript->ifdefTrack->RESULT = !curScript->ifdefTrack->RESULT; curScript->ifdefTrack->ELSE = TRUE; } PREP_OK = TRUE; break; /*--------------------------------------------------------------------*/ case PREPROCESS_ENDIF: //TODO fix this ReleaseIfDef(); PREP_OK = TRUE; break; /**********************************************************************/ case PREPROCESS_TODO: case PREPROCESS_WARNING: case PREPROCESS_ERROR: case PREPROCESS_FATAL: if(InFalseIfDef()) break; if(GetNextWord()[0]!='"' || !DoString()) strcpy(szString,"<user message>"); switch(code) { case PREPROCESS_TODO: todo(szString); break; case PREPROCESS_WARNING: warning(WRN_USERPREP,szString); break; case PREPROCESS_ERROR: error(ERR_USERPREP,szString); break; case PREPROCESS_FATAL: fatal(FTL_USERPREP,szString); break; } PREP_OK = TRUE; break; /**********************************************************************/ case PREPROCESS_TELL: if(InFalseIfDef()) break; PREP_OK = TRUE; switch(code=CheckSubList(code)) { case PREPROCESS_TELL_BANK: CheckCurBank(); notice(code,"Current Bank: %s (#%d)", curBank->label, curBank->bank); break; case PREPROCESS_TELL_BANKOFFSET: CheckCurBank(); notice(code,"Current Bank: %s (#%d); Offset: $%04X (%d)", curBank->label, curBank->bank, (BANK_OFFSET(curBank)+curBank->org), (BANK_OFFSET(curBank)+curBank->org)); break; case PREPROCESS_TELL_BANKSIZE: CheckCurBank(); notice(code,"Current Bank: %s (#%d); Current Size: $%04X (%d bytes)", curBank->label, curBank->bank, (BANK_OFFSET(curBank)), (BANK_OFFSET(curBank))); break; case PREPROCESS_TELL_BANKFREE: CheckCurBank(); notice(code,"Current Bank: %s (#%d); Current Bytes Free In Bank: $%04X (%d)", curBank->label, curBank->bank, (BANK_OFFSET(curBank)), (BANK_OFFSET(curBank))); break; case PREPROCESS_TELL_BANKTYPE: CheckCurBank(); notice(code,"Current Bank: %s (#%d); Type: %s", curBank->label, curBank->bank, szBankTypes[curBank->type]); break; default: error(ERR_PREPROCESSORID,szTemp); PREP_OK = FALSE; } break; /**********************************************************************/ case PREPROCESS_RAM: if(InFalseIfDef()) break; PREP_OK = TRUE; switch(code=CheckSubList(code)) { case PREPROCESS_RAM_ORG: // blockaddress[, maxsize] if(IsStrNum(GetNextWord())) { ramBank.org = 0; ramBank.ptr = ramBank.buffer+ConfirmWord(StrToInt(szTemp)); curBank = &ramBank; PREP_OK = TRUE; } else error(ERR_INTEXP); if(PeekNextWord()[0]==',') { GetNextWord(); if(IsStrNum(GetNextWord())) { ramBank.maxsize = BANK_OFFSET(curBank)+ConfirmWord(StrToInt(szTemp)); } else { error(ERR_INTEXP); PREP_OK = FALSE; } } curBank->end = curBank->buffer+ramBank.maxsize; break; case PREPROCESS_RAM_END: curBank = NULL; break; default: error(ERR_PREPROCESSORID,szTemp); PREP_OK = FALSE; } break; /**********************************************************************/ case PREPROCESS_ROM: if(InFalseIfDef()) break; PREP_OK = TRUE; switch(code=CheckSubList(code)) { case PREPROCESS_ROM_ORG: // blockaddress[, maxsize] CheckRomBank(); if(IsStrNum(GetNextWord())) { #if 0 curBank->org = ConfirmWord(StrToInt(szTemp)); #else curBank->org = ConfirmWord(StrToInt(szTemp))-BANK_OFFSET(curBank); #endif PREP_OK = TRUE; } else error(ERR_INTEXP); if(PeekNextWord()[0]==',') { GetNextWord(); if(IsStrNum(GetNextWord())) { curBank->maxsize = ConfirmWord(StrToInt(szTemp)); } else { error(ERR_INTEXP); PREP_OK = FALSE; } } break; case PREPROCESS_ROM_END: CheckRomBank(); curBank = NULL; break; case PREPROCESS_ROM_BANKSIZE: // size if(IsStrNum(GetNextWord())) { bankSizes[BANKTYPE_ROM] = StrToInt(szTemp); if(bankSizes[BANKTYPE_ROM] > MAX_BANKSIZE) { error(ERR_BANKSIZE,bankSizes[BANKTYPE_ROM],MAX_BANKSIZE); bankSizes[BANKTYPE_ROM] = MAX_BANKSIZE; } PREP_OK = TRUE; } else error(ERR_INTEXP); if(PeekNextWord()[0]==',') { GetNextWord(); CheckRomBank(); if(IsStrNum(GetNextWord())) { curBank->maxsize = (StrToInt(szTemp)); } else { error(ERR_INTEXP); PREP_OK = FALSE; } } break; case PREPROCESS_ROM_BANK: // label if(!IsStringLabel(GetNextWord())) { error(ERR_BADLABEL,szTemp); strcpy(szTemp,""); } SetBank(BANKTYPE_ROM, szTemp); break; default: error(ERR_PREPROCESSORID,szTemp); PREP_OK = FALSE; } break; /**********************************************************************/ case PREPROCESS_CHR: if(InFalseIfDef()) break; PREP_OK = TRUE; switch(code=CheckSubList(code)) { case PREPROCESS_CHR_BANKSIZE: // size if(IsStrNum(GetNextWord())) { bankSizes[BANKTYPE_CHR] = (StrToInt(szTemp)); if(bankSizes[BANKTYPE_CHR] > MAX_BANKSIZE) { error(ERR_BANKSIZE,bankSizes[BANKTYPE_CHR],MAX_BANKSIZE); bankSizes[BANKTYPE_CHR] = MAX_BANKSIZE; } PREP_OK = TRUE; } else error(ERR_INTEXP); if(PeekNextWord()[0]==',') { GetNextWord(); if(IsStrNum(GetNextWord())) { curBank->maxsize = (StrToInt(szTemp)); } else { error(ERR_INTEXP); PREP_OK = FALSE; } } break; case PREPROCESS_CHR_BANK: // label if(!IsStringLabel(GetNextWord())) { error(ERR_BADLABEL,szTemp); strcpy(szTemp,""); } SetBank(BANKTYPE_CHR, szTemp); break; case PREPROCESS_CHR_END: CheckChrBank(); curBank = NULL; break; default: error(ERR_PREPROCESSORID,szTemp); PREP_OK = FALSE; } break; /**********************************************************************/ case PREPROCESS_INES: if(InFalseIfDef()) break; PREP_OK = TRUE; switch(code=CheckSubList(code)) { case PREPROCESS_INES_MAPPER: // (number|"name") if(GetNextWord()[0]=='"') { if(DoString()) { if((index=StrInStrint(szString, siMappers))==-1) error(ERR_UNKMAPPER,szString); else { romHeader.mapper = siMappers[index].index; PREP_OK = TRUE; } } } else if(IsStrNum(szTemp)) { romHeader.mapper = ConfirmChar(StrToInt(szTemp)); PREP_OK = TRUE; } else error(ERR_INTEXP); break; case PREPROCESS_INES_MIRRORING: // (number|"name") if(GetNextWord()[0]=='"') { if(DoString()) { if((index=StrInStrint(szString, siMirroring))==-1) error(ERR_UNKMIRRORING,szString); else { romHeader.mirroring = siMirroring[index].index; PREP_OK = TRUE; } } } else if(IsStrNum(szTemp)) { romHeader.mirroring = ConfirmChar(StrToInt(szTemp)); PREP_OK = TRUE; } else error(ERR_INTEXP); break; case PREPROCESS_INES_BATTERY: romHeader.battery = PreprocessCheckYesNo(&PREP_OK); break; case PREPROCESS_INES_TRAINER: romHeader.trainer = PreprocessCheckYesNo(&PREP_OK); break; case PREPROCESS_INES_FOURSCREEN: romHeader.fourscreen = PreprocessCheckYesNo(&PREP_OK); break; case PREPROCESS_INES_PRGREPEAT: if(IsStrNum(GetNextWord())) { romHeader.prgrepeat = ConfirmChar(StrToInt(szTemp)); PREP_OK = TRUE; } else error(ERR_INTEXP); break; case PREPROCESS_INES_CHRREPEAT: if(IsStrNum(GetNextWord())) { romHeader.chrrepeat = ConfirmChar(StrToInt(szTemp)); PREP_OK = TRUE; } else error(ERR_INTEXP); break; case PREPROCESS_INES_OFF: cfg.output.enableHeader = FALSE; break; default: error(ERR_PREPROCESSORID,szTemp); PREP_OK = FALSE; } break; /**********************************************************************/ case PREPROCESS_INTERRUPT: if(InFalseIfDef()) break; PREP_OK = TRUE; if(!PRECOMPILING) switch(code=CheckSubList(code)) { case PREPROCESS_INTERRUPT_NMI: case PREPROCESS_INTERRUPT_START: case PREPROCESS_INTERRUPT_IRQ: PREP_OK = PreprocessInterrupt(code); break; default: error(ERR_PREPROCESSORID,szTemp); PREP_OK = FALSE; } break; /**********************************************************************/ default: error(ERR_PREPROCESSORID,szTemp); } if(!PREP_OK) SkipLine(TRUE); // if there was an error, skip to the next line return TRUE; }
void FASTCALL LabelBank(char *label) { CheckCurBank(); ssFree(curBank->label); curBank->label = strdup(label); }