picoc - A very small C interpreter - Google Project Hosting

http://code.google.com/p/picoc/ より

Picoc V2.1 Cインタプリター               
           (改造 V2.12a)                 2011.5.15 下村

使い方

1)コマンドライン

    picoc [-Iインクルードパス] {-i | -s cソースファイル名 [引数] | cソースファイル名1 cソースファイル名2 ... [引数]

    [-Iインクルードパス]: -I (大文字)のすぐ後からパスを指定する。1番目の引数で指定する。
    [引数]:  インタープリタで実行すうるプログラムに渡す引数の1番目は必ず"-" 2番目以降に引数を定義する。

 ・Cプログラムの実行

    > picoc myprogram.c

    複数のソースからなる場合は、

    > picoc myprog1.c myprog2.c myprog3.c

    引数がある場合は、一つ目は必ず "-" その後にパラメータを指定する。

    > picoc myprogram.c - arg1 arg2

 ・スクリプトとしての実行

    Cプログラムで書いたプログラムをスクリプトとして実行。
    通常使う関数のインクルードファイルは自動で読み込みます。
    main() は必要としません。
    ファイルの先頭から命令を実行します。

    > picoc -s myprogram.c

    ------- Start myprogram.c-----------

    printf("Starting my script\n");

    int total = 0;
    int i;
    for (i = 0; i < 10; i++)
    {
        printf("i = %d\n", i);
        total += i;
    }

    printf("The total is %d\n", total);
    ------- End  myprogram.c-----------

    結果は、

    $ ./picoc -s myscript.c
    Starting my script
    i = 0
    i = 1
    i = 2
    i = 3
    i = 4
    i = 5
    i = 6
    i = 7
    i = 8
    i = 9
    The total is 45

 ・インタラクティブモードの実行

    Cプログラムの即時実行。

    > picoc -i

    例:
    $ ./picoc -i
    starting picoc v2.12a
    picoc> char inbuf[80];
    picoc> gets(inbuf);
    hello!
    picoc> printf("I got: %s\n", inbuf);
    I got: hello!
    
    ・・・

    インタラクティブモードの終了は、WindowsではCtrl+Z です。

    変数、関数は同じ名前で上書きはしてくれませんので、削除・登録です。
    削除は、 delete {変数名|関数名};

    $ ./picoc -i
    starting picoc v2.12a
    picoc> int fred = 1234;
    picoc> printf("fred = %d\n", fred);
    fred = 1234
    picoc> delete fred;
    picoc> char *fred = "hello";
    picoc> printf("fred = '%s'\n", fred);
    fred = 'hello'


    ■■■■■■■■■■■■
    機能追加
  ■-Iパス名     --- インクルードファイルのパス名定義引数追加。
  ■unsigned char --- 定義追加。
  ■deltype 名前; --- struct定義の削除。
  ■my_show;    ----- 変数、関数の戻り値の表示をする。
    ■変数名;     ----- 変数の値表示。int, long, double, char , string
    ■関数名(引数);   ----- 関数の戻り値表示。
  ■my_list o_o;    ----- 全部のグローバル変数一覧, 構造体等の型一覧
  ■my_list xxx;   ----- 名前別のグローバル変数, 構造体等の検索
  ■my_list type_xxx; --- タイプ別のグローバル変数一覧
            xxx部分  void,int,short,char,long,unsignedchar,unsignedint,
                            unsignedshort,unsignedlong,float,function,macro,
                            pointer,array,struct,union,enum,label,typedef,
    ■sqlite3   ---- SQLITE3を使えるようにした。(いまはスタティックリンク)
                        sqlite3が新しくなったらソースを置き換えること。
    ■マイコン制御 ---- シリアル接続したマイコンボードでMPUのポート、I/O周辺レジスタ、メモリ
                        を読み書きする。

                        c記述のプロトタイプ
                        int MpuDebug_portlist();   <--- 使えるCOMポート一覧
                        int MpuDebug_open(int);    <--- COMポートを番号で指定してオープン
                        void MpuDebug_close(void); <--- 現在オープンしているCOMポートをクローズ
                        unsigned long GetLongRegister(unsigned long *, int *); <--- CPUレジスター、メモリLongデータ読み出し(アドレス、エラーフラグポインタ)
                        unsigned short GetWordRegister(unsigned short *, int *); <--- CPUレジスター、メモリShortデータ読み出し(アドレス、エラーフラグポインタ)
                        unsigned char GetByteRegister(unsigned char *, int *); <--- CPUレジスター、メモリByteデータ読み出し(アドレス、エラーフラグポインタ)
                        int SetLongRegister(unsigned long *, unsigned long); <--- CPUレジスター、メモリにLongにデータ設定(アドレス、データ)
                        int SetWordRegister(unsigned short *, unsigned short);<--- CPUレジスター、メモリにShortデータ設定(アドレス、データ)
                        int SetByteRegister(unsigned char *, unsigned char); <--- CPUレジスター、メモリにByteデータ設定(アドレス、データ)
                        int LoadProgram(char *, unsigned long);     <--- プログラムをCPUメモリにロードする(MOTファイル名、アドレス)
                        int RunProgram(unsigned long);              <--- CPUメモリにある関数(もどらない)を実行する(アドレス)
                        unsigned long CallProgram(unsigned long, unsigned long); <--- CPUメモリにある関数を呼び出す(アドレス、引数1)
                        int ReadMem(unsigned char *,unsigned char *, unsigned long, int); <--- CPUメモリを読み出す(手元のメモリアドレス、長さ、{0|1|2}) ▼0:Byte 1:Word 2:Long読み出し
                        int WriteMem(unsigned char *,unsigned char *, unsigned long); <--- CPUメモリにバイト単位で書き込む(CPUアドレス、手元のメモリアドレス、長さ)
                        unsigned char GetByteBit(unsigned char *, int, int, int *);  <--- CPUレジスター、メモリByteビットデータ読み込み(アドレス、開始位置、ビット数、エラーフラグポインタ)
                        unsigned char SetByteBit(unsigned char *, int, int, unsigned char); <--- CPUレジスター、メモリByteビットデータ書込み(アドレス、開始位置、ビット数、データ)
                        unsigned short GetShortBit(unsigned short *, int, int, int *); <--- CPUレジスター、メモリWordビットデータ読み込み(アドレス、開始位置、ビット数、エラーフラグポインタ)
                        unsigned short SetShortBit(unsigned short *, int, int, unsigned short); <--- CPUレジスター、メモリWoprdビットデータ書込み(アドレス、開始位置、ビット数、データ)
                        unsigned long GetLongBit(unsigned long *, int, int, int *); <--- CPUレジスター、メモリLongビットデータ読み込み(アドレス、開始位置、ビット数、エラーフラグポインタ)
                        unsigned long SetLongBit(unsigned long *, int, int, unsigned long); <--- CPUレジスター、メモリLongビットデータ読み込み(アドレス、開始位置、ビット数、データ)
                        int EraseRomAll(unsigned long); <--- CPU外付けフラッシュROM全消去(ROM先頭アドレス)
                        int EraseRomSecter(unsigned long); <--- CPU外付けフラッシュROMセクタ消去(ROMセクタ先頭アドレス)
                        void WriteRomData(unsigned char*, unsigned long); <--- CPU外付けフラッシュROMにプログラム書込み(MOTファイル名、ROMアドレス)

    starting picoc v2.12a
    picoc> int a = 8;
    picoc> my_show;
    picoc> int b = 7;
    7:char
    picoc> a;
    8:int
    picoc> b;
    7:int
    picoc> a + b;
    15:int
    picoc> a * b;
    56:int
    picoc> a / b;
    1:int
    picoc> log10(3);
    0.47712125471966244:double
    picoc> log(3)/log(10);
    0.47712125471966244:double
    picoc> 12+3*a;
    :10: parse error
    picoc> (12+3*a);
    36:int
    picoc> b = 12+3*a;
    36:int
    picoc> b;
    36:int

    picoc> char a = 127;
    picoc> unsigned char b = 127;
    picoc> my_show;
    picoc> ++a;
    128:int           <<== char -> int -> int + 1 -> char 表示はcharにすればいいのだが m(__)m
    picoc> a;
    -128:char
    picoc> ++b;
    128:int
    picoc> b;
    128:unsigned char
    picoc> ++a;
    -127:int
    picoc> a;
    -127:char
    picoc> ++b;
    129:int
    picoc> b;
    129:unsigned char
    picoc> my_list o_o;
    --- List of Grobal Variable (All)
    1 : tcgetpgrp (Function)
    2 : ENOTEMPTY (Int)
    3 : nice (Function)
    4 : getegid (Function)
    5 : EINTR (Int)
    6 : false (Int)
    7 : realloc (Function)
    8 : setpgid (Function)
    9 : sqlite3_get_table (Function)
    10 : isxdigit (Function)
    :
    :
    323 : fflush (Function)
    324 : lineno (Function)
    325 : _IONBF (Int)
    326 : cosh (Function)
    327 : fopen (Function)
    328 : getenv (Function)
    329 : atof (Function)
    330 : ualarm (Function)
    ---- Define Types List ------
    1 : __va_listStruct (Struct)
    2 : __FILEStruct (Struct)
    3 : tm (Struct)
    picoc> my_list type_typedef;
    --- List of Grobal Variable (TypeDef)
    1 : gid_t
    2 : bool
    3 : sqlite3_stmt
    4 : useconds_t
    5 : va_list
    6 : size_t
    7 : pid_t
    8 : time_t
    9 : intptr_t
    10 : FILE
    11 : uid_t
    12 : sqlite3
    13 : ssize_t
    14 : off_t
    15 : clock_t
    ---- Define Types List ------

    picoc> my_list type_float;
    --- List of Grobal Variable (Float)
    1 : M_LOG2E
    2 : M_LOG10E
    3 : M_E
    4 : M_LN2
    5 : M_LN10
    6 : M_PI
    7 : M_PI_2
    8 : M_PI_4
    9 : M_1_PI
    10 : M_2_PI
    11 : M_2_SQRTPI
    12 : M_SQRT2
    13 : M_SQRT1_2
    ---- Define Types List ------

    picoc> M_LN2;
    picoc> my_show;
    picoc> M_LN2;
    0.69314718055994529:double
    picoc> log(2);
    0.69314718055994529:double
    picoc> M_E;
    2.71828182845904510:double
    picoc> char s[10], c;
    10:char
    picoc> strcpy(s , "ABCD");
    "ABCD":string
    picoc> c = *s;
    65:int
    picoc> c;
    65:char
    picoc> *s;
    65:char
    picoc> *(s+1);
                 ^
    :14: invalid operation
    picoc> *(&s[0]+2);
    67:char
    picoc> *c;
              ^
    :15: Invalid Type

    picoc> void abc(void) {
         >   printf("test\n");
         > }
    picoc> struct abc {
         >  int a;
         >  char b;
         > };
    picoc> my_list abc;
    --- Check Grobal Variable (abc)
    1 : abc (Function)
    ---- Define Types List ------
    1 : abc (Struct)
    
    picoc> delete abc;
    picoc> my_list abc;
    --- Check Grobal Variable (abc)
    ---- Define Types List ------
    1 : abc (Struct)
    
    picoc> void abc(void) {
         >   printf("test\n");
         > }
    picoc> my_list abc;
    --- Check Grobal Variable (abc)
    1 : abc (Function)
    ---- Define Types List ------
    1 : abc (Struct)
    
    picoc> deltype abc;
    picoc> my_list abc;
    --- Check Grobal Variable (abc)
    1 : abc (Function)
    ---- Define Types List ------

    DOSウィンドウで
    ..\picoc-new\test-sqlite>picoc -Iinclude phonics.c
    データベース名:phonics.db
    (End:Ctrl+Z) Input Word:show
    | word | phonics | memo |
    ----------------------
    WORD:show ==> (s o u
    (End:Ctrl+Z) Input Word:money
    | word | phonics | memo |
    ----------------------
    WORD:money ==> m o u n i
    (End:Ctrl+Z) Input Word:cut
    | word | phonics | memo |
    ----------------------
    WORD:cut ==> k ^ t
    (End:Ctrl+Z) Input Word:cute
    | word | phonics | memo |
    ----------------------
    WORD:cute ==> k ju: t
    (End:Ctrl+Z) Input Word:valley
    | word | phonics | memo |
    ----------------------
    WORD:valley ==> v ae l i
    (End:Ctrl+Z) Input Word:^Z

    picoc> MpuDebug_portlist();
    COM1
    COM2
    picoc> MpuDebug_open(1);
    picoc> LoadProgram("include\\call_t01.mot", 0x1400);
    アドレス: 00001400 - 0000155D
    Write Block.      15E/     15E
    picoc> printf("%d\n",CallProgram(0x1400,12));
    2
    picoc> #include "include\\rtc.c"
    アドレス: 00001000 - 000011EB
    Write Block.      1EC/     1EC
    年/月/日>2011/5/14
    hh:mm:ss>16:29:55
    (^o^)丿 8秒後にアラーム!!
    Write Block.       10/      10
    Write Block.        C/       C
    11 20 05 00 14 00 16 00 29 00 55 00 00 00 00 00 |. ......).U.....
    11 20 05 00 14 00 16 00 30 00 03 00             |. ......0...
    2011年05月14日(土) 16:29:55
    2011年05月14日(土) 16:29:56
    2011年05月14日(土) 16:29:57
    2011年05月14日(土) 16:29:58
    2011年05月14日(土) 16:29:59
    2011年05月14日(土) 16:30:00
    2011年05月14日(土) 16:30:01
    2011年05月14日(土) 16:30:02
    2011年05月14日(土) 16:30:03 ALARM!!
    2011年05月14日(土) 16:30:04
    2011年05月14日(土) 16:30:05
    2011年05月14日(土) 16:30:06
    2011年05月14日(土) 16:30:07
    2011年05月14日(土) 16:30:08
    2011年05月14日(土) 16:30:09
    picoc>

    ------ rtc.c ----------------
    #include "include\\test.c"
    
    #ifndef MDBG_RTC
    #define MDBG_RTC
    
    #define ALARM_TIME 8
    
    struct rtctime {
      short y;
      short m;
      short d;
      short h;
      short min;
      short s;
      short w;
      short alarm;
    };
    struct rtcalrm {
      short y;
      short m;
      short d;
      short h;
      short min;
      short s;
    };
    struct rtctime ltm;
    struct rtcalrm lalm;
    int t1;
    int w, ss, mm, hh;
    char buf[120];
    char *ww[7] = { "日","月","火","水","木","金","土" };
    
    #endif
    
    LoadProgram("include\\call_t02.mot", 0x1000);
    
    printf("年/月/日>"); gets(buf);
    sscanf(buf, "%d/%d/%d", &ltm.y, &ltm.m, &ltm.d);
    w = (ltm.y/1000)&0x0F;
    w = w<<4 | ((ltm.y%1000)/100)&0x0F;
    w = w<<4 | ((ltm.y%100)/10)&0x0F;
    w = w<<4 | (ltm.y%10)&0x0F;
    ltm.y = w;
    ltm.m = ltm.m/10 * 16 + ltm.m % 10;
    ltm.d = ltm.d/10 * 16 + ltm.d % 10;
    printf("hh:mm:ss>"); gets(buf);
    sscanf(buf, "%d:%d:%d", &ltm.h, &ltm.min, &ltm.s);
    mm = ltm.min;
    hh = ltm.h;
    ss = ltm.s;
    ltm.h = ltm.h/10 * 16 + ltm.h % 10;
    ltm.min = ltm.min/10 * 16 + ltm.min % 10;
    ltm.s = ltm.s/10 * 16 + ltm.s % 10;
    ltm.alarm = 0;
    
    ss += ALARM_TIME;
    if( ss > 59) {
        ss = ss - 60;
        mm++;
    }
    if( mm > 59) {
        mm = 0;
        hh++;
    }
    if( hh > 23 ) {
        hh = 0;
    }
    // ちょっと手抜き
    
    lalm.y = ltm.y;
    lalm.m = ltm.m;
    lalm.d = ltm.d;
    lalm.h = hh/10 * 16 + hh % 10;
    lalm.min = mm/10 * 16 + mm % 10;
    lalm.s = ss/10 * 16 + ss %10;
    printf("(^o^)丿 %d秒後にアラーム!!\n", ALARM_TIME);
    WriteMem((unsigned char*)0x11ec, (unsigned char*)&ltm, 16);
    WriteMem((unsigned char*)0x11fc, (unsigned char*)&lalm, 12);
    dump((unsigned char*)&ltm, 16);
    dump((unsigned char*)&lalm, 12);
    CallProgram(0x1000, 0);
    for ( t1 = 0; t1 < 15; t1++) {
        CallProgram(0x1144,0);
        ReadMem((unsigned char*)&ltm, (unsigned char*)0x11ec, 16, 0);
        printf("%04X年%02X月%02X日(%s) %02X:%02X:%02X %s\n", ltm.y, ltm.m, ltm.d, ww[ltm.w], ltm.h, ltm.min, ltm.s, ltm.alarm?"ALARM!!":"");
    }
    -------- rtc.c 終わり -----------

2)環境変数

    プログラム内で持つメモリ領域は基本128KBです。
    変更する場合は環境変数"STACKSIZE" でバイト単位で指定します。


3)修正メモ

    元のはUNIX用なのでWindows用に修正して、VC++ 6.0で作成。

  (1)インタラクティブモードで関数内で変数未定義が発見されたら、次から関数定義が出来なくなる。
       deleteで削除してもだめです。
       ---- 修正。
  (2)インタラクティブモードで複数行のコメントが書けない。
    ---- 修正。
  (3)struct tm構造体はインクルードファイルにして、tm構造体タイプ登録をやめた。
    ---- 修正。
  (4)unsigned char 定義。
    ---- 追加修正。
  (5)インタラクティブモードで変数、関数戻り値、計算結果の内容表示。
    ---- 追加修正。
  (6)char s[10], c; 定義で c = *s; が出来るよう修正。
   *(s+1)はできない。sがポインターと認識しないから。かわりに *(&s[0]+1) とする。
    ---- 追加修正。
  (7)インタラクティブモードで#includeが出来るようにした。
    ---- 修正。
  (8)SQLITE3を扱えるようにした。
    ---- 修正。インクルードファイルは大きすぎるのでいる定義だけincludeする。
  (9)シリアル接続したマイコンを制御できるようにした。
    ---- 追加修正。
  (10)char a[128]が確保できない不具合修正。
    (11)cpuメモリ書込み追加。


4)使えないこと

  (1)setjumpは使えない。
  (2)複数行にまたがるコンスタント定義。
    (3)abc[2][3] = { { 1,2 },{ 3,4} };の配列の初期化定義。
    (4)関数ポインタが定義出来ない。
    (5)構造体のビットフィールドが扱えない。


6)参考

    CインタプリターEiC ---  the EiC project
    http://eic.sourceforge.net/

    コンピュータアルゴリズム事典  奥村晴彦著  技術評論社


一応は動作はしたが保障はしません。
自己責任で確かめてからにして下さい。

Copyright
---------

picoc is published under the "New BSD License".
http://www.opensource.org/licenses/bsd-license.php


Copyright (c) 2009-2011, Zik Saleeba
All rights reserved.

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are 
met:

    * Redistributions of source code must retain the above copyright 
      notice, this list of conditions and the following disclaimer.
      
    * Redistributions in binary form must reproduce the above copyright 
      notice, this list of conditions and the following disclaimer in 
      the documentation and/or other materials provided with the 
      distribution.
      
    * Neither the name of the Zik Saleeba nor the names of its 
      contributors may be used to endorse or promote products derived 
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-----
修正 (c)2011 下村清
-----