Пример #1
0
    def getLine(self,debug=False):
        # Validate source state for getLine() method
        if self.fo is None:
            cls_str=assembler.eloc(self,"getLine",module=this_module)
            raise ValueError("%s file object not created for file: %s" \
                % (cls_str,self.fname))
        if self.eof:
            if self.leof:
                cls_str=assembler.eloc(self,"getLine",module=this_module)
                raise ValueError("%s text file already at end-of-file: %s" \
                    % (cls_str,self.fname))
            else:
                raise SourceEmpty()

        # Read from queued physical lines before reading from file
        if len(self.queued)!=0:
            pline=self.queued[0]
            del self.queued[0]
            return pline

        # No queued lines, so read from the file
        line=self.fo.readline()
        if len(line)==0:
            self.fini()
            raise SourceEmpty()
        self.lineno+=1
        if line[-1]=="\n":
            line=line[:-1]
            
        # TBD: Need to add logic for the 'guess' continuation method....

        return self.pcls(Source(lineno=self.lineno,fileno=self.fileno),line)
Пример #2
0
    def inject(self,lines,debug=False):
        if isinstance(lines,PhysLine):
            # Inject a single physical line
            self.lines.append(lines)
            if __debug__:
                if debug:
                    print("%s injected line: %s" \
                        % (assembler.eloc(self,"inject",module=this_module),lines))
            return

        elif isinstance(lines,list):
            # Inject a list of physcical lines
            for ndx,line in enumerate(lines):
                if not isinstance(line,PhysLine):
                    raise ValueError("%s 'line' argument item %s not a string: %s" \
                        (assembler.eloc(self,"inject",module=this_module),ndx,line))
                if debug:
                    print("%s injected line: %s" \
                        % (assembler.eloc(self,"inject",module=this_module),line))
            self.lines.extend(lines)
            return

        raise ValueError(\
            "%s 'lines' argument must be a single or list of PhysLine objects: %s"\
                % assembler.eloc(self,"inject",module=this_module),lines)
Пример #3
0
    def fetch(self,indices=[],depth=0,debug=False):
        assert isinstance(indices,list),\
            "%s 'indices' argument must be a list: %s" \
                % (assembler.eloc(self,"fetch",module=this_module),indices)
        if __debug__:
            if debug:
                print("%s indices:%s depth:%s" \
                    % (assembler.eloc(self,"fetch",module=this_module),\
                        indices,depth))

        if len(indices)==0:      # Unsubscripted parameter or SYSLIST reference
            return self.cval
        ndxs=indices             # Subscripted parameter or SYSLIST reference

        if depth>=len(ndxs):
            raise SymbolError(msg="too many sublist subscripts: %s" % depth)

        this=ndxs[depth]
        if len(self.sublists)==0:
            # The requested sublist does not exist, so return an empty C_Val
            return C_Val()
        val=self.sublists[this-self.minimum]
        if depth==len(ndxs)-1:
            # Last requested index so return the retrieved sublist's C_Val object
            return val.value()
        # Not the last index so reach into the next level of sublist for its entry.
        return val.fetch(indices=ndxs,depth=depth+1)
Пример #4
0
    def __init__(self,asm,stmt,debug=False):
        self.asm=asm
        self.stmt=stmt
        self.debug=debug

        # These attributes are established during parsing operations
        self.label_fld=None       # See parse_label() method
        self.oper_fld=None        # See parse_operation() method
        self.operands=[]          # See parse_operands() method
        self.comments=[]          # See find_comment() method
        self.comment_pos=None     # Starting position of the comment

        # Symbolic replacements:
        self.rlbl=''
        self.roper=None
        self.ropnd=[]

        # Handle loud comment model statements here
        self.loud=None
        logline=stmt.logline
        if __debug__:
            if debug:
                print("%s logline: %s" \
                    % (assembler.eloc(self,"__init__",module=this_module),logline))

        if logline.comment and not logline.quiet:
            self.loud=logline.plines[0].text

        if __debug__:
            if debug:
                print("%s [%s] loud: %s" \
                    % (assembler.eloc(self,"__init__",module=this_module),\
                        stmt.lineno,self.loud))
Пример #5
0
    def fields(self,pline,debug=False):
        if pline.literal:
            # No fields to check for a literal
            return
        text=pline.text
        mo=re.match(LogLine.fieldre,text)
        if mo is None:
            # If we are here there should be an non-blank operation field.  If
            # not something unexpected happened
            raise ValueError("%s pline: %s\n    field match failed, returned None" \
                % (assembler.eloc(self,"fields",module=this_module),pline))

        # match object returned
        groups=mo.groupdict()
        if __debug__:
            if debug:
                print("%s match groups: %s" \
                    % (assembler.eloc(self,"fields",module=this_module),groups))
        end=mo.end()
        
        label=groups["label"]
        if label:
            amp= "&" in label
            self.label_fld=LField(label,pline.source,0,amp)

        oper=groups["oper"]
        assert oper is not None,\
            "%s re failure: oper field not found by re: %s" \
                % (assembler.eloc(self,"fields",module=this_module),oper)

        oper_start=mo.start("oper")
        amp= "&" in oper
        pline.oper_start=oper_start
        self.oper_fld=LField(oper,pline.source,oper_start,amp)
        bad_char = self.oper_fld.char_ck()
        if bad_char:
            self.error=LineError(source=pline.source,\
                msg="operation field contains an invalid char: %s" % bad_char)
        else:
            self.operu=oper.upper()

        if __debug__:
            if debug:
                print("%s pline: %s" \
                    % (assembler.eloc(self,"fields",module=this_module),pline))

        # Figure out if there are any operands and where they start in the first
        # (and required) physical line
        if end>=len(text):
            # Nothing beyond oper field except some spaces
            # No operands are present
            return
        pline.operand_start=end
        # Note where comments begin can not be determined until operands are parsed
        # and are sensitive to continuation convention used on the physical lines.
        if __debug__:
            if debug:
                print("%s pline: %s" \
                    % (assembler.eloc(self,"fields",module=this_module),pline))
Пример #6
0
    def __init__(self,source,content,genlvl=None):
        assert source is None or isinstance(source,Source),\
            "%s 'source' argumenet must be an instance of Source: %s" \
                % (assembler.eloc(self,"__init__",module=this_module),source)
        assert isinstance(content,str),\
            "%s 'content' argumenet must be a string: %s" \
                % (assembler.eloc(self,"__init__",module=this_module),content)

        self.source=source      # Location of source content
        # This attribute is the basis for the Statement column in the assembly
        # listing.
        self.content=content    # a string, may be of length of 0
        # This tracks the source of generated physical lines by macros or open code
        # If None, the input comes from a file.  If 0 it comes from open code.
        # If 1 or more, it comes from a macro.  Used to determine if a macro statement
        # is an inner macro call or not for listing purposes.
        self.genlvl=genlvl      # If generated by assembler, level of generator
        # literal.Literal object passed along for literal creation
        self.literal=None       # See PoolSource.__init__() method

        # Established by subclass init() method
        self.cont=False         # Whether physical line is continued
        self.empty=False        # Phyiscal line is empty
        self.text=None          # Actual parsable content of the line

        # Physical line flags - set below in this __init__() method
        self.comment=False      # Physical line is a comment
        self.quiet=False        # Physical line is also a quiet comment

        # Field information - starting index of fields
        self.oper_start=None        # Set by LogLine.fields() method
        self.operand_start=None     # Set by Logline.fields() method
        self.comment_start=None     # Set by asmline.cfsm.ACT_Found_Comment() method

        # Make sure we do not process an empty physical line
        if len(self.content)==0:
            self.empty=True
            self.cont=False
            self.text=""
            return

        # Perform subclass initialization
        self.init()
        
        # Also do not process a line with an empty logical content (like some spaces)
        if len(self.text)==0:
            self.empty=True
            self.cont=False
            return

        # Complete base class initialization
        # Continuation of comment lines is never recognized so no continuation forced
        if self.text[0]=="*":
            self.comment=True
            self.cont=False
        elif len(self.text)>=2 and self.text[:2]==".*":
            self.comment=self.quiet=True
            self.cont=False
Пример #7
0
    def validate(self,asm,stmt,types,debug=False):
        istyp="U"
        char=self.text[0]   # Get the first character for a quick sanity check

        for typ in types:
            
            if typ=="S":
                if char=="&":
                    # call back to the statement to do a full symbolic reference parse
                    result=stmt.validate_symbol(asm,self)
                    if result:
                        self.symid=result
                        self.amp=True
                        istyp="S"
                        break
                    continue
                else:
                    continue
            elif typ=="Q" and char!=".":
                continue 

            ltyp=LField.types[typ]

            # Use a lexical token to validate types: L, M and Q
            try:
                if __debug__:
                    if debug:
                        print("%s matching '%s' to typ: %s" \
                            % (assembler.eloc(self,"validate",module=this_module),\
                                self.text,typ))
                self.token=ltyp.match(self.text)
                if __debug__:
                    if debug:
                        print("%s %s match succeeded" \
                            % (assembler.eloc(self,"validate",module=this_module),\
                                typ))
                istyp=typ
                break

            except lexer.LexerError:
                if __debug__:
                    if debug:
                        print("%s %s match failed" \
                            % (assembler.eloc(self,"validate",module=this_module),\
                                typ))
                continue

        if __debug__:
            if debug:
                print("%s %s match succeeded" \
                    % (assembler.eloc(self,"validate",module=this_module),istyp))

        self.typ=istyp

        if typ=="M":
            self.amp = self.token.groups()[1] is not None

        return
Пример #8
0
    def __getLogical(self,debug=False):
        try:
            pline=self.LB.getLine()
            if __debug__:
                if debug:
                    print("%s pline: %s" \
                        % (assembler.eloc(self,"__getLogical",module=this_module),\
                            pline))

        except asminput.SourceEmpty:
            return

        # Start a new logical line with this physical input.  Regardless of whether
        # it is continued or not, the first physical line's operation field
        # dictates all of the remaining processing of the statement.  Processing
        # of the label and operation field occurs during the instantiation of the
        # logical line (see the LogLine.fields() method).
        logical=LogLine(pline,bend=self._end)
        if logical.bend:
            self._bend=True
            logical.error=LineError(source=pline.source,\
                msg="input beyond END directive ignored")

        while pline.cont:
            # Line is continued, so now add the next physical line
            try:
                pline=self.LB.getLine()
                if __debug__:
                    if debug:
                        print("%s pline: %s" \
                            % assembler.eloc(self,"__getLogical",module=this_module),\
                                pline)
            except asminput.SourceEmpty:
                logical.error=LineError(source=pline.source,\
                    msg="continuation line missing at end of file")
                break
                 # If the source is empty then previously continued physical
                 # line is missing a continuation
                 #raise ValueError("continuation line missing at end of file")
            contok=logical.addCont(pline)
            if __debug__:
                if debug:
                    print("%s contok from addCont: %s" \
                        % (assembler.eloc(self,"__getLogical",module=this_module),\
                            contok))

            if not contok:
                logical.error=LineError(source=pline.source,\
                    msg="invalid continuation line, previously continued line "
                        "rejected")
                self.LB.queue(pline)
            # Bad continue line so give up and assume it was meant to be a
            # new logical line and that is what follows.

        # Logical line is done, so process its operands
        self.categorize(logical)   # Determine the logical line's operation type
        return logical
Пример #9
0
    def str_cont(self, value):
        assert isinstance(value,StringToken),\
            "%s 'value' argument must be a StringToken object: %s"\
                % (assembler.eloc(self,"str_cont",module=this_module),value)
        assert isinstance(self._string,StringToken),\
            "%s '_string' attribute must be a StringToken object: %s" \
                % (assembler.eloc(self,"str_cont",module=this_module),self.string)

        self._string.extend(value)
Пример #10
0
    def str_cont(self,value):
        assert isinstance(value,StringToken),\
            "%s 'value' argument must be a StringToken object: %s"\
                % (assembler.eloc(self,"str_cont",module=this_module),value)
        assert isinstance(self._string,StringToken),\
            "%s '_string' attribute must be a StringToken object: %s" \
                % (assembler.eloc(self,"str_cont",module=this_module),self.string)

        self._string.extend(value)
Пример #11
0
    def __getLogical(self, debug=False):
        try:
            pline = self.LB.getLine()
            if __debug__:
                if debug:
                    print("%s pline: %s" \
                        % (assembler.eloc(self,"__getLogical",module=this_module),\
                            pline))

        except asminput.SourceEmpty:
            return

        # Start a new logical line with this physical input.  Regardless of whether
        # it is continued or not, the first physical line's operation field
        # dictates all of the remaining processing of the statement.  Processing
        # of the label and operation field occurs during the instantiation of the
        # logical line (see the LogLine.fields() method).
        logical = LogLine(pline, bend=self._end)
        if logical.bend:
            self._bend = True
            logical.error=LineError(source=pline.source,\
                msg="input beyond END directive ignored")

        while pline.cont:
            # Line is continued, so now add the next physical line
            try:
                pline = self.LB.getLine()
                if __debug__:
                    if debug:
                        print("%s pline: %s" \
                            % (assembler.eloc(self,"__getLogical",\
                                module=this_module),pline))
            except asminput.SourceEmpty:
                logical.error=LineError(source=pline.source,\
                    msg="continuation line missing at end of file")
                break
                # If the source is empty then previously continued physical
                # line is missing a continuation
                #raise ValueError("continuation line missing at end of file")
            contok = logical.addCont(pline)
            if __debug__:
                if debug:
                    print("%s contok from addCont: %s" \
                        % (assembler.eloc(self,"__getLogical",module=this_module),\
                            contok))

            if not contok:
                logical.error=LineError(source=pline.source,\
                    msg="invalid continuation line, previously continued line "
                        "rejected")
                self.LB.queue(pline)
            # Bad continue line so give up and assume it was meant to be a
            # new logical line and that is what follows.

        # Logical line is done, so process its operands
        self.categorize(logical)  # Determine the logical line's operation type
        return logical
Пример #12
0
    def categorize(self,logical,debug=False):
        assert isinstance(logical,LogLine),\
            "%s 'logical' argument must be a LogLine object: %s" \
                % (eloc(self,"categorize",module=this_module),logical)

        OMF=self.asm.OMF
        if logical.error:
            oper=OMF.getError()
        elif logical.comment or logical.empty:
            oper=OMF.getComment(quiet=logical.quiet)
        elif logical.literal:
            oper=OMF.getLiteral(logical.literal)
        else:
            oper=logical.operu
            if __debug__:
                if debug:
                    print("%s oper: %s" \
                        % (assembler.eloc(self,"categorize",module=this_module),oper))
            try:
                # Get the operation infomation, defining a macro from the macro
                # library if necessary.
                oper=OMF.getOper(oper,mbstate=self.mb.state,macread=True,\
                    lineno=logical.source,debug=debug)
                if __debug__:
                    if debug:
                        print("%s %s" \
                            % (assembler.eloc(self,"categorize",module=this_module),\
                                oper))
            except KeyError:
                print("%s KeyError" \
                    % assembler.eloc(self,"categorize",module=this_module))
                # If the operation is unrecognized, categorize it as unknown
                logical.T="U"
                logical.ignore=True  # Unknown operations must be ignored.
                source=logical.plines[0].source
                logical.error=LineError(source=source,\
                    msg="Unrecognized operation field: %s" % oper)
                oper=OMF.getError()
            except LineError as le:
                if __debug__:
                    if debug:
                        print("%s LineError: %s" \
                            % (assembler.eloc(self,"categorize",module=this_module),\
                                le))
                # Failed library macro definitions must also be ignored
                logical.T="U"
                logical.ignore=True  # Unknown operations must be ignored.
                logical.error=le
                oper=OMF.getError()

        # Update the logical line with this operation related information
        if __debug__:
            if debug:
                print("%s %s" \
                    % (assembler.eloc(self,"categorize",module=this_module),oper))
        logical.category(oper)
Пример #13
0
    def str_begin(self,value):
        assert isinstance(value,StringToken),\
            "%s 'value' argument must be a StringToken object: %s"\
                % (assembler.eloc(self,"str_begin",module=this_module),value)
        assert self._string is None,\
            "%s '_string' attribute is not None when starting a compound string: %s" \
                % (assembler.eloc(self,"str_begin",module=this_module),\
                    self._string)

        self._string=value
Пример #14
0
 def _ck_symid(self,symid):
     assert isinstance(symid,SymbolID),\
         "%s 'symbol' argument must be a SymbolID object: %s" \
             % (assembler.eloc(self,"_ck_symid",module=this_module),symid)
     assert symid.var==self.symbol,\
         "%s symbol's variable name ('%s') does not match symbol name being " \
             "referenced: '%s'" \
             % (assembler.eloc(self,"_ck_symid",module=this_module),\
                 self.symbol,symid.var)
     return
Пример #15
0
    def str_begin(self, value):
        assert isinstance(value,StringToken),\
            "%s 'value' argument must be a StringToken object: %s"\
                % (assembler.eloc(self,"str_begin",module=this_module),value)
        assert self._string is None,\
            "%s '_string' attribute is not None when starting a compound string: %s" \
                % (assembler.eloc(self,"str_begin",module=this_module),\
                    self._string)

        self._string = value
Пример #16
0
    def append(self, pline):
        assert isinstance(pline,asminput.PhysLine),\
            "%s 'pline' argument must be an asminput.PhysLine object: %s" \
                % (assembler.eloc(self,"__init__",module=this_module),pline)
        assert pline.operand_start is not None,\
            "%s 'pline.operand_start' must not be None" \
                % assembler.eloc(self,"__init__",module=this_module)

        loc = asmbase.ASMPLoc(source=pline.source, pndx=pline.operand_start)
        text = pline.text[pline.operand_start:]
        self.newloc(loc)
        self.text += text
        self.amp = self.amp or "&" in text
Пример #17
0
 def append(self,pline):
     assert isinstance(pline,asminput.PhysLine),\
         "%s 'pline' argument must be an asminput.PhysLine object: %s" \
             % (assembler.eloc(self,"__init__",module=this_module),pline)
     assert pline.operand_start is not None,\
         "%s 'pline.operand_start' must not be None" \
             % assembler.eloc(self,"__init__",module=this_module)
             
     loc=asmbase.ASMPLoc(source=pline.source,pndx=pline.operand_start)
     text=pline.text[pline.operand_start:]
     self.newloc(loc)
     self.text+=text
     self.amp = self.amp or "&" in text
Пример #18
0
    def __init__(self, pline):
        assert isinstance(pline,asminput.PhysLine),\
            "%s 'pline' argument must be an asminput.PhysLine object: %s" \
                % (assembler.eloc(self,"__init__",module=this_module),pline)
        assert pline.operand_start is not None,\
            "%s 'pline.operand_start' must not be None" \
                % assembler.eloc(self,"__init__",module=this_module)

        text = pline.text[pline.operand_start:]
        amp = "&" in text
        loc = asmbase.ASMPLoc(source=pline.source, pndx=pline.operand_start)

        super().__init__(text, start=loc, amp=amp)
Пример #19
0
    def __init__(self,pline):
        assert isinstance(pline,asminput.PhysLine),\
            "%s 'pline' argument must be an asminput.PhysLine object: %s" \
                % (assembler.eloc(self,"__init__",module=this_module),pline)
        assert pline.operand_start is not None,\
            "%s 'pline.operand_start' must not be None" \
                % assembler.eloc(self,"__init__",module=this_module)

        text=pline.text[pline.operand_start:]
        amp="&" in text
        loc=asmbase.ASMPLoc(source=pline.source,pndx=pline.operand_start)

        super().__init__(text,start=loc,amp=amp)
Пример #20
0
    def getLine(self, debug=False):
        # Throws a MacroError if a user error is detected
        # Note: Need to accept a list of physical lines and a line continuation
        # convention

        if len(self.queued) > 0:
            line = self.queued.pop(0)
            pline = StreamLine(None, line, genlvl=self.depth)
            if __debug__:
                if debug:
                    print("%s returning queued: %s" \
                        % (assembler.eloc(self,"getLine",module=this_module),pline))
            return pline

        # No previously queued physical lines so get one (or more) from the
        # macro.
        plines = self.exp.generate()
        if __debug__:
            if debug:
                print("%s received from macro %s Invoker: %s" \
                    % (assembler.eloc(self,"getLine",module=this_module),\
                        self.exp.name,plines))

        # Determine if the macro is done generating input
        if plines is None:
            if __debug__:
                if debug:
                    print("%s end of input from macro %s Invoker: " \
                        "raising SourceEmpty()" \
                            % (assembler.eloc(self,"getLine",module=this_module),\
                                self.exp.name))
            # Tell LineBuffer object that this source is exhausted
            raise SourceEmpty()

        # Create a new physical line - eventually multiple physical lines will be
        # required of different continuation styles.
        assert isinstance(plines,list) and len(plines)>0,\
            "%s macro invocation must return a non-empty list of strings: %s" \
                % (assembler.eloc(self,"getLine",module=this_module),plines)

        if len(plines) > 1:
            self.queued = plines[1:]  # Queue the extra lines for the next call

        # Return the first or only line
        pline = StreamLine(None, plines[0], genlvl=self.depth)
        if __debug__:
            if debug:
                print("%s returning: %s" \
                    % (assembler.eloc(self,"getLine",module=this_module),pline))

        return pline
Пример #21
0
    def getLine(self,debug=False):
        # Throws a MacroError if a user error is detected
        # Note: Need to accept a list of physical lines and a line continuation
        # convention

        if len(self.queued)>0:
            line=self.queued.pop(0)
            pline=StreamLine(None,line,genlvl=self.depth)
            if __debug__:
                if debug:
                    print("%s returning queued: %s" \
                        % (assembler.eloc(self,"getLine",module=this_module),pline))
            return pline

        # No previously queued physical lines so get one (or more) from the
        # macro.
        plines=self.exp.generate()
        if __debug__:
            if debug:
                print("%s received from macro %s Invoker: %s" \
                    % (assembler.eloc(self,"getLine",module=this_module),\
                        self.exp.name,plines))

        # Determine if the macro is done generating input
        if plines is None:
            if __debug__:
                if debug:
                    print("%s end of input from macro %s Invoker: " \
                        "raising SourceEmpty()" \
                            % (assembler.eloc(self,"getLine",module=this_module),\
                                self.exp.name))
            # Tell LineBuffer object that this source is exhausted
            raise SourceEmpty()

        # Create a new physical line - eventually multiple physical lines will be
        # required of different continuation styles.
        assert isinstance(plines,list) and len(plines)>0,\
            "%s macro invocation must return a non-empty list of strings: %s" \
                % (assembler.eloc(self,"getLine",module=this_module),plines)

        if len(plines)>1:
            self.queued=plines[1:]  # Queue the extra lines for the next call

        # Return the first or only line
        pline=StreamLine(None,plines[0],genlvl=self.depth)
        if __debug__:
            if debug:
                print("%s returning: %s" \
                    % (assembler.eloc(self,"getLine",module=this_module),pline))

        return pline
Пример #22
0
    def fetch(self,lit_str,debug=False):
        assert isinstance(lit_str,str),\
            "%s 'lit_str' argument not a string: %s" \
                % (assembler.eloc(self,"fetch",module=this_module),lit_str)
        assert len(lit_str)>1 and lit_str[0]=="=",\
            "%s 'lit_str' argument is not a valid literal: '%s'" \
                % (assembler.eloc(self,"fetch",module=this_module),lit_str)

        lit=self.literals[lit_str]
        if __debug__:
            if debug:
                print("%s RETURNING LITERAL OBJECT: %r" \
                    % (assembler.eloc(self,"fetch",module=this_module),lit))
        return lit
Пример #23
0
    def __init__(self,variable,indices=[],subscript=0):
        assert isinstance(variable,str) and len(variable)>0,\
            "%s 'variable' argument must be a non-empty string: %s" \
                % (assembler.eloc(self,"__init__",module=this_module),variable)
        assert variable[0]=='&',\
            "%s 'variable' argument must start with an '&': '%s'" \
                % (assembler.eloc(self,"__init__",module=this_module),variable)

        self.var=variable        # The symbolic symbols's name (with '&')
        self.indices=indices     # Variable number of integer indices.
        self.sub=None            # Integer of array subscript

        if len(indices)==1:
            self.sub=indices[0]
Пример #24
0
    def parse_sep(self,stmt,debug=False):
        parser=self.__fetch_parser(stmt.get_Operand_Parser())
        if __debug__:
            if debug:
                print("%s parser: %s" \
                    % (assembler.eloc(self,"parse_sep",module=this_module),parser))

        result=parser.parse_operands(stmt,debug=debug)
        if __debug__:
            if debug:
                print("%s result: %s" \
                    % (assembler.eloc(self,"parse_sep",module=this_module),result))

        return result
Пример #25
0
    def fetch(self, lit_str, debug=False):
        assert isinstance(lit_str,str),\
            "%s 'lit_str' argument not a string: %s" \
                % (assembler.eloc(self,"fetch",module=this_module),lit_str)
        assert len(lit_str)>1 and lit_str[0]=="=",\
            "%s 'lit_str' argument is not a valid literal: '%s'" \
                % (assembler.eloc(self,"fetch",module=this_module),lit_str)

        lit = self.literals[lit_str]
        if __debug__:
            if debug:
                print("%s RETURNING LITERAL OBJECT: %r" \
                    % (assembler.eloc(self,"fetch",module=this_module),lit))
        return lit
Пример #26
0
    def parse(self,logline,attrs="",spaces=False,alt=False,comma=False):
        self.start(logline,attrs=attrs,spaces=spaces,alt=alt,comma=comma)

        # If initial line has no operands then just exit
        isline=self.line(trace=False)
        self.new_operand()

        if not isline:
            return []
        else:
            # Test for the case of a comma followed by a space indicating
            # comments are present on a statement without operands.
            opnd=self.cndx
            
            # Note: the physical line object removes trailing blanks, so we
            # have to treat just a comma with nothing after it as if it had a space.
            # We also have to check for the normal case where a comma followed by 
            # a space indicates no operands.  In this case there may be a comment.
            if len(self.text)==opnd+1 and self.text[opnd]==",":
                if __debug__:
                    if self._trace is not None:
                        print("%s operand field '%s' treated as without operands, "\
                            "returning: []"\
                                % (assembler.eloc(self,"parse",module=this_module),\
                                    self.text[opnd]))
                return []
            elif len(self.text)>=opnd+2 and self.text[opnd:opnd+2]==", ":
                if __debug__:
                    if self._trace is not None:
                        print("%s operand field '%s' treated as without operands, "\
                            "returning: []"\
                                % (assembler.eloc(self,"parse",module=this_module),\
                                    self.text[opnd:]))
                return []

        # Use FSM to parse operands
        while True:
            c=self.char()
            if c is None:
                break
            done=self.machine(c)
            if done:
                break

        # Make sure we add to the list the last operand
        if self.opno:
            self.check_operand()
            self.add_operand()
        return self.operands
Пример #27
0
    def define(self, oper):
        assert isinstance(oper,asmbase.ASMOper),\
            "%s 'oper' argument must be an asmbase.ASMOper object: %s" \
                % (assembler.eloc(self,"define",module=this_module),oper)
        assert oper.info._defined is not None,\
            "%s macro definition line is None: %s" \
                % (assembler.eloc(self,"define",module=this_module),macro)

        name = oper.info.name
        try:
            entry = self.macros[name]
            # Macro is being redefined
            entry.redefine(oper)
        except KeyError:
            # First macro definition with this name
            self.macros[name] = MTE(oper)
Пример #28
0
 def literal_new(self, lit, line, debug=False):
     lit.reference(line)
     if lit.unique:
         self.unique.append(lit)
         if __debug__:
             if debug:
                 print("%s [%s] LITERAL POOL %s ADDING UNIQUE: %r" \
                     % (assembler.eloc(self,"literal_new",module=this_module),\
                         line,self.pool_id,lit))
     else:
         self.literals[lit.name] = lit
         if __debug__:
             if debug:
                 print("%s [%s] LITERAL POOL %s ADDING: %r" \
                     % (assembler.eloc(self,"literal_new",module=this_module),\
                         line,self.pool_id,lit))
Пример #29
0
    def build(self,asm,parsers,stmt,n,length,trace=False):
        if length != 2:
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s S-type explicit length invalid: %s" % (n+1,length))
        
        value=parsers.evaluate_expr(asm,stmt,self.expr,debug=False,trace=trace)
        
        if isinstance(value,int):
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s S-type value not an address: %s" % (n+1,value))

        try:
            base,disp=asm.bases.find(value,12,asm,trace=trace)
        except KeyError:
            # Could not resolve base register and displacement
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s S-type constant could not resolve implied base "
                "register for location: %s" % (n+1,value)) from None
            
        value=(base<<12)+(0xFFF & disp)
        b=value.to_bytes(2,byteorder="big",signed=False)
        
        if __debug__:
            if trace:
                print("%s return bytes: %s '%s'" \
                    % (assembler.eloc(self,"build",module=this_module),len(b),b))
        
        return b
Пример #30
0
    def __init__(self,value=0):
        assert isinstance(value,int),\
            "%s 'value' argument must be an integer: '%s'" \
                % (assembler.eloc(self,"__init__",module=this_module),value)

        super().__init__(value)
        self["T"]="N"
Пример #31
0
    def build(self, stmt, trace=False):
        assert isinstance(stmt,asmstmts.MachineStmt),\
            "%s 'stmt' argument requires instance of assembler.Stmt: %s" \
                % (assembler.eloc(self,"build",module=this_module),stmt)

        fmt = stmt.format  # msldb.Format instance
        insn = stmt.insn  # assembler.MSLentry instance
        line = stmt.lineno  # Source object of statement's input location
        if trace:
            insn.dump()  # Dump the MSL DB information

        # Marshall what we need to create the instruction
        i = Instruction(stmt.bin_oprs, insn, fmt, line)
        if trace:
            i.dump()
        # NOW!!! build the instruction
        barray = i.generate(self)

        if trace:
            print("%s: " % insn.mnemonic)
            s = ""
            for x in barray:
                s = "%s %s" % (s, hex(x))
            print("    %s" % s)

        # Update the statenent's binary object
        bin = stmt.content  # Get Binary object from the Stmt
        bin.update(barray, at=0, full=True, finalize=True, trace=trace)
Пример #32
0
 def literal_new(self,lit,line,debug=False):
     lit.reference(line)
     if lit.unique:
         self.unique.append(lit)
         if __debug__:
             if debug:
                 print("%s [%s] LITERAL POOL %s ADDING UNIQUE: %r" \
                     % (assembler.eloc(self,"literal_new",module=this_module),\
                         line,self.pool_id,lit))
     else:
         self.literals[lit.name]=lit
         if __debug__:
             if debug:
                 print("%s [%s] LITERAL POOL %s ADDING: %r" \
                     % (assembler.eloc(self,"literal_new",module=this_module),\
                         line,self.pool_id,lit))
Пример #33
0
    def define(self,oper):
        assert isinstance(oper,asmbase.ASMOper),\
            "%s 'oper' argument must be an asmbase.ASMOper object: %s" \
                % (assembler.eloc(self,"define",module=this_module),oper)
        assert oper.info._defined is not None,\
            "%s macro definition line is None: %s" \
                % (assembler.eloc(self,"define",module=this_module),macro)

        name=oper.info.name
        try:
            entry=self.macros[name]
            # Macro is being redefined
            entry.redefine(oper)
        except KeyError:
            # First macro definition with this name
            self.macros[name]=MTE(oper)
Пример #34
0
    def ltoken_update(self,stmt,ltok,asmstr=None):
        assert isinstance(asmstr,asmbase.ASMString),\
            "%s 'asmstr' argument must be an instance of asmbase.ASMString: %s" \
                 % (assembler.eloc(self,"ltoken_update",module=this_module),asmstr)

        loc=asmstr.ndx2loc(ltok.linepos)
        ltok.update_loc(stmt.lineno,loc)
Пример #35
0
    def build(self,stmt,trace=False):
        #cls_str="insnbldr.py - %s.build() -" % self.__class__.__name__
        if __debug__:
            if Builder.type_check:
                assert isinstance(stmt,assembler.Stmt),\
                    "%s 'stmt' argument requires instance of assembler.Stmt: %s" \
                        % (assembler.eloc(self,"build",module=this_module),stmt)

        fmt=stmt.format       # msldb.Format instance
        insn=stmt.insn        # assembler.MSLentry instance
        line=stmt.lineno      # Source object of statement's input location
        if trace:
            insn.dump()       # Dump the MSL DB information

        # Marshall what we need to create the instruction
        i=Instruction(stmt.operands,insn,fmt,line)
        if trace:
            i.dump()
        # NOW!!! build the instruction
        barray=i.generate(self)

        if trace:
            print("%s: " % insn.mnemonic)
            s=""
            for x in barray:
                s="%s %s" % (s,hex(x))
            print("    %s" % s)

        # Update the statenent's binary object
        bin=stmt.content    # Get Binary object from the Stmt
        bin.update(barray,at=0,full=True,finalize=True,trace=trace)
Пример #36
0
    def getLine(self):
        if self._end:
            raise ValueError("%s input statements present after END statement" \
                % assembler.eloc(self,"getline"))

        # This while statement ends with:
        #   - a BufferEmtpy exception being raised (to tell assembler input is done)
        #   - an AssemblerError exception if current source can not be terminated
        #   - has received a Line object from the source.
        # This while statement recycles only when a source ends and a previous
        # source has been made the current source.  The recycle simply tries to
        # read from the unnested source, now the current source.
        while True:
            try:
                ln=self._cur_src.getLine(debug=False)
                # WARNING: this break is required!  DO NOT DELETE
                break
            except SourceEmpty:
                # Current source is done
                # A BufferEmpty exception is raised when all input is exhausted
                self.__exhausted()
                continue   # try reading from the unnested source now
            except asmmacs.MacroError as me:
                # A macro invocation will throw this error when a problem is detected
                # We catch it here so we can terminate the macro source.
                self.__exhausted()
                # Then we raise it again to allow the assembler to handle it
                raise me from None

        return ln
Пример #37
0
    def build(self, asm, parsers, stmt, n, length, trace=False):
        if length != 2:
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s S-type explicit length invalid: %s" % (n+1,length))

        value = parsers.evaluate_expr(asm,
                                      stmt,
                                      self.expr,
                                      debug=False,
                                      trace=trace)

        if isinstance(value, int):
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s S-type value not an address: %s" % (n+1,value))

        try:
            base, disp = asm.bases.find(value, 12, asm, trace=trace)
        except KeyError:
            # Could not resolve base register and displacement
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s S-type constant could not resolve implied base "
                "register for location: %s" % (n+1,value)) from None

        value = (base << 12) + (0xFFF & disp)
        b = value.to_bytes(2, byteorder="big", signed=False)

        if __debug__:
            if trace:
                print("%s return bytes: %s '%s'" \
                    % (assembler.eloc(self,"build",module=this_module),len(b),b))

        return b
Пример #38
0
    def getLine(self):
        if self._end:
            raise ValueError("%s input statements present after END statement" \
                % assembler.eloc(self,"getline"))

        # This while statement ends with:
        #   - a BufferEmtpy exception being raised (to tell assembler input is done)
        #   - an AssemblerError exception if current source can not be terminated
        #   - has received a Line object from the source.
        # This while statement recycles only when a source ends and a previous
        # source has been made the current source.  The recycle simply tries to
        # read from the unnested source, now the current source.
        while True:
            try:
                ln = self._cur_src.getLine(debug=False)
                # WARNING: this break is required!  DO NOT DELETE
                break
            except SourceEmpty:
                # Current source is done
                # A BufferEmpty exception is raised when all input is exhausted
                self.__exhausted()
                continue  # try reading from the unnested source now
            except asmmacs.MacroError as me:
                # A macro invocation will throw this error when a problem is detected
                # We catch it here so we can terminate the macro source.
                self.__exhausted()
                # Then we raise it again to allow the assembler to handle it
                raise me from None

        return ln
Пример #39
0
    def extend(self,ltok):
        assert isinstance(ltok,StringToken),\
            "%s 'ltok' argument must be another StringToken object: %s" \
                % (assembler.eloc(self,"extend",module=this_module),ltok)  

        self.string="%s%s" % (self.string,ltok.string)
        #print('following extend: self.string="%s"' % self.string)
        self.end=ltok.end
Пример #40
0
    def __init__(self,typ,exp,stmtno=None,srcno=None):
        if not isinstance(exp,asmmacs.Invoker):
            cls_str=assembler.eloc(self,"__init__",module=this_module)
            raise ValueError("%s 'exp' argument must be an asmmacs.Expander object: "
                "%s" % (cls_str,exp))

        self.exp=exp          # asmmacs.Invoker object
        super().__init__(typ,exp.macro.name,stmtno=stmtno)
Пример #41
0
    def parse_model(self,stmt,field,debug=False):
        if __debug__:
            if debug:
                print("%s debug: %s" \
                    % (assembler.eloc(self,"parse_model",module=this_module),debug))

        parser=self.__fetch_parser("mopnd")
        return parser.parse_model(stmt,field,debug=debug)
Пример #42
0
 def __init__(self,addrexpr):
     assert isinstance(addrexpr,pratt2.PExpr),\
         "%s 'addrexpr' argument must be a pratt2.PExpr: %s" \
             % (assembler.eloc(self,"__init__",module=this_module),addrexpr)
     
     length,align=self.__class__.attr
     super().__init__(addrexpr,length=length,alignment=align,signed=False)
     self.ivalue=SCON(addrexpr)
Пример #43
0
    def parse_operation(self,asm,stmt,debug=False):
        if __debug__:
            if debug:
                print("%s called" % assembler.eloc(self,"parse_operation",\
                    module=this_module))

        result=self.__parse(asm,stmt,stmt.oper_fld,debug=debug)
        self.oper_fld=self.prepare_result(stmt,result,"oper",debug=debug)
Пример #44
0
    def parse_operation(self, asm, stmt, debug=False):
        if __debug__:
            if debug:
                print("%s called" % assembler.eloc(self,"parse_operation",\
                    module=this_module))

        result = self.__parse(asm, stmt, stmt.oper_fld, debug=debug)
        self.oper_fld = self.prepare_result(stmt, result, "oper", debug=debug)
Пример #45
0
    def extend(self, ltok):
        assert isinstance(ltok,StringToken),\
            "%s 'ltok' argument must be another StringToken object: %s" \
                % (assembler.eloc(self,"extend",module=this_module),ltok)

        self.string = "%s%s" % (self.string, ltok.string)
        #print('following extend: self.string="%s"' % self.string)
        self.end = ltok.end
Пример #46
0
    def build(self, asm, parsers, stmt, n, length, trace=False):
        try:
            value = parsers.evaluate_expr(asm,
                                          stmt,
                                          self.expr,
                                          debug=False,
                                          trace=trace)
        except assembler.AddrArithError as ae:
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s address arithmetic error, %s" \
                    % (n+1,ae))

        assert isinstance(value,(int,assembler.Address)),\
            "%s internal calculation of operand %s address expression resulted in an"\
            "unsupported value: %s" \
            % (assembler.eloc(self,"build",module=this_module),n+1,value)

        if isinstance(value, assembler.Address):
            if length not in self.lengths:
                raise assembler.AssemblerError(line=stmt.lineno,\
                    msg="operand %s %s-type explicit length invalid for an address "\
                    "nominal value: %s" % (n+1,self.typ,length))
            if value.isAbsolute():
                value = value.address
            else:
                raise assembler.AssemblerError(line=stmt.lineno,\
                    msg="operand %s address constant did not evaluate to an "\
                        "absolute address: %s" % (n+1,value))

        # Convert computed address constant to bytes
        b = value.to_bytes((value.bit_length() // 8) + 1,
                           byteorder="big",
                           signed=False)

        # Perform left truncation/padding
        pad = b'\x00' * length
        bindata = pad + b
        b = bindata[len(bindata) - length:]

        if __debug__:
            if trace:
                print("%s return bytes: %s '%s'" % (assembler.eloc(
                    self, "build", module=this_module), len(b), b))

        return b
Пример #47
0
 def normal(self):
     logline=self.logline
     logline.normal()
     self.text=logline.line
     self.empty=logline.empty
     assert isinstance(self.text,str),\
         "%s text attribute not a string: %s" \
             % (assembler.eloc(self,"normal",module=this_module),logline)
     self._normal=True
Пример #48
0
    def addCont(self, pline, debug=False):
        cont = pline.isContinuation()

        if not cont:
            if __debug__:
                if debug:
                    print("%s cont: %s" \
                        % (assembler.eloc(self,"addCont",module=this_module),cont))
            return False

        self.plines.append(pline)
        if __debug__:
            if debug:
                print("%s plines: %s" \
                    % (assembler.eloc(self,"addCont",module=this_module),\
                        len(self.plines)))

        return True
Пример #49
0
 def fini(self):
     if self.fo is None:
         raise ValueError("%s file object not created for file: %s" \
             % (assembler.eloc(self,"fini",module=this_module),self.fname))
     try:
         self.fo.close()
     except OSError:
         raise SourceError("could not close input text file: %s" % self.fname) \
             from None
Пример #50
0
 def get_O_attr(self, name):
     try:
         oper = self.getOper(name, macread=False, debug=False)
         assert isinstance(oper,asmbase.ASMOper),\
             "%s getOper did not return an asmbase.ASMOper instance: %s" \
                 % (assembler.eloc(self,"oper",module=this_module),oper)
     except KeyError:
         return "U"
     return oper.O
Пример #51
0
 def inject(self,lines,release=True):
     ln=[]
     if isinstance(lines,str):
         ln.append(lines)
     elif isinstance(lines,list):
         for ndx in range(len(lines)):
             line=lines[ndx]
             if not isinstance(line,str):
                 cls_str=assembler.eloc(self,"inject")
                 raise ValueError("%s 'line' argument item %s not a string: %s" \
                     (cls_str,ndx,line))
             if len(line)!=0 and line[-1]=="\n":
                 line=line[:-1]
             ln.append(line)
     else:
         cls_str=assembler.eloc(self,"inject")
         raise ValueError("%s 'lines' argument must be a string or list of "
             "strings: %s" % lines)
     self.lines.extend(ln)
Пример #52
0
    def redefine(self, oper):
        assert oper.info.name==self.name,\
            "%s macro entry name, '%s' does not match macro definition: '%s'" \
                % (assembler.eloc(self,"redefine",module=this_module),\
                    self.name,oper.info.name)

        self.oper = oper  # The ASMOper object has the macro definition!
        # Allow external users to update this macro refs. via the macro object
        oper.info._xref = self.xref
        self.xref.define(oper.info._defined)
Пример #53
0
    def str_end(self):
        if self._string is None:
            return
        assert isinstance(self._string,StringToken),\
            "%s '_string' attribute must be a StringToken object: %s" \
                % (assembler.eloc(self,"str_end",module=this_module),self._string)

        accum = self._string
        self._string = None
        return accum
Пример #54
0
    def value(self, external=None, debug=False, trace=False):
        # Need to do symbolic replacement with new searcher
        string = external.exp.symbol_replace(self.src.string, debug=debug)

        if __debug__:
            if trace:
                print('%s string: "%s"' \
                    % (assembler.eloc(self,"value",module=this_module)))

        return assembler.CPTRANS.a2e(string)
Пример #55
0
    def __init__(self, typ, exp, stmtno=None, srcno=None, fixed=False):
        if not isinstance(exp, asmmacs.Invoker):
            cls_str = assembler.eloc(self, "__init__", module=this_module)
            raise ValueError(
                "%s 'exp' argument must be an asmmacs.Expander object: "
                "%s" % (cls_str, exp))

        self.exp = exp  # asmmacs.Invoker object
        self.depth = None  # Macro level nesting depth - See init() method.
        super().__init__(typ, exp.macro.name, stmtno=stmtno)
        self.queued = []
Пример #56
0
    def __init__(self, addrexpr):
        assert isinstance(addrexpr,pratt2.PExpr),\
            "%s 'addrexpr' argument must be a pratt2.PExpr: %s" \
                % (assembler.eloc(self,"__init__",module=this_module),addrexpr)

        length, align = self.__class__.attr
        super().__init__(addrexpr,
                         length=length,
                         alignment=align,
                         signed=False)
        self.ivalue = SCON(addrexpr)
Пример #57
0
    def __init__(self,line,lineno=None,source=None,typ="X",macro=False):
        assert isinstance(line,asmcards.LogLine),\
            "%s 'line' argument must be an instance of asmcards.LogLine: %s" \
                % (assembler.eloc(self,"__init__",module=this_module),line)
        assert (source is None) or isinstance(source,Source),\
            "%s 'source' argument must be an instance of Source: %s" \
                % (assembler.eloc(self,"__init__",module=this_module),source)

        # typ attribute controls how the line is processed by the assembler
        #   'B' --> This is a macro body statement
        #   'E' --> Expanded line (typ after expansion)
        #   'F' --> Text expansion failed, see self.merror for reason
        #   'P' --> This is a macro prototype statement
        #   'X' --> This is a normal input line and must be expanded by the current
        #           asmmacs.Expander object
        self.typ=typ         # Line type
        self.logline=line    # asmcards.LogLine object
        self._normal=False   # normal method() called if True

        # THIS ATTRIBUTE IS USED FOR LISTING SOURCE CONTENT
        self.text=None       # Text of logical line of text
        
        self.lineno=lineno   # Global line number (The statement number in the listing)
        self.source=source   # Input source information
        self.psource=None    # This is used for printing source lines

        # Macro related information
        self.macro=macro     # If True, this line is a macro generated line
        self.merror=None     # MacroError exception if expansion failed

        self.comment=line.comment   # If True this is a comment statement
        self.silent=line.silent     # If comment and True, it is a silent comment
        self.empty=line.empty       # True if line is empty or all spaces
        
        # Validate the logical line.  LineError exceptions caught and reraised as
        # assembler errors which must be handled by Stmt instantiator
        self.validate()

        # Early comment and empty line detection
        if self.empty:
            self.text=""