Skip to content

Commit b58771d

Browse files
author
H. Peter Anvin
committed
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 <[email protected]>
1 parent e7dd0e8 commit b58771d

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

misc/emacstbl.pl

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#!/usr/bin/perl
2+
#
3+
# Automatically produce some tables useful for a NASM major mode
4+
#
5+
6+
use integer;
7+
use strict;
8+
use File::Spec;
9+
10+
my($outfile, $srcdir, $objdir) = @ARGV;
11+
12+
if (!defined($outfile)) {
13+
die "Usage: $0 outfile srcdir objdir\n";
14+
}
15+
16+
$srcdir = File::Spec->curdir() unless (defined($srcdir));
17+
$objdir = $srcdir unless (defined($objdir));
18+
19+
my %tokens = ();
20+
21+
sub xpush($@) {
22+
my $ref = shift @_;
23+
24+
$$ref = [] unless (defined($$ref));
25+
return push(@$$ref, @_);
26+
}
27+
28+
# Combine some specific token types
29+
my %override = ( 'id' => 'special',
30+
'float' => 'function',
31+
'floatize' => 'function',
32+
'strfunc' => 'function',
33+
'ifunc' => 'function',
34+
'seg' => 'special',
35+
'wrt' => 'special' );
36+
37+
sub read_tokhash_c($) {
38+
my($tokhash_c) = @_;
39+
40+
open(my $th, '<', $tokhash_c)
41+
or die "$0:$tokhash_c: $!\n";
42+
43+
my $l;
44+
my $tokendata = 0;
45+
while (defined($l = <$th>)) {
46+
if ($l =~ /\bstruct tokendata tokendata\[/) {
47+
$tokendata = 1;
48+
next;
49+
} elsif (!$tokendata) {
50+
next;
51+
}
52+
53+
last if ($l =~ /\}\;/);
54+
55+
if ($l =~ /^\s*\{\s*\"(.*?)\",.*?,\s*TOKEN_(\w+),.*\}/) {
56+
my $token = $1;
57+
my $type = lc($2);
58+
59+
if ($override{$type}) {
60+
$type = $override{$type};
61+
} elsif ($token !~ /^\w/) {
62+
$type = 'operator';
63+
} elsif ($token =~ /^__\?masm_.*\?__$/) {
64+
next;
65+
}
66+
xpush(\$tokens{$type}, $token);
67+
if ($token =~ /^__\?(.*)\?__$/) {
68+
# Also encode the "user" (macro) form without __?...?__
69+
xpush(\$tokens{$type}, $1);
70+
}
71+
}
72+
}
73+
close($th);
74+
}
75+
76+
sub read_pptok_c($) {
77+
my($pptok_c) = @_;
78+
79+
open(my $pt, '<', $pptok_c)
80+
or die "$0:$pptok_c: $!\n";
81+
82+
my $l;
83+
my $pp_dir = 0;
84+
85+
while (defined($l = <$pt>)) {
86+
if ($l =~ /\bpp_directives\[/) {
87+
$pp_dir = 1;
88+
next;
89+
} elsif (!$pp_dir) {
90+
next;
91+
}
92+
93+
last if ($l =~ /\}\;/);
94+
95+
if ($l =~ /^\s*\"(.*?)\"/) {
96+
xpush(\$tokens{'pp-directive'}, $1);
97+
}
98+
}
99+
close($pt);
100+
}
101+
102+
sub read_directiv_dat($) {
103+
my($directiv_dat) = @_;
104+
105+
open(my $dd, '<', $directiv_dat)
106+
or die "$0:$directiv_dat: $!\n";
107+
108+
my $l;
109+
my $directiv = 0;
110+
111+
while (defined($l = <$dd>)) {
112+
if ($l =~ /^\; ---.*?(pragma)?/) {
113+
$directiv = ($1 ne 'pragma');
114+
next;
115+
} elsif (!$directiv) {
116+
next;
117+
}
118+
119+
if ($l =~ /^\s*(\w+)/) {
120+
xpush(\$tokens{'directive'}, $1);
121+
}
122+
}
123+
124+
close($dd);
125+
}
126+
127+
sub make_lines($$@) {
128+
my $maxline = shift @_;
129+
my $indent = shift @_;
130+
131+
# The first line isn't explicitly indented and the last line
132+
# doesn't end in "\n"; assumed the surrounding formatter wants
133+
# do control that
134+
my $linepos = 0;
135+
my $linewidth = $maxline - $indent;
136+
137+
my $line = '';
138+
my @lines = ();
139+
140+
foreach my $w (@_) {
141+
my $l = length($w);
142+
143+
if ($linepos > 0 && $linepos+$l+1 >= $linewidth) {
144+
$line .= "\n" . (' ' x $indent);
145+
push(@lines, $line);
146+
$linepos = 0;
147+
$line = '';
148+
}
149+
if ($linepos > 0) {
150+
$line .= ' ';
151+
$linepos++;
152+
}
153+
$line .= $w;
154+
$linepos += $l;
155+
}
156+
157+
if ($linepos > 0) {
158+
push(@lines, $line);
159+
}
160+
161+
return @lines;
162+
}
163+
164+
sub quote_for_emacs(@) {
165+
return map { s/[\\\"\']/\\$1/g; '"'.$_.'"' } @_;
166+
}
167+
168+
sub write_output($) {
169+
my($outfile) = @_;
170+
171+
open(my $out, '>', $outfile)
172+
or die "$0:$outfile: $!\n";
173+
174+
foreach my $type (sort keys(%tokens)) {
175+
print $out "(defconst nasm-${type}\n";
176+
print $out " \'(";
177+
178+
print $out make_lines(78, 4, quote_for_emacs(sort @{$tokens{$type}}));
179+
print $out "))\n";
180+
}
181+
182+
close($out);
183+
}
184+
185+
read_tokhash_c(File::Spec->catfile($objdir, 'asm', 'tokhash.c'));
186+
read_pptok_c(File::Spec->catfile($objdir, 'asm', 'pptok.c'));
187+
read_directiv_dat(File::Spec->catfile($srcdir, 'asm', 'directiv.dat'));
188+
189+
write_output($outfile);

0 commit comments

Comments
 (0)