summaryrefslogtreecommitdiff
path: root/macros.pl
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-06-19 15:04:18 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-06-19 15:04:18 -0700
commitd2456590fc2216fd871ae566c9478176024d2e45 (patch)
tree0bf01b205495249c295913640ac70a111ff2fbd0 /macros.pl
parent9dee352dee05eb26da8f867cc0cbb429e5e8d9a1 (diff)
downloadnasm-d2456590fc2216fd871ae566c9478176024d2e45.tar.gz
nasm-d2456590fc2216fd871ae566c9478176024d2e45.tar.bz2
nasm-d2456590fc2216fd871ae566c9478176024d2e45.zip
preproc: add support for builtin include modules (%use)
Add a builtin equivalent to the %include directive called %use. %use includes a standard macro file compiled into the binary; these come from the macros/ directory in the source code. The idea here is to be able to provide optional macro packages with the distribution, without adding complex host filesystem dependencies.
Diffstat (limited to 'macros.pl')
-rwxr-xr-xmacros.pl122
1 files changed, 100 insertions, 22 deletions
diff --git a/macros.pl b/macros.pl
index 7bba2b1..c22185b 100755
--- a/macros.pl
+++ b/macros.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl
#
# macros.pl produce macros.c from standard.mac
#
@@ -7,42 +7,58 @@
# redistributable under the license given in the file "LICENSE"
# distributed in the NASM archive.
-use strict;
+require 'phash.ph';
my $fname;
my $line = 0;
my $index = 0;
-my $tasm_count;
+my $tasm_count = 0;
-undef $tasm_count;
+open(OUT,">macros.c") or die "unable to open macros.c\n";
-open(OUTPUT,">macros.c") or die "unable to open macros.c\n";
+print OUT "/*\n";
+print OUT " * Do not edit - this file auto-generated by macros.pl from:\n";
+print OUT " * ", join(' ', @ARGV), "\n";
+print OUT " */\n";
+print OUT "\n";
+print OUT "#include \"tables.h\"\n";
+print OUT "#include \"nasmlib.h\"\n";
+print OUT "#include \"hashtbl.h\"\n";
+print OUT "\n";
+print OUT "const char * const nasm_stdmac[] = {";
-print OUTPUT "/*\n";
-print OUTPUT " * Do not edit - this file auto-generated by macros.pl from:\n";
-print OUTPUT " * ", join(' ', @ARGV), "\n";
-print OUTPUT " */\n";
-print OUTPUT "\n";
-print OUTPUT "#include \"tables.h\"\n";
-print OUTPUT "\n";
-print OUTPUT "const char * const nasm_stdmac[] = {";
+my $nmodule = 0;
+my @module_list = ();
+my %module_number = ();
+my %module_index = ();
+my $module;
foreach $fname ( @ARGV ) {
open(INPUT,$fname) or die "unable to open $fname\n";
- print OUTPUT "\n /* From $fname */\n";
+ print OUT "\n /* From $fname */\n";
while (<INPUT>) {
$line++;
chomp;
if (m/^\s*\*END\*TASM\*MACROS\*\s*$/) {
$tasm_count = $index;
- print OUTPUT " /* End of TASM macros */\n";
+ print OUT " /* End of TASM macros */\n";
+ } elsif (m/^USE:\s*(\S+)\s*$/) {
+ $module = $1;
+ if (defined($module_number{$module})) {
+ die "$0: $fname: duplicate module: $module\n";
+ }
+ printf OUT " /* %4d */ NULL,\n", $index++;
+ print OUT " /* %use $module */\n";
+ push(@module_list, $module);
+ $module_number{$module} = $nmodule++;
+ $module_index{$module} = $index;
} elsif (m/^\s*((\s*([^\"\';\s]+|\"[^\"]*\"|\'[^\']*\'))*)\s*(;.*)?$/) {
$_ = $1;
+ s/(\s)\s+/$1/g;
s/\\/\\\\/g;
s/"/\\"/g;
if (length > 0) {
- print OUTPUT " \"$_\",\n";
- $index++;
+ printf OUT " /* %4d */ \"%s\",\n", $index++, $_;
}
} else {
die "$fname:$line: error unterminated quote";
@@ -50,8 +66,70 @@ foreach $fname ( @ARGV ) {
}
close(INPUT);
}
-print OUTPUT "\n NULL\n};\n\n";
-$tasm_count = $index unless ( defined($tasm_count) );
-print OUTPUT "const char * const * nasm_stdmac_after_tasm = ",
- "&nasm_stdmac[$tasm_count];\n";
-close(OUTPUT);
+printf OUT " /* %4d */ NULL\n};\n\n", $index++;
+print OUT "const char * const * const nasm_stdmac_after_tasm = ",
+ "&nasm_stdmac[$tasm_count];\n\n";
+
+my @hashinfo = gen_perfect_hash(\%module_number);
+if (!@hashinfo) {
+ die "$0: no hash found\n";
+}
+# Paranoia...
+verify_hash_table(\%module_number, \@hashinfo);
+my ($n, $sv, $g) = @hashinfo;
+die if ($n & ($n-1));
+
+print OUT "const char * const *nasm_stdmac_find_module(const char *module)\n";
+print OUT "{\n";
+print OUT " static const struct {\n";
+print OUT " const char *module;\n";
+print OUT " const char * const *macros;\n";
+print OUT " } modules[$nmodule] = {\n";
+foreach $module (@module_list) {
+ printf OUT " { \"%s\", nasm_stdmac+%d },\n",
+ $module, $module_index{$module};
+}
+print OUT " };\n";
+
+# Put a large value in unused slots. This makes it extremely unlikely
+# that any combination that involves unused slot will pass the range test.
+# This speeds up rejection of unrecognized tokens, i.e. identifiers.
+print OUT "#define UNUSED 16383\n";
+
+print OUT " static const int16_t hash1[$n] = {\n";
+for ($i = 0; $i < $n; $i++) {
+ my $h = ${$g}[$i*2+0];
+ print OUT " ", defined($h) ? $h : 'UNUSED', ",\n";
+}
+print OUT " };\n";
+
+print OUT " static const int16_t hash2[$n] = {\n";
+for ($i = 0; $i < $n; $i++) {
+ my $h = ${$g}[$i*2+1];
+ print OUT " ", defined($h) ? $h : 'UNUSED', ",\n";
+}
+print OUT " };\n";
+
+print OUT " uint32_t k1, k2;\n";
+print OUT " uint64_t crc;\n";
+# For correct overflow behavior, "ix" should be unsigned of the same
+# width as the hash arrays.
+print OUT " uint16_t ix;\n";
+print OUT "\n";
+
+printf OUT " crc = crc64i(UINT64_C(0x%08x%08x), module);\n",
+ $$sv[0], $$sv[1];
+print OUT " k1 = (uint32_t)crc;\n";
+print OUT " k2 = (uint32_t)(crc >> 32);\n";
+print OUT "\n";
+printf OUT " ix = hash1[k1 & 0x%x] + hash2[k2 & 0x%x];\n", $n-1, $n-1;
+printf OUT " if (ix >= %d)\n", scalar(@module_list);
+print OUT " return NULL;\n";
+print OUT "\n";
+print OUT " if (nasm_stricmp(modules[ix].module, module))\n";
+print OUT " return NULL;\n";
+print OUT "\n";
+print OUT " return modules[ix].macros;\n";
+print OUT "}\n";
+
+close(OUT);