mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-12-15 09:09:58 +08:00
2d5cf17130
Include the version number in the output (misc/nasmtok.el) and add a rule for generating it to the Makefiles. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
216 lines
4.4 KiB
Perl
Executable File
216 lines
4.4 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
#
|
|
# Automatically produce some tables useful for a NASM major mode
|
|
#
|
|
|
|
use integer;
|
|
use strict;
|
|
use File::Spec;
|
|
|
|
my($outfile, $srcdir, $objdir) = @ARGV;
|
|
|
|
if (!defined($outfile)) {
|
|
die "Usage: $0 outfile srcdir objdir\n";
|
|
}
|
|
|
|
$srcdir = File::Spec->curdir() unless (defined($srcdir));
|
|
$objdir = $srcdir unless (defined($objdir));
|
|
|
|
my %tokens = ();
|
|
|
|
sub xpush($@) {
|
|
my $ref = shift @_;
|
|
|
|
$$ref = [] unless (defined($$ref));
|
|
return push(@$$ref, @_);
|
|
}
|
|
|
|
# Combine some specific token types
|
|
my %override = ( 'id' => 'special',
|
|
'float' => 'function',
|
|
'floatize' => 'function',
|
|
'strfunc' => 'function',
|
|
'ifunc' => 'function',
|
|
'insn' => 'instruction',
|
|
'reg' => 'register',
|
|
'seg' => 'special',
|
|
'wrt' => 'special' );
|
|
|
|
sub read_tokhash_c($) {
|
|
my($tokhash_c) = @_;
|
|
|
|
open(my $th, '<', $tokhash_c)
|
|
or die "$0:$tokhash_c: $!\n";
|
|
|
|
my $l;
|
|
my $tokendata = 0;
|
|
while (defined($l = <$th>)) {
|
|
if ($l =~ /\bstruct tokendata tokendata\[/) {
|
|
$tokendata = 1;
|
|
next;
|
|
} elsif (!$tokendata) {
|
|
next;
|
|
}
|
|
|
|
last if ($l =~ /\}\;/);
|
|
|
|
if ($l =~ /^\s*\{\s*\"(.*?)\",.*?,\s*TOKEN_(\w+),.*\}/) {
|
|
my $token = $1;
|
|
my $type = lc($2);
|
|
|
|
if ($override{$type}) {
|
|
$type = $override{$type};
|
|
} elsif ($token !~ /^\w/) {
|
|
$type = 'operator';
|
|
} elsif ($token =~ /^__\?masm_.*\?__$/) {
|
|
next;
|
|
}
|
|
xpush(\$tokens{$type}, $token);
|
|
if ($token =~ /^__\?(.*)\?__$/) {
|
|
# Also encode the "user" (macro) form without __?...?__
|
|
xpush(\$tokens{$type}, $1);
|
|
}
|
|
}
|
|
}
|
|
close($th);
|
|
}
|
|
|
|
sub read_pptok_c($) {
|
|
my($pptok_c) = @_;
|
|
|
|
open(my $pt, '<', $pptok_c)
|
|
or die "$0:$pptok_c: $!\n";
|
|
|
|
my $l;
|
|
my $pp_dir = 0;
|
|
|
|
while (defined($l = <$pt>)) {
|
|
if ($l =~ /\bpp_directives\[/) {
|
|
$pp_dir = 1;
|
|
next;
|
|
} elsif (!$pp_dir) {
|
|
next;
|
|
}
|
|
|
|
last if ($l =~ /\}\;/);
|
|
|
|
if ($l =~ /^\s*\"(.*?)\"/) {
|
|
xpush(\$tokens{'pp-directive'}, $1);
|
|
}
|
|
}
|
|
close($pt);
|
|
}
|
|
|
|
sub read_directiv_dat($) {
|
|
my($directiv_dat) = @_;
|
|
|
|
open(my $dd, '<', $directiv_dat)
|
|
or die "$0:$directiv_dat: $!\n";
|
|
|
|
my $l;
|
|
my $directiv = 0;
|
|
|
|
while (defined($l = <$dd>)) {
|
|
if ($l =~ /^\; ---.*?(pragma)?/) {
|
|
$directiv = ($1 ne 'pragma');
|
|
next;
|
|
} elsif (!$directiv) {
|
|
next;
|
|
}
|
|
|
|
if ($l =~ /^\s*(\w+)/) {
|
|
xpush(\$tokens{'directive'}, $1);
|
|
}
|
|
}
|
|
|
|
close($dd);
|
|
}
|
|
|
|
my $version;
|
|
sub read_version($) {
|
|
my($vfile) = @_;
|
|
open(my $v, '<', $vfile)
|
|
or die "$0:$vfile: $!\n";
|
|
|
|
$version = <$v>;
|
|
chomp $version;
|
|
|
|
close($v);
|
|
}
|
|
|
|
sub make_lines($$@) {
|
|
my $maxline = shift @_;
|
|
my $indent = shift @_;
|
|
|
|
# The first line isn't explicitly indented and the last line
|
|
# doesn't end in "\n"; assumed the surrounding formatter wants
|
|
# do control that
|
|
my $linepos = 0;
|
|
my $linewidth = $maxline - $indent;
|
|
|
|
my $line = '';
|
|
my @lines = ();
|
|
|
|
foreach my $w (@_) {
|
|
my $l = length($w);
|
|
|
|
if ($linepos > 0 && $linepos+$l+1 >= $linewidth) {
|
|
$line .= "\n" . (' ' x $indent);
|
|
push(@lines, $line);
|
|
$linepos = 0;
|
|
$line = '';
|
|
}
|
|
if ($linepos > 0) {
|
|
$line .= ' ';
|
|
$linepos++;
|
|
}
|
|
$line .= $w;
|
|
$linepos += $l;
|
|
}
|
|
|
|
if ($linepos > 0) {
|
|
push(@lines, $line);
|
|
}
|
|
|
|
return @lines;
|
|
}
|
|
|
|
sub quote_for_emacs(@) {
|
|
return map { s/[\\\"\']/\\$1/g; '"'.$_.'"' } @_;
|
|
}
|
|
|
|
sub write_output($) {
|
|
my($outfile) = @_;
|
|
|
|
open(my $out, '>', $outfile)
|
|
or die "$0:$outfile: $!\n";
|
|
|
|
my($vol,$dir,$file) = File::Spec->splitpath($outfile);
|
|
|
|
print $out ";;; ${file} --- lists of NASM assembler tokens\n";
|
|
print $out ";;;\n";
|
|
print $out ";;; This file contains list of tokens from the NASM x86\n";
|
|
print $out ";;; assembler, automatically extracted from NASM ${version}.\n";
|
|
print $out ";;;\n";
|
|
print $out ";;; This file is intended to be (require)d from a `nasm-mode\'\n";
|
|
print $out ";;; major mode definition.\n";
|
|
|
|
foreach my $type (sort keys(%tokens)) {
|
|
print $out "\n(defconst nasm-${type}\n";
|
|
print $out " \'(";
|
|
|
|
print $out make_lines(78, 4, quote_for_emacs(sort @{$tokens{$type}}));
|
|
print $out ")\n";
|
|
print $out " \"NASM ${version} ${type} tokens for `nasm-mode\'.\")\n";
|
|
}
|
|
|
|
close($out);
|
|
}
|
|
|
|
read_tokhash_c(File::Spec->catfile($objdir, 'asm', 'tokhash.c'));
|
|
read_pptok_c(File::Spec->catfile($objdir, 'asm', 'pptok.c'));
|
|
read_directiv_dat(File::Spec->catfile($srcdir, 'asm', 'directiv.dat'));
|
|
read_version(File::Spec->catfile($srcdir, 'version'));
|
|
|
|
write_output($outfile);
|