281 lines
8.7 KiB
Plaintext
281 lines
8.7 KiB
Plaintext
/* Iconvert.e
|
|
|
|
This little utility converts a '.i' assembly include file
|
|
into an E binary module.
|
|
it understands '=' and 'EQU' for constant definitions, and builds
|
|
OBJECTs out of STRUCTURE definitions (from "exec/types.i").
|
|
it needs a macroassembler like A68k to run.
|
|
USAGE: iconvert <.ifile> */
|
|
|
|
OBJECT def
|
|
type:INT,name
|
|
ENDOBJECT
|
|
|
|
ENUM T_ARRAY,T_CHAR,T_INT,T_LONG=4,T_CONST=$10,T_STRUCT,T_END
|
|
ENUM ER_NONE,ER_IN,ER_OUT,ER_MEM,ER_WORK,ER_BREAK,ER_FORM,ER_TEMPW,
|
|
ER_INVOKE,ER_TEMPR,ER_OFORM,ER_I
|
|
|
|
CONST MAX_DEF=2500,IDMAX=10
|
|
|
|
DEF defs[MAX_DEF]:ARRAY OF def,
|
|
infile[100]:STRING,outfile[100]:STRING,
|
|
handle=NIL,flen,buf,bbuf,defn=0,line=0,mode=0,a,phx=FALSE
|
|
|
|
PROC main()
|
|
WriteF('Iconvert v0.2 1992 $#%!\n\n')
|
|
readinfile()
|
|
collectidents()
|
|
makeasmfile()
|
|
invokea68k()
|
|
readbinary()
|
|
makemodule()
|
|
error(ER_NONE)
|
|
ENDPROC
|
|
|
|
PROC readinfile()
|
|
DEF len
|
|
IF (arg[0]="-") AND (arg[1]="p") AND (arg[2]=" ")
|
|
arg:=arg+3
|
|
phx:=TRUE
|
|
ENDIF
|
|
StrCopy(infile,arg,ALL)
|
|
len:=EstrLen(infile)-2
|
|
IF infile[len]<>"." THEN error(ER_I)
|
|
StrCopy(outfile,arg,ALL); outfile[len+1]:="m"
|
|
IF (flen:=FileLength(infile))<1 THEN error(ER_IN)
|
|
IF (buf:=New(flen+1))=NIL THEN error(ER_MEM)
|
|
buf[flen]:=10
|
|
IF (handle:=Open(infile,OLDFILE))=NIL THEN error(ER_IN)
|
|
IF Read(handle,buf,flen)<>flen THEN error(ER_IN)
|
|
Close(handle); handle:=NIL
|
|
ENDPROC
|
|
|
|
PROC collectidents()
|
|
DEF p,a,id[IDMAX]:ARRAY OF LONG,num,f,c,end,zero=NIL,macro=FALSE
|
|
DEF struct=FALSE,d:PTR TO def,size,work[10]:STRING
|
|
WriteF('Now trying to convert "\s".\n',infile)
|
|
INC line; p:=buf; end:=p+flen; d:=defs
|
|
WHILE p<end
|
|
FOR a:=0 TO IDMAX-1 DO id[a]:=0
|
|
num:=0; f:=TRUE
|
|
WHILE f
|
|
c:=p[]++
|
|
IF zero; zero[]:=0; zero:=NIL; ENDIF
|
|
IF (c=10) OR (c=0)
|
|
f:=FALSE
|
|
ELSEIF (c<=" ") OR (c=",")
|
|
ELSEIF (c=";") OR (c="*")
|
|
f:=FALSE
|
|
WHILE p[]++<>10 DO NOP
|
|
ELSE
|
|
id[num]:=p-1
|
|
WHILE ((c:=p[]++)>" ") AND (c<>",") AND (c<>";") DO NOP
|
|
p--; zero:=p
|
|
IF num++=IDMAX THEN error(ER_WORK)
|
|
ENDIF
|
|
ENDWHILE
|
|
IF num
|
|
size:=-1
|
|
IF StrCmp(id[1],'MACRO',ALL)
|
|
macro:=TRUE
|
|
ELSEIF StrCmp(id[1],'EQU',ALL) OR StrCmp(id[1],'=',ALL) OR StrCmp(id[1],'equ',ALL)
|
|
IF macro=FALSE
|
|
d.type:=T_CONST
|
|
d.name++:=id[0]
|
|
defn++
|
|
ENDIF
|
|
ELSEIF StrCmp(id[0],'STRUCTURE',ALL)
|
|
struct:=TRUE
|
|
d.type:=T_STRUCT
|
|
d.name++:=id[1]
|
|
defn++
|
|
IF (InStr(id[2],'SIZEOF',0)<>-1) OR (InStr(id[2],'SIZE',0)<>-1)
|
|
IF defn>=MAX_DEF THEN error(ER_WORK)
|
|
d.type:=T_ARRAY
|
|
c:=InStr(id[2],'_',0)
|
|
IF c<>-1 THEN PutChar(id[2]+c,0)
|
|
d.name++:=id[2]
|
|
defn++
|
|
ELSEIF (Val(id[2],{c})<>0) OR (c=0)
|
|
WriteF('WARNING: object "\s" does not start at offset 0\n',id[1])
|
|
ENDIF
|
|
ELSEIF StrCmp(id[0],'LABEL',ALL)
|
|
IF struct=FALSE THEN error(ER_FORM)
|
|
IF (InStr(id[1],'SIZEOF',0)<>-1) OR (InStr(id[1],'SIZE',0)<>-1)
|
|
struct:=FALSE
|
|
d.type:=T_END
|
|
d.name++:=id[1]
|
|
defn++
|
|
ENDIF
|
|
ELSEIF StrCmp(id[0],'BYTE',ALL); size:=1
|
|
ELSEIF StrCmp(id[0],'UBYTE',ALL); size:=1
|
|
ELSEIF StrCmp(id[0],'WORD',ALL); size:=2
|
|
ELSEIF StrCmp(id[0],'UWORD',ALL); size:=2
|
|
ELSEIF StrCmp(id[0],'SHORT',ALL); size:=2
|
|
ELSEIF StrCmp(id[0],'USHORT',ALL); size:=2
|
|
ELSEIF StrCmp(id[0],'LONG',ALL); size:=4
|
|
ELSEIF StrCmp(id[0],'ULONG',ALL); size:=4
|
|
ELSEIF StrCmp(id[0],'APTR',ALL); size:=4
|
|
ELSEIF StrCmp(id[0],'BPTR',ALL); size:=4
|
|
ELSEIF StrCmp(id[0],'CPTR',ALL); size:=4
|
|
ELSEIF StrCmp(id[0],'BSTR',ALL); size:=4
|
|
ELSEIF StrCmp(id[0],'BOOL',ALL); size:=2
|
|
ELSEIF StrCmp(id[0],'FPTR',ALL); size:=4
|
|
ELSEIF StrCmp(id[0],'STRUCT',ALL); size:=0
|
|
ELSEIF StrCmp(id[1],'MACRO',ALL)
|
|
macro:=TRUE
|
|
ELSEIF StrCmp(id[0],'ENDM',ALL)
|
|
macro:=FALSE
|
|
ELSEIF StrCmp(id[0],'BITDEF',ALL) /* depends on correctness */
|
|
c:=id[1]-1
|
|
FOR a:=1 TO id[2]-id[1]-1 DO c[]++:=c[1]
|
|
c[]++:="F"; c[]++:="_"
|
|
d.type:=T_CONST
|
|
d.name++:=id[1]-1
|
|
defn++
|
|
ELSEIF StrCmp(id[0],'EITEM',ALL)
|
|
d.type:=T_CONST
|
|
d.name++:=id[1]
|
|
defn++
|
|
ELSEIF StrCmp(id[0],'DEVCMD',ALL)
|
|
d.type:=T_CONST
|
|
d.name++:=id[1]
|
|
defn++
|
|
ELSEIF StrCmp(id[1],'SET',ALL) OR StrCmp(id[0],'IFND',ALL) OR StrCmp(id[0],'ENDC',ALL) OR StrCmp(id[0],'INCLUDE',ALL) OR StrCmp(id[0],'ENUM',ALL) OR StrCmp(id[0],'LIBENT',ALL) OR StrCmp(id[0],'LIBINIT',ALL) OR StrCmp(id[0],'LIBDEF',ALL) OR StrCmp(id[0],'DEVINIT',ALL) OR StrCmp(id[0],'FUNCDEF',ALL) OR StrCmp(id[0],'include',ALL) OR StrCmp(id[0],'IFD',ALL)
|
|
ELSE
|
|
IF macro=FALSE THEN error(ER_FORM)
|
|
ENDIF
|
|
IF size<>-1
|
|
IF (InStr(id[1],'Kludge',0)<>-1) /* ask for deletion */
|
|
WriteF('Skip member "\s" (y/n)? >',id[1])
|
|
Read(stdout,work,2)
|
|
c:=work[0]
|
|
ELSE
|
|
c:=0
|
|
ENDIF
|
|
IF (c<>"y") AND (macro=FALSE)
|
|
IF struct=FALSE THEN error(ER_FORM)
|
|
IF size=1 THEN d.type:=T_CHAR ELSE IF size=2 THEN d.type:=T_INT ELSE IF size=4 THEN d.type:=T_LONG ELSE d.type:=T_ARRAY
|
|
d.name++:=id[1]
|
|
defn++
|
|
ENDIF
|
|
ENDIF
|
|
IF defn>=MAX_DEF THEN error(ER_WORK)
|
|
ENDIF
|
|
IF CtrlC() THEN error(ER_BREAK)
|
|
IF (line AND $F)=0 THEN WriteF('line=\d\b',line)
|
|
INC line
|
|
ENDWHILE
|
|
line:=0
|
|
ENDPROC
|
|
|
|
PROC makeasmfile()
|
|
DEF a,oldout,d:PTR TO def
|
|
IF (handle:=Open('ram:iconvert.s',NEWFILE))=NIL THEN error(ER_TEMPW)
|
|
IF defn=0 THEN error(ER_FORM)
|
|
d:=defs
|
|
oldout:=SetStdOut(handle)
|
|
IF phx THEN WriteF(' TTL ""\n')
|
|
WriteF(' INCLUDE "\s"\n\n',infile)
|
|
FOR a:=1 TO defn
|
|
WriteF(' DC.L \s\n',d.name++)
|
|
ENDFOR
|
|
WriteF('\n END\n')
|
|
SetStdOut(oldout)
|
|
Close(handle); handle:=NIL
|
|
ENDPROC
|
|
|
|
PROC invokea68k()
|
|
IF phx
|
|
IF Execute('SmallPhxAss I INCLUDES: FROM ram:iconvert.s noexe opt 0',NIL,stdout)=FALSE THEN error(ER_INVOKE)
|
|
ELSE
|
|
IF Execute('A68k -iINCLUDES: ram:iconvert.s',NIL,stdout)=FALSE THEN error(ER_INVOKE)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC readbinary()
|
|
DEF bsize
|
|
bsize:=defn*4+32
|
|
IF FileLength('ram:iconvert.o')<>bsize THEN error(ER_TEMPR)
|
|
bbuf:=New(bsize)
|
|
IF bbuf=NIL THEN error(ER_MEM)
|
|
IF (handle:=Open('ram:iconvert.o',OLDFILE))=NIL THEN error(ER_TEMPR)
|
|
IF Read(handle,bbuf,bsize)<>bsize THEN error(ER_TEMPR)
|
|
Close(handle); handle:=NIL
|
|
ENDPROC
|
|
|
|
PROC makemodule()
|
|
DEF v:PTR TO LONG,work[3]:ARRAY OF INT,d:PTR TO def,l,x,obj=NIL
|
|
v:=bbuf+28; d:=defs
|
|
IF (handle:=Open(outfile,NEWFILE))=NIL THEN error(ER_OUT)
|
|
Write(handle,'EMOD',4)
|
|
FOR a:=1 TO defn
|
|
IF d.type=T_CONST
|
|
IF mode=2 THEN endobj(obj)
|
|
IF mode=0 THEN Write(handle,[1]:INT,2)
|
|
l:=StrLen(d.name)+1
|
|
work[0]:=IF Odd(l) THEN l+1 ELSE l
|
|
PutLong(work+2,v[]++)
|
|
Write(handle,work,6)
|
|
UpperStr(d.name)
|
|
Write(handle,d.name++,l)
|
|
IF Odd(l) THEN Write(handle,'',1)
|
|
mode:=1
|
|
ELSEIF d.type=T_END
|
|
IF mode<>2 THEN error(ER_OFORM)
|
|
mode:=0
|
|
Write(handle,[0,v[]++]:INT,4)
|
|
d++
|
|
ELSE
|
|
IF (mode=2) AND (d.type=T_STRUCT) THEN endobj(obj)
|
|
IF mode=1 THEN Write(handle,[0]:INT,2)
|
|
IF mode<>2
|
|
Write(handle,[2]:INT,2)
|
|
IF d.type<>T_STRUCT THEN error(ER_OFORM)
|
|
obj:=d.name
|
|
ENDIF
|
|
work[1]:=IF d.type=T_STRUCT THEN -1 ELSE d.type
|
|
work[2]:=v[]++
|
|
x:=InStr(d.name,'_',0)
|
|
IF x<>-1 THEN d.name:=d.name+x+1
|
|
LowerStr(d.name)
|
|
l:=StrLen(d.name)+1
|
|
work[0]:=IF Odd(l) THEN l+1 ELSE l
|
|
Write(handle,work,6)
|
|
Write(handle,d.name++,l)
|
|
IF Odd(l) THEN Write(handle,'',1)
|
|
mode:=2
|
|
ENDIF
|
|
ENDFOR
|
|
IF mode=2 THEN endobj(obj)
|
|
IF mode=1 THEN Write(handle,[0]:INT,2)
|
|
Close(handle); handle:=NIL
|
|
ENDPROC
|
|
|
|
PROC endobj(obj)
|
|
Write(handle,[0,-1]:INT,4)
|
|
WriteF('WARNING: object "\s" has no SIZE\n',obj)
|
|
mode:=0
|
|
ENDPROC
|
|
|
|
PROC error(er)
|
|
IF handle THEN Close(handle)
|
|
SELECT er
|
|
CASE ER_NONE; WriteF('Done.\n')
|
|
CASE ER_IN; WriteF('Could not read "\s"\n',infile)
|
|
CASE ER_OUT; WriteF('Could not write "\s"\n',outfile)
|
|
CASE ER_MEM; WriteF('Could not allocate memory\n')
|
|
CASE ER_WORK; WriteF('Work buffer overflow\n')
|
|
CASE ER_BREAK; WriteF('User terminated convertion\n')
|
|
CASE ER_FORM; WriteF('.i file format error\n')
|
|
CASE ER_TEMPW; WriteF('Trouble creating temporarily file\n')
|
|
CASE ER_TEMPR; WriteF('Trouble reading temporarily file\n')
|
|
CASE ER_INVOKE; WriteF('Could not invoke A68k\n')
|
|
CASE ER_OFORM; WriteF('Error in object order line \d in "ram:iconvert.s"\n',a+1)
|
|
CASE ER_I; WriteF('Not a ".i" file: "\s"\n',infile)
|
|
ENDSELECT
|
|
IF line THEN WriteF('At line \d in file "\s"\n',line,infile)
|
|
IF er>0 THEN DeleteFile(outfile)
|
|
CleanUp(0)
|
|
ENDPROC
|