ReadC is an attempt to convert some C++ code written for the allegro game engine into python code. It will also take a fair bash at Java and is, in theory, extensible for library function conversion.
Get the script for version 0.1 here plus the optional function dictionary py.dic.
readC managed to convert:
void main() {
printf("Hello");
printf("Size = %d\n",big);
printf("String = %s is long %d",name,strlen(name));
fprintf(stdout,"File print %d",size);
dummy(france,ostrucg);
strcpy(e1,e2);
strcat(e1,e2);
strncpy(e1,e2,30);
stricpy(e1,e2);
do_waht(e1 != e2);
e1 = !e2;
if(e1 && !(e2))
memcpy(e1,e2,34);
}
to
#!/usr/bin/env python
# Converted from print.c using readC by robert parker 2008
def main():
print "Hello"
print "Size = %d\n" %(big,),
print "String = %s is long %d" %(name,),
print >> stdout,"File print %d" %(size,),
dummy(france,ostrucg)
e1 = e2
e1 += e2
e1 = e2 [: 30 ]
e1 = e2 .lcase()
do_waht(e1!=e2)
e1= not e2
if e1& not(e2):
e1 = e2 [: 34 ]
if __name__ == '__main__': main()
The python call for this would have been:python readC test.c -o test,py -d py.dic. If you forget use python readC -h for help.
The -d py.dic option is required only to give a better conversion of common C library functions like printf() and strcpy(). If you examine py.dic you will see it is fairly sparse at present.
readC also managed to convert code with that has include headers:
#include "dummy.h"
#include "test.h"
#define CONSTANT 3
#define TRUE 1
int var1 = { 2 ,3 ,4};
unsigned int bitfield :1;
int var2;
int var3 = 4;
int fuzz = 3;
int *pntr = NULL;
char* pntr2 = pntr;
char LoadedFile[80];
char* ss[] = {"1","2","3"};
/* A test
of what
a multi line might do */
int main(int argc, char* argv[]) {
# int gotolimit = (metadata[0]<<8) + metadata[1];
Sequencer->TimeDen = 1< 20;j-=5)
fuzz--;
default:
fuzz = 0;
}
}
}
if(c == 5) // a single comment
d = 3;
else d = k;
}
which includes header test.h:
#ifndef testh #define testh extern int fuzz; #endif
and a dummy header which does not exist, into:
#!/usr/bin/env python
# Converted from test.c using readC by robert parker 2008
from dummy import *
# Converted from include file:test.h
# End of conversion of include file:test.h
CONSTANT = 3
TRUE = 1
var1=(2,3,4)
var2 = 0
var3=4
fuzz=3
pntr=None
pntr2=pntr
LoadedFile
ss=("1","2","3")
''' A test of what
a multi line might do '''
def main():
Sequencer.TimeDen=1< < metadata[1]
bitfield=TRUE
d=(d *e ^ 3)
a=(float(b ))
c=(unsigned int(d )) *3
for i in range(0,argc,-1):
if argv[i][0]==' - ':
if argv[i][1] == 'o':
if argv[i][2] == 'i':
x=3
elif argv[i][1] == 'x':
for j in range(5,20,-5.0):
fuzz -= 1
else:
fuzz=0
if c==5:
# a single comment
d=3
else:
d=k
global TimeDen, bitfield, d, a, c, x, j, fuzz,
if __name__ == '__main__': main()
Notice how the global defines are at the end of the function instead of the start - I've left it to the programmer to move them since everything needs to be double and triple checked anyhow.
readC even managed to convert some almost real code:
int Load_Midi(char* fid)
{ if(Sequencer)
delete Sequencer;
if(TrackStatus)
{ delete TrackStatus;
TrackStatus = NULL;
}
printf("Loading midi file:%s\n",fid);
Sequencer_Feedback = FeedBack;
Sequencer = new SequencerClass(fid,"",NO,2,NO);
if(!Sequencer)
return(2);
if(!Sequencer->Tracks)
return(3);
strcpy(LoadedFile,fid,strlen(fid)-4); // strip out name of file
Sequencer->Reset();
FocusTrack = 0;
TrackStatus = new unsigned[Sequencer->Tracks];
if(TrackStatus)
{ for(int t = 0 ; t < Sequencer->Tracks; t++)
TrackStatus[t] = 0;
}
return(0);
}
int main() {
some_func(3,TRUE);
switch(k)
{ case F1:
Display(2,TRUE);
Display(0);
break;
}
if((dpos >0) && (dpos < (16*Sequencer->BeatTicks))) next_time =
current_time + dpos*SEC/Sequencer->BeatTicks/8; }
to
#!/usr/bin/env python
# Converted from test3.c using readC by robert parker 2008
def Load_Midi(fid):
if Sequencer:
pass
if TrackStatus:
pass
TrackStatus=None
print "Loading midi file:%s\n" %(fid,),
Sequencer_Feedback=FeedBack
Sequencer=SequencerClass(fid,"",NO,2,NO)
if not Sequencer:
return 2)
if not Sequencer.Tracks:
return 3)
strcpy((LoadedFile,fid,len(string)-4)
# strip out name of file
Sequencer.Reset()
FocusTrack=0
TrackStatus=new unsigned[Sequencer.Tracks]
if TrackStatus:
for t in range(0,t < Sequencer.Tracks):
TrackStatus[t]=0
return 0)
global TrackStatus, Sequencer_Feedback, Sequencer, FocusTrack,
def main():
some_func(3,TRUE)
if k == F1:
Display(2,TRUE)
Display(0)
if (dpos >0) and (dpos <(16 * Sequencer.BeatTicks)):
next_time=current_time + dpos * SEC / Sequencer.BeatTicks / 8
global next_time,
if __name__ == '__main__': main()
These tests were all very fine but when I tried to use it with a real application the daunting task of comparing every C line with the produced python code proved impossible.
What is needed is a way of showing the converted results side by side - though I'm still not sure if this will make conversion practical for big applications.
A few more gritty level:
One of the problems with C is that you can so easily get the curly brackets unbalanced and then it can take forever to find the error. If indenting is used, as is required by Python, then readCindent.py will check for indent imbalance.
In case you didn't notice them, please heed the warnings on the microde page.
Copyright Robert Parker November 2009