pmacs3/mode/nasm.py

109 lines
4.6 KiB
Python

from mode import Fundamental
from lex import Grammar, PatternRule, RegionRule, PatternMatchRule
from mode.python import StringGrammar1, StringGrammar2, StringGrammar3, StringGrammar4
from method import Method, arg
from subprocess import Popen, PIPE, STDOUT
chr1 = '[a-zA-Z_.?]'
chr2 = '[a-zA-Z0-9_.?$#@~]'
word = chr1 + chr2 + '*'
class NasmGrammar(Grammar):
rules = [
PatternRule('comment', ';.*$'),
RegionRule('comment', '%if +0', Grammar, r'%%endif'),
# for use with ndisasm files
PatternMatchRule('x', '^([0-9a-fA-F]{8})( )([0-9a-fA-F]+)', 'nasm.integer', 'spaces', 'nasm.address'),
PatternRule('nasm.address', '^[0-9a-fA-F]{8} [0-9a-fA-F]+'),
PatternRule('spaces', ' +'),
PatternRule("nasm.integer", "(0[xX][0-9a-fA-F]+|0|[1-9][0-9]*|0[0-7]+)[lL]?"),
PatternRule('nasm.register', "(?:eax|ebx|ecx|edx|ax|ah|al|bx|bh|bl|bp|cx|ch|cl|cmpsb|dh|di|dl|ds|dx|esi|es|edi|esp|ebp|si|sp|stosd)(?!" + chr2 + ")"),
PatternRule('nasm.pseudo', "(?:a16|a32|byte|db|dd|do|dq|dt|dword|qword|tword|fs|gs|near|o16|o32|short)(?!" + chr2 + ")"),
PatternRule('nasm.instruction', "(?:jg|jeq|jecxz|jne|ja|jmp|push|pushad|pushfd|call|ret|sub|adc|add|popad|popaw|popa|popfd|pop|call|and|arpl|bound|cwd|cdq|clc|cld|cli|cmp|cmpxchg|cpuid|das|dec|divpd|div|enter|leave|fadd|fld|fmul|fsqrt|fsub|fs|hlt|imul|inc|insb|insd|insw|ins|int|int3|in|jcxz|jc|jna|jnc|jnz|jo|js|jz|lea|lldt|loadsb|lock|loopne|movzx|movd|mov|mul|neg|not|nop|or|outsb|outsd|outsw|repe|retf|rol|sal|sar|sbb|scasw|shl|shr|shld|shrd|sldt|syscall|sysenter|sysexit|test|xchg|xadd|xor)(?!" + chr2 + ")"),
PatternRule('nasm.macro', "\%(?:define|undef|assign|strlen|macro|endmacro|if|elif|else|endif|ifdef|ifndef|include|push|pop|stacksize)(?!" + chr2 + ")"),
PatternRule('nasm.keyword', "(?:section|global|extern)(?!" + chr2 + ")"),
PatternRule('nasm.prefix', "(?:dword|word|lock)(?!" + chr2 + ")"),
PatternMatchRule('x', '(' + word + ')(:)', 'nasm.label', 'delimiter'),
PatternRule("nasm.identifier", r'\$?' + word),
PatternRule("nasm.float", r"[0-9]+\.[0-9]*|\.[0-9]+|([0-9]|[0-9]+\.[0-9]*|\.[0-9]+)[eE][\+-]?[0-9]+"),
PatternRule('delimiter', r'(?://|%%|<<|>>|[~!\.\*/%\-\+\(\)\[\],\|\^\&])'),
# TODO: nasm strings seem like they are single-line only
RegionRule('string', '"""', StringGrammar4, '"""'),
RegionRule('string', "'''", StringGrammar3, "'''"),
RegionRule('string', '"', StringGrammar2, '"'),
RegionRule('string', "'", StringGrammar1, "'"),
PatternRule('eol', '\n'),
PatternRule('continuation', r'\\\n$'),
]
class NasmDisassembleFile(Method):
args = [arg("path", dt='path', p="Path: "),
arg('flags', p='Flags: ', dv=lambda w: '-b 16', ld=True)]
def _execute(self, w, **vargs):
p = Popen(['ndisasm', vargs['path']], stdout=PIPE, stderr=STDOUT)
output = p.stdout.read()
retval = p.wait()
modename = None
bufname = '*Disasm:%s*' % vargs['path']
w.application.data_buffer(bufname, output, switch_to=True,
modename=modename)
# white is for delimiters, operators, numbers
default = ('default', 'default')
# magenta is for keywords/builtins
lo_magenta = ('magenta202', 'default')
hi_magenta = ('magenta414', 'default')
# red is for comments
lo_red = ('red300', 'default')
hi_red = ('red511', 'default')
# orange is for macro definitions, headers and constants
hi_orange = ('yellow531', 'default')
lo_orange = ('yellow520', 'default')
# yellow is for parts of macros
hi_yellow = ('yellow551', 'default')
lo_yellow = ('yellow330', 'default')
# green is for strings and characters
lo_green = ('green030', 'default')
hi_green = ('green050', 'default')
# cyan is for types
lo_cyan = ('cyan033', 'default')
hi_cyan = ('cyan155', 'default')
# blue is definitions, functions and some macros
lo_blue = ('blue113', 'default')
hi_blue = ('blue225', 'default')
class Nasm(Fundamental):
name = 'nasm'
extensions = ['.s']
grammar = NasmGrammar
commentc = ';'
colors = {
'nasm.address': hi_cyan,
'nasm.pseudo': hi_cyan,
'nasm.keyword': hi_cyan,
'nasm.macro': hi_blue,
'nasm.register': hi_yellow,
'nasm.instruction': hi_magenta,
'nasm.label': hi_blue,
'nasm.integer': hi_green,
'nasm.identifier': hi_orange,
}
_bindings = {
'close-paren': (')',),
'close-brace': ('}',),
'close-bracket': (']',),
}
actions = [NasmDisassembleFile]
install = Nasm.install