/* p2bin.c */ /*****************************************************************************/ /* AS-Portierung */ /* */ /* Umwandlung von AS-Codefiles in Binaerfiles */ /* */ /* Historie: 3. 6.1996 Grundsteinlegung */ /* 30. 5.1999 0x statt $ erlaubt */ /* */ /*****************************************************************************/ #include "stdinc.h" #include #include #include "version.h" #include "endian.h" #include "bpemu.h" #include "strutil.h" #include "hex.h" #include "nls.h" #include "nlmessages.h" #include "p2bin.rsc" #include "ioerrs.h" #include "chunks.h" #include "cmdarg.h" #include "toolutils.h" #define BinSuffix ".bin" typedef void (*ProcessProc)( #ifdef __PROTOS__ char *FileName, LongWord Offset #endif ); static CMDProcessed ParProcessed; static FILE *TargFile; static String SrcName,TargName; static LongWord StartAdr,StopAdr,EntryAdr,RealFileLen; static LongWord MaxGran,Dummy; static Boolean StartAuto,StopAuto,AutoErase,EntryAdrPresent; static Byte FillVal; static Boolean DoCheckSum; static Byte SizeDiv; static LongInt ANDMask,ANDEq; static ShortInt StartHeader; static ChunkList UsedList; #ifdef DEBUG #define ChkIO(s) ChkIO_L(s,__LINE__) static void ChkIO_L(char *s, int line) BEGIN if (errno!=0) BEGIN fprintf(stderr,"%s %d\n",s,line); exit(3); END END #endif static void ParamError(Boolean InEnv, char *Arg) BEGIN printf("%s%s\n%s\n",getmessage((InEnv)?Num_ErrMsgInvEnvParam:Num_ErrMsgInvParam),Arg,getmessage(Num_ErrMsgProgTerm)); exit(1); END #define BufferSize 4096 static Byte Buffer[BufferSize]; static void OpenTarget(void) BEGIN LongWord Rest,Trans; TargFile=fopen(TargName,OPENWRMODE); if (TargFile==Nil) ChkIO(TargName); RealFileLen=((StopAdr-StartAdr+1)*MaxGran)/SizeDiv; if (StartHeader!=0) BEGIN memset(Buffer,0,abs(StartHeader)); if (fwrite(Buffer,1,abs(StartHeader),TargFile)!=abs(StartHeader)) ChkIO(TargName); END memset(Buffer,FillVal,BufferSize); Rest=RealFileLen; while (Rest!=0) BEGIN Trans=min(Rest,BufferSize); if (fwrite(Buffer,1,Trans,TargFile)!=Trans) ChkIO(TargName); Rest-=Trans; END END static void CloseTarget(void) BEGIN LongWord Sum,Rest,Trans,Real,z,bpos; if ((EntryAdrPresent) AND (StartHeader!=0)) BEGIN rewind(TargFile); bpos=((StartHeader>0) ? 0 : -1-StartHeader)<<3; for (z=0; z> bpos) & 0xff; bpos += (StartHeader>0) ? 8 : -8; END if (fwrite(Buffer,1,abs(StartHeader),TargFile)!=abs(StartHeader)) ChkIO(TargName); END if (fclose(TargFile)==EOF) ChkIO(TargName); if (DoCheckSum) BEGIN TargFile=fopen(TargName,OPENUPMODE); if (TargFile==Nil) ChkIO(TargName); if (fseek(TargFile,abs(StartHeader),SEEK_SET)==-1) ChkIO(TargName); Rest=FileSize(TargFile)-1; Sum=0; while (Rest!=0) BEGIN Trans=min(Rest,BufferSize); Rest-=Trans; Real=fread(Buffer,1,Trans,TargFile); if (Real!=Trans) ChkIO(TargName); for (z=0; z>%s",FileName,TargName); ChkIO(OutName); SumLen=0; do BEGIN ReadRecordHeader(&InpHeader,&InpSegment,&Gran,FileName,SrcFile); if (InpHeader==FileHeaderStartAdr) BEGIN if (NOT Read4(SrcFile,&ErgStart)) ChkIO(FileName); if (NOT EntryAdrPresent) BEGIN EntryAdr=ErgStart; EntryAdrPresent=True; END END else if (InpHeader!=FileHeaderEnd) BEGIN if (NOT Read4(SrcFile,&InpStart)) ChkIO(FileName); if (NOT Read2(SrcFile,&InpLen)) ChkIO(FileName); NextPos=ftell(SrcFile)+InpLen; if (NextPos>=FileSize(SrcFile)-1) FormatError(FileName,getmessage(Num_FormatInvRecordLenMsg)); doit=(FilterOK(InpHeader) AND (InpSegment==SegCode)); if (doit) BEGIN InpStart+=Offset; ErgStart=max(StartAdr,InpStart); ErgStop=min(StopAdr,InpStart+(InpLen/Gran)-1); doit=(ErgStop>=ErgStart); if (doit) BEGIN ErgLen=(ErgStop+1-ErgStart)*Gran; if (AddChunk(&UsedList,ErgStart,ErgStop-ErgStart+1,True)) BEGIN errno=0; printf(" %s\n",getmessage(Num_ErrMsgOverlap)); ChkIO(OutName); END END END if (doit) BEGIN /* an Anfang interessierender Daten */ if (fseek(SrcFile,(ErgStart-InpStart)*Gran,SEEK_CUR)==-1) ChkIO(FileName); /* in Zieldatei an passende Stelle */ if (fseek(TargFile,(((ErgStart-StartAdr)*Gran)/SizeDiv)+abs(StartHeader),SEEK_SET)==-1) ChkIO(TargName); /* umkopieren */ while (ErgLen>0) BEGIN TransLen=min(BufferSize,ErgLen); if (fread(Buffer,1,TransLen,SrcFile)!=TransLen) ChkIO(FileName); if (SizeDiv==1) ResLen=TransLen; else BEGIN ResLen=0; for (z=0; z<(LongInt)TransLen; z++) if (((ErgStart*Gran+z)&ANDMask)==ANDEq) Buffer[ResLen++]=Buffer[z]; END if (fwrite(Buffer,1,ResLen,TargFile)!=ResLen) ChkIO(TargName); ErgLen-=TransLen; ErgStart+=TransLen; SumLen+=ResLen; END END if (fseek(SrcFile,NextPos,SEEK_SET)==-1) ChkIO(FileName); END END while (InpHeader!=0); errno=0; printf(" (%d Byte)\n",SumLen); ChkIO(OutName); if (fclose(SrcFile)==EOF) ChkIO(FileName); END static ProcessProc CurrProcessor; static LongWord CurrOffset; static void Callback(char *Name) BEGIN CurrProcessor(Name,CurrOffset); END static void ProcessGroup(char *GroupName_O, ProcessProc Processor) BEGIN String Ext,GroupName; CurrProcessor=Processor; strmaxcpy(GroupName,GroupName_O,255); strmaxcpy(Ext,GroupName,255); if (NOT RemoveOffset(GroupName,&CurrOffset)) ParamError(False,Ext); AddSuffix(GroupName,getmessage(Num_Suffix)); if (NOT DirScan(GroupName,Callback)) fprintf(stderr,"%s%s%s\n",getmessage(Num_ErrMsgNullMaskA),GroupName,getmessage(Num_ErrMsgNullMaskB)); END static void MeasureFile(char *FileName, LongWord Offset) BEGIN FILE *f; Byte Header,Gran,Segment; Word Length,TestID; LongWord Adr,EndAdr,NextPos; f=fopen(FileName,OPENRDMODE); if (f==Nil) ChkIO(FileName); if (NOT Read2(f,&TestID)) ChkIO(FileName); if (TestID!=FileMagic) FormatError(FileName,getmessage(Num_FormatInvHeaderMsg)); do BEGIN ReadRecordHeader(&Header,&Segment,&Gran,FileName,f); if (Header==FileHeaderStartAdr) BEGIN if (fseek(f,sizeof(LongWord),SEEK_CUR)==-1) ChkIO(FileName); END else if (Header!=FileHeaderEnd) BEGIN if (NOT Read4(f,&Adr)) ChkIO(FileName); if (NOT Read2(f,&Length)) ChkIO(FileName); NextPos=ftell(f)+Length; if (NextPos>FileSize(f)) FormatError(FileName,getmessage(Num_FormatInvRecordLenMsg)); if (FilterOK(Header) AND (Segment==SegCode)) BEGIN Adr+=Offset; EndAdr=Adr+(Length/Gran)-1; if (Gran>MaxGran) MaxGran=Gran; if (StartAuto) if (StartAdr>Adr) StartAdr=Adr; if (StopAuto) if (EndAdr>StopAdr) StopAdr=EndAdr; END fseek(f,NextPos,SEEK_SET); END END while(Header!=0); if (fclose(f)==EOF) ChkIO(FileName); END static CMDResult CMD_AdrRange(Boolean Negate, char *Arg) BEGIN char *p,Save; Boolean err; if (Negate) BEGIN StartAdr=0; StopAdr=0x7fff; return CMDOK; END else BEGIN p=strchr(Arg,'-'); if (p==Nil) return CMDErr; Save=(*p); *p='\0'; if ((StartAuto = AddressWildcard(Arg))) err = True; else StartAdr = ConstLongInt(Arg, &err); *p = Save; if (NOT err) return CMDErr; if ((StopAuto = AddressWildcard(p + 1))) err = True; else StopAdr = ConstLongInt(p+1, &err); if (NOT err) return CMDErr; if ((NOT StartAuto) AND (NOT StopAuto) AND (StartAdr>StopAdr)) return CMDErr; return CMDArg; END END static CMDResult CMD_ByteMode(Boolean Negate, char *Arg) BEGIN #define ByteModeCnt 9 static char *ByteModeStrings[ByteModeCnt]={"ALL","EVEN","ODD","BYTE0","BYTE1","BYTE2","BYTE3","WORD0","WORD1"}; static Byte ByteModeDivs[ByteModeCnt]={1,2,2,4,4,4,4,2,2}; static Byte ByteModeMasks[ByteModeCnt]={0,1,1,3,3,3,3,2,2}; static Byte ByteModeEqs[ByteModeCnt]={0,0,1,0,1,2,3,0,2}; int z; if (*Arg=='\0') BEGIN SizeDiv=1; ANDEq=0; ANDMask=0; return CMDOK; END else BEGIN for (z=0; z4)) return CMDErr; StartHeader*=Sgn; return CMDArg; END END static CMDResult CMD_EntryAdr(Boolean Negate, char *Arg) BEGIN Boolean err; if (Negate) BEGIN EntryAdrPresent=False; return CMDOK; END else BEGIN EntryAdr=ConstLongInt(Arg,&err); return (err) ? CMDArg : CMDErr; END END static CMDResult CMD_FillVal(Boolean Negate, char *Arg) BEGIN Boolean err; FillVal=ConstLongInt(Arg,&err); if (NOT err) return CMDErr; else return CMDArg; END static CMDResult CMD_CheckSum(Boolean Negate, char *Arg) BEGIN DoCheckSum=NOT Negate; return CMDOK; END static CMDResult CMD_AutoErase(Boolean Negate, char *Arg) BEGIN AutoErase=NOT Negate; return CMDOK; END #define P2BINParamCnt 8 static CMDRec P2BINParams[P2BINParamCnt]= {{"f", CMD_FilterList}, {"r", CMD_AdrRange}, {"s", CMD_CheckSum}, {"m", CMD_ByteMode}, {"l", CMD_FillVal}, {"e", CMD_EntryAdr}, {"S", CMD_StartHeader}, {"k", CMD_AutoErase}}; int main(int argc, char **argv) BEGIN int z; char *ph1,*ph2; String Ver; ParamStr=argv; ParamCount=argc-1; nls_init(); NLS_Initialize(); endian_init(); strutil_init(); bpemu_init(); hex_init(); nlmessages_init("p2bin.msg",*argv,MsgId1,MsgId2); ioerrs_init(*argv); chunks_init(); cmdarg_init(*argv); toolutils_init(*argv); sprintf(Ver,"P2BIN/C V%s",Version); WrCopyRight(Ver); InitChunk(&UsedList); if (ParamCount==0) BEGIN errno=0; printf("%s%s%s\n",getmessage(Num_InfoMessHead1),GetEXEName(),getmessage(Num_InfoMessHead2)); ChkIO(OutName); for (ph1=getmessage(Num_InfoMessHelp),ph2=strchr(ph1,'\n'); ph2!=Nil; ph1=ph2+1,ph2=strchr(ph1,'\n')) BEGIN *ph2='\0'; printf("%s\n",ph1); *ph2='\n'; END exit(1); END StartAdr=0; StopAdr=0x7fff; StartAuto=False; StopAuto=False; FillVal=0xff; DoCheckSum=False; SizeDiv=1; ANDEq=0; EntryAdr=(-1); EntryAdrPresent=False; AutoErase=False; StartHeader=0; ProcessCMD(P2BINParams,P2BINParamCnt,ParProcessed,"P2BINCMD",ParamError); if (ProcessedEmpty(ParProcessed)) BEGIN errno=0; printf("%s\n",getmessage(Num_ErrMsgTargMissing)); ChkIO(OutName); exit(1); END z=ParamCount; while ((z>0) AND (NOT ParProcessed[z])) z--; strmaxcpy(TargName,ParamStr[z],255); if (NOT RemoveOffset(TargName,&Dummy)) ParamError(False,ParamStr[z]); ParProcessed[z]=False; if (ProcessedEmpty(ParProcessed)) BEGIN strmaxcpy(SrcName,ParamStr[z],255); DelSuffix(TargName); END AddSuffix(TargName,BinSuffix); MaxGran=1; if ((StartAuto) OR (StopAuto)) BEGIN #ifdef __STDC__ if (StartAuto) StartAdr=0xffffffffu; #else if (StartAuto) StartAdr=0xffffffff; #endif if (StopAuto) StopAdr=0; if (ProcessedEmpty(ParProcessed)) ProcessGroup(SrcName,MeasureFile); else for (z=1; z<=ParamCount; z++) if (ParProcessed[z]) ProcessGroup(ParamStr[z],MeasureFile); if (StartAdr>StopAdr) BEGIN errno=0; printf("%s\n",getmessage(Num_ErrMsgAutoFailed)); ChkIO(OutName); exit(1); END END OpenTarget(); if (ProcessedEmpty(ParProcessed)) ProcessGroup(SrcName,ProcessFile); else for (z=1; z<=ParamCount; z++) if (ParProcessed[z]) ProcessGroup(ParamStr[z],ProcessFile); CloseTarget(); if (AutoErase) BEGIN if (ProcessedEmpty(ParProcessed)) ProcessGroup(SrcName,EraseFile); else for (z=1; z<=ParamCount; z++) if (ParProcessed[z]) ProcessGroup(ParamStr[z],EraseFile); END return 0; END