Mercurial > hg > Document > Growi
view Gears/Xv6/src/gearsTools/generate_stub.pl.md @ 2:b6c284fd5ae4
backup 2020-12-16
author | autobackup |
---|---|
date | Wed, 16 Dec 2020 15:11:16 +0900 |
parents | e12992dca4a0 |
children |
line wrap: on
line source
# generate_stub.pl - 入力した.cbcファイル、Interfaceのヘッダファイルを元に.cのファイルを作成する - 別にcbc->cに変換するわけではなく、マクロや `*_stub`CodeGearを生成する ## %var ```perl if (/^\s*(.*)\s+(\w+);$/ ) { my $ttype = $1; my $tname = $2; if ($ttype =~ /^(union|struct|const)?\s*(\w+)/) { if ($1 ne 'const') { $ttype = $2; } else { $ttype = "const $2"; } } $var{$name}->{$tname} = $ttype; ``` - `__code`の引数で使う変数がこの`%var`に登録される - Interfaceのフィードにあるかないかで生成されるマクロが異なる - ここで`%var`には `$name`と`$tname(変数名)`, `$ttype(型名)`が登録される - `$ttype`は`struct|union`は外された状態で登録される - これらは `typedef`で外された型名でも使えるので、そちらで生成している - そのため`Gearef`のマクロではstructを外した状態で書かれる - constの場合は `const char`で1つの型なので、constが来ていたらconstを戻している - いずれにせよポインタの`*`はここでは落とさなければならない - `if ($ttype =~ /^(union|struct|const)?\s*(\w+)/)`の正規表現でポインタを外している # TODO ## OutPutDataGearが2つ存在するケース Stackのinterfaceで言うところの`get2`と`pop2`のケース ```c typedef struct Stack<Type, Impl>{ union Data* stack; union Data* data; union Data* data1; /* Type* stack; */ /* Type* data; */ /* Type* data1; */ __code whenEmpty(...); __code clear(Impl* stack,__code next(...)); __code push(Impl* stack,Type* data, __code next(...)); __code pop(Impl* stack, __code next(Type* data, ...)); __code pop2(Impl* stack, __code next(Type* data, Type* data1, ...)); __code isEmpty(Impl* stack, __code next(...), __code whenEmpty(...)); __code get(Impl* stack, __code next(Type* data, ...)); __code get2(Impl* stack, __code next(Type* data, Type* data1, ...)); __code next(...); } Stack; ``` `pop2`と`get2`はそれぞれ`__code next`に2つの出力が存在する - これを取り出して来るのは`pop2`などの呼び出し元が設定したContinuationによって異なる 例えばRedBlackTreeの例題では、このように呼び出している ```c __code insertCase3(struct RedBlackTree* tree) { struct Stack* nodeStack = tree->nodeStack; struct Node* uncle; if (tree->grandparent->left == tree->parent) { uncle = tree->grandparent->right; } else { uncle = tree->grandparent->left; } if (uncle && (uncle->color == Red)) { // do insertcase1 on grandparent, stack must be pop by two tree->parent->color = Black; uncle->color = Black; tree->grandparent->color = Red; tree->current = tree->grandparent; goto nodeStack->pop2(insertCase1); } goto insertCase4(); } ``` 上の例題では `goto nodeStack->pop2(insertCase1);`の部分が相当する - Stackの実装はnodeStack - pop2に渡している継続は`insertCase1` この場合、insertCase1はstubでStackのInterfaceから値を2つ取り出す必要がある - 現状のgenerate_stubはこの出力に対応していないので、👇のようなstubを静的に書いている ``` __code insertCase1_stub(struct Context* context) { goto insertCase1(context, &Gearef(context, Tree)->tree->Tree.tree->RedBlackTree, &context->data[D_Stack]->Stack.data->Node, &context->data[D_Stack]->Stack.data1->Node); } ``` ### やりたいこと - 呼び出すAPIの出力に応じて、継続先のstubをいい感じに整形する - 呼び出した先のInterfaceがなんであるかを判定する必要がありそう