Anonymous avatar Anonymous committed 1413232

#2: Mainlining. Ported head of branches/issue_0002_dwhall_separate_stdlib_from_user since it had merged-forward.

Comments (0)

Files changed (17)

 
 # Build configuration
 TARGET := DESKTOP
-SIZE := size
-DEFS = -DTARGET_$(TARGET) -DHEAP_SIZE=$(HEAP_SIZE)
-CFLAGS = -g -Os -Wall -gstabs -Wstrict-prototypes $(DEFS)
 HEAP_SIZE = 0x1000
-ARFLAGS := rcs
-
-# Product configuration
-PRODUCT_VM := libpmvm.a
 
 # Changes for an embedded target
 ifeq ($(TARGET), AVR)
 	# TARGET_MCU should equal avr-gcc option "-mmcu" possible values.
 	TARGET_MCU := atmega103
-	
-	CFLAGS += -mmcu=$(TARGET_MCU)
 	HEAP_SIZE = 0x0D00
-
-	AR = avr-ar
-	CC = avr-gcc
-	SIZE = avr-size
-	CFLAGS += -DTARGET_MCU=$(TARGET_MCU)
-else
-	CFLAGS += -ansi
 endif
 
 # Export config to child makefiles
-export  AR ARFLAGS CC CFLAGS HEAP_SIZE PRODUCT_VM SIZE TARGET
+export TARGET HEAP_SIZE TARGET_MCU
 
 .PHONY: all vm pmstdlib docs TAGS dist check clean
 
-# TODO: Hopefully can uncomment when issue #2 is resolved
-#all : vm pmstdlib
 all : vm
 
 vm :
 	$(MAKE) -C src/vm
 
-# TODO: Hopefully can uncomment when issue #2 is resolved
-#pmstdlib :
-#	$(MAKE) -C src/lib
-
 html : docs/src/*.txt
 	$(MKDIR) docs/html
 	$(MAKE) -C docs/src
 else
 	# TODO: issue #5
 	# Make a script in tools/ that will:
-	# 	- make fresh checkout,
+	# 	- make fresh export (no .svn folders),
 	#   - build docs
 	#   - make pymite-RR.tar.gz
 	#	- create release tag in svn repos
 endif
 
-check : vm
+check :
 	$(MAKE) -C src/tests
 
 # Removes all files created during default make
 clean :
 	$(MAKE) -C src/vm clean
-# TODO: Hopefully can uncomment when issue #2 is resolved
-#	$(MAKE) -C src/lib clean
 

docs/src/BuildSystem.txt

 Overview
 --------
 
-PyMite shall use a makefile based build system with an emphasis
-on using features of `GNU make`_.  The project shall have a
+PyMite shall use a makefile based build system with an allowance for
+using features of `GNU make`_.  The project shall have a
 ``Makefile`` in the project root directory that, when called by
 typing ``make`` at the command prompt, will compile:
 
-    - the PyMite library to an image file, ``src/lib/pmstdlib_img.c``,
-      and native code file, ``src/lib/pmstdlib_nat.c``
-    - the PyMite VM to an archive, ``libpmvm.a``.
-      that must be included by PyMite end-user programs.
+    - the PyMite standard library ``src/lib/`` to an image file,
+      ``src/vm/pmstdlib_img.c``, and native code file, ``src/vm/pmstdlib_nat.c``
+    - the PyMite VM to an archive, ``libpmvm.a``
+      that shall be linked with PyMite end-user programs.
 
 More options for building the project are available by using the available
 ``make`` targets as explained in the next section.
 most software projects.  Most projects compile source code to create a library
 as a product and put that library in a ``lib/`` directory.  PyMite, on the
 other hand, converts Python code that is meant to run inside the PyMite VM
-to an `image`, an equivalent to a ``.pyc`` file.  The `image` is usually in the
-form of an array of bytes listed in a C file, ``pmstdlib_img.c``.
-This header file containing the image of the PyMite libraries is what is built
-in ``src/lib/``.
+to an `image` file, an equivalent to a ``.pyc`` file.  The `image` file is
+a C file, ``pmstdlib_img.c``, containing an array of bytes.
+The file containing the image of the PyMite libraries is what is built when
+``make`` is run in ``src/lib/``.
 
 .. _`GNU make`: http://www.gnu.org/software/make/
 
 Available Targets
 -----------------
 
-GNU ``make`` has a set of standard targets for users.
-One builds a target by typing ``make`` `<target>` at the command prompt.
-The PyMite build system shall support the following set of targets:
+GNU project have, by convention, a set of typical targets that can be built.
+The PyMite build system shall support the following set of targets
+by typing ``make`` `<target>` at the command prompt:
 
 ``all``:
-    Compiles the entire program.  This should be the default target.
+    Compiles the entire program.  This shall be the default target.
 
 ``clean``:
     Deletes all files in the current directory that are normally created by
 
 ``dist``:
     Create a distribution tar file for this program.
-    *This target should only be used by the PyMite developer.*
+    *This target should only be used by the PyMite release manager.*
 
 ``check``:
     Compiles and executes PyMite self-tests found in ``src/tests/``.
 -------
 
 While it is possible to write unit tests for PyMite's VM.  It is often more
-effective to write small Python programs to run on the PyMite VM to test the
+effective to write small Python programs to run in the PyMite VM to test the
 VM and libraries.  The tests in ``src/tests/`` do exactly this.  By running
 ``make check``, the VM, pmstdlib, and all programs in ``src/tests/`` are built.
 
 Distribution
 ------------
 
-The PyMite developer should be the only one who needs to use the distribution
-target.  The makefiles shall be set up in such a way that all the developer
-must do is update the PyMite revision number in the root makefile and type
-``make dist`` to create a file fit for release, ``pymite-RR.tar.gz``
-where `RR` is the release number.
+The PyMite release manager should be the only one who uses the
+distribution target.  The makefiles shall be configured so that
+all the release manager must do is run ``make dist PYMITE_RELEASE=RR``
+(where `RR` is the release number, in hexadecimal) to create the
+release file, ``pymite-RR.tar.gz``.
 
-The project documentation is pre-built for a release and included in the
-distributiion file.
+The html documentation shall be pre-built and included in the release file.
 def lcdPrintStr(ps):
     """__NATIVE__
     pPyObj_t ps = C_NULL;
-    P_U8 str = C_NULL;
+    P_U8 s = C_NULL;
 
     /* If wrong number of args, throw type exception */
     if (NATIVE_GET_NUM_ARGS() != 1)
     }
 
     /* Get a pointer to the string */
-    P_U8 s = (P_U8)((pPyString_t)ps)->val;
+    s = (P_U8)((pPyString_t)ps)->val;
 
     /* Print the string on the mmb's lcd */
     /* WARNING: PyMite's strings aren't null term 100% of the time */

src/sample/Makefile

 
 
 # PyMite Configuration
-LIBNATIVE_SOURCES = ../lib/__bi.py \
-                    ../lib/sys.py \
-					../lib/mmb.py
+LIBNATIVE_SOURCES = ../lib/mmb.py
 PMIMGCREATOR := ../tools/pmImgCreator.py
 PM_HEAP_SIZE = 0x0D00
 
 
 
 # Define all object files.
-OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) 
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) $(TARGET)_img.o $(TARGET)_nat.o
 
 # Define all listing files.
 LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
 
 # Combine all necessary flags and optional flags.
 # Add target processor to flags.
-ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
+# Removed from below until cygwin's make (3.81) is corrected: $(GENDEPFLAGS)
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) 
 ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
 
 
 %.elf: $(OBJ)
 	@echo
 	@echo $(MSG_LINKING) $@
-	$(CC) $(ALL_CFLAGS) $(OBJ) $*_nat.o $*_img.o --output $@ $(LDFLAGS)
+	$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
 
 
 # Compile: create object files from C source files.
 	@echo $(MSG_ASSEMBLING) $<
 	$(CC) -c $(ALL_ASFLAGS) $< -o $@
 
-# PyMite note:  avr-ar rcsv libmmb103.a libmmb103.o
 # PyMite: The native fxn table and bytecode image are generated from python source
-$(TARGET).c: $(TARGET)_nat.c $(TARGET)_img.c
-
 $(TARGET)_nat.c $(TARGET)_img.c: $(TARGET).py
-	$(PMIMGCREATOR) -c -o $(TARGET)_img.c --native-file=$(TARGET)_nat.c $(TARGET).py $(LIBNATIVE_SOURCES)
-	$(CC) -I../vm -DHEAP_SIZE=$(PM_HEAP_SIZE) -c $(TARGET)_nat.c 
-	$(CC) -I../vm -DHEAP_SIZE=$(PM_HEAP_SIZE) -c $(TARGET)_img.c
+	$(PMIMGCREATOR) -c -u -o $(TARGET)_img.c --native-file=$(TARGET)_nat.c $(TARGET).py $(LIBNATIVE_SOURCES)
 
 
 # Target: clean project.
 	$(REMOVE) $(TARGET).sym
 	$(REMOVE) $(TARGET).lnk
 	$(REMOVE) $(TARGET).lss
-	$(REMOVE) $(TARGET)_img.c
-	$(REMOVE) $(TARGET)_nat.c
+	$(REMOVE) $(TARGET)_img.*
+	$(REMOVE) $(TARGET)_nat.*
 	$(REMOVE) $(OBJ)
 	$(REMOVE) $(LST)
 	$(REMOVE) $(SRC:.c=.s)

src/sample/libmmb103.h

 /* avr system headers */
 #ifdef __AVR__
 #include <avr/io.h>
-#include <avr/signal.h>
 #include <avr/interrupt.h>
 #endif
 

src/sample/sample.c

  */
 
 
-#if defined(__AVR__)
-#include <avr/pgmspace.h>
-#endif
-
 #include "py.h"
 
-extern unsigned char lib_img[];
+extern unsigned char stdlib_img[];
+extern unsigned char usrlib_img[];
 
 
 int main(void)
 {
     /* ptr to code imgs */
-    P_U8 pimg = (P_U8)lib_img;
+    P_U8 pimg;
     pPyObj_t pstring = C_NULL;
     /* ptr to module obj */
     pPyFunc_t pmod;
     global_init();
     heap_init();
 
-    /* get image info into global struct */
-    retval = img_findInMem(MEMSPACE_FLASH, &pimg);
+    /* load std image info */
+    pimg = (P_U8)&stdlib_img;
+    retval = img_findInMem(MEMSPACE_RAM, &pimg);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* load usr image info */
+    pimg = (P_U8)&usrlib_img;
+    retval = img_findInMem(MEMSPACE_RAM, &pimg);
     PY_RETURN_IF_ERROR(retval);
 
     /* import module from global struct */

src/tests/Makefile

 SHELL = /bin/sh
+
+TARGET ?= DESKTOP
+HEAP_SIZE ?= 0x1000
+TARGET_MCU ?= atmega103
+
 PMIMGCREATOR := ../tools/pmImgCreator.py
+DEFS = -DHEAP_SIZE=$(HEAP_SIZE) -DTARGET_$(TARGET)
+CFLAGS = -g -Os -Wall -gstabs -Wstrict-prototypes $(DEFS)
 CFLAGS += -I../vm
-LDFLAGS = -L../vm -lpmvm
 SOURCES = $(wildcard t???.c)
 PY_SOURCES = $(SOURCES:.c=.py)
 EXECS = $(SOURCES:.c=.out)
 IMG_SOURCES = $(subst .py,_img.c, $(PY_SOURCES))
 NAT_SOURCES = $(subst .py,_nat.c, $(PY_SOURCES))
-PMSTDLIB_SOURCES = ../lib/__bi.py \
-                   ../lib/sys.py
 
+ifeq ($(TARGET), DESKTOP)
+	CFLAGS += -ansi
+endif
+ifeq ($(TARGET), AVR)
+	AR = avr-ar
+	CC = avr-gcc
+	SIZE = avr-size
+	CFLAGS += -mmcu=$(TARGET_MCU) -DTARGET_MCU=$(TARGET_MCU)
+endif
 
 # Build an executable from the C sources
 %.out : %*_nat.c %*_img.c %.c
-	$(CC) $(CFLAGS) -g -o $@ $*_nat.c $*_img.c $*.c ../vm/libpmvm.a
+	$(CC) $(CFLAGS) -o $@ $*_nat.c $*_img.c $*.c ../vm/libpmvm.a
 ifeq ($(TARGET), DESKTOP)
 	$(addprefix ./,$@)
 endif
 
 # The module images and native code are generated from python source
 %*_nat.c %*_img.c : %.py
-	$(PMIMGCREATOR) -c -o $*_img.c --native-file=$*_nat.c $*.py $(PMSTDLIB_SOURCES)
+	$(PMIMGCREATOR) -c -u -o $*_img.c --native-file=$*_nat.c $*.py $(PMSTDLIB_SOURCES)
 
 
 .PHONY: all check clean
 # Default action is to build tests; run tests if target is desktop
 all : check
 
-check : $(EXECS)
+check : vm $(EXECS)
+
+vm :
+	make -C ../vm
 
 # Removes files made by default make
 clean :
+/**
+ * Feature Test for Issue #2
+ *
+ * Separate stdlib from user app
+ *
+ */
+
+#include "py.h"
+
+extern unsigned char stdlib_img[];
+extern unsigned char usrlib_img[];
+
+
+int main(void)
+{
+    /* ptr to code imgs */
+    P_U8 pimg;
+    pPyObj_t pstring = C_NULL;
+    /* ptr to module obj */
+    pPyFunc_t pmod;
+    /* name of module to run */
+    P_U8 modstr = (P_U8)"t002";
+    PyReturn_t retval = PY_RET_OK;
+
+    heap_init();
+    retval = global_init();
+    PY_RETURN_IF_ERROR(retval);
+
+    /* load std image info */
+    pimg = (P_U8)&stdlib_img;
+    retval = img_findInMem(MEMSPACE_FLASH, &pimg);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* load usr image info */
+    pimg = (P_U8)&usrlib_img;
+    retval = img_findInMem(MEMSPACE_FLASH, &pimg);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* import module from global struct */
+    retval = string_new(&modstr, &pstring);
+    PY_RETURN_IF_ERROR(retval);
+    retval = mod_import(pstring, &pmod);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* load builtins into root module */
+    retval = global_loadBuiltins(pmod);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* XXX set "__name__" == "__main__" in mod's attrs here? */
+
+    /* interpret the module's bcode */
+    retval = interpret(pmod);
+
+    return retval;
+}
+

src/tests/t002.py

+#
+# Feature Test for Issue #2
+# Regression Test for Issue #28
+#
+# Separate stdlib from user app
+#
+# The test below proves that push42() was called from the usrlib native code
+# and assert was called from the stdlib native code.
+#
+"""__NATIVE__
+/*
+ * This is a regression test for issue #28.
+ * Having this doc-level native block should not affect
+ * the index of the native func below.
+ */
+"""
+
+#
+# Pushes the int, 42, onto the stack
+#
+def push42():
+    """__NATIVE__
+    pPyObj_t pint = C_NULL;
+    PyReturn_t retval;
+
+    retval = int_new((S32)42, &pint);
+    NATIVE_SET_TOS(pint);
+
+    return retval;
+    """
+    pass
+
+foo = push42()
+bar = 6 * 7
+assert foo == bar
  * Globals
  **************************************************************/
 
-extern unsigned char lib_img[];
+extern unsigned char stdlib_img[];
+extern unsigned char usrlib_img[];
 
 /***************************************************************
  * Main
 int main(void)
 {
     /* ptr to code imgs */
-    P_U8 pimg = (P_U8)&lib_img;
+    P_U8 pimg;
     pPyObj_t pstring = C_NULL;
     /* ptr to module obj */
     pPyFunc_t pmod;
     retval = global_init();
     PY_RETURN_IF_ERROR(retval);
 
-    /* get image info into global struct */
+    /* load std image info */
+    pimg = (P_U8)&stdlib_img;
+    retval = img_findInMem(MEMSPACE_FLASH, &pimg);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* load usr image info */
+    pimg = (P_U8)&usrlib_img;
     retval = img_findInMem(MEMSPACE_FLASH, &pimg);
     PY_RETURN_IF_ERROR(retval);
 
 
 #include "py.h"
 
-extern unsigned char lib_img[];
+extern unsigned char stdlib_img[];
+extern unsigned char usrlib_img[];
 
 
 int main(void)
 {
-    P_U8 pimg = (P_U8)&lib_img;
+    P_U8 pimg;
     PyReturn_t retval = PY_RET_OK;
 
     heap_init();
     retval = global_init();
     PY_RETURN_IF_ERROR(retval);
 
-    /* Read in the string of modules */
+    /* Read in the stdlib modules */
+    pimg = (P_U8)&stdlib_img;
+    retval = img_findInMem(MEMSPACE_FLASH, &pimg);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* The module image list terminator must be a null */
+    pimg -= 1;
+    PY_ASSERT(*pimg == C_NULL);
+
+    /* Read in the usrlib modules */
+    pimg = (P_U8)&usrlib_img;
     retval = img_findInMem(MEMSPACE_FLASH, &pimg);
     PY_RETURN_IF_ERROR(retval);
 
  *              not header files
  */
 
-#if defined(__AVR__)
-#include <avr/pgmspace.h>
-#endif
-
 #include "py.h"
 
-extern unsigned char lib_img[];
+extern unsigned char stdlib_img[];
+extern unsigned char usrlib_img[];
 
 
 int main(void)
 {
     /* ptr to code imgs */
-    P_U8 pimg = (P_U8)&lib_img;
+    P_U8 pimg;
     pPyObj_t pstring = C_NULL;
     /* ptr to module obj */
     pPyFunc_t pmod;
     retval = global_init();
     PY_RETURN_IF_ERROR(retval);
 
-    /* get image info into global struct */
+    /* load std image info */
+    pimg = (P_U8)&stdlib_img;
+    retval = img_findInMem(MEMSPACE_FLASH, &pimg);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* load usr image info */
+    pimg = (P_U8)&usrlib_img;
     retval = img_findInMem(MEMSPACE_FLASH, &pimg);
     PY_RETURN_IF_ERROR(retval);
 
 
 #include "py.h"
 
-extern unsigned char lib_img[];
+extern unsigned char stdlib_img[];
+extern unsigned char usrlib_img[];
 
 
 int main(void)
 {
     /* ptr to code imgs */
-    P_U8 pimg = (P_U8)&lib_img;
+    P_U8 pimg;
     pPyObj_t pstring = C_NULL;
     /* ptr to module obj */
     pPyFunc_t pmod;
     retval = global_init();
     PY_RETURN_IF_ERROR(retval);
 
-    /* get image info into global struct */
+    /* load std image info */
+    pimg = (P_U8)&stdlib_img;
+    retval = img_findInMem(MEMSPACE_FLASH, &pimg);
+    PY_RETURN_IF_ERROR(retval);
+
+    /* load usr image info */
+    pimg = (P_U8)&usrlib_img;
     retval = img_findInMem(MEMSPACE_FLASH, &pimg);
     PY_RETURN_IF_ERROR(retval);
 

src/tools/pmImgCreator.py

 
 Converts Python source files to a PyMite code image library.
 Performs code filtering to ensure it will run in PyMite.
-Formats the image as a C header file containing a byte array
-or a raw binary file.
+Formats the image as a raw binary file or a C file
+containing a byte array.
 
 16- and 32-bit values are in LITTLE ENDIAN order.
 This matches both Python and the AVR compiler's access to EEPROM.
 
-The order of the images in the file is undetermined.
-PyMite scans the images and makes a dict of available code objects.
+The order of the images in the output is undetermined.
 
 If the Python source contains a native code declaration
 and '--native-file=filename" is specified, the native code
 is formatted as C functions and an array of functions and output
-to the given filename.
+to the given filename.  When native functions are present, the user
+should specify where the native functions should be placed-- in the
+standard library or the user library--using the argument -s or -u,
+respectively.
 
 Log
 ---
 ==========      ==============================================================
 Date            Action
 ==========      ==============================================================
+2006/09/15      #28: Module with __NATIVE__ at root doesn't load
+2006/09/12      #2: Separate stdlib from user app
 2006/09/06      #24: Remove consts[0] == docstring assumption
 2006/09/01      #11: Make src/tests/ build module images as C files, not
                 header files
 __version__ = (0, 0, 7)
 __date__  = "2006/08/10"
 __usage__ = """USAGE:
-    pmImgCreator.py [-b|c] [OPTIONS] -o imgfilename infile0.py [infileN.py ...]
+    pmImgCreator.py [-b|c] [-s|u] [OPTIONS] -o imgfilename file0.py [files...]
 
-    -b                      Generates a raw binary file of the image
-    -c                      Generates a C file of the image (default)
-    -h                      Deprecated.  Use -c instead.
+    -b      Generates a raw binary file of the image
+    -c      Generates a C file of the image (default)
+
+    -s      Place native functions in the PyMite standard library (default)
+    -u      Place native functions in the user library
 
     OPTIONS:
     --native-file=filename  If specified, pmImgCreator will write a C source
 # CONSTANTS
 ################################################################
 
+# Exit error codes (from /usr/include/sysexits.h)
+EX_USAGE = 64
+
 # remove documentation string from const pool
 REMOVE_DOC_STR = 0
 
 NATIVE_INDICATOR_LENGTH = len(NATIVE_INDICATOR)
 
 # String name of function table variable
-NATIVE_TABLE_NAME = "nat_fxn_table"
+NATIVE_TABLE_NAME = {"std": "std_nat_fxn_table",
+                     "usr": "usr_nat_fxn_table"
+                    }
 
 # String name to prefix all native functions
 NATIVE_FUNC_PREFIX = "nat_"
     "IMPORT_FROM",
 #    "JUMP_FORWARD", "JUMP_IF_FALSE", "JUMP_IF_TRUE",
 #    "JUMP_ABSOLUTE", "FOR_LOOP", "LOAD_GLOBAL",
-    "CONTINUE_LOOP",
+## The following bytecode is not present in Python 2.0
+##    "CONTINUE_LOOP",
 #    "SETUP_LOOP",
     "SETUP_EXCEPT",
     "SETUP_FINALLY",
 #    "LOAD_FAST", "STORE_FAST",
     "DELETE_FAST",
 #    "SET_LINENO", "RAISE_VARARGS", "CALL_FUNCTION", "MAKE_FUNCTION",
-    "BUILD_SLICE", "MAKE_CLOSURE", "LOAD_CLOSURE",
-    "LOAD_DEREF", "STORE_DEREF",
+    "BUILD_SLICE",
+## The following bytecodes are not present in Python 2.0
+##    "MAKE_CLOSURE", "LOAD_CLOSURE", "LOAD_DEREF", "STORE_DEREF",
     "CALL_FUNCTION_VAR", "CALL_FUNCTION_KW",
     "CALL_FUNCTION_VAR_KW", "EXTENDED_ARG"
     )
 
 class PmImgCreator:
 
-    def __init__(self, ui=False,):
+    def __init__(self,):
 
         self.formatFromExt = {".c": self.format_img_as_c,
                               ".bin": self.format_img_as_bin,
-                              ".s19": self.format_img_as_s19,
                              }
 
         # bcode to mnemonic conversion (sparse list of strings)
         self._str_to_U8 = ord
 
 
-    def set_input(self, outfn=None, imgtype=".c", infiles=None):
+    def set_options(self,
+                    outfn,
+                    imgtype,
+                    imgtarget,
+                    memspace,
+                    nativeFilename,
+                    infiles,
+                   ):
         self.outfn = outfn
         self.imgtype = imgtype
-        self.infiles = infiles
-
-    def set_options(self, memspace=None, nativeFilename=None):
-        if not memspace:
-            memspace = "ram"
+        self.imgtarget = imgtarget
         self.memspace = memspace
         self.nativeFilename = nativeFilename
+        self.infiles = infiles
 
 ################################################################
 # CONVERSION FUNCTIONS
         # init image dict
         imgs = {"imgs": [], "fns": []}
 
-        # init native table
+        # init module table and native table
+        self.nativemods = []
         self.nativetable = []
 
+        # if creating usr lib, create placeholder in 0th index
+        if self.imgtarget == "usr":
+            self.nativetable.append((NATIVE_FUNC_PREFIX + "placeholder_func",
+                                    "\n/*\n"
+                                    " * Use placeholder because an index \n"
+                                    " * value of zero denotes the stdlib.\n"
+                                    " * This function should not be called.\n"
+                                    " */\n"
+                                    "return PY_RET_EX_SYS;\n"
+                                   ))
+
         # for each src file, convert and format
         for fn in self.infiles:
 
 
         # set image type byte
         objtype = OBJ_TYPE_CIM
-        if nativecode:
-            objtype = OBJ_TYPE_NIM
 
         # skip co_type and size
         # co_argcount
                 nativecode = consts[0][NATIVE_INDICATOR_LENGTH:]
                 consts[0] = None
 
+                # If this co is a module
+                # Issue #28: Module root, "?", must keep its bytecode
+                if co.co_name == "?":
+                    self.nativemods.append((co.co_filename, nativecode))
+
+                # Else this co is a function;
                 # replace code with native table index
-                code = self._U16_to_str(len(self.nativetable))
+                else:
+                    # stdlib code gets a positive index
+                    if self.imgtarget == "std":
+                        code = self._U16_to_str(len(self.nativetable))
+                    # usr code gets a negative index
+                    else:
+                        code = self._U16_to_str(-len(self.nativetable))
 
-                # native function name is
-                # "nat_<modname>_<pyfuncname>".
-                # append (nat func name, nat code) to table
-                self.nativetable.append((NATIVE_FUNC_PREFIX +
-                                         mn + "_" + co.co_name,
-                                        nativecode))
+                    # native function name is
+                    # "nat_<modname>_<pyfuncname>".
+                    # append (nat func name, nat code) to table
+                    self.nativetable.append((NATIVE_FUNC_PREFIX +
+                                             mn + "_" + co.co_name,
+                                            nativecode))
 
             ## Consts filter
             # if want to remove __doc__ string
                            )
             fileBuff.append("/* Place the image into FLASH */\n"
                             "unsigned char __attribute__((progmem))\n"
-                            "lib_img[] =\n"
+                            "%slib_img[] =\n"
+                            % (self.imgtarget)
                            )
         else:
             fileBuff.append("/* Place the image into RAM */\n"
                             "unsigned char\n"
-                            "lib_img[] =\n"
+                            "%slib_img[] =\n"
+                            % (self.imgtarget)
                            )
 
         fileBuff.append("{\n");
         return string.join(fileBuff, "")
 
 
-    def format_img_as_s19(self, img):
-        """format_img_as_s19(img) --> string
-
-        Format image bytes to Motorola S-Record format string.
-        The resulting string is suitable to write to a file.
-        """
-        pass
-
-
     def format_native_table(self,):
         """format_native_table() --> string
 
         fileBuff.append("#undef __FILE_ID__\n"
                         "#define __FILE_ID__ 0x0A\n"
                         "/**\n"
-                        " * PyMite native function file\n"
+                        " * PyMite %s native function file\n"
                         " *\n"
                         " * automatically created by pmImgCreator.py\n"
                         " * on %s\n"
                         " */\n\n"
                         "#define __IN_LIBNATIVE_C__\n"
                         "#include \"py.h\"\n\n"
-                        % (time.ctime(time.time()), self.nativeFilename)
+                        % (self.imgtarget,
+                           time.ctime(time.time()),
+                           self.nativeFilename
+                          )
                        )
 
         # module-level native sections (for #include headers)
-        for (funcname, funcstr) in self.nativetable:
-            if funcname[-1:] == "?":
-                fileBuff.append("/* From: %s */%s\n"
-                                % (funcname[len(NATIVE_FUNC_PREFIX):-2],
-                                   funcstr)
-                               )
+        for (modname, modstr) in self.nativemods:
+            fileBuff.append("/* From: %s */%s\n" % (modname, modstr))
 
         # for each entry create fxn
         for (funcname, funcstr) in self.nativetable:
-            if funcname[-1:] != "?":
-                fileBuff.append("static PyReturn_t\n"
-                                "%s(pPyFrame_t pframe, signed char numargs)\n"
-                                "{\n"
-                                "%s\n"
-                                "}\n\n" % (funcname, funcstr))
+            fileBuff.append("static PyReturn_t\n"
+                            "%s(pPyFrame_t pframe, signed char numargs)\n"
+                            "{\n"
+                            "%s\n"
+                            "}\n\n" % (funcname, funcstr))
 
         # create fxn table
         fileBuff.append("/* native function lookup table */\n"
                         "PyReturn_t (* %s[])(pPyFrame_t, signed char) =\n"
-                        "{\n" % (NATIVE_TABLE_NAME))
+                        "{\n" % (NATIVE_TABLE_NAME[self.imgtarget]))
+
+        # put all native funcs in the table
         for (funcname, funcstr) in self.nativetable:
-            if funcname[-1:] != "?":
-                fileBuff.append("    %s,\n" % funcname)
+            fileBuff.append("    %s,\n" % funcname)
         fileBuff.append("};\n")
 
         return string.join(fileBuff, "")
     """
     try:
         opts, args = getopt.getopt(sys.argv[1:],
-                                   "bhcso:",
+                                   "bcsuo:",
                                    ["memspace=", "native-file="])
     except:
         print __usage__
-        sys.exit(2)
+        sys.exit(EX_USAGE)
 
     # Parse opts for the image type to write
     imgtype = ".c"
+    imgtarget = "std"
+    memspace = "ram"
     outfn = None
-    memspace = None
     nativeFilename = None
     for opt in opts:
         if opt[0] == "-b":
             imgtype = ".bin"
-        elif opt[0] == "-h":
-            imgtype = ".c"
         elif opt[0] == "-c":
             imgtype = ".c"
+        elif opt[0] == "-s":
+            imgtarget = "std"
+        elif opt[0] == "-u":
+            imgtarget = "usr"
         elif opt[0] == "--memspace":
             # Error if memspace switch given without arg
             if not opt[1] or (opt[1].lower() not in ["ram", "flash"]):
                 print "Only one of these memspace types allowed: ram, flash"
                 print __usage__
-                sys.exit(2)
+                sys.exit(EX_USAGE)
             memspace = opt[1]
         elif opt[0] == "--native-file":
             # Error if switch given without arg
             if not opt[1]:
                 print "Specify a filename like this: --native-file=libnative.c"
                 print __usage__
-                sys.exit(2)
+                sys.exit(EX_USAGE)
             nativeFilename = opt[1]
         elif opt[0] == "-o":
             # Error if out filename switch given without arg
             if not opt[1]:
                 print __usage__
-                sys.exit(2)
+                sys.exit(EX_USAGE)
             outfn = opt[1]
 
     # Error if no image type was given
     if not imgtype:
         print __usage__
-        sys.exit(2)
+        sys.exit(EX_USAGE)
 
     # Error if no input filenames are given
     if len(args) == 0:
         print __usage__
-        sys.exit(2)
+        sys.exit(EX_USAGE)
 
-    return outfn, imgtype, args, memspace, nativeFilename
+    return outfn, imgtype, imgtarget, memspace, nativeFilename, args
 
 
 def main():
-    fn, imgtype, infiles, memspace, nativeFilename = parse_cmdline()
     pic = PmImgCreator()
-    pic.set_input(outfn=fn,
-                  imgtype=imgtype,
-                  infiles=infiles
-                 )
-    pic.set_options(memspace=memspace,
-                    nativeFilename=nativeFilename
-                   )
+    outfn, imgtyp, imgtarget, memspace, natfn, fns = parse_cmdline()
+    pic.set_options(outfn, imgtyp, imgtarget, memspace, natfn, fns)
     pic.convert_files()
     pic.write_image_file()
     pic.write_native_file()
 # Builds the PyMite VM as an archive
 #
 
-# Files to build
-SOURCES = $(wildcard *.c)
-HEADERS = $(wildcard *.h)
+# Configure the contents of pmstdlib by editing this list
+PMSTDLIB_SOURCES = ../lib/__bi.py \
+                   ../lib/sys.py
+
+TARGET ?= DESKTOP
+HEAP_SIZE ?= 0x1000
+TARGET_MCU ?= atmega103
+
+PMIMGCREATOR := ../tools/pmImgCreator.py
+DEFS = -DTARGET_$(TARGET) -DHEAP_SIZE=$(HEAP_SIZE)
+CFLAGS = -g -Os -Wall -gstabs -Wstrict-prototypes $(DEFS)
+ARFLAGS := rcs
+SOURCE_IMG := pmstdlib_img.c
+SOURCE_NAT := pmstdlib_nat.c
+SOURCES = $(wildcard *.c) $(SOURCE_IMG) $(SOURCE_NAT)
 OBJECTS = $(SOURCES:.c=.o)
+PRODUCT_VM := libpmvm.a
+
+ifeq ($(TARGET), DESKTOP)
+	CFLAGS += -ansi
+endif
+ifeq ($(TARGET), AVR)
+	AR = avr-ar
+	CC = avr-gcc
+	SIZE = avr-size
+	CFLAGS += -mmcu=$(TARGET_MCU) -DTARGET_MCU=$(TARGET_MCU)
+endif
 
 .PHONY: all size clean
 
 # Default action is to build the archive from object files
-all : $(PRODUCT_VM)
+all : $(SOURCE_IMG) $(SOURCE_NAT) $(PRODUCT_VM)
 
 # The archive is generated by placing object files inside it
 $(PRODUCT_VM) : $(PRODUCT_VM)($(OBJECTS))
 
+# Build the standard library into an image file and native function file
+$(SOURCE_IMG) $(SOURCE_NAT) : $(PMSTDLIB_SOURCES)
+	$(PMIMGCREATOR) -c -o $(SOURCE_IMG) --native-file=$(SOURCE_NAT) $(PMSTDLIB_SOURCES)
+
 # Lists the size of the obejcts in the archive
 size : $(PRODUCT_VM)
 	@$(SIZE) $(PRODUCT_VM)
 
 # Remove files made by default make
 clean :
-	@echo Deleting archive
 	@$(RM) $(PRODUCT_VM)
+	@$(RM) $(SOURCE_IMG) $(SOURCE_NAT)
     pno->od.od_type = OBJ_TYPE_NOB;
     pno->no_argcount = mem_getByte(memspace, paddr);
     /* get index into native fxn table */
-    pno->no_funcindx = mem_getWord(memspace, paddr);
+    pno->no_funcindx = (S16)mem_getWord(memspace, paddr);
 
     *r_pno = (pPyObj_t)pno;
     return PY_RET_OK;
  * Prototypes
  **************************************************************/
 
-extern PyReturn_t (* nat_fxn_table[])(pPyFrame_t, signed char);
+extern PyReturn_t (* std_nat_fxn_table[])(pPyFrame_t, signed char);
+extern PyReturn_t (* usr_nat_fxn_table[])(pPyFrame_t, signed char);
 
 /***************************************************************
  * Functions
 
             case RAISE_VARARGS:
                 t16 = GET_ARG();
-                
+
                 /* Only supports taking 1 arg for now */
                 if (t16 != 1)
                 {
                     retval = PY_RET_EX_SYS;
                     break;
                 }
-                
+
                 /* Raise type error if TOS is not an exception object */
                 pobj1 = PY_POP();
                 if (pobj1->od.od_type != OBJ_TYPE_EXN)
                 PY_PUSH(PY_NONE);
                 PY_PUSH(PY_NONE);
                 PY_PUSH(pobj1);
-                
+
                 /* Get the exception's code attr */
-                retval = dict_getItem((pPyObj_t)((pPyClass_t)pobj1)->cl_attrs, 
+                retval = dict_getItem((pPyObj_t)((pPyClass_t)pobj1)->cl_attrs,
                                       PY_CODE_STR,
                                       &pobj2);
                 PY_BREAK_IF_ERROR(retval);
-                
+
                 /* Get the value from the code int */
                 retval = (U8)(((pPyInt_t)pobj2)->val & 0xFF);
-                
+
                 /* Raise exception by breaking with retval set to code */
                 break;
 
                                 PY_POP();
                     }
                     /* get native function index */
-                    t16 = (S16)((pPyNo_t)((pPyFunc_t)pobj1)->
-                                f_co)->no_funcindx;
+                    pobj2 = (pPyObj_t)((pPyFunc_t)pobj1)->f_co;
+                    t16 = ((pPyNo_t)pobj2)->no_funcindx;
+
                     /*
                      * CALL NATIVE FXN
                      * pass caller's frame and numargs
                      */
-                    retval = nat_fxn_table[t16](FP, t8);
+                    /* Positive index is a stdlib func */
+                    if (t16 >= 0)
+                    {
+                        retval = std_nat_fxn_table[t16](FP, t8);
+                    }
+                    /* Negative index is a usrlib func */
+                    else
+                    {
+                        retval = usr_nat_fxn_table[-t16](FP, t8);
+                    }
                     /*
                      * RETURN FROM NATIVE FXN
                      */
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.