generate_stub.plの外観

generate_stub.plの外観

  • 書き直したいので何をしているかを読み解いてみる

# 使用しているモジュール

  • Getopt::Std
    • オプション解析部分
  • File::Path
    • ディレクトリパスを作るmake_pathのみ使用
    • mkdir -pとほぼ同じ

# 流れ

  • ファイルを入力でもらう
  • getDataGear($fh)
  • generateDataGear($fh)
  • おわり

# getDataGear

# 実行に必要な引数

$filename

  • パースする対象のファイルネーム
  • CbCのファイルか.h(ヘッダファイル/Interface想定)が来る

# 内部で使用されている変数

  • $codeGearName
    • gotoで継続する対象のCodeGearの名前が設定される
  • $name
  • $inTypedef
    • 型定義かどうかのファイル
    • つまるところInterfaceのヘッダファイルなら1になっている
    • 具体的には /^typedef struct (\w+)\s*<(.*)>//^typedef struct (\w+)/にヒットすればこのモードになる
  • $described_data_gear

# InTypedefがtrueの時に実行されるもの

Interfaceの定義(読み込んでいる対象がヘッダファイルだった場合)に実行されるのが想定されていそう

  • InTypedefをfalseにするコードが無いので、一度ここに来たらずっとこれが実行されているはず

👇のコードはstruct hoge* foo;int hoge;などがキャプチャされる

  • $ttypeには型名もキャプチャされるケースがある(union, struct, const)
  • 発見されたフィールどは、型名と識別子をハッシュ%varに設定する必要がある
  • この時点では型名のstructなどは外す必要がある
    • そのために、const以外のケースは$ttypeの中身を更に確認して、キャプチャ出来た値を利用する
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# gather type name and type
$dataGear{$name} .= $_;
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";
        }
    }
    $described_data_gear = 1;
    $var{$name}->{$tname} = $ttype;
}

このコードは__codeである場合にキャプチャする

  • Interfaceの定義で、__codeの中だけに引数を書いておけば、静的に書く必要がなくなる機能を実装する際に書かれた
  • __codeのCodeGearの名前は特にキャプチャせず、中の引数をキャプチャしていく
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
if (/__code (\w+)/) {
    next if $described_data_gear;
    my $args = $';
    while ($args =~ /\s*(struct|union|const)?\s*([\w\[\]_]+)\*?\s*(\w+),?/g) {
      #$args eq  (Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...));
      my $const_type = $1;
      my $ttype = $2;
      my $tname = $3;

      $ttype =~ s/(Impl|Isa|Type)/Data/;
      if ($const_type eq 'const') {
        $ttype = "const $ttype";
      }
      $var{$name}->{$tname} = $ttype;
    }
}
if (/^}/) {
    $inTypedef = 0;
}

# falseの時

入力されたファイルがCbCで無いときに実行されるのが想定されている

  • 実際はinTypedefを1にする正規表現のブロックが実行されるまではデフォルトでこのブロックが処理される
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
if (/^typedef struct (\w+)\s*<(.*)>/) {
    $inTypedef = 1;
    $name = $1;
    $dataGear{$name} = $_;
    $var{$name} = {};
    $code{$name} = {};
    $generic{$name} = \split(/,/,$2);
} elsif (/^typedef struct (\w+)/) {
    $inTypedef = 1;
    $name = $1;
    $dataGear{$name} = $_;
    $var{$name} = {};
    $code{$name} = {};
    $generic{$name} = [];
} elsif (/^(\w+)(\*)+ create(\w+)\(/) {
    if (defined $interface) {
       die "duplicate interface $interface\n";
    }
    $interface = $1;
    $implementation = $3;
    if ( -f "$interface.cbc") {
        &getDataGear("$interface.cbc");
    }
} elsif(/^(.*)par goto (\w+)\((.*)\)/) {
    my $codeGearName = $2;
    if ($filename =~ /^(.*)\/(.*)/) {
        $codeGearName = "$1/$codeGearName";
    }
    if ( -f "$codeGearName.cbc") {
        &getCodeGear("$codeGearName.cbc");
    }
} elsif(/^#interface "(.*)"/) {
    # use interface
    my $interfaceHeader = $1;
    next if ($interfaceHeader =~ /context.h/);
    if (-f $interfaceHeader) {
        &getDataGear("$interfaceHeader");
        &getCodeGear("$interfaceHeader");
    }
} elsif (/^\_\_code (\w+)\((.*)\)(.*)/) {
    my $codeGearName = $1;
    if ($filename =~ /^(.*)\/(.*)/) {
        $codeGearName = "$1/$codeGearName";
    }
    if ( -f "$codeGearName.cbc") {
        &getCodeGear("$codeGearName.cbc");
    }
}
next;
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy