[nasm:emacs] misc/emacstbl.el: script to produce token lists for an emacs mode

nasm-bot for H. Peter Anvin hpa at zytor.com
Thu Nov 17 15:36:03 PST 2022


Commit-ID:  b58771d8278968e2ea36e8e66675c7d6d4105af9
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=b58771d8278968e2ea36e8e66675c7d6d4105af9
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Thu, 17 Nov 2022 11:50:03 -0800
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Thu, 17 Nov 2022 11:50:03 -0800

misc/emacstbl.el: script to produce token lists for an emacs mode

Add a simple script to auto-generate token lists for an emacs major
mode, e.g. https://github.com/skeeto/nasm-mode

It is recommended to use "require" this file separately from the main
code, so it can be automatically kept up to date.

If this ends up being used, I will include the generated result in the
NASM release distribution.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 misc/emacstbl.pl | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 189 insertions(+)

diff --git a/misc/emacstbl.pl b/misc/emacstbl.pl
new file mode 100755
index 00000000..4c7673c9
--- /dev/null
+++ b/misc/emacstbl.pl
@@ -0,0 +1,189 @@
+#!/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',
+		 '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);
+}
+
+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";
+
+    foreach my $type (sort keys(%tokens)) {
+	print $out "(defconst nasm-${type}\n";
+	print $out "  \'(";
+
+	print $out make_lines(78, 4, quote_for_emacs(sort @{$tokens{$type}}));
+	print $out "))\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'));
+
+write_output($outfile);


More information about the Nasm-commits mailing list