From e58e308366c466f6edb26a06d4b4eb40b7ef46cc Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Mon, 18 May 2026 12:31:43 -0400 Subject: [PATCH] Commit code, circa 2010 --- cblnum.c | 80 ++++++ pcfconv.py | 739 +++++++++++++++++++++++++++++++++++++++++++++++++++++ pycc | 290 +++++++++++++++++++++ tocaps.c | 13 + wrap.c | 41 +++ 5 files changed, 1163 insertions(+) create mode 100755 cblnum.c create mode 100755 pcfconv.py create mode 100755 pycc create mode 100755 tocaps.c create mode 100755 wrap.c diff --git a/cblnum.c b/cblnum.c new file mode 100755 index 0000000..30bb799 --- /dev/null +++ b/cblnum.c @@ -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 + +#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; +} diff --git a/pcfconv.py b/pcfconv.py new file mode 100755 index 0000000..5b99b69 --- /dev/null +++ b/pcfconv.py @@ -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 \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 \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:])) + diff --git a/pycc b/pycc new file mode 100755 index 0000000..0fd214f --- /dev/null +++ b/pycc @@ -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, +usage: pycc 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:]) diff --git a/tocaps.c b/tocaps.c new file mode 100755 index 0000000..f2846c7 --- /dev/null +++ b/tocaps.c @@ -0,0 +1,13 @@ +#include + +int main(void) +{ + char c = 0x00; + c = fgetc(stdin); + while (!feof(stdin)) { + c = toupper(c); + printf("%c", c); + c = fgetc(stdin); + } + return 0; +} diff --git a/wrap.c b/wrap.c new file mode 100755 index 0000000..c0b424b --- /dev/null +++ b/wrap.c @@ -0,0 +1,41 @@ +#include + +const char *usage = "\ +wrap - wrap a text file.\n\ +Usage: wrap \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; +}