File:  [Isaki's NoNo m68k/m88k emulator] / nono / lib / monitor_id.pl
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:48 2026 UTC (3 months ago) by root
Branches: MAIN, Isaki
CVS tags: v027, v026, v025, HEAD
nono 1.5.0

#
# nono
# Copyright (C) 2021 nono project
# Licensed under nono-license.txt
#

# monitor_id.txt から monitor_id.h, monitor_id.cpp を作る。
#
# usage: perl monitor_id.pl monitor_id.txt

{
	$defs = "";
	$body = "";
	$first_mon_id = "";
	$first_sub_id = "";
	@maxes = ();

	# $#ARGV は引数の数-1。ここでいう引数は monitor_id.pl の後ろから。
	if ($#ARGV != 0) {
		die "usage: $0 <id.txt>\n";
	}

	# ファイル名
	$infile = $ARGV[0];
	$hdrfile = $infile;
	$srcfile = $infile;
	$hdrfile =~ s/txt$/h/;
	$srcfile =~ s/txt$/cpp/;

	# 先頭に一つダミーエントリを入れる。
	# (あまりサポートしてないけど) wxMac ではメニュー ID が 0 だと死ぬので。
	$id = "ID_MONITOR_zeroth_dummy_for_wxmac";
	$mon_defs .= "\t$id = 0,\n";
	$mon_body .= "\t{ $id, },\n";

	open(IN, $infile) || die "Cannot open infile: ${infile}\n";
	while (<IN>) {
		# Remove comments.
		chomp;
		s/#.*$//;
		next if /^$/;

		@names = split(/\s+/);

		if ($names[0] =~ /([^%]+)%(\d+)/) {
			# %n なら 0..(n-1) に展開
			$basename = $1;
			$atnum = $2 + 0;

			# モニタの最大数はここが一次情報なので、これから定数を作る
			push(@maxes, "MAX_${basename}_MONITOR = ${atnum}");
			for ($i = 0; $i < $atnum; $i++) {
				@rep_names = ();
				foreach $n (@names) {
					$r = $n;
					$r =~ s/%${atnum}/${i}/g;
					$r =~ s/%/${i}/g;
					push(@rep_names, $r);
				}
				parse_line(@rep_names);
			}
		} else {
			# default
			parse_line(@names);
		}
	}
	close(IN);

	# 文字列として出力
	$hdrnew = "";
	$srcnew = "";

	$hdrnew .= "// Generated from ${0}\n";
	$hdrnew .= "\n";
	$hdrnew .= $mon_defs;
	$hdrnew .= "\n";
	$hdrnew .= $sub_defs;
	$hdrnew .= "\n";
	$hdrnew .= "\tID_MONITOR_START = ${first_mon_id},\n";
	$hdrnew .= "\tID_MONITOR_END = ${last_mon_id},\n";
	$hdrnew .= "\tID_MONITOR_MAX = ID_MONITOR_END + 1,\n";
	$hdrnew .= "\tID_SUBWIN_START = ${first_sub_id},\n";
	$hdrnew .= "\tID_SUBWIN_END = ${last_sub_id},\n";
	$hdrnew .= "\tID_SUBWIN_MAX = ID_SUBWIN_END + 1,\n";
	$hdrnew .= "\n";
	$hdrnew .= "\t// これは enum じゃないけど自動生成の都合でここに置く\n";
	foreach $str (@maxes) {
		$hdrnew .= "\t${str},\n";
	}

	$srcnew .= "// Generated from ${0}\n";
	$srcnew .= "\n";
	$srcnew .= "#include \"monitor.h\"\n";
	$srcnew .= "\n";
	$srcnew .= "/*static*/ const std::vector<MonitorManager::MonitorInfo>\n";
	$srcnew .= "MonitorManager::info {\n";
	$srcnew .= $mon_body;
	$srcnew .= "\n";
	$srcnew .= $sub_body;
	$srcnew .= "};\n";
	$srcnew .= "\n";
	$srcnew .= "/*static*/ const std::vector<std::pair<uint, const char *>>\n";
	$srcnew .= "Monitor::idtext {\n";
	$srcnew .= $label_body;
	$srcnew .= "};\n";

	# 更新があれば書き出す
	do_update($hdrfile, $hdrnew);
	do_update($srcfile, $srcnew);

	exit 0;
}

sub parse_line()
{
	local @names = @_;
	local $id = shift(@names);
	local $type = shift(@names);
	local $flag = shift(@names);
	local $first;

	if ($#names == -1) {
		# If <names...> are ommited, use ID instead.
		$first = lc $id;
	} else {
		# If <names...> are specified, use it.
		$first = shift(@names);
	}

	if ($type eq "m") {
		$id = "ID_MONITOR_${id}";
		if ($first_mon_id eq "") {
			$first_mon_id = $id;
		}
		$last_mon_id = $id;
	} else {
		$id = "ID_SUBWIN_${id}";
		if ($first_sub_id eq "") {
			$first_sub_id = $id;
		}
		$last_sub_id = $id;
	}

	if ($flag eq ".") {
		# フラグ省略時(モニタの場合)は vmcap を参照することはないはず
		$flag = "NONE";
	}
	# フラグは '|' で並べることが出来る。
	@flags = split(/\|/, $flag);
	@caps = map { "VMCap::".$_ } @flags;
	$cap = join('|', @caps);

	$defs = "\t${id},\n";
	$body = "\t{ ${id},\t${cap},\t{ \"${first}\"";
	foreach $name (@names) {
		$body .= ", \"${name}\"";
	}
	$body .= " } },\n";

	if ($type eq "m") {
		$mon_defs .= $defs;
		$mon_body .= $body;
	} else {
		$sub_defs .= $defs;
		$sub_body .= $body;
	}

	# デバッグ用の ID と文字列の対応表
	$label_body .= "\t{ ${id}, \"${id}\" },\n";
}

sub do_update()
{
	local $filename = $_[0];
	local $filebody = $_[1];
	local $old;
	local @contents;

	# まず出力先ファイルを文字列として読み込む
	$old = "";
	if (open(IN, $filename)) {
		@contents = <IN>;
		$old = join("", @contents);
		close(IN);
	}

	# 全文を比較して変更があれば出力
	if ($filebody ne $old) {
		open(OUT, ">${filename}") || die "Cannot open ${filename}\n";
		print OUT $filebody;
		close(OUT);
		print "Updated ${filename}\n";
	}
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.