00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 """
00016 PyMite Image Creator
00017 ====================
00018
00019 Converts Python source files to a PyMite code image library.
00020 Performs code filtering to ensure it will run in PyMite.
00021 Formats the image as a raw binary file or a C file
00022 containing a byte array.
00023
00024 16- and 32-bit values are in LITTLE ENDIAN order.
00025 This matches both Python and the AVR compiler's access to EEPROM.
00026
00027 The order of the images in the output is undetermined.
00028
00029 If the Python source contains a native code declaration
00030 and '--native-file=filename" is specified, the native code
00031 is formatted as C functions and an array of functions and output
00032 to the given filename. When native functions are present, the user
00033 should specify where the native functions should be placed-- in the
00034 standard library or the user library--using the argument -s or -u,
00035 respectively.
00036 """
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 __usage__ = """USAGE:
00047 pmImgCreator.py -f pmfeaturesfilename [-b|c] [-s|u] [OPTIONS] -o imgfilename file0.py [files...]
00048
00049 -f <fn> Specify the file containing the PM_FEATURES dict to use
00050 -b Generates a raw binary file of the image
00051 -c Generates a C file of the image (default)
00052
00053 -s Place native functions in the PyMite standard library (default)
00054 -u Place native functions in the user library
00055
00056 OPTIONS:
00057 --native-file=filename If specified, pmImgCreator will write a C source
00058 file with native functions from the python files.
00059 --memspace=ram|flash Sets the memory space in which the image will be
00060 placed (default is "ram")
00061 """
00062
00063
00064 import exceptions, string, sys, types, dis, os, time, getopt, struct, types
00065
00066
00067
00068
00069
00070
00071
00072 EX_USAGE = 64
00073
00074
00075 REMOVE_DOC_STR = False
00076
00077
00078
00079 OBJ_TYPE_NON = 0x00
00080 OBJ_TYPE_INT = 0x01
00081 OBJ_TYPE_FLT = 0x02
00082 OBJ_TYPE_STR = 0x03
00083 OBJ_TYPE_TUP = 0x04
00084 OBJ_TYPE_COB = 0x05
00085 OBJ_TYPE_MOD = 0x06
00086 OBJ_TYPE_CLO = 0x07
00087 OBJ_TYPE_FXN = 0x08
00088 OBJ_TYPE_CLI = 0x09
00089 OBJ_TYPE_CIM = 0x0A
00090 OBJ_TYPE_NIM = 0x0B
00091 OBJ_TYPE_NOB = 0x0C
00092
00093
00094
00095 NATIVE_IMG_SIZE = 4
00096
00097
00098 MAX_TUPLE_LEN = 253
00099
00100
00101 MAX_STRING_LEN = 999
00102
00103
00104 MAX_IMG_LEN = 32767
00105
00106
00107 CO_OPTIMIZED = 0x0001
00108 CO_NEWLOCALS = 0x0002
00109 CO_VARARGS = 0x0004
00110 CO_VARKEYWORDS = 0x0008
00111 CO_NESTED = 0x0010
00112 CO_GENERATOR = 0x0020
00113 CO_NOFREE = 0x0040
00114
00115
00116 NATIVE_INDICATOR = "__NATIVE__"
00117 NATIVE_INDICATOR_LENGTH = len(NATIVE_INDICATOR)
00118
00119
00120 NATIVE_TABLE_NAME = {"std": "std_nat_fxn_table",
00121 "usr": "usr_nat_fxn_table"
00122 }
00123
00124
00125 NATIVE_FUNC_PREFIX = "nat_"
00126
00127
00128 NATIVE_MAX_NUM_LOCALS = 8
00129
00130
00131 if float(sys.version[:3]) < 2.5:
00132 MODULE_IDENTIFIER = "?"
00133 else:
00134 MODULE_IDENTIFIER = "<module>"
00135
00136
00137 IMG_LIST_TERMINATOR = "\xFF"
00138
00139
00140
00141
00142
00143
00144
00145
00146 CO_IMG_FIXEDPART_SIZE = 7
00147
00148
00149 UNIMPLEMENTED_BCODES = [
00150 "SLICE+1", "SLICE+2", "SLICE+3",
00151 "STORE_SLICE+0", "STORE_SLICE+1", "STORE_SLICE+2", "STORE_SLICE+3",
00152 "DELETE_SLICE+0", "DELETE_SLICE+1", "DELETE_SLICE+2", "DELETE_SLICE+3",
00153 "PRINT_ITEM_TO", "PRINT_NEWLINE_TO",
00154 "WITH_CLEANUP",
00155 "EXEC_STMT",
00156 "END_FINALLY",
00157 "SETUP_EXCEPT", "SETUP_FINALLY",
00158 "BUILD_SLICE",
00159 "CALL_FUNCTION_VAR", "CALL_FUNCTION_KW", "CALL_FUNCTION_VAR_KW",
00160 "EXTENDED_ARG",
00161 ]
00162
00163
00164
00165
00166
00167
00168 class PmImgCreator:
00169 def __init__(self, pmfeatures_filename):
00170
00171
00172
00173 locs = {}
00174 execfile(pmfeatures_filename, {}, locs)
00175 global PM_FEATURES
00176 PM_FEATURES = locs['PM_FEATURES']
00177 assert type(PM_FEATURES) == dict
00178
00179
00180 global CO_IMG_FIXEDPART_SIZE
00181 global UNIMPLEMENTED_BCODES
00182
00183 if PM_FEATURES["HAVE_CLOSURES"]:
00184 CO_IMG_FIXEDPART_SIZE += 1
00185
00186 if PM_FEATURES["HAVE_DEBUG_INFO"]:
00187 CO_IMG_FIXEDPART_SIZE += 2
00188
00189 if not PM_FEATURES["HAVE_DEL"]:
00190 UNIMPLEMENTED_BCODES.extend([
00191 "DELETE_SUBSCR",
00192 "DELETE_NAME",
00193 "DELETE_GLOBAL",
00194 "DELETE_ATTR",
00195 "DELETE_FAST",
00196 ])
00197
00198 if not PM_FEATURES["HAVE_IMPORTS"]:
00199 UNIMPLEMENTED_BCODES.extend([
00200 "IMPORT_STAR",
00201 "IMPORT_FROM",
00202 ])
00203
00204 if not PM_FEATURES["HAVE_ASSERT"]:
00205 UNIMPLEMENTED_BCODES.extend([
00206 "RAISE_VARARGS",
00207 ])
00208
00209 if not PM_FEATURES["HAVE_CLASSES"]:
00210 UNIMPLEMENTED_BCODES.extend([
00211 "BUILD_CLASS",
00212 ])
00213
00214
00215 if not PM_FEATURES["HAVE_GENERATORS"]:
00216 UNIMPLEMENTED_BCODES.extend([
00217 "YIELD_VALUE",
00218 ])
00219
00220
00221 if not PM_FEATURES["HAVE_BACKTICK"]:
00222 UNIMPLEMENTED_BCODES.extend([
00223 "UNARY_CONVERT",
00224 ])
00225
00226
00227
00228 if not PM_FEATURES["HAVE_FLOAT"]:
00229 UNIMPLEMENTED_BCODES.extend([
00230 "BINARY_TRUE_DIVIDE",
00231 "INPLACE_TRUE_DIVIDE",
00232 ])
00233
00234
00235 if not PM_FEATURES["HAVE_CLOSURES"]:
00236 UNIMPLEMENTED_BCODES.extend([
00237 "MAKE_CLOSURE",
00238 "LOAD_CLOSURE",
00239 "LOAD_DEREF",
00240 "STORE_DEREF",
00241 ])
00242
00243
00244 self.formatFromExt = {".c": self.format_img_as_c,
00245 ".bin": self.format_img_as_bin,
00246 }
00247
00248
00249 bcodes = dis.opname[:]
00250
00251
00252 for i in range(len(bcodes)):
00253 if bcodes[i][0] == '<':
00254 bcodes[i] = None
00255
00256
00257 for bcname in UNIMPLEMENTED_BCODES:
00258 if bcname in bcodes:
00259 i = bcodes.index(bcname)
00260 bcodes[i] = None
00261
00262
00263 self.bcodes = bcodes
00264
00265
00266 self._U8_to_str = chr
00267 self._str_to_U8 = ord
00268
00269
00270 def set_options(self,
00271 outfn,
00272 imgtype,
00273 imgtarget,
00274 memspace,
00275 nativeFilename,
00276 infiles,
00277 ):
00278 self.outfn = outfn
00279 self.imgtype = imgtype
00280 self.imgtarget = imgtarget
00281 self.memspace = memspace
00282 self.nativeFilename = nativeFilename
00283 self.infiles = infiles
00284
00285
00286
00287
00288
00289 def convert_files(self,):
00290 """Attempts to convert all source files.
00291 Creates a dict whose keys are the filenames
00292 and values are the code object string.
00293 """
00294
00295 imgs = {"imgs": [], "fns": []}
00296
00297
00298 self.nativemods = []
00299 self.nativetable = []
00300
00301
00302 if self.imgtarget == "usr":
00303 self.nativetable.append((NATIVE_FUNC_PREFIX + "placeholder_func",
00304 "\n /*\n"
00305 " * Use placeholder because an index \n"
00306 " * value of zero denotes the stdlib.\n"
00307 " * This function should not be called.\n"
00308 " */\n"
00309 " PmReturn_t retval;\n"
00310 " PM_RAISE(retval, PM_RET_EX_SYS);\n"
00311 " return retval;\n"
00312 ))
00313 self.nfcount = 1
00314 else:
00315 self.nfcount = 0
00316
00317
00318 for fn in self.infiles:
00319
00320
00321 co = compile(open(fn).read(), fn, 'exec')
00322 imgs["fns"].append(fn)
00323 imgs["imgs"].append(self.co_to_str(co))
00324
00325
00326 imgs["fns"].append("img-list-terminator")
00327 imgs["imgs"].append(IMG_LIST_TERMINATOR)
00328
00329 self.imgDict = imgs
00330 return
00331
00332
00333 def _str_to_U16(self, s):
00334 """Convert two bytes from a sequence to a 16-bit word.
00335
00336 The bytes are expected in little endian order.
00337 LSB first.
00338 """
00339
00340 return self._str_to_U8(s[0]) | (self._str_to_U8(s[1]) << 8)
00341
00342
00343 def _U16_to_str(self, w):
00344 """Convert the 16-bit word, w, to a string of two bytes.
00345
00346 The 2 byte string is in little endian order.
00347 DOES NOT INSERT TYPE BYTE.
00348 """
00349
00350 return self._U8_to_str(w & 0xff) + \
00351 self._U8_to_str((w >> 8) & 0xff)
00352
00353
00354 def _float_to_str(self, f):
00355 """Convert the float object, f, to a string of four bytes
00356 in little-endian order.
00357 """
00358 return struct.pack("<f", f)
00359
00360
00361 def _seq_to_str(self, seq):
00362 """Convert a Python sequence to a PyMite image.
00363
00364 The sequence is converted to a tuple of objects.
00365 This handles both co_consts and co_names.
00366 This is recursive to handle tuples in the const pool.
00367 Return string shows type in the leading byte.
00368 """
00369
00370
00371 _U8_to_str = self._U8_to_str
00372
00373
00374 assert len(seq) <= MAX_TUPLE_LEN
00375
00376
00377 imgstr = _U8_to_str(OBJ_TYPE_TUP) + \
00378 _U8_to_str(len(seq))
00379
00380
00381 for i in range(len(seq)):
00382 obj = seq[i]
00383 objtype = type(obj)
00384
00385
00386 if objtype == types.StringType:
00387
00388 assert len(obj) <= MAX_STRING_LEN
00389
00390 imgstr += _U8_to_str(OBJ_TYPE_STR) + \
00391 self._U16_to_str(len(obj)) + obj
00392
00393
00394 elif objtype == types.IntType:
00395
00396 imgstr += _U8_to_str(OBJ_TYPE_INT) + \
00397 _U8_to_str(obj & 0xff) + \
00398 _U8_to_str((obj >> 8) & 0xff) + \
00399 _U8_to_str((obj >> 16) & 0xff) + \
00400 _U8_to_str((obj >> 24) & 0xff)
00401
00402
00403 elif objtype == types.CodeType:
00404
00405 if (len(obj.co_consts) > 0 and
00406 (type(obj.co_consts[0]) == types.StringType) and
00407 (obj.co_consts[0][0:NATIVE_INDICATOR_LENGTH] ==
00408 NATIVE_INDICATOR)):
00409 imgstr += self.no_to_str(obj)
00410 else:
00411 imgstr += self.co_to_str(obj)
00412
00413
00414 elif objtype == types.TupleType:
00415 imgstr += self._seq_to_str(obj)
00416
00417
00418 elif objtype == types.NoneType:
00419
00420 imgstr += _U8_to_str(OBJ_TYPE_NON)
00421
00422
00423 elif objtype == types.FloatType and PM_FEATURES["HAVE_FLOAT"]:
00424 imgstr += _U8_to_str(OBJ_TYPE_FLT) + self._float_to_str(obj)
00425
00426
00427 else:
00428 raise exceptions.NotImplementedError(
00429 "Unhandled type %s." % objtype)
00430 return imgstr
00431
00432
00433
00434
00435 def co_to_str(self, co):
00436 """Converts a Python code object to a PyMite image.
00437
00438 The code image is relocatable and goes in the device's
00439 memory. Return string shows type in the leading byte.
00440 """
00441
00442
00443 consts, names, code, nativecode = self._filter_co(co)
00444
00445
00446
00447
00448 imgstr = self._U8_to_str(co.co_argcount) + \
00449 self._U8_to_str(co.co_flags & 0xFF) + \
00450 self._U8_to_str(co.co_stacksize) + \
00451 self._U8_to_str(co.co_nlocals)
00452
00453
00454 if PM_FEATURES["HAVE_CLOSURES"]:
00455 imgstr += self._U8_to_str(len(co.co_freevars))
00456
00457
00458 if PM_FEATURES["HAVE_DEBUG_INFO"]:
00459 imgstr += self._U16_to_str(co.co_firstlineno)
00460
00461
00462
00463 s = self._seq_to_str(names)
00464 lennames = len(s)
00465 imgstr += s
00466
00467
00468 lenlnotab = 0
00469 lenfilename = 0
00470 if PM_FEATURES["HAVE_DEBUG_INFO"]:
00471
00472
00473 assert len(co.co_lnotab) <= MAX_STRING_LEN
00474 s = self._U8_to_str(OBJ_TYPE_STR) + \
00475 self._U16_to_str(len(co.co_lnotab)) + co.co_lnotab
00476 lenlnotab = len(s)
00477 imgstr += s
00478
00479
00480
00481 fn = co.co_filename
00482 assert len(fn) <= MAX_STRING_LEN
00483 s = self._U8_to_str(OBJ_TYPE_STR) + \
00484 self._U16_to_str(len(fn) + 1) + fn + '\0'
00485 lenfilename = len(s)
00486 imgstr += s
00487
00488
00489 s = self._seq_to_str(consts)
00490 lenconsts = len(s)
00491 imgstr += s
00492
00493
00494
00495 if PM_FEATURES["HAVE_CLOSURES"]:
00496
00497 l = [-1,] * len(co.co_cellvars)
00498 for i,name in enumerate(co.co_cellvars):
00499 if name in co.co_varnames:
00500 l[i] = list(co.co_varnames).index(name)
00501 s = self._seq_to_str(tuple(l))
00502 lenconsts += len(s)
00503 imgstr += s
00504
00505
00506 imgstr += code
00507
00508 size = CO_IMG_FIXEDPART_SIZE + lennames + lenlnotab + lenfilename + \
00509 lenconsts + len(code)
00510
00511
00512 imgstr = self._U8_to_str(OBJ_TYPE_CIM) + \
00513 self._U16_to_str(size) + \
00514 imgstr
00515 assert len(imgstr) <= MAX_IMG_LEN
00516
00517 return imgstr
00518
00519
00520 def no_to_str(self, co):
00521 """Convert a native code object to a PyMite image.
00522
00523 The native image is relocatable and goes in the device's
00524 memory. Return string shows type in the leading byte.
00525 """
00526
00527
00528 consts, names, code, nativecode = self._filter_co(co)
00529
00530
00531
00532
00533 objtype = OBJ_TYPE_NIM
00534
00535
00536
00537 imgstr = (self._U8_to_str(OBJ_TYPE_NIM) +
00538 self._U8_to_str(co.co_argcount) +
00539 code)
00540
00541
00542 assert len(imgstr) <= MAX_IMG_LEN
00543
00544 return imgstr
00545
00546
00547
00548
00549
00550
00551 def _filter_co(self, co):
00552 """Run the Python code obj, co, through various filters.
00553
00554 Ensure it is compliant with PyMite restrictions.
00555
00556 Consts filter:
00557 Ensure num consts is less than 256.
00558 Replace __doc__ with None if present.
00559
00560 Flags filter:
00561 Check co_flags for flags that indicate an unsupported feature
00562 Supported flags: CO_NOFREE, CO_OPTIMIZED, CO_NEWLOCALS, CO_NESTED,
00563 Unsupported flags: CO_VARARGS, CO_VARKEYWORDS
00564 Conditionally supported flags: CO_GENERATOR if HAVE_GENERATORS
00565
00566 Native code filter:
00567 If this function has a native indicator,
00568 extract the native code from the doc string
00569 and clear the doc string.
00570 Ensure num args is less or equal to
00571 NATIVE_MAX_NUM_LOCALS.
00572
00573 Names/varnames filter:
00574 Ensure num names is less than 256.
00575 If co_name is the module identifier replace it with
00576 the trimmed module name
00577 otherwise just append the name to co_name.
00578
00579 Bcode filter:
00580 Raise NotImplementedError for an invalid bcode.
00581
00582 If all is well, return the filtered consts list,
00583 names list, code string and native code.
00584 """
00585
00586
00587
00588 assert len(co.co_consts) < 256, "too many constants."
00589 assert len(co.co_names) < 256, "too many names."
00590 assert co.co_argcount < 256, "too many arguments."
00591 assert co.co_stacksize < 256, "too large of a stack."
00592 assert co.co_nlocals < 256, "too many local variables."
00593
00594
00595 consts = list(co.co_consts)
00596
00597
00598 unsupported_flags = CO_VARARGS | CO_VARKEYWORDS
00599 if not PM_FEATURES["HAVE_GENERATORS"]:
00600 unsupported_flags |= CO_GENERATOR
00601 assert co.co_flags & unsupported_flags == 0,\
00602 "Unsupported code identified by co_flags (%s)." % hex(co.co_flags)
00603
00604
00605 fn = os.path.basename(co.co_filename)
00606 mn = os.path.splitext(fn)[0]
00607
00608
00609 nativecode = None
00610
00611
00612
00613 s = co.co_code
00614
00615 code = ""
00616
00617 lno = 0
00618 i = 0
00619 len_s = len(s)
00620 while i < len_s:
00621
00622
00623 c = ord(s[i])
00624
00625
00626 if self.bcodes[c] == None:
00627 raise NotImplementedError(
00628 "Illegal bytecode (%d/%s/%s) "
00629 "comes at offset %d in file %s." %
00630 (c, hex(c), dis.opname[c],
00631 i, co.co_filename))
00632
00633
00634 if c < dis.HAVE_ARGUMENT:
00635 code += s[i]
00636 i += 1
00637
00638
00639 else:
00640
00641
00642 if (not PM_FEATURES["HAVE_DEFAULTARGS"]
00643 and c == dis.opmap["MAKE_FUNCTION"]
00644 and self._str_to_U16(s[i+1:i+3]) > 0):
00645
00646 raise NotImplementedError(
00647 "Bytecode (%d/%s/%s) not configured "
00648 "to support default arguments; "
00649 "comes at offset %d in file %s." %
00650 (c, hex(c), dis.opname[c], i, co.co_filename))
00651
00652
00653 code += s[i:i+3]
00654 i += 3
00655
00656
00657 if (len(consts) > 0 and type(consts[0]) == types.StringType):
00658
00659
00660
00661 if (consts[0][:NATIVE_INDICATOR_LENGTH] ==
00662 NATIVE_INDICATOR):
00663
00664
00665
00666 assert co.co_nlocals <= NATIVE_MAX_NUM_LOCALS
00667
00668
00669 nativecode = consts[0][NATIVE_INDICATOR_LENGTH:]
00670 consts[0] = None
00671
00672
00673
00674 if co.co_name == MODULE_IDENTIFIER:
00675 self.nativemods.append((co.co_filename, nativecode))
00676
00677
00678
00679 else:
00680
00681 if self.imgtarget == "std":
00682 code = self._U16_to_str(len(self.nativetable))
00683
00684 else:
00685 code = self._U16_to_str(-len(self.nativetable))
00686
00687
00688
00689
00690 self.nativetable.append(
00691 ("%s%02d_%s_%s"
00692 % (NATIVE_FUNC_PREFIX, self.nfcount, mn, co.co_name),
00693 nativecode))
00694 self.nfcount += 1
00695
00696
00697
00698
00699 elif (REMOVE_DOC_STR and len(co.co_names) > 0
00700 and co.co_names[0] == "__doc__"):
00701 consts[0] = None
00702
00703
00704 names = list(co.co_names)
00705
00706
00707 if REMOVE_DOC_STR and len(names) > 0 and names[0] == "__doc__":
00708 names[0] = ''
00709
00710
00711 if co.co_name == MODULE_IDENTIFIER:
00712 names.append(mn)
00713
00714 else:
00715 names.append(co.co_name)
00716
00717
00718 return consts, names, code, nativecode
00719
00720
00721
00722
00723
00724
00725 def write_image_file(self,):
00726 """Writes an image file
00727 """
00728 fmtfxn = self.formatFromExt[self.imgtype]
00729 f = open(self.outfn, 'wb')
00730 f.write(fmtfxn())
00731 f.close()
00732
00733 def write_native_file(self,):
00734 """Writes native functions if filename was given
00735 """
00736 if not self.nativeFilename:
00737 return
00738 f = open(self.nativeFilename, 'wb')
00739 f.write(self.format_native_table())
00740 f.close()
00741
00742
00743 def format_img_as_bin(self,):
00744 """format_img_as_bin() --> string
00745
00746 Write image bytes to raw binary string.
00747 The resulting string is suitable to write to a file.
00748 """
00749
00750
00751 return string.join(self.imgDict["imgs"], "")
00752
00753
00754 def format_img_as_c(self,):
00755 """format_img_as_c() --> string
00756
00757 Format image bytes to a string that is a C byte array.
00758 The C byte array can be located in RAM
00759 or program memory. The byte array is named lib_img.
00760 """
00761
00762
00763 fns = self.imgDict["fns"]
00764 imgs = self.imgDict["imgs"]
00765
00766
00767 fileBuff = []
00768 fileBuff.append("/**\n"
00769 " * PyMite library image file.\n"
00770 " *\n"
00771 " * Automatically created from:\n"
00772 " * \t%s\n"
00773 " * by pmImgCreator.py on\n"
00774 " * %s.\n"
00775 " * \n"
00776 " * Byte count: %d\n"
00777 " * \n"
00778 " * Selected memspace type: %s\n"
00779 " * \n"
00780 " * DO NOT EDIT THIS FILE.\n"
00781 " * ANY CHANGES WILL BE LOST.\n"
00782 " */\n\n"
00783 % (string.join(fns, "\n *\t"),
00784 time.ctime(time.time()),
00785 len(string.join(imgs, "")),
00786 self.memspace.upper()
00787 )
00788 )
00789 fileBuff.append("/* Place the image into %s */\n"
00790 "#ifdef __cplusplus\n"
00791 "extern\n"
00792 "#endif\n"
00793 "unsigned char const\n"
00794 % self.memspace.upper()
00795 )
00796
00797 if self.memspace.lower() == "flash":
00798 fileBuff.append("#if defined(__AVR__)\n"
00799 "__attribute__((progmem))\n"
00800 "#endif\n"
00801 )
00802
00803 fileBuff.append("%slib_img[] =\n"
00804 "{\n"
00805 % (self.imgtarget)
00806 )
00807
00808
00809 i = 0
00810 for fn in fns:
00811
00812
00813 img = imgs[i]
00814 i += 1
00815
00816
00817 fileBuff.append("\n\n/* %s */" % fn)
00818 j = 0
00819 while j < len(img):
00820 if (j % 8) == 0:
00821 fileBuff.append("\n ")
00822 fileBuff.append("0x%02X, " % ord(img[j]))
00823 j += 1
00824
00825
00826 fileBuff.append("\n};\n")
00827
00828 return string.join(fileBuff, "")
00829
00830
00831 def format_native_table(self,):
00832 """format_native_table() --> string
00833
00834 Format native table to a C file containing
00835 native functions and a function table.
00836 """
00837
00838 fileBuff = []
00839 fileBuff.append("#undef __FILE_ID__\n"
00840 "#define __FILE_ID__ 0x0A\n"
00841 "/**\n"
00842 " * PyMite %s native function file\n"
00843 " *\n"
00844 " * automatically created by pmImgCreator.py\n"
00845 " * on %s\n"
00846 " *\n"
00847 " * DO NOT EDIT THIS FILE.\n"
00848 " * ANY CHANGES WILL BE LOST.\n"
00849 " *\n"
00850 " * @file %s\n"
00851 " */\n\n"
00852 "#define __IN_LIBNATIVE_C__\n"
00853 "#include \"pm.h\"\n\n"
00854 % (self.imgtarget,
00855 time.ctime(time.time()),
00856 self.nativeFilename
00857 )
00858 )
00859
00860
00861 for (modname, modstr) in self.nativemods:
00862 fileBuff.append("/* From: %s */%s\n" % (modname, modstr))
00863
00864
00865 for (funcname, funcstr) in self.nativetable:
00866 fileBuff.append("PmReturn_t\n"
00867 "%s(pPmFrame_t *ppframe)\n"
00868 "{\n"
00869 "%s\n"
00870 "}\n\n" % (funcname, funcstr))
00871
00872
00873 fileBuff.append("/* Native function lookup table */\n"
00874 "pPmNativeFxn_t const %s[] =\n"
00875 "{\n" % NATIVE_TABLE_NAME[self.imgtarget])
00876
00877
00878 for (funcname, funcstr) in self.nativetable:
00879 fileBuff.append(" %s,\n" % funcname)
00880 fileBuff.append("};\n")
00881
00882 return string.join(fileBuff, "")
00883
00884
00885
00886
00887
00888
00889 def parse_cmdline():
00890 """Parses the command line for options.
00891 """
00892 try:
00893 opts, args = getopt.getopt(sys.argv[1:],
00894 "f:bcsuo:",
00895 ["memspace=", "native-file="])
00896 except:
00897 print __usage__
00898 sys.exit(EX_USAGE)
00899
00900
00901 imgtype = ".c"
00902 imgtarget = "std"
00903 memspace = "ram"
00904 outfn = None
00905 nativeFilename = None
00906 for opt in opts:
00907 if opt[0] == "-b":
00908 imgtype = ".bin"
00909 elif opt[0] == "-c":
00910 imgtype = ".c"
00911 elif opt[0] == "-s":
00912 imgtarget = "std"
00913 elif opt[0] == "-u":
00914 imgtarget = "usr"
00915 elif opt[0] == "--memspace":
00916
00917 if not opt[1] or (opt[1].lower() not in ["ram", "flash"]):
00918 print "Only one of these memspace types allowed: ram, flash"
00919 print __usage__
00920 sys.exit(EX_USAGE)
00921 memspace = opt[1]
00922 elif opt[0] == "--native-file":
00923
00924 if not opt[1]:
00925 print "Specify a filename like this: --native-file=libnative.c"
00926 print __usage__
00927 sys.exit(EX_USAGE)
00928 nativeFilename = opt[1]
00929 elif opt[0] == "-f":
00930 pmfeatures_filename = opt[1]
00931 elif opt[0] == "-o":
00932
00933 if not opt[1]:
00934 print __usage__
00935 sys.exit(EX_USAGE)
00936 outfn = opt[1]
00937
00938
00939 if not imgtype:
00940 print __usage__
00941 sys.exit(EX_USAGE)
00942
00943
00944 if len(args) == 0:
00945 print __usage__
00946 sys.exit(EX_USAGE)
00947
00948 return outfn, imgtype, imgtarget, memspace, nativeFilename, args, pmfeatures_filename
00949
00950
00951 def main():
00952 outfn, imgtyp, imgtarget, memspace, natfn, fns, pmfn = parse_cmdline()
00953 pic = PmImgCreator(pmfn)
00954 pic.set_options(outfn, imgtyp, imgtarget, memspace, natfn, fns)
00955 pic.convert_files()
00956 pic.write_image_file()
00957 pic.write_native_file()
00958
00959
00960 if __name__ == "__main__":
00961 main()