Mercurial > hg > CbC > old > device
changeset 59:eeca07d1b1c2
*** empty log message ***
author | kono |
---|---|
date | Wed, 19 Feb 2003 21:22:19 +0900 |
parents | 727c280bdd25 |
children | aa779bcffef7 |
files | Changes Idea Makefile mc-parse.c mc.h |
diffstat | 5 files changed, 1668 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Changes Wed Feb 19 21:22:19 2003 +0900 @@ -0,0 +1,1621 @@ + +Thu Nov 25 17:27:12 JST 1999 + +subroutine call がない +局所変数もない +その代わり、大域変数を多用する +大域変数のスコープは局所的 +Fortran の用に局所変数は静的に取る +recursion する時には、自分で保存する +subroutine call時のレジスタのセーブも局所的に行う +それは、ちょっと変じゃない? +やっぱりデフォルトのフレームは持ち歩くか? + +recursive call とそうでないのを区別するか? + +fp は用意する方が良い + +関数定義と同時に、それ専用のfpの構造体を用意する + +C をcompileする時には、stackを持ち歩く + fp = (struct func_state *)stack +えっと、どこに代入するの? そういう問題もあるわけね。 +じゃあ、fpは特別? それは気に入らないな。static +なfpにすれば良いわけね。 + +func(void *stack) { + static struct func_state { + static struct func_state *fp; + int local1; + brahbrah... + } func_state; // ここまで hidden + func_state.fp = (stack -= sizeof(struct func_state)); +} + +func_state をとってくる演算子があった方が良い? そうね。 + func.state +ぐらい? + +fp->local1 みたいなことだけするなら、C と同じになる。 + +call する時のarguemnt も、 + static な func_state に置く + stack 上の func_state に置く +という二通りの選択肢がある。Cと互換なら、当然、後者。 + +Recursive なら後者だが、この言語は状態遷移を記述するから、static +なものでも良いはず。 + +Internal function は? あってもいいんだけど... + +Recursive call する時には、 fp をsaveする必要があるね。 + (--(struct func_state *)stack) = fp; + call callee(&fp->arg,continuation,stack); +call しても、戻って来ないから... continuation は一般的にはcode +だから... それは Internal function にするか。 + +continuation に一般的にcompileする方法を考えないといけないか。 +self は必要なわけね? + +言語の名前も考えないといかんなぁ。 + +C からのコンパイラも書かないといけないのか... + +Mon Dec 13 18:53:04 JST 1999 + +compiler based で、内部で partial evaluation できる? + +func をdatabaseとして扱えないなら、それはできない。 + +しかし、状態遷移としては取り扱える。 + + func.state + func.code + +みたいな形にしてpartial evaluationすれば良い + +でも止まるのか? + +textual でない、中間的なコード表現があった方が良い? <-> interpreter? + +Prolog ではなんでいけないの? --> Unification が重いから + +Sat Nov 27 13:50:41 JST 1999 + +func.state とか作るのだったら、 + struct { + struct { + int i; + } state; + state *code = { + i = i+1; + }; + } name; +みたいな形で、それ自体を構造化すれば? で、代入すると部分評価される。 +代入も可能。なるほど。 + *name.code; +値はあるわけ? 値は &state でしょうね。 +self があれば、 + struct { + struct { + int i; + } state, + *code = { + self->i = self->i+1; + }; + } name; +かな。self = state だよね。 + +union の拡張もあわせて議論すると... + +Partial evalutator をセマンティクスや実行系にいれておくことは可能か? + +byte code とか仮想マシンだったら可能。そうでない場合は? + +いずれにせよ、構造体のタグのunique性を修正しないとだめだな。 + +ヘッダファイルはどうするの? + +Mon Dec 13 18:53:18 JST 1999 + +library との整合性は? + +exec sequence では、 + (--(struct func_state *)stack) = fp; + call callee(&fp->arg); +という形でpointerだけ渡すの? それは変だよね。 + +値渡しにするとすれば、複数の値を渡せたほうが良い。 + + func(void *stack) { + static struct func_state { + static struct func_state *fp; + int local1; + brahbrah... + } func_state; // ここまで hidden + func_state.fp = (stack -= sizeof(struct func_state)); + } + +の引数自体が、構造体であるべき。 + + func( + struct void *stack + ) { + static struct func_state { + static struct func_state *fp; + int local1; + brahbrah... + } func_state; // ここまで hidden + func_state.fp = (stack -= sizeof(struct func_state)); + } + +で、構造体に register storage を許す。 + + func( + static struct argment { + register void *stack; + register void *continuation; + } + ) { + static struct func_state { + static struct func_state *fp; + int local1; + brahbrah... + } func_state; // ここまで hidden + func_state.fp = (stack -= sizeof(struct func_state)); + } + +すると、caller の方も、構造体を引数とするのが自然。 + + call caller( + static struct argment { + register void *stack; + register void *continuation; + } arg = {a,b}; + ) + +みたいな。もちろん、この構造体はインタフェースと呼ばれる。 + +argument は、callee にあった方が良いけど、caller 側にあっても +良い。register なんかは、そう。 + + caller(interface caller_arg = {a,b,c}) +みたいなsyntax かな。 + caller->interface = {a,b,c}; + *caller->code; +を、 + caller(a,b,c); +と称する。 + +function には、interface と code と state があることになる。 + +state にアクセスする時のlockは? protected state? synchonized state かな? +もちろん、sequential implementatoinでは、そんなものはいらない。 + +function { + interface: + register int a; + register struct self self; + state: + int b; + serialized int c; + code: + b = a; +} + +int にvoid value を定義する。実装は重くなるけど... + +serialzed の semantics は? + +もう少しmicro-Cに近く! + +carring state と static state。 + +Mon Dec 13 19:42:41 JST 1999 + +interface に regsiter keyword を使うのは、あまりに +実装よりすぎる。でも、でないと状態にできない? +そんなことはないか。やっぱりcaller側のstatic 領域に +直接書き込む? + +だとCより遅そう。でも、引数に40個とかかかれたら... + +Wed Dec 15 14:09:49 JST 1999 + +C と互換にする? + goto function(argments); + goto *continuation(argments); +みたいな感じで。 + +stackの管理は? どうせ、library との互換はとらないと +いけないんだから... + +local 変数がある場合は stack を動かす。でも、戻す奴がいない。 +closure 化するか? + +return した時の挙動が複雑になる。大域returnするわけだら。 + +argments をstatic 領域にかきこむ方式だと互換性がとれない。 +stack 上の frmae pointer 上にないとダメだから。 + +両立させるのは無理か? つまり、これだと、呼び出された方の +frame semantics は、C と互換になる。だから、stackの直後に +frame pointer があると思っている (そうか? ) frame pointer +stack pointer に沿って移動した直後に、そこからのoffset +で引数を操作することになる。 + +つまり、それはだめだったことじゃない? つまり、goto だと、 +frame pointer は、stack の直後とは限らないから。前の +frmae pointer 相対に引数にアクセスしてくれれば別だけどね。 + +stack に引数を積むのは容認して、goto の場合は、向こう側で +stack を畳むってのは? ということは、普通の関数と定義の +方法を変えるってことか。ま、悪くはないか。 + +すると、goto のsemantics は、C と互換になる。それを受ける +方が異なることをする。それは、なんかおかしいな。それに、 +それだと関数呼び出しが軽くならない... + +ということは、やはり、C のcall は、call funciton で +実現して、その他の呼び出しは、すべて、goto 扱いに +する方が正しいだろう。 + +問題は、この言語の関数をcallされた時だな。dual entry にして、 +call の時と、goto の時を区別するか。 + func: stack processing + func_goto: normal processing + ... +みたいな感じ。でも、return はないから... + +このあたりも自分で記述できる言語であるべきだよね。その通り。 +つまり、C とのstub も自分で記述すると言うことか。 + +protocol function { + interface c { + register "%esp" struct { + entry code ret(int); + void *fp; + } *sp; + register "%ebp" void *fp; + }; + code function_code { + fp = sp; + sp += sizeof(struct local); + struct local *local = sp; + + local->i = 1; + goto *fp->ret(local->i),sp=fp; // return(local->i); + }; +} + +みたいな感じでさ。さっすが、アセンブラ。いまいちreturnが汚いけど。 +まぁ、return はそのままreturnでもいいけどさ。 + +あ、これは良いかも知れない。code が複数かけるから。 + +state 以外は、consitent state であることを保証しない。ってのは? +local 変数は使っても良いけど、call/goto の前後で、値を保証しないか... + +うーん、だんだん炸裂してるなぁ。 + +だから、レジスタに対するマッピングの記述と、そうでない部分の +記述は分離するべきでしょうね。 + + +全部一辺に実装するわけにはいかないからぁ... + +Thu Dec 16 13:44:21 JST 1999 + +lock は状態遷移レベルで実現するのだから、self などを +使ってlockする必要はないはず。 + +全体の直列化は、状態遷移レベルで、 + lock(storage) -> transition +みたいな形で記述すれば良い。この当たりを、どのように記述するかは +もう少し先送りしよう。 + + +引数はレジスタ渡しにしよう。長い引数は、呼び出し側の領域への +ポインタとする。実装を規定しても良い。そうすれば、varargs +みたいなものはなくなる。だいたい、なんで、そんなものがいるんだろう? +配列を渡せばいいじゃん。 + +なので、引数は一つ(or 二つ)に限るという方法もある。 + +とすると、やはり、前もって静的領域や動的領域を確保することは +できない。 + +この言語では動的領域は自分で確保するわけだから、その点は問題ない。 + +Thu Dec 16 20:24:55 JST 1999 + +とすると関数呼び出しは、 + # register save + # set 1st argument in register %eax + # set 2nd argument in register %ecx + # set extra aguments in save area + # set extra argument pointer in %edx + jmp function +という形式になるわけね。second を処理するのはめんどくさいから一つ +にしよう。 + +えーと、frame pointer はないけど、コンパイルの手順からすると +あった方が良い。しかし、frame pointer そのものをstatic +にとるのはまずい。だから、frame pointer がfirst argment +ということにする方が正しい。とすると引数は、さらに、その +後と言うわけか。 + f(fp,argment) +fp を渡すのにさらにargment をレジスタで渡すのはおかしい。おかしいけど、 +ま、良いか。 + +return しないなら、return type の定義をとるのは変だな。 + +f(fp,arg1,arg2,arg3) とすると、それぞれが決まったレジスタに入って、 +多い分は配列にあると思われる。ふむふむ... + fp->xx +でアクセスすれば、そのまま局所変数になる。全部、配列で +送っても良い。 + + .set label,value + +で as は値をセットするようですね。 + +関数コールの後は戻って来ないから後始末の心配はしなくてよい。 +frame pointer を使ったら自分で面倒を見ること。 + +だと + a = atoi(s); +みたいなことはできない... + +普通のCの定義と交じると間違いやすい。 + +とすると、struct と同様に、 + protocol + code + interface + state +を用意するわけね。時間あるのかぁ? + +とりあえず、register 渡しのfunction 定義とgoto文を実装する。 + +code name(register "%ebp" void *arg) { + goto name(arg); +} + +ぐらいかな? で、first argment が必ずregisterにのるようにしないと +いけない。register storage class を入れて、 + register "%ebp" void *arg +とかするわけね。 + +ってことは、まず、レジスタを実装しないといけないわけね。 + +で、stack を使った演算は、一応、そのままにする? それでも動くはず。 +式の途中でgotoは使えないんだから、それでいいはず。 + +で、それから、これを拡張していく。 + +interface c { + register "%ebp" void *arg; +} +code name(interface c) { + goto name(c.arg); // c. は省略可能 +} + +とかね。さらに、 + +protocol name { + interface c { + register "%ebp" void *arg; + } + code name(interface c) { + goto name(arg); + } + code name1(interface c) { + goto name(arg); + } +} + +などとするわけか。なんと、これが C と共存するわけね。うーん。 + +Fri Dec 31 11:44:03 JST 1999 + +code でなくて、別な名前のほうが良くない? segment? action? + +レジスタ名が入るのは、やっぱりいや。optionalには許す。 + +interface は構造体のようなものだから... 構造体でいいんじゃない? +構造体の場合は... malloc する? う、うーん。malloc するとして、 +いつfree するの? + +再入するときには、壊れてていいんじゃない? multi-thread でなければね。 +multi thread では、状態は、レジスタ経由または、thread local に持つ +必要がある。static は、だから thread local に持たなくてはならない。 +大域変数に割り振っちゃだめ。でも、いまは、やめて + +interface は、とりあえず、二つまでの値渡しにしよう。 + self と arg +ですね。 + +もう少し拡張しやすいコンパイラがいいなぁ。 + + code name (c,a) + struct state *c; struct arg *a; + { + goto name(arg); + } + +local 変数は? この互換性の問題かぁ。 + +KL/1 を意識して、interface は heap に置くことにしても良い。 +GC は言語に入れておくべきだが、interfaceは machine independent +であるべき。だとすれば use/forget みたいものはいるだろう。 +でも今のところは考える必要はない。 + +えーと、 + code name (c,a) + struct state *c; struct arg *a; + { + int i; + goto name(arg); + } +の時の一時変数iはどうするの? 基本的にはレジスタ割り当てだけど... +使用させない? んー、大胆な御意見。まぁ、やっぱりheapに割り当てちゃう +のが簡単か。でも、どうせ抜ける時にはいらなくなるわけだから... + +ほんらい、この変数は、次のcallでは必要無くなるのが普通。 + +とにかく、レジスタ変数は必要なんでしょう? + +だから、GC と合わせて言語を設計すべきだよね。API を規定して、 +異なるGCを選択できるようにする。 + +Sat Jan 1 22:40:22 JST 2000 + +とーにかく、 storage class regisgter を実装しよう。 + + stmode=REGISTER + +で、local storage とおなじ扱いとする + static register? は、ない。 + +symbol table に storage class をたせば? dsp==EXTRN で判定しているから、 +local 変数が36以上あるとおかしくなるぞ? + +sc は GVAR/LVAR だけど、regsiter は LVAR の特殊な奴だから、 +sc に入れるほうが正しいか... + +Sun Jan 2 01:47:17 JST 2000 + +register 変数はできました。けど、regsiter を二つ使うと、 +一杯になってしまうので、REGISTER6 でコンパイルしないと +結構ひどい。が、register 変数を%esi,%edi に割り当てれば +いいか。 + +Sun Jan 2 04:43:04 JST 2000 + +で、 + code name (c,a) + struct state *c; struct arg *a; + { + goto name(c); + } +の一時変数無しは実装できます。引数は二つまでね。 + + .file "tmp.c" + .version "01.01" +gcc2_compiled.: +.text +# +# code name(c,a) + .align 2 +.globl code +code: + .type code,@function +# struct state *c; struct arg *a; +# { +# goto name(c); + movl %esi,%esi + jmp name +_5: + .size code,_5-code + .ident "Micro-C compiled" + +う、すごい。 + +goto 文がめんどくさい。stack をたたんで、jmp すれば +よいだけだが.. + +Sun Jan 2 11:17:50 JST 2000 + +普通のcallをcontinuation baseにすることができる? + +Sun Jan 2 20:28:45 JST 2000 + +goto 文だけど、やはり、一度、expr で生成してから、top level +で jump code を生成しよう。 + +Tue Jan 4 03:32:55 JST 2000 + +code をtypeにしないと、 + code *p; +とか書けないね。 + int *p(); +と同じだけどさ。 + + + main(ac,av) + int ac; + char *av[]; + { + goto code1(ac,av); + } + + code code1(ac,av) + int ac; + char *av[]; + { + if (ac) + goto code1(ac,av); + else + goto ac(ac,av); + } + +Tue Jan 4 04:56:56 JST 2000 + +うーん、なんかレジスタにつむ順序が違う +これは、adecl がreverseにつむから。 + +code のretrun + +やはりcodeはtypeにしないとだめ。 + +main() +{ + goto code1(); +} + +とかだと、main に戻って来れない。もちろん、code1() 以降で、 +return するわけにはいかない。(main の disp をcode1 は知り得ない) +goto label をcode1の引数に送れば? + +main() +{ + goto code1(ret); +ret: +} + +これだと、ret がforward labelかどうか分からないけど? + +code1 中で使う中間変数を stack 上にとるのは悪くない。しかし、それを +%ebp 経由でアクセスするということは、main の中間変数を壊すということ。 +それを防ぐには、main 中のgoto codeで、%ebp を修正してやれば良い。 +(今は戻って来ないので問題ない) + +code1 のgoto では、戻って来ないから、その必要はない。しかし、 +label をcode1 中で渡されると、ちょっと気まずい。 + +とすると、それは禁止して、main() 中でstackをたたんでからgotoするか? +そうすると、無限後退して、結局、帰れないことになる... うーん。 + +main() 中のlocal code を許せば、それは解決するが.. + +main() +{ + goto code1(code2); + code code2() { + return; + } +} + +みたいな感じ。でも、そうするとscope rule を変える必要があるので厳しい。 +ま、悪くはないけどね。 + +continuation を明示する方法もある。 + +main() +{ + goto code1(continuation); +} +code code1(ret) +code (*ret)(); +{ + goto *ret; +} + +かな? call/cc ? + +label へのgotoを許すのもいいけど、 +でも、label を許すと、すごくspagettyにならない? + + +Tue Jan 4 11:47:24 JST 2000 + +contiunation じゃなくて、return keyword を使おう。 +(実際、continuation と少し違うし) +type が少し変になるけど、まあ良い。 + +int +main() +{ + goto code1(return); +} +code code1(ret) +code (*ret)(int); +{ + goto *ret(3); +} + +だな。prototype も付けないといけないか。 + +Tue Jan 4 12:21:44 JST 2000 + +これだとmethodがすべてstatic になってしまう。dynamic なmethod +呼び出しにするには? dipatcher を自分で作ることになる。かなり +めんどくさいが... + +code method(obj,arg) +{ +} + +か、あるいは、inline にするか... #define のかわりに inline ねぇ。 +これはあとで考えて良い。 + +Tue Jan 4 14:22:19 JST 2000 + +main の変数を書き潰すのと、gotgo (*reg)(123) での値は、 +register 渡しで、current register にのらないので、 +結局、return label は専用に作る必要がある。 + +Tue Jan 4 18:14:07 JST 2000 + +stack を継ぎ足して、呼び出す方式を取れば、call by value +のregister 渡しを制限する必要は無くなる。 + +複数の値を返すことも容易だ。 + + .file "tmp.c" + .version "01.01" +gcc2_compiled.: +.text +# +# code name(a,b,c,d,e,f) + .align 2 +.globl code +code: + .type code,@function +# struct arg *a,*b,*c,*d,*e,*f; +# { +# int g; +# goto name(a,b,d,e,f); + jmp name +_5: + .size code,_5-code + .ident "Micro-C compiled" + +おお?! + %esp new %esp = old %esp - 12 -4 + %ebp-4 = g + %esi = a + %edi = b + %ebp = old %esp 0 + %ebp+4 = c code_arg_offset=0 + %ebp+8 = d + %ebp+12 = e + %ebp+16 = f + +interface は付けよう! というか、 + goto name(struct {xxxx}) +みたいな感じで良いわけね。どれをregisterにいれるかと言う問題はあるが。 + +で、どうやってcallすればいいわけ? emit_pushするかわりにpush +する? + +うう、これでは、だめか。code argument の数が変わると、 +ebp をいちいち動かすことになる。そこにはold sp があるから +そいつもコピーする必要がある。 + + %esp new %esp = old %esp - 20 + %ebp-20 = g + %esi = a + %edi = b + %ebp-16 = c code_arg_offset= -16 ((nargs-max_reg)*int_size) + %ebp-12 = d + %ebp-8 = e + %ebp-4 = f + %ebp = old %esp 0 + +そうか、function からcallする時には、local 変数を書き潰して良い。 + +# goto name(a,b,d,e,f); + + %esp new %esp = old %esp - 20 + %ebp-20 = g + %esi = a + %edi = b + %ebp-16 = c code_arg_offset= -16 ((nargs-max_reg)*int_size) + %ebp-12 = d + %ebp-8 = e + %ebp-4 = f + %ebp = old %esp 0 disp=0 (*) + local1 <----16 local variable + %edx -12 <- disp_offset + %ecx -8 + %ebx -4 + %ebp = %esp 0 + %eip 4 <- arg_offset + +となる。ということは、pushl %ebp は、間違い。 + +だけど、%ebp をそのまま使うのは良くない。disp_offset がかかっているから。 +だから、もう一度 pushl %ebp したほうがよい。しかし、push する先は、 +上の、(*)。 + leave movl %ebp,%esp + popl %ebp +じゃなかったか? + +Thu Jan 6 13:00:33 JST 2000 + +できたね。これでとりあえず動くはず。速度は問題だが... +あとは、 + ANSI-C prototype + ANSI-C prototype check + Interface Definietion + GC support + Direct handling of Frame +だね。簡単に出来そう? たぶん... + +Fri Jan 7 09:42:53 JST 2000 + +goto 文が動いてなかった。あと peep hole optimization version も +作るか? + +continuation として label を送れるようにするべきか? +そうすると便利なんだけど、ちょっと、汚いプログラムが +出来るようになる。あと、送り側の環境(frame)を維持する +必要がある。ま、できなくはないか... + +そうすると、label が値を持つようになる。 + a = label:; +とか。うーん。label:(a,b,c) {}; みたいな形で、parallel 代入を許すと言う +手もあるね。 + +こちらの方がCとの相性は良いが... main() { label:(){ ... } } +みたいなnestを許すかどうかと言う問題がある。 +変数の参照を許さなければ、特に問題はない。 + +a = label: は、二重の意味があるなぁ。 + +言語の名前。DinnerBell II とか? join も入れる? + code entry_a().entry_b() {} +ですか? parallel call も? + +Fri Jan 7 19:53:53 JST 2000 + +いまのままだと return が環境を持ってないから、大域脱出できない。 +まぁ、環境を入れてもいいんだけど、どこに置くかと言う問題が +あるね。 + +そうじゃなくて、return 側で判断するか? + retrun(ID) +みたいな形でIDで判断する。そうすれば、return 側でID +を見て判断できる。けど... + +まぁ、はやり、環境を持って歩く方がいいかなぁ。でも、 +引き渡しているから、二つ引き渡して、片方を使われたときに、 +反対側が消えてしまうのはいたいよね。今のままならば、 +そういうことは起こらない。 + +continuation 特有の問題を避けるなら、このままでもいいんだが... +contrinuation や環境は、このシステムでは自分で作ることが +できるからね。 + +そうなんだけど.... retlabel や retcont は実はオブジェクト +全体に一つあれば良い。 + +引数を渡すときに、そこに環境へのポインタをいれてやれば良いので、 +解決は割と簡単だが、そうすると、例の構造体を引数で渡すと言う +問題を解決する必要がある。 + +でも、今の実装ならば、まったく同じ変数の構成ならばコピーは +実際には起こらないわけだから問題ないはず。特に、それを保証するために、 +interface を実装する必要がある。 + +return -> + (void *)old bp + return address + +bp を直接操作できるようにするといいんだけど.... + +Sat Jan 8 08:49:59 JST 2000 + +今は、code 内ではreturnできないわけだけど。実は、return って、 + code return0(i) int i; { return(i); } +か? 今は禁止してないから書けちゃうよね。どういうcodeが出るんだろう? + +doreturn() では retpending をセットしているだけだから、control=1 +のまま。で、code の終りにくるのでエラーになる。checkret は、 +statement の引数で判断するようにしたほうが合理的だろう。 + +大域脱出は結構根が深いよね。途中をスキップされてうれしいか? +destructor と同じで、途中のcodeは全部呼びたいのが普通だろう。 + +bp が同じになるまで return すれば良いわけだよね。 +return と同じで、明示的に環境を引き渡すようにするか。 +type は void * で良い? + +return する時にstackの上限を越えているかどうかを自分でチェックする +必要があるね。誰にreturnするかをcodeで明示すれば良いわけだけど。 + + code return0(i) int i; { return(i); } + +を許して、そこで、frame pointer を大域あるいは渡した引数と +比較して処理する? + code return0(i,env) int i; env *env; { + if (env==self) return(i); + } +あれ? これはおかしいよね。 + code return0(i,env) int i; env *env; { + if (env!=self) { + env->return(); + return(i); + } + } +も、なんか変だよなぁ。呼び出しと逆順に帰りたいわけだが... +実際、逆順には帰っているわけだよね。 + +return の中でこそこそ比較するという技もあるけど。 + +問題は、destructor に渡す情報だよね。もちろん、self で良いわけだが、 +このあたりは、言語外の問題で、それを明示的にしたいから、この言語を +作っているわけなのだから、これを内部で処理するのはおかしい。 + + code return0(i) int i; { return(i); } + +これだと、return の型が合わないと言う問題が生じるな。簡単には +チェックできない。 + int + main() { + code a() { + } + code b() { + return(i); + } + } +にすれば、check はできるようになる。でも、これだと、 + int + main() { + a: { + } + b: { + return(i); + } + } +と差がない。module 化を言語外でやるというのが主旨なのだから、これでは +まずい。これは高級アセンブラなのだから。 + +あそうか、return と、大域脱出時のabortとは、状況が違う。だから、 +別なcode を呼び出さないとだめ。あるいは、値で区別するか。これは、 +logic programming のfail/success と似ている。 + main() { } abort { ... } +でもいいけど? + main() { code abort { ... }; code return { ... }} +かな? + +本来、subroutine call自体が、かなりの省略形なわけだから、これは +仕方がない。今のままで通常のsubroutine callをシミュレートできるのか? + code (struct arg {...},void *sp) { + struct env; + push(sp,arg); + push(env,arg); + } +できるけど、ちょっと重い。やはり、frame pointer を直接操作しないと +だめ。 + +goto 文のほうに、env を一緒に送るものを作ったほうがいいのかも。 + goto (*ret)(),environment; +かな。type は? (void *)? + goto ret(),environment; +にはならないの? そうすれば、自分でthreadを制御できる。environment +の正当性を評価しなくて良いの? まぁ、ねぇ。 + +これは実装は容易だが... goto といちいち書くのが本当にいいのか? +env に対するoperationがあった方がいいなぁ。push とか? + + code return0(i) int i; { return(i); } + +を認めれば、return 擬変数はいらなくなる。 + +でも、実は、return は、caller の引数の数と一致してないといけない +わけだから、 code return0(i) int i; { return(i); } はだめ。env +と一致してないといけない。ということは分離するとまずいんじゃない? +あれ? そんなはずないな。 + +Sun Jan 9 01:15:56 JST 2000 + +やはり、分離してはまずい。もともと、 + goto func(arg); +自体が、 + goto func(arg) with current.env +みたいなものだ。つまり、これは、DinnerBell の、 + self message: arg +と同じ。self->func(arg); でも良い。が、function callと区別が付かないのは +良くない。 + +そうすると、type code はsize int でなくなる。 + code *p = func; +ではいけなくて、 + code p = {func,env}; +でないといけない。実際、 + goto func(arg) +では、current environment を pushl %ebp でstack = current env +に積んでいるわけだから。 + +いずれにせよ、 + struct p = q; +は実装する必要がある。localな、 + code p = {func,env}; +も動くはずだが... + + code (*p)(); + goto (*p)(arg); + +はだから少しおかしい。これは、goto がenv を補っていると考えるべき。 + +このようにすると、常に、 + func,env +の組をcodeとみなすことになる。これは、object と呼ぶべきだ。 +ただ、既存のobjectとは別だよな。actor の方が良い? + +うーん、これでjoinを入れれば、完璧なDinnerBellだな。並列送信はないけど。 + +Sun Jan 9 01:40:05 JST 2000 + +local 変数の初期化はallocation の後に遅らせる必要がある。 +nptr に入れられるはずだよね? nptr に初期化フラグを足すか? + +文途中で出現するlocal変数の初期化。ちゃんと動いているの? + +構造体のcopyは、lcheck を修正すべきでない。 + +Sun Jan 9 08:49:43 JST 2000 + +うーん、なんか修正が多いなぁ。あと、関数呼び出し、goto 文の +構造体への対応か。 + + goto (*code)(); + +が、self env を使うのか、code の先の値を使うのかを区別する +必要がある。もし*を使わないとするとlabel(FNAME)との区別が +つかないぞ。あ、でも、環境を持ち歩くことにしたから、label +へもjumpしようと思えばできるね。 + +並列送信はなくても、この構成ならばstatement単位の並列性を検出するのは +容易だろう。 + +やればできるけど、この修正の量だと1日じゃ終らないかなぁ。 +不動小数点も入れるのでしょう? + +Mon Jan 10 09:00:12 JST 2000 + +引数に構造体を許すには、必ずANSI-Cにする必要がある。難しくは +ないが... + +goto 文には label, code, continuation の3つが来る。 + continuation = code + env + | label +env +なのだが、code/label では、env の内容が異なる。できれば面白いが、 +その価値はあるのか? + +しかし、code , env を分離するとあまりに危険すぎる。どうせgoto +が危険なんだからいいか? その方が簡単。簡単なら、そっちの方法を +とるべきじゃない? うーん。 + +return の関数依存性はなくした方が良い。 +一つにするのは、pop の問題があるので良くないが... + +そうか、ret をenvを指定して戻るようにしたから、leave する必要は +なくなった。そして、push %ebp に相当する部分は、lea -disp(%ebp),%sp +で消去されている。ということは、jump のfunction依存部分はいらない +ということだね。 + +でも、汚いなぁ。read only属性をhardware supportできればなあ。 + +sched_yeilds() 相当を書けるかな? lock は? + +一応、できたけど、やっぱり汚い。 + +Wed Jan 12 16:12:27 JST 2000 + +あは。ANSI prototype はめんどい。 + bexpr() +で、関数での引数の順序と、そのあとの宣言の順序が変わることがある。 +そうすると、うしろの方が優先されてしまう。これは、こまる。 + +そうか、code_arg_offset のような方法だと、ANSI style では、 +困ってしまう。 + +Thu Jan 13 04:46:12 JST 2000 + +# goto name(a,b,d,e,f); + code name { int g; ... + + %esp new %esp = old %esp - 20 + %ebp-20 = g code's local variable + %ebp-12 = f <- new_disp + %ebp-8 = d + %ebp-4 = d + %ebp-0 = c + %edi = b + %esi = a + %ebp = old %esp 0 disp=0 new env + local1 <----16 old local variable ( to be erased ) + %edx -12 <- disp_offset + %ecx -8 + %ebx -4 + %ebp = %esp 0 <- old env + %eip 4 <- arg_offset + + +Thu Jan 13 13:38:24 JST 2000 + +だいたいできたけど、test/tmp7.c のprintf のtype mismatch は +なんなんだろう? ASNI の副作用だろうなぁ。 + +これだと、プロセスの切替えのときには、結構な量のデータを +コピーすることになる。それでもいいんだけど... + +それごと、どっかにとって置く。continuationへの参照みたいなもの +ができないかな。 + +コピーができれば、environment/return の組は動くわけだから、 +それへの参照と切替えがあっても良いよね。 + +Fri Jan 14 12:03:35 JST 2000 + +Libretto のkeyboardが壊れた... control key が効かない... + +printf の参照の問題は解決しました。list2 がlocalなheap +に割り当てているのがいけなかったね。 + +return の処理は、goto 文で処理するより、environment に +returnto する方が良くはないか? + +environment は実は送り先でそれなりの準備が必要。 +new-environment() みたいなlibrary があれば、thread にできる。 + +join は? + +funcall を用意すると良いね。 + +Mon Jan 17 15:23:34 JST 2000 + + struct aa f1() { + return bb; + } + +みたいなのは? 関数の型か代入の型を見て、crn にpointerを渡して、 +あとでcopyしてから stack を畳む。 + + # bb=f1(aaa); + movl $bb,%eax + pushl %eax + movl $aaa,%eax + pushl %eax + call main2 + popl %edx + copy %eax,%edx,$400 + addl $400,%esp + # return a1; + +あ、でも、それだと、local変数を返したときに困るね。leave; ret; +してはいけなくて... + +あ、やっぱり、こういう場合はコピー先をmain2に引き渡しているみたいね。 + void f1(struct aa *ret) { + *ret = bb ; + return; + } +と同じか。これは簡単。 + f1().a[55] +みたいな場合は、局所変数に強制的に取ってしまうみたいね。それはそうだ... +が、うちの実装だとちょっと厳しいか。 + leal $-sizeof(struct),%esp + pushl %esp +なんだけど、関数呼び出しの途中ではできないから.... + + # main(ac,av) + # int ac; + .align 2 + .globl main + main: + .type main,@function + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + # char *av[]; + # { + # register int i; + # register char *p; + # int j = 3; + # struct { int b; void (*c)(struct aa); } q = {3,main1},r; + # + # j = 3; + subl $20,%esp + +このsublを後から指定してやればOk。 + +でも、それだと jump の時にずれない? ずれるか? ずれるね。うーん。 +実行時にチェックしてやるのも変だし。 + +まぁ、それほど必要な機能ではないんだけど。 + +これもcontinuationを渡してやると言う手法が使えないことはないんだが... + +関数呼び出しの最初にやってやればいいか。それでできるかな? + + +Sun Feb 20 23:59:16 JST 2000 + +MIPS のcall frame + + $sp = $fp + local variables + saved register (including $31 = return address) + +mask は使用したレジスタのbit pattern + -4 は何? + + 18 .mask 0xc0000000,-4 + 19 .fmask 0x00000000,0 + 20 0000 D0FFBD27 subu $sp,$sp,48 + 21 0004 2C00BFAF sw $31,44($sp) + 22 0008 2800BEAF sw $fp,40($sp) + 23 000c 0000000C move $fp,$sp + 24 0010 21F0A003 jal __main + 25 0014 03000224 li $2,0x00000003 # 3 + 26 0018 000082AF sw $2,a + 27 001c 04000224 li $2,0x00000004 # 4 + 28 0020 00C082AF sw $2,b + 29 0024 05000224 li $2,0x00000005 # 5 + 30 0028 000082A3 sb $2,c + 31 002c 06000224 li $2,0x00000006 # 6 + 32 0030 08C082A3 sb $2,d + 33 $L1: + 34 0034 21E8C003 move $sp,$fp # sp not trusted + here + 35 0038 2C00BF8F lw $31,44($sp) + 36 003c 2800BE8F lw $fp,40($sp) + 37 0040 0800E003 addu $sp,$sp,48 + 38 0044 3000BD27 j $31 + 39 .end main + +これと同じようにするならば、regiterの使用数を最初に調べる必要が +あるのだけど、one path compiler である micro-C では、それは +できない。したがって、enter は後ろでする方が良い。 +Mon Jan 20 18:25:27 JST 2003 + +3年間さわってないのかよ。何やってんだ? + +goto 文のバグをとらないといけない。 + +まず、関数引数の構造体の展開。これは、どうってことないはず。 + + goto (*code)(i+1,j,...) + +まず、いじらなくてすむ変数を摘出する。 + + foreach arg + compare + +単純演算 ( op+const , pointer , const assign ) などは、ここで検出する。 +大半は、そのようになるはず。 +レジスタに乗せる分があるから... それには触らないとして... + +複雑なものは、前もって計算しておく。(get_register する) +スタック上かレジスタ上に作る。 + +残りは並列代入となる。再帰的に計算する。 + +えーと、大きな順にやるんだっけ? 小さな順にやるんだっけ? + code f( int a, int b, int c ) { + goto g(b,c,a); + } +みたいなやつだよね。 + + 移動するものを一つ検出する。 + そのために移動が必要なものを移動しておく(再帰) + 代入する + +こんなんでいいのか? ループしない? するよね。ループしたら +get_register する。 + +前の例だと、 + + g(b,c,a) のbに着目する。 + bに代入するコードを出すと、a が壊れる。 + a が必要かどうかを調べる。それは、引数のリストを見ればわかる。 + その前に、a を移動する。a の移動先を見て、 + 空いていれば、移動してOk。しかし、c + なので、 c を見る。と b になるので、ループするのがわかるので、 + b を get_register する。 + で、c が移動できる。で、aを移動して、とっておいたbを代入。 + +Tue Jan 21 22:45:09 JST 2003 + +とりあえず、jump は複雑すぎる。もっと簡単にすることを考える。 +parser 側である程度処理できない? + + goto f(a+3,b(),c); + +などを、 + + a = a+3; + b = b(); + goto f(a,b,c); + +程度に簡略化する。この時、f(a,b,c) は(できるだけ)、元の +関数の引数リストに近付ける。のは無理なので、単純変数 +まで落す。 + +あまり関係ないか。一時変数はどうせいるわけだし。ってこと +みたいね。 + +だとすると、元のコードと、そう変わらんね。前のも、そんなに +悪くないってことか。 + +Wed Jan 22 14:33:12 JST 2003 + +やっぱり、途中で局所変数を増やしたいよね。 + +Fri Jan 31 20:30:36 JST 2003 + +なんか #ifdef / #if がないとだめだな。実装する? +しました。 + +Tue Feb 4 01:04:12 JST 2003 + +## while ((*chptr++ = c = getc(filep->fcb)) != '\n') { +_1120: + movl $10,%eax + movl $8,%ecx + movl filep,%edx + addl %ecx,%edx + movl (%edx),%edx + pushl %edx + xchg %edx,%eax .... edx に$10が入る (なんでxchg?) + call getc + addl $4,%esp + movl %eax,-20(%ebp) c に代入 + movl $chptr,%ecx + pushl %ecx + popl %ebx + movl (%ebx),%ecx ecx にchptrの中身 + addl $1,(%ebx) + movb %al,(%ecx) + subl %edx,%eax eax-edx ($10) + je _1119 + +が壊れる理由なんだけど... + +edx,ecx が破壊されちゃうみたいね。 + +Tue Feb 4 12:17:07 JST 2003 + +ようやっと直したよ... + +use_pointer って、なにもしなくていいんだよね? eax,ebx を避ける +ってことらしいけど。 + +inline/引数付き #define 欲しくない? 置き換えは、local name stack に積んじゃう。 +展開は function で行う。 + +getch を工夫する必要はあるが。置き換えスタックが必要。 + + +Wed Feb 5 01:16:00 JST 2003 + +大域で定義された struct field が大域変数と重なっていると落ちる。 +そりゃそうだけど。どうするの? (直した記憶があるんだけどなぁ...) +struct 毎に field 名とoffset/type の組を持てばい良いんだよね。 + +なんだけど、タグ無しの構造体もあるから、型名の方に付ける必要 +もある。というのは、型名のない構造体もあるから。タグ名には、 +一応、リストがついている。なんかに使う必要があったんでしょう +ね。あ、めんどう。無条件にやっても大域変数名を汚すのを直すの +が難しい。 + +ちょっと、あれだけど、「型名.フィールド名」で登録してしまうのはどう? +型名が後で出て来るところが気まずいが... + +def で登録するときに、nptrにdispを代入せずに、struct field list +(大域変数) に入れて、type の方に、field list (list3(nptr,offset, +type)) を入れれば良い。 + +あとは、strop の方でtypeのlistを見るようにすれば良いわけだ。 + +これなら、簡単に直せるはず。LUSTR/GUSTRなどの区別もなくなるし。 + +Wed Feb 5 02:10:14 JST 2003 + +浮動小数点ねぇ。完全なANSI Cにするのは大変。でも、 +浮動小数点ぐらいないと。 + +code generation part を、さらに分割して、 +複数のコード対応にしやすいようにする。 +おそらく、それほど共有する部分はないけどね。 + +Sample C code をコンパイルして、その結果から(半分手動で) +Micro CbC code generation part を生成する方法を用意する。 + + + +Thu Feb 6 11:47:03 JST 2003 + +Code Segement を単位として使うときに、大域変数はどういう +ように分けるの? static なんかは意味ないよね。 + +もちろん、自然にグループ分けされるわけだけど。 + +あとデータフローだよね。データフローに関しては、 +あんまりやってないなぁ + +Fri Feb 7 14:36:15 JST 2003 + +inline では、必らず、局所変数の増加がある。また、inline +は普通の関数として展開しておく必要もあるらしい。(何故?) + +#define ねぇ。 + + #define c(a,b) g(a+1,b+1) + #define g(a,b) printf("%d %d\n",a+1,b+1); + + main() { + int a,b; + a =1; b = 3; + c(a,b); + } + +local #define がいるんだよね。g の中で a が出て来た時には、 +c のa の置き換えは起こってはいけない。ということは、c +の置き換えはg が始まる前に終っている必要がある。dynamic +scope なんだから、assoc の上乗せで良いはず。 +macro のlevelを定義して、あるレベルでは、それ以前の展開 +を行わないという手法が良いかな。 + + c(a,b) => a=>"a+1", b=>"b+1" + g(a,b) => (a=>"a+1+1",a=>"a+1"), (b=>"b+1+1",a=>"a+1") + +みたいな感じ? + +やっぱり関数解析でマクロ処理をやらせるのは無理かな? 先読みされちゃうし。 + +Sat Feb 8 00:53:52 JST 2003 + +macro は途中まで書きました。置き換えをマクロが呼び出された +時点で cheap に置くと、それを解消するタイミングがない。 +ここだけmallocしても良いが.. + +chptrsave はlistにする必要がある。list で良い。 + +やっぱりmacro levelを見て、自分と一致したassoc valueまで +手繰って置換するんでしょう。そうすれば、置き換える必要は無い。 +ということは、local_define にmflagsを格納する必要がある。 + + c(a,b) => a=>"a", b=>"b" + a=>"a" .. mflag == 1 + g(a,b) => (a=>"a+1+1",a=>"a+1"), (b=>"b+1+1",a=>"a+1") + a=>"a+1" .. mflag == 2 + +macro のもとのnptr が残ってないと、オリジナルを返せない。オ +リジナルは、sc などが破壊されてしまう。ってことは、local macro +は、local table を汚してはいけないってことだよね。ってことは、 +macro table は、もとのとは別に用意する必要がある。 + +#define c(a,b) g(a+1,b+1) +#define g(a,b) printf("%d %d\n",a+2,b+2); + +main() { + int a,b; a ... local + a =1; b = 3; +#ifndef a + c(a, a = "a".. macro mflag==1 + g(a, + a="a+1" mflag==2 + ^ a = "a" mflag==1 + While replacing a in g's body, a should not + be replaced to (original) "a", should be c's a. + b); + /* 3,5 expected */ +#endif +} + +うーむ。ややこしい。 + + main() + c(a,b) mflag++ + a=>"a" mflag ==1 + g(a,b) mflag++; + a=>"a+1" mflag ==2 + ^ is replaced by c's "a" not g's a; +いったん mflag level n で展開したら、それは mflag level n-1 となる。 + +Sat Feb 8 18:13:43 JST 2003 + +いちおう、mflag まではデバッグしたが.... mflag を戻してないんじゃないの? + + ---c(a,b)----------------------- mflag ==1 + a=>hoge, b=>hoga (mflag==1) + ----g(ac,bc)----------------- mflag ==2 + ac=>goge, bc=>goga(mflag==2) + ----printf(a,b)---------- mflag ==3 + a=>poge, b=>poga(mflag==3) + +g が呼び出されると、ac,bc は mflag==1 でのみ置換される。 + +あるテキストを置き換えると、それは置き換えたマクロのmflag level +(つまり一つ少ないレベル)になる。 +置き換え終ったら、元のlevelに戻す。 + +mflag==2のlevel では、mflag==2のlocal macroの展開しかしない。 + +置き換えると、mflag level 1 になるので、そこで mflag==1 のlocal +macro を展開する。mflag==0 は常に展開を行う。 + +Sun Feb 9 11:35:23 JST 2003 + +うーん、なんかtypeが、list とCHARなどと入混じっているじゃん。 + int save = chptrsave; +で、chptrsave が、$chptrsave になってしまう。 + +Sun Feb 9 22:33:36 JST 2003 + + +#define car(e) (heap[(int)(e)]) +#define cadr(e) (heap[((int)(e))+1]) + car(cadr(e)) + +だろ。 + car -> + #define e cadr(e) (mleve=1) + cadr -> + #define e e (mleve=2) + +むぅ。これ、うまくいかないんじゃん。こまったなぁ。 + +#define c(a,b) g(a+1,b+1) +#define g(a,b) printf("%d %d\n",a+1,b+1); + c(a, b); + +こっちもだめじゃん。ふーむ。lisp interpreter のように +作ればいいはずなんだけど。 + +Mon Feb 10 08:10:25 JST 2003 + +結局、list base のinterpreter を実装しました。きちゃないが。 +前の方法でも、頑張ればできるんでしょうけどね。 + +Tue Feb 11 13:50:03 JST 2003 + +struct copy だけど... 関数がstructを返すときに、引数に前もって +積んでおくのでは、そこに値がコピーされてしまうし、あとで、 +スタックをたたんで置くときにきまずい。 + +function call の時に、引数の型のチェックをしてない + +type に -1 とheapの引数が混在しているやつだけど.. +やっぱまずいんじゃないか? + +temproal struct は再利用できるんだけど、dispの変更ができないので +新しく作るしかない。大きいときだけ新しく作るなんていうセコイ +技はあるけど。(そうすると、帰って来た値へのポインタを使えなく +なるが.... 別にいいよね。戻り値それ自身を直接 return する +時もだいじょうぶなはず) + +結局、呼出側で、領域を確保して引き渡すことにしました。この方法だと、 +代入のときに二度コピーする必要もない。 + +register を使用しているかだけじゃなくて、実際にcreg/dregに +値があるかどうかを記憶する必要がある。 + +Wed Feb 12 11:09:22 JST 2003 + +それだけどさ... やっぱりアドホックに実現するのは難しいんじゃないの? + +まぁねぇ。register の場所の確保と、寿命は別だから、それで +いいんだけど、regs flag だけでなんとかならないのかな。 +こういう変更ははまるが虚しい。 + +Thu Feb 13 18:37:36 JST 2003 + +さて、そろそろ jump にとりかかりますか。 + +構造体の引き渡しのシークエンスに使う局所変数の位置がgccと違う... + +そろそろ register は構造体にすべきだね。 + struct register { + int used; + int valued; + char *name; + char *wname; + char *bname; + int type; /* register variable or not */ + int number; + } +virtual/real は、どうする。 + +Sat Feb 15 14:00:03 JST 2003 + +fdecl_struct を構文的に引数が出現するときに行うと、int *f(int +a) などで、* の評価が終る前に、int aが評価されしまう。*obj +のobj を評価し終らないとfのタイプが確定しない。int*f()[] み +たいな場合があるから。(?) なので、gcc と、そろえるためには、 +arg の先頭で fdecl_struct を行う方法ではだめで、fdecl 中であ +とから修正する方が良い。 + +fix しようにも引数リストなんて、存在しないじゃん! + +varargs を実装するのはめんどくさかろう... + +rvalue(expr(),type) では、expr() のtypeをrvalueに引き渡せな +い。でも、type を大域変数にすると、rvalueを異なるタイプで呼 +び出すときにtypeを変更する必要がある。このrvalueのtype の扱 +いは、かなりはまったことがあるので、rvalue(int e,int type)の +方が良いことは確かなんだが... + +struct_push のregisterの扱いが複雑すぎ。なんか、もっと +簡単にならないの? + +Sun Feb 16 07:58:23 JST 2003 + +代入しなくて良いからと言って、ソース +のリストから除いては、上書きを防げない。 + +Sun Feb 16 22:55:58 JST 2003 + +vdisp ってなんだったんだ? + +Mon Feb 17 12:35:39 JST 2003 + +並列代入は出来たみたい。代入は小さいものを先にすべきなのか? +まぁ、できりゃいいんだけど、横に避けるものが大きいのはいや +だよね。 + +Tue Feb 18 11:56:10 JST 2003 + +overraped 用の emit_copy +float/double +long long + +Tue Feb 18 19:34:31 JST 2003 + +code argument の符号を反転させると、list2(LVAR,offset) +のoffsetがアドレスの方向と一致しているという前提が +崩れる。それで、構造体の格納順序がずれてしまう... + +ということは... def(n) でcodeの時はargumentは、局所変数と同じ +扱いでマイナス符号で処理した方が良い。 + +できたみたい。でもさ、 + +int main( int ac, char *av[]) +{ + int n; + goto arg1(0,1,2,3,4,return,environment); +} + +って、きっと return 文がないと、文句を +言われるよね。むむむ。 + +post processing する時にoverrapしてないという保証がない。 + +Wed Feb 19 15:38:55 JST 2003 + +自分自身とのoverrrapを見てないので、 + struct a a,int i + int i,struct a a +みたいな時に自分自身を壊してしまう。なので、emit_copy +が、ちゃんと方向を見て壊さないように処理する必要がある。 + +call bcop でいいじゃん。まね。
--- a/Idea Wed Feb 19 18:48:37 2003 +0900 +++ b/Idea Wed Feb 19 21:22:19 2003 +0900 @@ -1618,4 +1618,15 @@ みたいな時に自分自身を壊してしまう。なので、emit_copy が、ちゃんと方向を見て壊さないように処理する必要がある。 -call bcop でいいじゃん。まね。 +call bcopy でいいじゃん。まね。 + +Wed Feb 19 20:42:07 JST 2003 + +楊さんの C2CbC と CbC2C を、micro C に取り込む。各所に、 +conv->func(); を埋め込む。conv は、構造体。 + + conv: original + c2cbc + cbc2c + +とする。なるほど。
--- a/Makefile Wed Feb 19 18:48:37 2003 +0900 +++ b/Makefile Wed Feb 19 21:22:19 2003 +0900 @@ -1,15 +1,16 @@ CC = gcc -CFLAGS = -g -Wall +CFLAGS = -g -Wall -I. BASE=0 STAGE=1 MFLAGS=$(MFALGS) BASE=$(BASE) STAGE=$(STAGE) MC=mc PRINTF= # printf.c +CONVERTER=conv/c.o conv/c2cbc.o conv/cbc2c.o conv/null.o all: mc -mc : mc-parse.o mc-nop-386.o mc-tree.o - $(CC) -g mc-parse.o mc-nop-386.o mc-tree.o -o $@ +mc : mc-parse.o mc-nop-386.o mc-tree.o $(CONVERTER) + $(CC) -g mc-parse.o mc-nop-386.o mc-tree.o $(CONVERTER) -o $@ tar : make clean tar cBf - . | gzip > ../comp.tgz
--- a/mc-parse.c Wed Feb 19 18:48:37 2003 +0900 +++ b/mc-parse.c Wed Feb 19 21:22:19 2003 +0900 @@ -97,6 +97,7 @@ static void fdecl_struct(int type); static int append3(int p,int a1,int a2); extern int append4(int p,int a1,int a2,int a3); +static void set_converter(char *s); extern void display_ntable(NMTBL *n, char *s); extern void closing(void); @@ -139,6 +140,8 @@ static int struct_return = 0; static int arglist = 0; +Converter *conv = &null_converter; + int main(int argc, char **argv) { @@ -153,18 +156,21 @@ av=argv; for (ac2=1; (ac2 < ac) && (*av[ac2] == '-'); ++ac2) { switch (*(av[ac2]+1)) { - case 'S': case 's': + case 's': lsrc = 1; break; - case 'O': case 'o': + case 'o': ccout = av[ac2]+2; break; - case 'C': case 'c': + case 'c': chk = 1; break; - case 'D': case 'd': + case 'd': debug = 1; break; + case 'C': + if (av[ac2+1]) { set_converter(av[ac2+1]); ac2++; } + break; default: error(OPTION); exit(1); @@ -338,6 +344,16 @@ } void +set_converter(char *s) +{ + chptr = s; + if (macroeq("c2cbc")) conv=&c2cbc_converter; + else if (macroeq("cbc2c")) conv=&cbc2c_converter; + else if (macroeq("c")) conv=&c_converter; + else conv=&null_converter; +} + +void reserve(char *s, int d) { NMTBL *nptr;
--- a/mc.h Wed Feb 19 18:48:37 2003 +0900 +++ b/mc.h Wed Feb 19 21:22:19 2003 +0900 @@ -223,4 +223,15 @@ #define cadddr(e) (heap[((int)(e))+3]) +typedef struct converter { + void (*print)(char *); +} Converter; + +#include "conv/c2cbc.h" +#include "conv/cbc2c.h" +#include "conv/c.h" +#include "conv/null.h" + +EXTERN Converter *conv; + /* end */