Commit code, circa 2010

This commit is contained in:
2026-05-18 12:31:43 -04:00
commit e58e308366
5 changed files with 1163 additions and 0 deletions

80
cblnum.c Executable file
View File

@@ -0,0 +1,80 @@
/* cblnum - automated COBOL line numberer
* (C) 2005 Andrew Kesterson andrew@aklabs.net
* Possible room for improvement here: use getopt() or
* similar to allow the user to specify the step in the
* line numbering. */
#include <stdio.h>
#define LINESIZE 4096
int getline(FILE *fp, char *buff)
{
if ( fp != NULL && buff != NULL ) {
int i = 0;
int ws = 0;
char c = 0x00;
c = fgetc(fp);
while ( !feof(fp) ) {
if ( (c == ' ' || c == '\t') && i == 0 && ws <= 8) {
/* skip leading whitespace for editors
* that autoindent like slickedit for
* cobol -- but don't strip >8 */
ws++;
c = fgetc(fp);
continue;
}
else if ( c != '\n' && i < LINESIZE ) {
buff[i] = c;
}
else if ( i >= LINESIZE ) {
fprintf(stderr, "buff was too small for line from file.\n");
return -1;
}
else break;
i++;
c = fgetc(fp);
}
return i;
}
else return -1;
}
int main(int argc, char **argv)
{
if ( argc < 2 ) {
printf("(C)Andrew Kesterson andrew@aklabs.net 2005\n");
printf("\tcblnum (input file) \n\toutputs to stdout\n");
return 0;
}
char *buffer = (char *)malloc(LINESIZE); // should be big enough for most..
if ( !buffer ) {
fprintf(stderr, "cblnum: Out of memory.\n");
return -1;
}
FILE *fp = fopen(argv[1], "r");
if ( !fp ) {
fprintf(stderr, "cblnum: Couldn't open file for reading.\n");
return -1;
}
int line = 100;
while (!feof(fp)) {
if ( getline(fp, buffer) > 1 ) {
// the >1 is an ugly hack to account for junk coming
// up at EOF, but I don't think any cobol statements
// could be just 1 char long.....
printf("%06d %s\n", line, buffer);
line += 100;
memset(buffer, 0x00, LINESIZE);
}
}
fclose(fp);
return 0;
}

739
pcfconv.py Executable file
View File

@@ -0,0 +1,739 @@
#!/usr/bin/python
# pcfconf.py : A utility to convert mathetmatical formulas
# from one language to another. it currently only supports
# Microsoft PowerToy Calculator save files for reading,
# and Python for writing. But it can be easily extended
# to handle other file formats; see SOURCE DOC below
# for details.
# TODO: Set default data type (short, int, long, double, float)
# it currently defaults to int or float, depending on
# what's in the file
# Implement some sanity checking on function arguments, to
# make sure only arguments present in the arg list or the
# parent object's body, are referenced. Currently, there
# are no such checks.
################# SOURCE DOC ##############################################
############## (read here if you want to extend this program) #############
# The actual conversion is done by XXXXConverter classes that
# do the actual conversion. They are passed a generic list of the following
# form:
#
# [ [TYPE, NAME, VALUE] ]
#
# where TYPE is either "VAR" or "FUNC". If TYPE is "VAR", then the rest of
# the values are obvious (the name and value of the variable). If TYPE is
# "FUNC", then VALUE is actually another list of the form:
#
# [ARGS, CODE]
#
# where ARGS is yet another list containing the names of the function's arguments,
# and CODE is the original PowerToyCalc code for the function.
#
# To extend this program with a new filetype, scan down to the "PROCESSOR CLASSES"
# comment. At this point there is no programmatic reason to inherit your classes
# from GenericProcessor, but GenericProcessor is to be considered the base class
# for all new file processors; if GenericProcessor has a method, your class
# must have it as well. Use the PythonProcessor class as a guide to how the existing
# code works, if you need to. But as long as the converter winds up printing usable
# code to the output file, and errors to sys.__stderr__ (via the *err functions), then
# you're doing it right. Once you've done that, add it to the "PROCESSORS" dictionary
# in the global variables section. The format of the dictionary is obvious.
#
# To extend this program with a new target language, scan down to the "GENERATOR
# CLASSES" comment. The general process for processor classes applies here; if it's
# in the base class, it needs to be in your new subclass. Use the PythonConverter
# class as a guide to how to write your own converter, if necessary. The converter just
# needs to return usable output to the processor class, which prints it to whatever
# output file has been specified. Once you've done that, add it to the "CONVERTERS"
# dictionary in the global variables section. The format of the dictionary is obvious.
#
# Got it? easy.
import sys
import getopt
import math
# Functions that will be used throughout the module.
def syntaxerr (linenum, line, err):
sys.__stderr__.write("%d : %s : %s\n" % (linenum, err, line))
def generalerr (err):
sys.__stderr__.write("%s\n" % err)
def debugmsg (err):
global DEBUG
if ( DEBUG ) :
sys.__stderr__.write("DEBUG: %s\n" % err)
def cloneList (list1):
list2 = []
for item in list1:
list2.append(item)
return list2
################## CONVERTER CLASSES #######################
class GenericConverter:
def __init__ (self, langopts, contextName=""):
"""contextname is the name of the class, context, or namespace that should be
generated for the incoming data. langopts is a dictionary containing
the language specific options that the processor should follow."""
return
def convertFile (self, data):
"""data is the data to interpret to your native language"""
generalerr("convertFile is not implemented in GenericConverter")
return 1
def convertCalls (self, code):
"""For the given block of code, translate any calls to things like atan() and
acos() to functions that exist in your language's internal math library."""
global MATHSYMS
ourlist = cloneList(MATHSYMS)
ourlist.append(",")
ourlist.append(" ")
ourlist.append("\t")
# we do our best here to ensure we don't change someone's defined function that
# happens to have the name of one of ours inside of it. For example, if someone
# makes a function MYacos(), then a replace on "acos" with "math.acos" would result
# in the code being MYmath.acos(), which is guaranteed to do nothing but explode.
# So we try to make sure that we're only replacing exact matches, by checking that
# it follows any of the items in MATHSYMS, a comma(,), " ", or \t. The downside
# to this is that it winds up being pretty slow.
for call in self.__subs__.keys():
for symbol in ourlist :
toreplace = "%s%s" % (symbol, call)
replacer = "%s%s" % (symbol, self.__subs__[call])
if ( toreplace in code ):
debugmsg("Replacing %s with %s in code line %s" % (toreplace, replacer, code))
code = code.replace(toreplace, replacer)
return code
def supportedTranslations (self):
"""return a string that lists all of the translations your language's
converter supports"""
generalerr("supportedTranslations is not implemetned in GenericConverter")
class CPPConverter:
class CPPVariable:
def __init__ (self, name, initValue, baseType, namespace):
self.__name__ = name
self.__value__ = initValue
self.__vartype__ = baseType
self.__namespace__ = namespace
def __str__ (self, defonly = False):
retStr = ""
if ( isinstance(self.__value__, list) or isinstance(self.__value__, tuple) ):
if ( defonly ):
return "%s %s[%d];" % (self.__vartype__, self.__name__, len(self.__value__))
# if we're not doing definitions, then assignments only occur in the constructor
for i in range(0, len(self.__value__)-1):
retStr += "\tthis->%s[%d] = %s;\n" % (self.__name__, i, self.__value__[i])
else:
if ( defonly ):
return "%s %s;" % (self.__vartype__, self.__name__)
retStr = "\tthis->%s = %s;" % (self.__name__, self.__value__)
return retStr
class CPPFunction:
def __init__ (self, namespace, argtype, rettype, name, arguments, code):
self.__rettype__ = rettype
self.__argtype__ = argtype
self.__name__ = name
self.__namespace__ = namespace
self.__args__ = arguments
self.__code__ = code
def replaceVars (self, varlist):
"""Find any instance of a variable in our code that is not in our argument list,
and is a member variable of our parent class"""
codeCopy = self.__code__
ourlist = cloneList(MATHSYMS)
ourlist.append(",")
ourlist.append(" ")
for var in varlist :
if ( var.__name__ in self.__args__ ):
continue
for symbol in ourlist:
toreplace = "%s%s" % (symbol, var.__name__)
replacer = "this->%s" % (var.__name__)
debugmsg("Searching for \" %s\" in code block %s" % (toreplace, codeCopy))
if ( toreplace in codeCopy ):
debugmsg("Replacing \"%s\" with \"%s\" in %s" % (toreplace, replacer, codeCopy))
codeCopy = codeCopy.replace(toreplace, replacer)
self.__code__ = codeCopy
def __str__ (self, defonly=False):
if ( defonly ):
str = "%s %s (" % (self.__rettype__, self.__name__)
else:
str = "%s %s::%s (" % (self.__rettype__, self.__namespace__, self.__name__)
argcnt = 0
for item in self.__args__:
if ( argcnt > 0 ):
str += ", "
str += "%s %s" % (self.__argtype__, item)
argcnt += 1
str += ")"
if ( defonly ):
return str+";"
str += "\n{\n\treturn (%s);\n}\n" % (self.__code__)
return str
class CPPClass:
def __init__ (self, namespace, variables, functions, langopts):
self.__namespace__ = namespace
self.__vars__ = variables
self.__funcs__ = functions
self.__langopts__ = langopts
def toASCII (self):
hdrstr = ""
impstr = ""
# generate definition
hdrstr = "#ifndef __%s__\n" % self.__namespace__
hdrstr += "#define __%s__\n" % self.__namespace__
hdrstr += "#include <math.h>\n\n"
hdrstr += "class %s {\n" % self.__namespace__
hdrstr += "public:\n"
hdrstr += "\t%s::%s(void);\n" % (self.__namespace__, self.__namespace__)
for func in self.__funcs__:
hdrstr += "\t%s\n" % func.__str__(True)
hdrstr += "protected:\n"
for var in self.__vars__ :
hdrstr += "\t%s\n" % (var.__str__(True))
hdrstr += "}\n"
hdrstr += "#endif /* __%s__ */\n" % self.__namespace__
# generate implementation
if ( self.__langopts__["writefiles"].lower() == "true" ):
impstr = "#include \"%s.h\"\n\n" % self.__namespace__
impstr += "\n"
# generate the constructor
impstr += "void %s::%s(void)\n{\n" % (self.__namespace__, self.__namespace__)
# assignments happen in the constructor, not the class def
for var in self.__vars__ :
impstr += "%s\n" % str(var)
impstr += "}\n"
for func in self.__funcs__:
impstr += "%s\n" % str(func)
if ( self.__langopts__["writefiles"].lower() == "true" ):
# write the definition to the header file
ofile = open(("%s.h" % self.__namespace__), "w")
ofile.write(hdrstr)
ofile.close()
# write the implementation to the C file
ofile = open(("%s.c" % self.__namespace__), "w")
ofile.write(impstr)
ofile.close()
return ""
return hdrstr+"\n"+impstr
def __init__ (self, langopts, namespace="PTC"):
self.__namespace__ = namespace
self.__langopts__ = { "deftype" : "double",
"defrettype" : "double",
"writefiles" : "false" }
self.__funclist__ = []
self.__varlist__ = []
self.__subs__ = {}
for key in langopts.keys():
self.__langopts__[key] = langopts[key]
return
def convertFile (self, data):
for item in data:
debugmsg("Processing item %s" % (item))
if ( item[0] == "VAR" ):
self.__varlist__.append( CPPConverter.CPPVariable(item[1],
item[2], self.__langopts__["deftype"], self.__namespace__ ))
else:
self.__funclist__.append( CPPConverter.CPPFunction(self.__namespace__,
self.__langopts__["deftype"], self.__langopts__["defrettype"],
item[1], item[2][0], item[2][1]))
for func in self.__funclist__ :
func.replaceVars(self.__varlist__)
defclass = CPPConverter.CPPClass(self.__namespace__, self.__varlist__, self.__funclist__, self.__langopts__)
return defclass.toASCII()
def supportedTranslations (self):
return "The entire C++ math.h library is supported. You are almost guaranteed 100% conversion."
class CConverter:
class CVariable:
def __init__ (self, name, initValue, baseType, namespace):
self.__name__ = name
self.__value__ = initValue
self.__vartype__ = baseType
self.__namespace__ = namespace
def __str__ (self, defonly = False):
retStr = ""
if ( isinstance(self.__value__, list) or isinstance(self.__value__, tuple) ):
if ( defonly ):
return "%s %s_%s[%d];" % (self.__vartype__, self.__namespace__, self.__name__, len(self.__value__))
retStr = "%s %s_%s[%d] = {" % (self.__vartype__, self.__namespace__, self.__name__, len(self.__value__))
for i in self.__value__:
retStr += "%s, " % i
retStr += "};"
else:
if ( defonly ):
return "%s %s_%s;" % (self.__vartype__, self.__namespace__, self.__name__)
retStr = "%s %s_%s = %s;" % (self.__vartype__, self.__namespace__, self.__name__, self.__value__)
return retStr
class CFunction:
def __init__ (self, namespace, argtype, rettype, name, arguments, code):
self.__rettype__ = rettype
self.__argtype__ = argtype
self.__name__ = name
self.__namespace__ = namespace
self.__args__ = arguments
self.__code__ = code
def replaceVars (self, varlist):
"""Find any instance of a variable in our code that is not in our argument list,
and is a member variable of our parent class"""
codeCopy = self.__code__
ourlist = cloneList(MATHSYMS)
ourlist.append(",")
ourlist.append(" ")
for var in varlist :
if ( var.__name__ in self.__args__ ):
continue
for symbol in ourlist:
toreplace = "%s%s" % (symbol, var.__name__)
replacer = "%s_%s" % (self.__namespace__, var.__name__)
debugmsg("Searching for \" %s\" in code block %s" % (toreplace, codeCopy))
if ( toreplace in codeCopy ):
debugmsg("Replacing \"%s\" with \"%s\" in %s" % (toreplace, replacer, codeCopy))
codeCopy = codeCopy.replace(toreplace, replacer)
self.__code__ = codeCopy
def __str__ (self, defonly=False):
str = "%s %s_%s (" % (self.__rettype__, self.__namespace__, self.__name__)
argcnt = 0
for item in self.__args__:
if ( argcnt > 0 ):
str += ", "
str += "%s %s" % (self.__argtype__, item)
argcnt += 1
str += ")"
if ( defonly ):
return str+";"
str += "\n{\n\treturn (%s);\n}\n" % (self.__code__)
return str
class CInclude:
def __init__ (self, namespace, variables, functions):
self.__namespace__ = namespace
self.__vars__ = variables
self.__funcs__ = functions
def toASCII (self, writefiles):
hdrstr = ""
impstr = ""
# generate definition
hdrstr = "#ifndef __%s__\n" % self.__namespace__
hdrstr += "#define __%s__\n" % self.__namespace__
hdrstr += "#include <math.h>\n\n"
for var in self.__vars__ :
hdrstr += "extern %s\n" % (var.__str__(True))
hdrstr += "\n"
for func in self.__funcs__:
hdrstr += "extern %s\n" % func.__str__(True)
hdrstr += "#endif /* __%s__ */" % self.__namespace__
# generate implementation
if ( writefiles.lower() == "true" ):
impstr = "#include \"%s.h\"\n\n" % self.__namespace__
for var in self.__vars__ :
impstr += "%s\n" % (str(var))
impstr += "\n"
for func in self.__funcs__:
impstr += "%s\n" % str(func)
if ( writefiles.lower() == "true" ):
# write the definition to the header file
ofile = open(("%s.h" % self.__namespace__), "w")
ofile.write(hdrstr)
ofile.close()
# write the implementation to the C file
ofile = open(("%s.c" % self.__namespace__), "w")
ofile.write(impstr)
ofile.close()
return ""
return hdrstr+"\n"+impstr
def __init__ (self, langopts, namespace="PTC"):
self.__namespace__ = namespace
self.__langopts__ = { "deftype" : "double",
"defrettype" : "double",
"writefiles" : "false" }
self.__funclist__ = []
self.__varlist__ = []
# thankfully C doesn't require any substitutions; we just include math.h and
# everything is groovy.
self.__subs__ = {}
for key in langopts.keys():
self.__langopts__[key] = langopts[key]
return
def convertFile (self, data):
# forcibly process all the variables first, then do the functions.
# We do it in this specific order so we can do some variable replacement.
for item in data:
debugmsg("Processing item %s" % (item))
if ( item[0] == "VAR" ):
self.__varlist__.append( CConverter.CVariable(item[1],
item[2], self.__langopts__["deftype"], self.__namespace__ ))
else:
self.__funclist__.append( CConverter.CFunction(self.__namespace__,
self.__langopts__["deftype"], self.__langopts__["defrettype"],
item[1], item[2][0], item[2][1]))
for func in self.__funclist__ :
func.replaceVars(self.__varlist__)
defclass = CConverter.CInclude(self.__namespace__, self.__varlist__, self.__funclist__)
return defclass.toASCII(self.__langopts__["writefiles"])
def supportedTranslations (self):
return "The entire C math.h library is supported. You are almost guaranteed 100% conversion."
class PythonConverter:
# what the class needs to know:
# - the name of the class being generated. All data found in the .pcf file is
# placed into a generated class of the given name. Variables are listed as
# instance variables, and functions are of course generated as member functions.
# - list of functions
# - list of variables
class PythonVariable:
def __init__ (self, name, initValue, baseType):
# note that initValue can be a list when the baseType constructor
# requires more than one argument
self.__name__ = name
self.__value__ = initValue
self.__vartype__ = baseType
def __str__ (self):
retStr = ""
if ( isinstance(self.__value__, list) or isinstance(self.__value__, tuple) ):
retStr = "%s = %s(" % (self.__name__, self.__vartype__)
for i in self.__value__:
retStr += "%s, " % i
retStr += ")"
else:
retStr = "__%s__ = %s(%s)" % (self.__name__, self.__vartype__, self.__value__)
return retStr
class PythonFunction:
def __init__ (self, name, arguments, code):
self.__name__ = name
self.__args__ = arguments
self.__code__ = code
def replaceVars (self, varlist):
"""Find any instance of a variable in our code that is not in our argument list,
and is a member variable of our parent class"""
codeCopy = self.__code__
ourlist = cloneList(MATHSYMS)
ourlist.append(",")
ourlist.append(" ")
for var in varlist :
if ( var.__name__ in self.__args__ ):
continue
for symbol in ourlist:
toreplace = "%s%s" % (symbol, var.__name__)
replacer = "self.__%s__" % (var.__name__)
debugmsg("Searching for \" %s\" in code block %s" % (toreplace, codeCopy))
if ( toreplace in codeCopy ):
debugmsg("Replacing \"%s\" with \"%s\" in %s" % (toreplace, replacer, codeCopy))
codeCopy = codeCopy.replace(toreplace, replacer)
self.__code__ = codeCopy
def __str__ (self):
str = "def %s (self, " % (self.__name__)
argcnt = 0
for item in self.__args__:
if ( argcnt > 0 ):
str += ", "
str += "%s" % (item)
argcnt += 1
str += "): return (%s)" % (self.__code__)
return str
class PythonClass:
def __init__ (self, name, variables, functions):
self.__name__ = name
self.__vars__ = variables
self.__funcs__ = functions
def toASCII (self, tabstop):
# return all elements in a string suitable for printing to stdout
# "tabstop" specifies the tabstop to use. Pass "\t" or "" with a number of
# spaces per tabstop. There will be one additional space per tabstop
# because it makes it easier for me to write that way.
retstr = "import math\n"
retstr += "class %s:\n" % self.__name__
retstr += "%s def __init__(self):\n" % (tabstop)
for var in self.__vars__ :
retstr += "%s self.%s\n" % ((tabstop*2), str(var))
retstr += "%s return\n" % ((tabstop *2))
for func in self.__funcs__:
retstr += "%s %s\n" % (tabstop, str(func))
return retstr
def __init__ (self, langopts, className="PowerToyCapsule"):
self.__className__ = className
self.__langopts__ = langopts
self.__funclist__ = []
self.__varlist__ = []
self.__subs__ = {}
for item in dir(math):
if ( "__" in item ):
continue
self.__subs__[item] = "math.%s" % item
return
def convertFile (self, data):
# forcibly process all the variables first, then do the functions.
# We do it in this specific order so we can do some variable replacement.
for item in data:
debugmsg("Processing item %s" % (item))
if ( item[0] == "VAR" ):
if ( "." in item[2] ):
self.__varlist__.append( PythonConverter.PythonVariable(item[1], item[2], "float") )
else:
self.__varlist__.append( PythonConverter.PythonVariable(item[1], item[2], "int") )
else:
self.__funclist__.append( PythonConverter.PythonFunction(item[1], item[2][0], item[2][1]) )
for func in self.__funclist__ :
func.replaceVars(self.__varlist__)
defclass = PythonConverter.PythonClass(self.__className__, self.__varlist__, self.__funclist__)
return defclass.toASCII(" ")
def supportedTranslations (self):
retstr = ""
for call in self.__subs__.keys():
retstr += "%s " % call
return retstr
############################# PROCESSOR CLASSES ###################
class GenericProcessor:
def __init__ (self, converters):
# "converters" is a dictionary of language types and the corresponding classes that
# convert for that type
self.__converters__ = converters
def convertFile (self, filename, outfile, language, ignoreErrors, recovery, translate, langopts):
debugmsg("convertFile is not implemented in the GenericConverter base class.")
return 1
class MSPowerToyProcessor(GenericProcessor):
def convertFile (self, filename, outfile, language, ignoreErrors, recovery, translate, langopts):
global MATHSYMS
# get the right converter for our language type
convclass = self.__converters__[language]
converter = convclass(langopts)
data = []
if ( filename == "-" ):
ifile = sys.__stdin__
else:
ifile = open(filename, "rb")
if ( not ifile ):
generalerr("Unable to open input file %s, aborting." % filename)
linenum = 1
line = ifile.readline()
while ( line and (len(line) != 0) and line != "\x00"):
debugmsg("Operating on line %d with length %d : %s" % (linenum, len(line), line))
dataTYPE = ""
dataNAME = ""
dataVALUELITERAL = 0
dataVALUELIST = [[], ""]
# if there are parenthesis present on the LEFT side of the =, then the line is a function
# replace the BS nulls that PowerToyCalc puts into these files for some reason
line = line.replace("\x00", "").replace("\r", "").replace("\n", "")
# strip out the parts
parts = line.split("=")
debugmsg("Operating on parts %s" % parts)
# strip out all arithmetic operators and spaces, and drop the bare contents into a
# temporary string
if ( len(parts) > 1 ):
temp = parts[1]
for oper in MATHSYMS:
temp = temp.replace(oper, "")
# this final string will be used to test if any of the data in it is non-constant
# e.g., are there just numbers, or are there alphanumerics in there too?
temp = temp.replace(" ", "")
else:
sys.__stderr__.write("%s : %d : syntax error : no value in variable assignment : %s\n" \
% (filename, linenum, line))
if ( ignoreErrors ):
sys.__stderr__.write("%s : %d : defaulting value to 0 to continue\n" % (filename, linenum))
temp = "0"
else:
if ( ifile != sys.__stdin__ ):
ifile.close()
return 1
# if they are present on the right side of the equals, it's a variable
# If the variable has non-constant values to the right of =, then define that as a
# function with no arguments that returns the contents of the right side of the
# equals
if ( temp.isdigit() ):
# it's a variable, regardless of the presence of (), because it's just digits
dataTYPE = "VAR"
dataNAME = parts[0].replace(" ", "")
dataVALUELITERAL = parts[1].replace(" ", "")
elif ( "(" in parts[0] and ")" in parts[0] ):
# it's a function (though it may have been defined as a variable with non-constant
# values, such as the results of other functions, in PowerToyCalc. We define such
# variables as funtions in the converter because they may have data in them
# that needs to be re-calculated every time they are used, and a function is the
# only way to do that. We're actually beyond PowerToyCalc in that, because
# the user has to manually change a variable in PowerToyCalc to update it, we
# don't.)
dataTYPE = "FUNC"
dataNAME = parts[0].split("(")[0].split(")")[0].replace(" ", "")
dataVALUELIST[0] = parts[0].replace(" ", "").split("(")[1].replace(")", "").split(",")
if ( translate ):
dataVALUELIST[1] = converter.convertCalls(parts[1])
else:
dataVALUELIST[1] = parts[1]
else:
# if it didn't fit into the two top categories, I dunno WTF it is
sys.__stderr__.write("%s : %d : syntax error, no value in variable assignment : %s\n" % (filename, linenum, line))
# unless we're ignoring all errors, stop processing!
if ( ignoreErrors ):
if ( recovery ):
sys.__stderr__.write("%s : %d : defaulting value to 0 to continue\n" % (filename, linenum))
dataTYPE = "VAR"
dataNAME = parts[0].replace(" ", "")
dataVALUELITERAL = "0"
else:
line = ifile.readline()
continue
else:
if ( ifile != sys.__stdin__ ):
ifile.close()
return 1
if ( dataTYPE == "FUNC" ):
newlist=[dataTYPE, dataNAME, dataVALUELIST]
else:
newlist=[dataTYPE, dataNAME, dataVALUELITERAL]
debugmsg("Adding new list : %s" % newlist)
data.append(newlist)
line = ifile.readline()
linenum += 1
# out of the main conversion loop
if ( ifile != sys.__stdin__ ):
ifile.close()
if ( outfile == "-" ):
sys.__stdout__.write(converter.convertFile(data))
else:
try:
ofile = file(outfile, "w")
ofile.write(converter.convertFile(data))
ofile.close()
except IOError, e:
sys.__stderr__.write("Failed to open output file %s : %s" % (outfile, e))
return 1
return 0
################ GLOBALS ########################
DEBUG=False
MATHSYMS=["*", "+", "-", "=", "/", ">>", "<<", "%", "(", ")"]
CONVERTERS = { "python" : PythonConverter,
"C" : CConverter,
"C++" : CPPConverter }
PROCESSORS = { "mspcf" : [MSPowerToyProcessor, "MS Powertoy Calculator variable / function save data"]}
SHORTOPTS = "hf:l:t:o:erTSdO:"
LONGOPTS = ["help", "filename=", "language=", "filetype=",
"outfile=", "ignore-err", "recovery", "translate",
"supp-trans", "debug", "langopts="]
USAGE = \
"""Interpret mathematical formulae from various formats (such as
MS PowerToy Calculator saves) to usable source code for one of
a number of languages.
usage: pcfconv.py (opts)
options:
-h | --help : print this help
-f | --filename : filename to read from. If unspecified,
stdin is read by default.
-o | --outfile : filename to write to. If unspecified,
the text is written to stdout.
-t | --filetype : type of file being processed. If unspecified,
MS Powertoy Calculator is the default.
The interpreter cannot currently accurately
determine filetypes on its own.
-l | --language : language to write out. If unspecified,
python is the default output language.
-e | --ignore-err : ignore syntax errors in the source file
when one is encountered and continue
processing (note that the error will
still be reported to stderr)
-r | --recovery : Attempt to recover from any ignored
errors, in the best way the interpreter
can see fit. This could be dangerous.
Don't blame the interpreter if this
results in a divide by zero, you've
been warned!
-T | --translate : Setting this option will force the interpreter
to attempt to translate calls to math functions,
such as cos, acos, tan and log10, etc, to the
internal math functions of whatever host language
you're converting to. If this is unset - which
is the default - such calls will be left as-is,
and if necessary, you will have to change them
yourself. Note that some functions may not
be interpreted properly by your host language.
-S | --supp-trans : Print out what function translations (handled
by the -T option) are supported by the converter
for your host language
-d | --debug : Print debug output (normally supressed.)
-O | --langopts : A comma separated list of options for the
language processor for your given language,
with each option conforming to option=value. For
a list of options for each language processor,
refer to the complete documentation.
Languages currently supported: \n"""
USAGE += "\t" + (" ".join(CONVERTERS.keys())) + "\n"
USAGE += """Filetypes currently supported:\n"""
for proc in PROCESSORS.keys() :
USAGE += "\t%s : %s\n" % (proc, PROCESSORS[proc][1])
USAGE += """\npcfconv.py by Andrew Kesterson, 2008, released under the AKLabs
License. Go to http://www.aklabs.net/source/license.txt for the
full text of this license. Email the author andrew@aklabs.net for
all questions and bug reports.
"""
######################## MAIN LOGIC #############################
def main (argc, argv):
global DEBUG
infile = "-"
outfile = "-"
language = "python"
filetype = "mspcf"
ignoreErrors = False
recovery = False
translate = False
supp_trans = False
langopts = {}
opts = getopt.getopt(argv, SHORTOPTS, LONGOPTS)
for pair in opts[0]:
if ( pair[0] == "-h" or pair[0] == "--help" ):
sys.__stderr__.write(USAGE)
return 1
elif ( pair[0] == "-d" or pair[0] == "--debug" ):
DEBUG=True
elif ( pair[0] == "-l" or pair[0] == "--language" ):
language = pair[1]
elif ( pair[0] == "-f" or pair[0] == "--filename" ):
infile = pair[1]
elif ( pair[0] == "-o" or pair[0] == "--outfile" ):
outfile = pair[1]
elif ( pair[0] == "-e" or pair[0] == "--ignore-err" ):
ignoreErrors = True
elif ( pair[0] == "-r" or pair[0] == "--recovery" ):
recovery = True
elif ( pair[0] == "-t" or pair[0] == "--filetype" ):
filetype = pair[1]
elif ( pair[0] == "-T" or pair[0] == "--translate" ):
translate = True
elif ( pair[0] == "-S" or pair[0] == "--supp-trans" ):
supp_trans = True
elif ( pair[0] == "-O" or pair[0] == "--langopts" ):
splitopts = pair[1].split("=")
for i in range(0, len(splitopts)-1, 2):
#print "Assigning language option %s = %s" % (splitopts[i], splitopts[i+1])
langopts[splitopts[i]] = splitopts[i+1]
procclass = PROCESSORS[filetype][0]
proc = procclass(CONVERTERS)
if ( supp_trans ):
convclass = CONVERTERS[language]
conv = convclass(langopts)
print conv.supportedTranslations()
return 0
return proc.convertFile(infile, outfile, language, ignoreErrors, recovery, translate, langopts)
if ( __name__ == "__main__" ):
sys.exit(main(len(sys.argv[1:])-1, sys.argv[1:]))

290
pycc Executable file
View File

@@ -0,0 +1,290 @@
#!/usr/bin/python
# python script that compiles files and directories to python bytecode,
# possibly with optimizations
# TODO:
# Distinguish between files and directories
# Accept the optimization flag
# Enforce command option rules
import py_compile
import compileall
import sys
import os
import re
import getopt
import traceback
usage = r"""
pycc : Python byteCode Compiler (pronounced "pie-sees")
(C) Andrew Kesterson 2006, <andrew@aklabs.net>
usage: pycc <options> src_files ...
options:
-L dir : Add the following directory to the sys.path; similar to
the -L directive in gcc
-l lib : Specifically import the given module before compiling
any modules (successive -l directives are processed in
the order received); similar to -l directive in gcc. The
argument should be in standard python 'import' notation.
"from xxx import y' should be enclosed in quotes. Otherwise
provide 'xxx' alone for the module name to import
-O : Enable the python compiler's optimizations; default output
will have a .pyo extension instead of a .pyc. NOTE: FOR
SOME REASON, this option doesn't work on single files.
Only directories. This is a limitation of the python
compiler libraries, not this program.
-o : When compiling a single file, specify the output filename.
When compiling a directory or multiple files, this directive
has no effect.
-r : Recurse beyond the first level of directories given on the
command line, so that for example passing src/dir on the
command line would compile src/dir/src1.py and also
src/dir/subdir/src2.py.
src_files This is a list of single files and directories. Directories
are not recursed into (beyond the first level) unless the
-r option is specified.
-E : Stop compilation of all source files when one source file
has an error (otherwise, an error message is printed to
stderr and compilation continues to the next file). Error
messages are printed regardless of this flag.
-d n : Tells the compiler to descend up to (at maximum) n levels of
directories when running recursively
-F : Force the generation of code, even when the .pyc/.pyo
timestamps are up to date
-v : Be verbose (errors are always printed regardless)
-h : display this help
"""
shortopts = "L:l:Oo:rd:EvhF"
class ArgChecker:
def printErr(self, msg):
if ( not msg.endswith("\n") ):
msg += "\n"
sys.__stdout__.write(msg)
def importPaths (self, importStr):
fromRE = re.compile(r"""^from\s+([\w.]+)\s+import\s+(\w+).*$""")
importRE = re.compile(r"""^import\s+([.\w]+).*$""")
fromparts = fromRE.findall(importStr)
importparts = importRE.findall(importStr)
try:
if ( (len(fromparts) != 1 or len(fromparts[0]) != 2 ) and len(importparts) == 0):
self.printErr("Bad option: -l %s : invalid syntax : not enough arguments!" % (importStr))
self.printErr("%s : %s" % (fromparts, importparts))
return False
elif ( len(fromparts) == 1 and len(fromparts[0]) == 2 ):
__import__(fromparts[0][1], globals(), None, fromparts[0][0].split("."))
return True
elif ( len(importparts) == 1):
__import__(importparts[0][0], globals(), None, None)
return True
return False
except Exception, e:
self.printErr("Import error:%s: %s" % (importStr, str(e)))
return False
def checkArgs (self, argc, argv):
global shortopts
global usage
compiler = PYCompiler()
opts, args = getopt.getopt(argv, shortopts)
# self.printErr("%s : %s" % (opts, args))
errors = False
if ( len(args) == 0 ):
self.printErr(usage)
return None
for file in args:
if ( os.path.exists(file) ):
if ( os.path.isfile(file) ):
compiler.queueFile(file)
elif ( os.path.isdir(file) ):
compiler.queueDir(file)
else:
self.printErr("Bad Option: Unable to determine type of file %s" % file)
errors = True
else:
self.printErr("Bad Option: File or directory does not exist %s" % file)
errors = True
for opt in opts:
if ( opt[0] == "-L" ):
# add library path
if ( os.path.exists(opt[1]) and os.path.isdir(opt[1]) ):
sys.path.append(opt[1])
else:
self.printErr("Bad option: -L %s : Path is not a directory or is nonexistant" % opt[1])
errors = True
elif ( opt[0] == "-l" ):
# specifically import the given module before continuing
if ( not self.importPaths(opt[1]) ):
errors = True
elif ( opt[0] == "-O" ) :
compiler.optimize(True)
elif ( opt[0] == "-o" ) :
if ( len(compiler.files) == 1 and len(compiler.dirs) == 0 ):
compiler.ofile = opt[1]
else:
if ( compiler.verbose ):
self.printErr("Ignoring option -o with multiple files or directories...")
elif ( opt[0] == "-r" ):
compiler.recursive(True)
elif ( opt[0] == "-E" ):
compiler.stopOnError(True)
elif ( opt[0] == "-v" ):
compiler.setVerbose(True)
elif ( opt[0] == "-F" ):
compiler.forceGen(True)
elif ( opt[0] == "-h" ):
self.printErr("HELP FOUND")
return False
elif ( opt[0] == "-d" ):
try:
compiler.setMaxDepth(int(opt[1]))
except Exception, e:
self.printErr("Bad Option: %s : must pass an integer" % opt[0])
else:
self.printErr(usage)
errors = True
if ( not errors ):
return compiler
else:
#self.printErr("%s : %s" % (opts, args))
return None
class PYCompiler :
def __init__ (self):
self.files = []
self.dirs = []
self.opt = False
self.recurse = False
self.stopErr = False
self.verbose = 0
self.depth = 10
self.force = 0
self.ofile = ""
def setVerbose (self, opt):
if ( opt ):
self.verbose = 1
else:
self.verbose = 0
def forceGen (self, opt):
if ( opt ):
self.force = 1
else:
self.force = 0
def setMaxDepth (self, depth):
self.depth = depth
def printErr(self, msg):
sys.__stdout__.write(msg)
if ( (not msg.endswith("\n")) ):
sys.__stdout__.write("\n")
def queueFile (self, fname):
self.files.append(fname)
def queueDir (self, dirname):
self.dirs.append(dirname)
def printCompileErr (self, e):
#self.printErr("printErr called with exception %s" % str(e))
efile = e.file
etype = e.exc_type_name
if ( len(e.exc_value) > 1 ) :
eline = e.exc_value[1][1]
ecode = e.exc_value[1][3]
else:
eline = -1
ecode = "(no code given)"
edesc = e.exc_value[0]
msg = "%s:%d: %s : %s : %s" % (efile, eline, etype, edesc, str(ecode))
self.printErr(msg)
def compile (self):
for fname in self.files:
ofile = ""
if ( len(self.files) == 1 and len(self.dirs) == 0 and self.ofile) :
ofile = self.ofile
else:
ofile = fname + "c"
if ( not self.__compile_file(fname, ofile) ):
if ( self.stopErr or ( len(self.files) + len(self.dirs)) == 1):
return False
for dirname in self.dirs :
if ( not os.path.walk(dirname, self.__compile_dir, None) ):
if ( self.stopErr ):
return False
return True
def __compile_file (self, fname, ofile = None):
try:
if ( self.force == 1 and len(self.files) == 1 and len(self.dirs) == 0):
if ( os.path.exists(ofile) and os.path.isfile(ofile) ):
try:
os.remove(ofile)
except OSError, e:
if ( self.verbose ):
self.printErr("%s : Failed to remove original - ignoring ... " % fname)
else:
if ( self.verbose ):
self.printErr("%s : Original output does not exist - ignoring ... " % fname)
#self.printErr("%s -> %s ..." % (fname, ofile))
py_compile.compile(fname, ofile, None, True)
if ( (fname in self.files) and self.verbose ):
# don't print this if we're being called from __compile_dir
self.printErr("%s -> %s ... OK" % (fname, ofile))
return True
except py_compile.PyCompileError, e:
self.printCompileErr(e)
if ( fname in self.files ):
self.printErr("%s -> %s ... FAILED" % (fname, ofile))
return False
def __compile_dir (self, arg, dirname, fnames):
try:
for fname in fnames:
if ( not (fname.endswith("py") or fname.endswith("PY")) ):
continue
tocompile = os.path.join(dirname, fname)
if ( os.path.isdir(tocompile) ):
os.path.walk(dirname, self.__compile_dir, None)
outfile = tocompile+"c"
if ( not self.__compile_file(tocompile, outfile) ):
self.printErr("%s -> %s ... FAILED" % (tocompile, outfile))
if ( self.stopErr ):
return False
else:
continue
else:
if ( self.verbose ):
self.printErr("%s -> %s ... OK" % (tocompile, outfile))
return True
except py_compile.PyCompileError, e:
self.printCompileErr(e)
return False
def optimize (self, opt):
self.opt = opt
def recursive (self, opt):
self.recurse = opt
def stopOnError (self, opt):
self.stopErr = opt
def main (argc, argv):
checker = ArgChecker()
compiler = checker.checkArgs(argc, argv)
if ( not compiler ):
sys.exit(1)
else:
if ( not compiler.compile() ):
sys.exit(2)
else:
sys.exit(0)
if ( __name__ == "__main__" ):
main(len(sys.argv)-1, sys.argv[1:])

13
tocaps.c Executable file
View File

@@ -0,0 +1,13 @@
#include <stdio.h>
int main(void)
{
char c = 0x00;
c = fgetc(stdin);
while (!feof(stdin)) {
c = toupper(c);
printf("%c", c);
c = fgetc(stdin);
}
return 0;
}

41
wrap.c Executable file
View File

@@ -0,0 +1,41 @@
#include <stdio.h>
const char *usage = "\
wrap - wrap a text file.\n\
Usage: wrap <infile> <outfile>\n";
int main(int argc, char **argv)
{
if ( argc < 3 ) {
printf("%s", usage);
return 1;
}
FILE *in = fopen(argv[1], "r");
FILE *out = fopen(argv[2], "w");
int cn = 0;
char c = 0x00;
if ( !in || !out ) {
printf("Failed to open input/output file.\n");
in ? fclose(in) : 0 ;
out ? fclose(out) : 0 ;
return 1;
}
while ( !feof(in) ) {
c = fgetc(in);
if ( cn > 60 &&
( c == ' ' || c == '\n' || c == '\t' )) {
fputc('\n', out);
cn = 0;
if ( c != '\t' ) continue;
}
fputc(c, out);
cn++;
}
fclose(in);
fclose(out);
return 0;
}