|
|
1.1 root 1: #
2: # nono
3: # Copyright (C) 2021 nono project
4: # Licensed under nono-license.txt
5: #
6:
7: # monitor_id.txt から monitor_id.h, monitor_id.cpp を作る。
8: #
9: # usage: perl monitor_id.pl monitor_id.txt
10:
11: {
12: $defs = "";
13: $body = "";
14: $first_mon_id = "";
15: $first_sub_id = "";
1.1.1.3 root 16: @maxes = ();
1.1 root 17:
18: # $#ARGV は引数の数-1。ここでいう引数は monitor_id.pl の後ろから。
19: if ($#ARGV != 0) {
20: die "usage: $0 <id.txt>\n";
21: }
22:
23: # ファイル名
24: $infile = $ARGV[0];
25: $hdrfile = $infile;
26: $srcfile = $infile;
27: $hdrfile =~ s/txt$/h/;
28: $srcfile =~ s/txt$/cpp/;
29:
1.1.1.6 ! root 30: # 先頭に一つダミーエントリを入れる。
! 31: # (あまりサポートしてないけど) wxMac ではメニュー ID が 0 だと死ぬので。
! 32: $id = "ID_MONITOR_zeroth_dummy_for_wxmac";
! 33: $mon_defs .= "\t$id = 0,\n";
! 34: $mon_body .= "\t{ $id, },\n";
! 35:
1.1 root 36: open(IN, $infile) || die "Cannot open infile: ${infile}\n";
37: while (<IN>) {
38: # Remove comments.
39: chomp;
40: s/#.*$//;
41: next if /^$/;
42:
43: @names = split(/\s+/);
44:
1.1.1.3 root 45: if ($names[0] =~ /([^%]+)%(\d+)/) {
46: # %n なら 0..(n-1) に展開
47: $basename = $1;
48: $atnum = $2 + 0;
1.1 root 49:
1.1.1.3 root 50: # モニタの最大数はここが一次情報なので、これから定数を作る
51: push(@maxes, "MAX_${basename}_MONITOR = ${atnum}");
1.1 root 52: for ($i = 0; $i < $atnum; $i++) {
53: @rep_names = ();
54: foreach $n (@names) {
55: $r = $n;
56: $r =~ s/%${atnum}/${i}/g;
1.1.1.4 root 57: $r =~ s/%/${i}/g;
1.1 root 58: push(@rep_names, $r);
59: }
60: parse_line(@rep_names);
61: }
62: } else {
63: # default
64: parse_line(@names);
65: }
66: }
67: close(IN);
68:
69: # 文字列として出力
70: $hdrnew = "";
71: $srcnew = "";
72:
73: $hdrnew .= "// Generated from ${0}\n";
74: $hdrnew .= "\n";
75: $hdrnew .= $mon_defs;
76: $hdrnew .= "\n";
77: $hdrnew .= $sub_defs;
78: $hdrnew .= "\n";
79: $hdrnew .= "\tID_MONITOR_START = ${first_mon_id},\n";
80: $hdrnew .= "\tID_MONITOR_END = ${last_mon_id},\n";
81: $hdrnew .= "\tID_MONITOR_MAX = ID_MONITOR_END + 1,\n";
82: $hdrnew .= "\tID_SUBWIN_START = ${first_sub_id},\n";
83: $hdrnew .= "\tID_SUBWIN_END = ${last_sub_id},\n";
84: $hdrnew .= "\tID_SUBWIN_MAX = ID_SUBWIN_END + 1,\n";
85: $hdrnew .= "\n";
86: $hdrnew .= "\t// これは enum じゃないけど自動生成の都合でここに置く\n";
1.1.1.3 root 87: foreach $str (@maxes) {
88: $hdrnew .= "\t${str},\n";
89: }
1.1 root 90:
91: $srcnew .= "// Generated from ${0}\n";
92: $srcnew .= "\n";
93: $srcnew .= "#include \"monitor.h\"\n";
94: $srcnew .= "\n";
95: $srcnew .= "/*static*/ const std::vector<MonitorManager::MonitorInfo>\n";
96: $srcnew .= "MonitorManager::info {\n";
97: $srcnew .= $mon_body;
98: $srcnew .= "\n";
99: $srcnew .= $sub_body;
100: $srcnew .= "};\n";
1.1.1.3 root 101: $srcnew .= "\n";
1.1.1.5 root 102: $srcnew .= "/*static*/ const std::vector<std::pair<uint, const char *>>\n";
1.1.1.3 root 103: $srcnew .= "Monitor::idtext {\n";
104: $srcnew .= $label_body;
105: $srcnew .= "};\n";
1.1 root 106:
107: # 更新があれば書き出す
108: do_update($hdrfile, $hdrnew);
109: do_update($srcfile, $srcnew);
110:
111: exit 0;
112: }
113:
114: sub parse_line()
115: {
116: local @names = @_;
117: local $id = shift(@names);
118: local $type = shift(@names);
119: local $flag = shift(@names);
120: local $first;
121:
122: if ($#names == -1) {
123: # If <names...> are ommited, use ID instead.
124: $first = lc $id;
125: } else {
126: # If <names...> are specified, use it.
127: $first = shift(@names);
128: }
129:
130: if ($type eq "m") {
131: $id = "ID_MONITOR_${id}";
132: if ($first_mon_id eq "") {
133: $first_mon_id = $id;
134: }
135: $last_mon_id = $id;
136: } else {
137: $id = "ID_SUBWIN_${id}";
138: if ($first_sub_id eq "") {
139: $first_sub_id = $id;
140: }
141: $last_sub_id = $id;
142: }
143:
1.1.1.4 root 144: if ($flag eq ".") {
145: # フラグ省略時(モニタの場合)は vmcap を参照することはないはず
146: $flag = "NONE";
147: }
148: # フラグは '|' で並べることが出来る。
1.1.1.3 root 149: @flags = split(/\|/, $flag);
150: @caps = map { "VMCap::".$_ } @flags;
151: $cap = join('|', @caps);
152:
1.1 root 153: $defs = "\t${id},\n";
1.1.1.3 root 154: $body = "\t{ ${id},\t${cap},\t{ \"${first}\"";
1.1 root 155: foreach $name (@names) {
156: $body .= ", \"${name}\"";
157: }
158: $body .= " } },\n";
159:
160: if ($type eq "m") {
161: $mon_defs .= $defs;
162: $mon_body .= $body;
163: } else {
164: $sub_defs .= $defs;
165: $sub_body .= $body;
166: }
1.1.1.3 root 167:
168: # デバッグ用の ID と文字列の対応表
169: $label_body .= "\t{ ${id}, \"${id}\" },\n";
1.1 root 170: }
171:
172: sub do_update()
173: {
174: local $filename = $_[0];
175: local $filebody = $_[1];
176: local $old;
177: local @contents;
178:
179: # まず出力先ファイルを文字列として読み込む
180: $old = "";
181: if (open(IN, $filename)) {
182: @contents = <IN>;
183: $old = join("", @contents);
184: close(IN);
185: }
186:
187: # 全文を比較して変更があれば出力
188: if ($filebody ne $old) {
189: open(OUT, ">${filename}") || die "Cannot open ${filename}\n";
190: print OUT $filebody;
191: close(OUT);
192: print "Updated ${filename}\n";
193: }
194: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.