#
使用しているモジュール
- 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;
|