Ophis/src/Ophis/CorePragmas.py

203 lines
5.8 KiB
Python

"""Core pragmas
Provides the core assembler directives. It does not guarantee
compatibility with older versions of P65-Perl."""
# Copyright 2002 Michael C. Martin.
# You may use, modify, and distribute this file under the BSD
# license: See LICENSE.txt for details.
from __future__ import nested_scopes
import Ophis.IR as IR
import Ophis.Frontend as FE
import Ophis.Errors as Err
loadedfiles={}
basecharmap = "".join([chr(x) for x in range(256)])
currentcharmap = basecharmap
def reset():
global loadedfiles, currentcharmap, basecharmap
loadedfiles={}
currentcharmap = basecharmap
def pragmaInclude(ppt, line, result):
"Includes a source file"
filename = line.expect("STRING").value
line.expect("EOL")
if type(filename)==str: result.append(FE.parse_file(ppt, filename))
def pragmaRequire(ppt, line, result):
"Includes a source file at most one time"
filename = line.expect("STRING").value
line.expect("EOL")
if type(filename)==str:
global loadedfiles
if filename not in loadedfiles:
loadedfiles[filename]=1
result.append(FE.parse_file(ppt, filename))
def pragmaIncbin(ppt, line, result):
"Includes a binary file"
filename = line.expect("STRING").value
line.expect("EOL")
if type(filename)==str:
f = file(filename, "rb")
bytes = f.read()
f.close()
bytes = [IR.ConstantExpr(ord(x)) for x in bytes]
result.append(IR.Node(ppt, "Byte", *bytes))
def pragmaCharmap(ppt, line, result):
"Modify the character map."
global currentcharmap, basecharmap
bytes = readData(line)
if len(bytes) == 0:
currentcharmap = basecharmap
else:
try:
base = bytes[0].data
newsubstr = "".join([chr(x.data) for x in bytes[1:]])
currentcharmap = currentcharmap[:base] + newsubstr + currentcharmap[base+len(newsubstr):]
if len(currentcharmap) != 256 or base < 0 or base > 255:
Err.log("Charmap replacement out of range")
currentcharmap = currentcharmap[:256]
except ValueError:
Err.log("Illegal character in .charmap directive")
def pragmaCharmapbin(ppt, line, result):
"Load a new character map from a file"
global currentcharmap
filename = line.expect("STRING").value
line.expect("EOL")
if type(filename)==str:
f = file(filename, "rb")
bytes = f.read()
f.close()
if len(bytes)==256:
currentcharmap = bytes
else:
Err.log("Character map "+filename+" not 256 bytes long")
def pragmaOrg(ppt, line, result):
"Relocates the PC with no output"
newPC = FE.parse_expr(line)
line.expect("EOL")
result.append(IR.Node(ppt, "SetPC", newPC))
def pragmaAdvance(ppt, line, result):
"Outputs filler until reaching the target PC"
newPC = FE.parse_expr(line)
line.expect("EOL")
result.append(IR.Node(ppt, "Advance", newPC))
def pragmaCheckpc(ppt, line, result):
"Enforces that the PC has not exceeded a certain point"
target = FE.parse_expr(line)
line.expect("EOL")
result.append(IR.Node(ppt, "CheckPC", target))
def pragmaAlias(ppt, line, result):
"Assigns an arbitrary label"
lbl = line.expect("LABEL").value
target = FE.parse_expr(line)
result.append(IR.Node(ppt, "Label", lbl, target))
def pragmaSpace(ppt, line, result):
"Reserves space in a data segment for a variable"
lbl = line.expect("LABEL").value
size = line.expect("NUM").value
line.expect("EOL")
result.append(IR.Node(ppt, "Label", lbl, IR.PCExpr()))
result.append(IR.Node(ppt, "SetPC", IR.SequenceExpr([IR.PCExpr(), "+", IR.ConstantExpr(size)])))
def pragmaText(ppt, line, result):
"Switches to a text segment"
next = line.expect("LABEL", "EOL")
if next.type == "LABEL":
line.expect("EOL")
segment = next.value
else:
segment = "*text-default*"
result.append(IR.Node(ppt, "TextSegment", segment))
def pragmaData(ppt, line, result):
"Switches to a data segment (no output allowed)"
next = line.expect("LABEL", "EOL")
if next.type == "LABEL":
line.expect("EOL")
segment = next.value
else:
segment = "*data-default*"
result.append(IR.Node(ppt, "DataSegment", segment))
def readData(line):
"Read raw data from a comma-separated list"
if line.lookahead(0).type == "STRING":
data = [IR.ConstantExpr(ord(x)) for x in line.expect("STRING").value.translate(currentcharmap)]
else:
data = [FE.parse_expr(line)]
next = line.expect(',', 'EOL').type
while next == ',':
if line.lookahead(0).type == "STRING":
data.extend([IR.ConstantExpr(ord(x)) for x in line.expect("STRING").value])
else:
data.append(FE.parse_expr(line))
next = line.expect(',', 'EOL').type
return data
def pragmaByte(ppt, line, result):
"Raw data, a byte at a time"
bytes = readData(line)
result.append(IR.Node(ppt, "Byte", *bytes))
def pragmaWord(ppt, line, result):
"Raw data, a word at a time, little-endian"
words = readData(line)
result.append(IR.Node(ppt, "Word", *words))
def pragmaDword(ppt, line, result):
"Raw data, a double-word at a time, little-endian"
dwords = readData(line)
result.append(IR.Node(ppt, "Dword", *dwords))
def pragmaWordbe(ppt, line, result):
"Raw data, a word at a time, big-endian"
words = readData(line)
result.append(IR.Node(ppt, "WordBE", *words))
def pragmaDwordbe(ppt, line, result):
"Raw data, a dword at a time, big-endian"
dwords = readData(line)
result.append(IR.Node(ppt, "DwordBE", *dwords))
def pragmaScope(ppt, line, result):
"Create a new lexical scoping block"
line.expect("EOL")
result.append(IR.Node(ppt, "ScopeBegin"))
def pragmaScend(ppt, line, result):
"End the innermost lexical scoping block"
line.expect("EOL")
result.append(IR.Node(ppt, "ScopeEnd"))
def pragmaMacro(ppt, line, result):
"Begin a macro definition"
lbl = line.expect("LABEL").value
line.expect("EOL")
result.append(IR.Node(ppt, "MacroBegin", lbl))
def pragmaMacend(ppt, line, result):
"End a macro definition"
line.expect("EOL")
result.append(IR.Node(ppt, "MacroEnd"))
def pragmaInvoke(ppt, line, result):
macro = line.expect("LABEL").value
if line.lookahead(0).type == "EOL":
args = []
else:
args = readData(line)
result.append(IR.Node(ppt, "MacroInvoke", macro, *args))