plat.c

00001 /*
00002  * PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
00003  * Copyright 2002 Dean Hall.  All rights reserved.
00004  * PyMite is offered through one of two licenses: commercial or open-source.
00005  * See the LICENSE file at the root of this package for licensing details.
00006  *
00007  * Win32 host version, tweaked from original 'desktop' version
00008  */
00009 
00010 
00011 #undef __FILE_ID__
00012 #define __FILE_ID__ 0x70
00013 
00014 //  determine how we handle time in Windows
00015 //#define USE_SETTIMER 1   /* this requires an active message loop*/
00016 #define USE_TIMESETEVENT 1 /* (Older) Windows multi-media function */
00017 //#define USE_CREATETIMERQUEUETIMER 0 /* CreateTimerQueueTimer function */
00018 
00021 #include <stdio.h>
00022 #include <string.h>
00023 
00024 #include "pm.h"
00025 
00026 //#define WIN32_LEAN_AND_MEAN
00027 #include <windows.h>
00028 
00029 #if defined(USE_SETTIMER)
00030     /* local prototypes */
00031     VOID CALLBACK on_timer(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
00032 #endif
00033 
00034 #if defined(USE_TIMESETEVENT)
00035     // shortcut so we do not need an explicit addition to the linker command line
00036     #pragma comment(lib, "winmm")
00037 
00038     void CALLBACK on_mm_timer(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2);
00039 #endif
00040 
00041 
00042 /* local variables*/
00043 static UINT_PTR idEvent = 0;
00044 static DWORD dwLastTime = 0;
00045 static const UINT uTimeOut = 200;  /* # of ms for each timer tick */
00046 
00047 
00048 /* Desktop target shall use stdio for I/O routines. */
00049 PmReturn_t
00050 plat_init(void)
00051 {
00052     /*
00053      * The *nix version used the sigalrm to generate a timer. On Windows, we
00054      * use a standard Windows timer. Note we do not use an HWND so we do not
00055      * need to actually create any windows. But we do need a Windows event loop
00056      * to allow the timer callback to be called properly.
00057      */
00058     dwLastTime = GetTickCount();
00059 
00060 #if defined(USE_SETTIMER)
00061     idEvent = SetTimer(NULL, 0, uTimeOut, on_timer);
00062     // use the return value in a KillTimer function. But we need a plat_uninit() call...
00063 #endif
00064 
00065 #if defined(USE_TIMESETEVENT)
00066     idEvent = timeSetEvent(uTimeOut, 0 /*change later, if system load too high*/, on_mm_timer, 0, TIME_PERIODIC|TIME_CALLBACK_FUNCTION);
00067 #endif
00068 
00069     return PM_RET_OK;
00070 }
00071 
00072 #if defined(USE_SETTIMER)
00073 /* Called from Windows every X ms */
00074 VOID CALLBACK on_timer(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
00075 {
00076     PmReturn_t retval = PM_RET_OK;
00077     DWORD delta = dwTime - dwLastTime;
00078     //printf("diff = %ld\n", delta);
00079 
00080     // update our system time
00081     pm_timerMsTicks = dwTime;
00082 
00083     retval = pm_vmPeriodic((uint16_t)delta);
00084     dwLastTime = dwTime;
00085 
00086     PM_REPORT_IF_ERROR(retval);
00087 }
00088 #endif
00089 
00090 #if defined(USE_TIMESETEVENT)
00091 void
00092 CALLBACK on_mm_timer(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
00093 {
00094     PmReturn_t retval = PM_RET_OK;
00095     DWORD dwTime = GetTickCount();
00096     DWORD delta =  dwTime - dwLastTime;
00097     //printf("diff = %ld\n", delta);
00098 
00099     // update our system time
00100     pm_timerMsTicks = dwTime;
00101 
00102     retval = pm_vmPeriodic((uint16_t)delta);
00103     dwLastTime = dwTime;
00104 
00105     PM_REPORT_IF_ERROR(retval);
00106 }
00107 #endif
00108 
00109 /*
00110  * Undo anything we may have done in the plat_init function
00111  */
00112 PmReturn_t
00113 plat_deinit(void)
00114 {
00115 #if defined(USE_SETTIMER)
00116     KillTimer(idEvent);
00117     idEvent = 0;
00118 #endif
00119 
00120 #if defined(USE_TIMESETEVENT)
00121     timeKillEvent(idEvent);
00122     idEvent = 0;
00123 #endif
00124     return PM_RET_OK;
00125 }
00126 
00127 /*
00128  * Gives us time to update our clock, etc.
00129  */
00130 void
00131 plat_tick(void)
00132 {
00133     //BOOL bRet;
00134     MSG msg;
00135 
00136     //if ((bRet = GetMessage(&msg, 0, 0, 0)) != 0)
00137     if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
00138     {
00139         TranslateMessage(&msg);
00140         DispatchMessage(&msg);
00141     }
00142 }
00143 
00144 /*
00145  * Gets a byte from the address in the designated memory space
00146  * Post-increments *paddr.
00147  */
00148 uint8_t
00149 plat_memGetByte(PmMemSpace_t memspace, uint8_t const **paddr)
00150 {
00151     uint8_t b = 0;
00152 
00153     switch (memspace)
00154     {
00155         case MEMSPACE_RAM:
00156         case MEMSPACE_PROG:
00157             b = **paddr;
00158             *paddr += 1;
00159             return b;
00160 
00161         case MEMSPACE_EEPROM:
00162         case MEMSPACE_SEEPROM:
00163         case MEMSPACE_OTHER0:
00164         case MEMSPACE_OTHER1:
00165         case MEMSPACE_OTHER2:
00166         case MEMSPACE_OTHER3:
00167         default:
00168             return 0;
00169     }
00170 }
00171 
00172 
00173 /* Desktop target shall use stdio for I/O routines */
00174 PmReturn_t
00175 plat_getByte(uint8_t *b)
00176 {
00177     int c;
00178     PmReturn_t retval = PM_RET_OK;
00179 
00180     c = getchar();
00181     *b = c & 0xFF;
00182 
00183     if (c == EOF)
00184     {
00185         PM_RAISE(retval, PM_RET_EX_IO);
00186     }
00187 
00188     return retval;
00189 }
00190 
00191 
00192 /* Desktop target shall use stdio for I/O routines */
00193 PmReturn_t
00194 plat_putByte(uint8_t b)
00195 {
00196     int i;
00197     PmReturn_t retval = PM_RET_OK;
00198 
00199     i = putchar(b);
00200     fflush(stdout);
00201 
00202     if ((i != b) || (i == EOF))
00203     {
00204         PM_RAISE(retval, PM_RET_EX_IO);
00205     }
00206 
00207     return retval;
00208 }
00209 
00210 
00211 PmReturn_t
00212 plat_getMsTicks(uint32_t *r_ticks)
00213 {
00214     *r_ticks = pm_timerMsTicks;
00215 
00216     return PM_RET_OK;
00217 }
00218 
00219 
00220 void
00221 plat_reportError(PmReturn_t result)
00222 {
00223 
00224 #ifdef HAVE_DEBUG_INFO
00225 #define LEN_FNLOOKUP 26
00226 #define LEN_EXNLOOKUP 17
00227 
00228     uint8_t res;
00229     pPmFrame_t pframe;
00230     pPmObj_t pstr;
00231     PmReturn_t retval;
00232     uint8_t bcindex;
00233     uint16_t bcsum;
00234     uint16_t linesum;
00235     uint16_t len_lnotab;
00236     uint8_t const *plnotab;
00237     uint16_t i;
00238 
00239     /* This table should match src/vm/fileid.txt */
00240     char const * const fnlookup[LEN_FNLOOKUP] = {
00241         "<no file>",
00242         "codeobj.c",
00243         "dict.c",
00244         "frame.c",
00245         "func.c",
00246         "global.c",
00247         "heap.c",
00248         "img.c",
00249         "int.c",
00250         "interp.c",
00251         "pmstdlib_nat.c",
00252         "list.c",
00253         "main.c",
00254         "mem.c",
00255         "module.c",
00256         "obj.c",
00257         "seglist.c",
00258         "sli.c",
00259         "strobj.c",
00260         "tuple.c",
00261         "seq.c",
00262         "pm.c",
00263         "thread.c",
00264         "float.c",
00265         "class.c",
00266         "bytearray.c",
00267     };
00268 
00269     /* This table should match src/vm/pm.h PmReturn_t */
00270     char const * const exnlookup[LEN_EXNLOOKUP] = {
00271         "Exception",
00272         "SystemExit",
00273         "IoError",
00274         "ZeroDivisionError",
00275         "AssertionError",
00276         "AttributeError",
00277         "ImportError",
00278         "IndexError",
00279         "KeyError",
00280         "MemoryError",
00281         "NameError",
00282         "SyntaxError",
00283         "SystemError",
00284         "TypeError",
00285         "ValueError",
00286         "StopIteration",
00287         "Warning",
00288     };
00289 
00290     /* Print traceback */
00291     printf("Traceback (most recent call first):\n");
00292 
00293     /* Get the top frame */
00294     pframe = gVmGlobal.pthread->pframe;
00295 
00296     /* If it's the native frame, print the native function name */
00297     if (pframe == (pPmFrame_t)&(gVmGlobal.nativeframe))
00298     {
00299 
00300         /* The last name in the names tuple of the code obj is the name */
00301         retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
00302                                f_co->co_names, -1, &pstr);
00303         if ((retval) != PM_RET_OK)
00304         {
00305             printf("  Unable to get native func name.\n");
00306             return;
00307         }
00308         else
00309         {
00310             printf("  %s() __NATIVE__\n", ((pPmString_t)pstr)->val);
00311         }
00312 
00313         /* Get the frame that called the native frame */
00314         pframe = (pPmFrame_t)gVmGlobal.nativeframe.nf_back;
00315     }
00316 
00317     /* Print the remaining frame stack */
00318     for (; pframe != C_NULL; pframe = pframe->fo_back)
00319     {
00320         /* The last name in the names tuple of the code obj is the name */
00321         retval = tuple_getItem((pPmObj_t)pframe->fo_func->f_co->co_names,
00322                                -1,
00323                                &pstr);
00324         if ((retval) != PM_RET_OK) break;
00325 
00326         /*
00327          * Get the line number of the current bytecode. Algorithm comes from:
00328          * http://svn.python.org/view/python/trunk/Objects/lnotab_notes.txt?view=markup
00329          */
00330         bcindex = pframe->fo_ip - pframe->fo_func->f_co->co_codeaddr;
00331         plnotab = pframe->fo_func->f_co->co_lnotab;
00332         len_lnotab = mem_getWord(MEMSPACE_PROG, &plnotab);
00333         bcsum = 0;
00334         linesum = pframe->fo_func->f_co->co_firstlineno;
00335         for (i = 0; i < len_lnotab; i += 2)
00336         {
00337             bcsum += mem_getByte(MEMSPACE_PROG, &plnotab);
00338             if (bcsum > bcindex) break;
00339             linesum += mem_getByte(MEMSPACE_PROG, &plnotab);
00340         }
00341         printf("  File \"%s\", line %d, in %s\n",
00342                ((pPmFrame_t)pframe)->fo_func->f_co->co_filename,
00343                linesum,
00344                ((pPmString_t)pstr)->val);
00345     }
00346 
00347     /* Print error */
00348     res = (uint8_t)result;
00349     if ((res > 0) && ((res - PM_RET_EX) < LEN_EXNLOOKUP))
00350     {
00351         printf("%s", exnlookup[res - PM_RET_EX]);
00352     }
00353     else
00354     {
00355         printf("Error code 0x%02X", result);
00356     }
00357     printf(" detected by ");
00358 
00359     if ((gVmGlobal.errFileId > 0) && (gVmGlobal.errFileId < LEN_FNLOOKUP))
00360     {
00361         printf("%s:", fnlookup[gVmGlobal.errFileId]);
00362     }
00363     else
00364     {
00365         printf("FileId 0x%02X line ", gVmGlobal.errFileId);
00366     }
00367     printf("%d\n", gVmGlobal.errLineNum);
00368 
00369 #else /* HAVE_DEBUG_INFO */
00370 
00371     /* Print error */
00372     printf("Error:     0x%02X\n", result);
00373     printf("  Release: 0x%02X\n", gVmGlobal.errVmRelease);
00374     printf("  FileId:  0x%02X\n", gVmGlobal.errFileId);
00375     printf("  LineNum: %d\n", gVmGlobal.errLineNum);
00376 
00377     /* Print traceback */
00378     {
00379         pPmObj_t pframe;
00380         pPmObj_t pstr;
00381         PmReturn_t retval;
00382 
00383         printf("Traceback (top first):\n");
00384 
00385         /* Get the top frame */
00386         pframe = (pPmObj_t)gVmGlobal.pthread->pframe;
00387 
00388         /* If it's the native frame, print the native function name */
00389         if (pframe == (pPmObj_t)&(gVmGlobal.nativeframe))
00390         {
00391 
00392             /* The last name in the names tuple of the code obj is the name */
00393             retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
00394                                    f_co->co_names, -1, &pstr);
00395             if ((retval) != PM_RET_OK)
00396             {
00397                 printf("  Unable to get native func name.\n");
00398                 return;
00399             }
00400             else
00401             {
00402                 printf("  %s() __NATIVE__\n", ((pPmString_t)pstr)->val);
00403             }
00404 
00405             /* Get the frame that called the native frame */
00406             pframe = (pPmObj_t)gVmGlobal.nativeframe.nf_back;
00407         }
00408 
00409         /* Print the remaining frame stack */
00410         for (;
00411              pframe != C_NULL;
00412              pframe = (pPmObj_t)((pPmFrame_t)pframe)->fo_back)
00413         {
00414             /* The last name in the names tuple of the code obj is the name */
00415             retval = tuple_getItem((pPmObj_t)((pPmFrame_t)pframe)->
00416                                    fo_func->f_co->co_names, -1, &pstr);
00417             if ((retval) != PM_RET_OK) break;
00418 
00419             printf("  %s()\n", ((pPmString_t)pstr)->val);
00420         }
00421         printf("  <module>.\n");
00422     }
00423 #endif /* HAVE_DEBUG_INFO */
00424 }

Generated on Mon Oct 18 07:40:46 2010 for Python-on-a-chip by  doxygen 1.5.9