mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 09:39:32 +01:00 
			
		
		
		
	* rename old ttype variables *type to *def * rename resulttypepass to pass_typecheck * rename pass_2 to pass_generate_code git-svn-id: trunk@5077 -
		
			
				
	
	
		
			1535 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			1535 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
    Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
 | 
						|
 | 
						|
    Does the parsing for the GAS styled inline assembler.
 | 
						|
 | 
						|
    This program is free software; you can redistribute it and/or modify
 | 
						|
    it under the terms of the GNU General Public License as published by
 | 
						|
    the Free Software Foundation; either version 2 of the License, or
 | 
						|
    (at your option) any later version.
 | 
						|
 | 
						|
    This program is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU General Public License
 | 
						|
    along with this program; if not, write to the Free Software
 | 
						|
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
 | 
						|
 ****************************************************************************
 | 
						|
}
 | 
						|
unit raatt;
 | 
						|
 | 
						|
{$i fpcdefs.inc}
 | 
						|
 | 
						|
  interface
 | 
						|
 | 
						|
    uses
 | 
						|
      { common }
 | 
						|
      cutils,cclasses,
 | 
						|
      { global }
 | 
						|
      globtype,
 | 
						|
      { aasm }
 | 
						|
      cpubase,cpuinfo,aasmbase,aasmtai,aasmdata,aasmcpu,
 | 
						|
      { assembler reader }
 | 
						|
      rabase,
 | 
						|
      rasm,
 | 
						|
      rautils,
 | 
						|
      { symtable }
 | 
						|
      symconst,
 | 
						|
      { cg }
 | 
						|
      cgbase;
 | 
						|
 | 
						|
    type
 | 
						|
      tasmtoken = (
 | 
						|
        AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_INTNUM,
 | 
						|
        AS_REALNUM,AS_COMMA,AS_LPAREN,
 | 
						|
        AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,
 | 
						|
        AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_DOLLAR,
 | 
						|
        AS_HASH,AS_LSBRACKET,AS_RSBRACKET,AS_LBRACKET,AS_RBRACKET,
 | 
						|
        {------------------ Assembler directives --------------------}
 | 
						|
        AS_DB,AS_DW,AS_DD,AS_DQ,AS_GLOBAL,
 | 
						|
        AS_ALIGN,AS_BALIGN,AS_P2ALIGN,AS_ASCII,
 | 
						|
        AS_ASCIIZ,AS_LCOMM,AS_COMM,AS_SINGLE,AS_DOUBLE,AS_EXTENDED,
 | 
						|
        AS_DATA,AS_TEXT,AS_END,
 | 
						|
        {------------------ Assembler Operators  --------------------}
 | 
						|
        AS_TYPE,AS_SIZEOF,AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR,AS_NOR,AS_AT,
 | 
						|
        AS_LO,AS_HI);
 | 
						|
 | 
						|
        tasmkeyword = string[10];
 | 
						|
 | 
						|
    const
 | 
						|
      { These tokens should be modified accordingly to the modifications }
 | 
						|
      { in the different enumerations.                                   }
 | 
						|
      firstdirective = AS_DB;
 | 
						|
      lastdirective  = AS_END;
 | 
						|
 | 
						|
      token2str : array[tasmtoken] of tasmkeyword=(
 | 
						|
        '','Label','LLabel','string','integer',
 | 
						|
        'float',',','(',
 | 
						|
        ')',':','.','+','-','*',
 | 
						|
        ';','identifier','register','opcode','/','$',
 | 
						|
        '#','{','}','[',']',
 | 
						|
        '.byte','.word','.long','.quad','.globl',
 | 
						|
        '.align','.balign','.p2align','.ascii',
 | 
						|
        '.asciz','.lcomm','.comm','.single','.double','.tfloat',
 | 
						|
        '.data','.text','END',
 | 
						|
        'TYPE','SIZEOF','%','<<','>>','!','&','|','^','~','@','lo','hi');
 | 
						|
 | 
						|
    type
 | 
						|
       tattreader = class(tasmreader)
 | 
						|
         actasmtoken    : tasmtoken;
 | 
						|
         prevasmtoken   : tasmtoken;
 | 
						|
         procedure SetupTables;
 | 
						|
         procedure BuildConstant(constsize: byte);
 | 
						|
         procedure BuildConstantOperand(oper : toperand);
 | 
						|
         procedure BuildRealConstant(typ : tfloattype);
 | 
						|
         procedure BuildStringConstant(asciiz: boolean);
 | 
						|
         procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint);
 | 
						|
         procedure BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
 | 
						|
         function BuildConstExpression(allowref,betweenbracket:boolean): aint;
 | 
						|
         function Assemble: tlinkedlist;override;
 | 
						|
         procedure handleopcode;virtual;abstract;
 | 
						|
         function is_asmopcode(const s: string) : boolean;virtual;abstract;
 | 
						|
         Function is_asmdirective(const s: string):boolean;
 | 
						|
         function is_register(const s:string):boolean;virtual;
 | 
						|
         function is_locallabel(const s: string):boolean;
 | 
						|
         procedure GetToken;
 | 
						|
         function consume(t : tasmtoken):boolean;
 | 
						|
         procedure RecoverConsume(allowcomma:boolean);
 | 
						|
         procedure handlepercent;virtual;
 | 
						|
       end;
 | 
						|
       tcattreader = class of tattreader;
 | 
						|
 | 
						|
    var
 | 
						|
      cattreader : tcattreader;
 | 
						|
 | 
						|
  implementation
 | 
						|
 | 
						|
    uses
 | 
						|
      { globals }
 | 
						|
      verbose,systems,
 | 
						|
      { input }
 | 
						|
      scanner,
 | 
						|
      { symtable }
 | 
						|
      symbase,symtype,symsym,symtable,
 | 
						|
{$ifdef x86}
 | 
						|
      rax86,
 | 
						|
{$endif x86}
 | 
						|
      itcpugas,
 | 
						|
      procinfo;
 | 
						|
 | 
						|
 | 
						|
    procedure tattreader.SetupTables;
 | 
						|
      { creates uppercased symbol tables for speed access }
 | 
						|
      var
 | 
						|
        i : tasmop;
 | 
						|
        str2opentry: tstr2opentry;
 | 
						|
      Begin
 | 
						|
        { opcodes }
 | 
						|
        iasmops:=TDictionary.Create;
 | 
						|
        iasmops.delete_doubles:=true;
 | 
						|
        for i:=firstop to lastop do
 | 
						|
          begin
 | 
						|
            str2opentry:=tstr2opentry.createname(upper(gas_op2str[i]));
 | 
						|
            str2opentry.op:=i;
 | 
						|
            iasmops.insert(str2opentry);
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tattreader.is_asmdirective(const s: string):boolean;
 | 
						|
      var
 | 
						|
        i : tasmtoken;
 | 
						|
        hs : string;
 | 
						|
      Begin
 | 
						|
        { GNU as is also not casesensitive with this }
 | 
						|
        hs:=lower(s);
 | 
						|
        for i:=firstdirective to lastdirective do
 | 
						|
         if hs=token2str[i] then
 | 
						|
          begin
 | 
						|
            actasmtoken:=i;
 | 
						|
            is_asmdirective:=true;
 | 
						|
            exit;
 | 
						|
          end;
 | 
						|
        is_asmdirective:=false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tattreader.is_register(const s:string):boolean;
 | 
						|
      begin
 | 
						|
        is_register:=false;
 | 
						|
        actasmregister:=gas_regnum_search(lower(s));
 | 
						|
        if actasmregister<>NR_NO then
 | 
						|
          begin
 | 
						|
            is_register:=true;
 | 
						|
            actasmtoken:=AS_REGISTER;
 | 
						|
          end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tattreader.is_locallabel(const s: string):boolean;
 | 
						|
      begin
 | 
						|
        is_locallabel:=(length(s)>=2) and (s[1]='.') and (s[2]='L');
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tattreader.handlepercent;
 | 
						|
      begin
 | 
						|
        c:=current_scanner.asmgetchar;
 | 
						|
        actasmtoken:=AS_MOD;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tattreader.GetToken;
 | 
						|
      var
 | 
						|
        len : longint;
 | 
						|
        srsym : tsym;
 | 
						|
        srsymtable : tsymtable;
 | 
						|
      begin
 | 
						|
        { save old token and reset new token }
 | 
						|
        prevasmtoken:=actasmtoken;
 | 
						|
        actasmtoken:=AS_NONE;
 | 
						|
        { reset }
 | 
						|
        actasmpattern:='';
 | 
						|
        { while space and tab , continue scan... }
 | 
						|
        while c in [' ',#9] do
 | 
						|
         c:=current_scanner.asmgetchar;
 | 
						|
        { get token pos }
 | 
						|
{$ifdef arm}
 | 
						|
        if not (c in [#10,#13,';']) then
 | 
						|
          current_scanner.gettokenpos;
 | 
						|
{$else arm}
 | 
						|
        if not (c in [#10,#13,'{',';']) then
 | 
						|
          current_scanner.gettokenpos;
 | 
						|
{$endif arm}
 | 
						|
 | 
						|
        { Local Label, Label, Directive, Prefix or Opcode }
 | 
						|
{$ifdef arm}
 | 
						|
        if firsttoken and not(c in [#10,#13,';']) then
 | 
						|
{$else arm}
 | 
						|
        if firsttoken and not(c in [#10,#13,'{',';']) then
 | 
						|
{$endif arm}
 | 
						|
         begin
 | 
						|
           firsttoken:=FALSE;
 | 
						|
           len:=0;
 | 
						|
           { directive or local label }
 | 
						|
           if c = '.' then
 | 
						|
            begin
 | 
						|
              inc(len);
 | 
						|
              actasmpattern[len]:=c;
 | 
						|
              { Let us point to the next character }
 | 
						|
              c:=current_scanner.asmgetchar;
 | 
						|
              while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
 | 
						|
               begin
 | 
						|
                 inc(len);
 | 
						|
                 actasmpattern[len]:=c;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
               end;
 | 
						|
              actasmpattern[0]:=chr(len);
 | 
						|
              { this is a local label... }
 | 
						|
              if (c=':') and is_locallabel(actasmpattern) then
 | 
						|
               Begin
 | 
						|
                 { local variables are case sensitive }
 | 
						|
                 actasmtoken:=AS_LLABEL;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 firsttoken:=true;
 | 
						|
                 exit;
 | 
						|
               end
 | 
						|
              { must be a directive }
 | 
						|
              else
 | 
						|
               Begin
 | 
						|
                 { directives are case sensitive!! }
 | 
						|
                 if is_asmdirective(actasmpattern) then
 | 
						|
                  exit;
 | 
						|
                 Message1(asmr_e_not_directive_or_local_symbol,actasmpattern);
 | 
						|
               end;
 | 
						|
            end;
 | 
						|
           { only opcodes and global labels are allowed now. }
 | 
						|
           while c in ['A'..'Z','a'..'z','0'..'9','_'] do
 | 
						|
            begin
 | 
						|
              inc(len);
 | 
						|
              actasmpattern[len]:=c;
 | 
						|
              c:=current_scanner.asmgetchar;
 | 
						|
            end;
 | 
						|
           actasmpattern[0]:=chr(len);
 | 
						|
           { Label ? }
 | 
						|
           if c = ':' then
 | 
						|
            begin
 | 
						|
              actasmtoken:=AS_LABEL;
 | 
						|
              { let us point to the next character }
 | 
						|
              c:=current_scanner.asmgetchar;
 | 
						|
              firsttoken:=true;
 | 
						|
              exit;
 | 
						|
            end;
 | 
						|
{$ifdef POWERPC}
 | 
						|
           { some PowerPC instructions can have the postfix -, + or .
 | 
						|
             this code could be moved to is_asmopcode but I think
 | 
						|
             it's better to ifdef it here (FK)
 | 
						|
           }
 | 
						|
           case c of
 | 
						|
             '.', '-', '+':
 | 
						|
               begin
 | 
						|
                 actasmpattern:=actasmpattern+c;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
               end
 | 
						|
           end;
 | 
						|
{$endif POWERPC}
 | 
						|
{$ifdef POWERPC64}
 | 
						|
           { some PowerPC instructions can have the postfix -, + or .
 | 
						|
             this code could be moved to is_asmopcode but I think
 | 
						|
             it's better to ifdef it here (FK)
 | 
						|
           }
 | 
						|
           case c of
 | 
						|
             '.', '-', '+':
 | 
						|
               begin
 | 
						|
                 actasmpattern:=actasmpattern+c;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
               end
 | 
						|
           end;
 | 
						|
{$endif POWERPC64}
 | 
						|
           { Opcode ? }
 | 
						|
           If is_asmopcode(upper(actasmpattern)) then
 | 
						|
            Begin
 | 
						|
              uppervar(actasmpattern);
 | 
						|
              exit;
 | 
						|
            end;
 | 
						|
           { End of assemblerblock ? }
 | 
						|
           if upper(actasmpattern) = 'END' then
 | 
						|
            begin
 | 
						|
              actasmtoken:=AS_END;
 | 
						|
              exit;
 | 
						|
            end;
 | 
						|
           message1(asmr_e_unknown_opcode,actasmpattern);
 | 
						|
           actasmtoken:=AS_NONE;
 | 
						|
         end
 | 
						|
        else { else firsttoken }
 | 
						|
        { Here we must handle all possible cases }
 | 
						|
         begin
 | 
						|
           case c of
 | 
						|
             '.' :  { possiblities : - local label reference , such as in jmp @local1 }
 | 
						|
                    {               - field of object/record                         }
 | 
						|
                    {               - directive.                                     }
 | 
						|
               begin
 | 
						|
                 if (prevasmtoken in [AS_ID,AS_RPAREN]) then
 | 
						|
                  begin
 | 
						|
                    c:=current_scanner.asmgetchar;
 | 
						|
                    actasmtoken:=AS_DOT;
 | 
						|
                    exit;
 | 
						|
                  end;
 | 
						|
                 actasmpattern:=c;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 while c in  ['A'..'Z','a'..'z','0'..'9','_','$'] do
 | 
						|
                  begin
 | 
						|
                    actasmpattern:=actasmpattern + c;
 | 
						|
                    c:=current_scanner.asmgetchar;
 | 
						|
                  end;
 | 
						|
                 if is_asmdirective(actasmpattern) then
 | 
						|
                  exit;
 | 
						|
                 { local label references and directives }
 | 
						|
                 { are case sensitive                    }
 | 
						|
                 actasmtoken:=AS_ID;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
          { identifier, register, prefix or directive }
 | 
						|
             '_','A'..'Z','a'..'z':
 | 
						|
               begin
 | 
						|
                 len:=0;
 | 
						|
                 while c in ['A'..'Z','a'..'z','0'..'9','_','$'] do
 | 
						|
                  begin
 | 
						|
                    inc(len);
 | 
						|
                    actasmpattern[len]:=c;
 | 
						|
                    c:=current_scanner.asmgetchar;
 | 
						|
                  end;
 | 
						|
                 actasmpattern[0]:=chr(len);
 | 
						|
                 uppervar(actasmpattern);
 | 
						|
{$ifdef x86}
 | 
						|
                 { only x86 architectures have instruction prefixes }
 | 
						|
 | 
						|
                 { Opcode, can only be when the previous was a prefix }
 | 
						|
                 If is_prefix(actopcode) and is_asmopcode(actasmpattern) then
 | 
						|
                  Begin
 | 
						|
                    uppervar(actasmpattern);
 | 
						|
                    exit;
 | 
						|
                  end;
 | 
						|
{$endif x86}
 | 
						|
                 { check for end which is a reserved word unlike the opcodes }
 | 
						|
                 if actasmpattern = 'END' then
 | 
						|
                  Begin
 | 
						|
                    actasmtoken:=AS_END;
 | 
						|
                    exit;
 | 
						|
                  end;
 | 
						|
                 if actasmpattern = 'TYPE' then
 | 
						|
                  Begin
 | 
						|
                    actasmtoken:=AS_TYPE;
 | 
						|
                    exit;
 | 
						|
                  end;
 | 
						|
                 if actasmpattern = 'SIZEOF' then
 | 
						|
                  Begin
 | 
						|
                    actasmtoken:=AS_SIZEOF;
 | 
						|
                    exit;
 | 
						|
                  end;
 | 
						|
                 if is_register(actasmpattern) then
 | 
						|
                   begin
 | 
						|
                     actasmtoken:=AS_REGISTER;
 | 
						|
                     exit;
 | 
						|
                   end;
 | 
						|
                 { if next is a '.' and this is a unitsym then we also need to
 | 
						|
                   parse the identifier }
 | 
						|
                 if (c='.') then
 | 
						|
                  begin
 | 
						|
                    searchsym(actasmpattern,srsym,srsymtable);
 | 
						|
                    if assigned(srsym) and
 | 
						|
                       (srsym.typ=unitsym) and
 | 
						|
                       (srsym.owner.symtabletype in [staticsymtable,globalsymtable]) and
 | 
						|
                       srsym.owner.iscurrentunit then
 | 
						|
                     begin
 | 
						|
                       actasmpattern:=actasmpattern+c;
 | 
						|
                       c:=current_scanner.asmgetchar;
 | 
						|
                       while c in  ['A'..'Z','a'..'z','0'..'9','_','$'] do
 | 
						|
                        begin
 | 
						|
                          actasmpattern:=actasmpattern + upcase(c);
 | 
						|
                          c:=current_scanner.asmgetchar;
 | 
						|
                        end;
 | 
						|
                     end;
 | 
						|
                  end;
 | 
						|
                 actasmtoken:=AS_ID;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '%' : { register or modulo }
 | 
						|
               handlepercent;
 | 
						|
 | 
						|
             '1'..'9': { integer number }
 | 
						|
               begin
 | 
						|
                 len:=0;
 | 
						|
                 while c in ['0'..'9'] do
 | 
						|
                  Begin
 | 
						|
                    inc(len);
 | 
						|
                    actasmpattern[len]:=c;
 | 
						|
                    c:=current_scanner.asmgetchar;
 | 
						|
                  end;
 | 
						|
                 actasmpattern[0]:=chr(len);
 | 
						|
                 actasmpattern:=tostr(ParseVal(actasmpattern,10));
 | 
						|
                 actasmtoken:=AS_INTNUM;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
             '0' : { octal,hexa,real or binary number. }
 | 
						|
               begin
 | 
						|
                 actasmpattern:=c;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 case upcase(c) of
 | 
						|
                   'B': { binary }
 | 
						|
                     Begin
 | 
						|
                       c:=current_scanner.asmgetchar;
 | 
						|
                       while c in ['0','1'] do
 | 
						|
                        Begin
 | 
						|
                          actasmpattern:=actasmpattern + c;
 | 
						|
                          c:=current_scanner.asmgetchar;
 | 
						|
                        end;
 | 
						|
                       actasmpattern:=tostr(ParseVal(actasmpattern,2));
 | 
						|
                       actasmtoken:=AS_INTNUM;
 | 
						|
                       exit;
 | 
						|
                     end;
 | 
						|
                   'D': { real }
 | 
						|
                     Begin
 | 
						|
                       c:=current_scanner.asmgetchar;
 | 
						|
                       { get ridd of the 0d }
 | 
						|
                       if (c in ['+','-']) then
 | 
						|
                        begin
 | 
						|
                          actasmpattern:=c;
 | 
						|
                          c:=current_scanner.asmgetchar;
 | 
						|
                        end
 | 
						|
                       else
 | 
						|
                        actasmpattern:='';
 | 
						|
                       while c in ['0'..'9'] do
 | 
						|
                        Begin
 | 
						|
                          actasmpattern:=actasmpattern + c;
 | 
						|
                          c:=current_scanner.asmgetchar;
 | 
						|
                        end;
 | 
						|
                       if c='.' then
 | 
						|
                        begin
 | 
						|
                          actasmpattern:=actasmpattern + c;
 | 
						|
                          c:=current_scanner.asmgetchar;
 | 
						|
                          while c in ['0'..'9'] do
 | 
						|
                           Begin
 | 
						|
                             actasmpattern:=actasmpattern + c;
 | 
						|
                             c:=current_scanner.asmgetchar;
 | 
						|
                           end;
 | 
						|
                          if upcase(c) = 'E' then
 | 
						|
                           begin
 | 
						|
                             actasmpattern:=actasmpattern + c;
 | 
						|
                             c:=current_scanner.asmgetchar;
 | 
						|
                             if (c in ['+','-']) then
 | 
						|
                              begin
 | 
						|
                                actasmpattern:=actasmpattern + c;
 | 
						|
                                c:=current_scanner.asmgetchar;
 | 
						|
                              end;
 | 
						|
                             while c in ['0'..'9'] do
 | 
						|
                              Begin
 | 
						|
                                actasmpattern:=actasmpattern + c;
 | 
						|
                                c:=current_scanner.asmgetchar;
 | 
						|
                              end;
 | 
						|
                           end;
 | 
						|
                          actasmtoken:=AS_REALNUM;
 | 
						|
                          exit;
 | 
						|
                        end
 | 
						|
                       else
 | 
						|
                        begin
 | 
						|
                          Message1(asmr_e_invalid_float_const,actasmpattern+c);
 | 
						|
                          actasmtoken:=AS_NONE;
 | 
						|
                        end;
 | 
						|
                     end;
 | 
						|
                   'X': { hexadecimal }
 | 
						|
                     Begin
 | 
						|
                       c:=current_scanner.asmgetchar;
 | 
						|
                       while c in ['0'..'9','a'..'f','A'..'F'] do
 | 
						|
                        Begin
 | 
						|
                          actasmpattern:=actasmpattern + c;
 | 
						|
                          c:=current_scanner.asmgetchar;
 | 
						|
                        end;
 | 
						|
                       actasmpattern:=tostr(ParseVal(actasmpattern,16));
 | 
						|
                       actasmtoken:=AS_INTNUM;
 | 
						|
                       exit;
 | 
						|
                     end;
 | 
						|
                   '1'..'7': { octal }
 | 
						|
                     begin
 | 
						|
                       actasmpattern:=actasmpattern + c;
 | 
						|
                       while c in ['0'..'7'] do
 | 
						|
                        Begin
 | 
						|
                          actasmpattern:=actasmpattern + c;
 | 
						|
                          c:=current_scanner.asmgetchar;
 | 
						|
                        end;
 | 
						|
                       actasmpattern:=tostr(ParseVal(actasmpattern,8));
 | 
						|
                       actasmtoken:=AS_INTNUM;
 | 
						|
                       exit;
 | 
						|
                     end;
 | 
						|
                   else { octal number zero value...}
 | 
						|
                     Begin
 | 
						|
                       actasmpattern:=tostr(ParseVal(actasmpattern,8));
 | 
						|
                       actasmtoken:=AS_INTNUM;
 | 
						|
                       exit;
 | 
						|
                     end;
 | 
						|
                 end; { end case }
 | 
						|
               end;
 | 
						|
 | 
						|
             '&' :
 | 
						|
               begin
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 actasmtoken:=AS_AND;
 | 
						|
               end;
 | 
						|
 | 
						|
             '''' : { char }
 | 
						|
               begin
 | 
						|
                 current_scanner.in_asm_string:=true;
 | 
						|
                 actasmpattern:='';
 | 
						|
                 repeat
 | 
						|
                   c:=current_scanner.asmgetchar;
 | 
						|
                   case c of
 | 
						|
                     '\' :
 | 
						|
                       begin
 | 
						|
                         { copy also the next char so \" is parsed correctly }
 | 
						|
                         actasmpattern:=actasmpattern+c;
 | 
						|
                         c:=current_scanner.asmgetchar;
 | 
						|
                         actasmpattern:=actasmpattern+c;
 | 
						|
                       end;
 | 
						|
                     '''' :
 | 
						|
                       begin
 | 
						|
                         c:=current_scanner.asmgetchar;
 | 
						|
                         break;
 | 
						|
                       end;
 | 
						|
                     #10,#13:
 | 
						|
                       Message(scan_f_string_exceeds_line);
 | 
						|
                     else
 | 
						|
                       actasmpattern:=actasmpattern+c;
 | 
						|
                   end;
 | 
						|
                 until false;
 | 
						|
                 actasmpattern:=EscapeToPascal(actasmpattern);
 | 
						|
                 actasmtoken:=AS_STRING;
 | 
						|
                 current_scanner.in_asm_string:=false;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '"' : { string }
 | 
						|
               begin
 | 
						|
                 current_scanner.in_asm_string:=true;
 | 
						|
                 actasmpattern:='';
 | 
						|
                 repeat
 | 
						|
                   c:=current_scanner.asmgetchar;
 | 
						|
                   case c of
 | 
						|
                     '\' :
 | 
						|
                       begin
 | 
						|
                         { copy also the next char so \" is parsed correctly }
 | 
						|
                         actasmpattern:=actasmpattern+c;
 | 
						|
                         c:=current_scanner.asmgetchar;
 | 
						|
                         actasmpattern:=actasmpattern+c;
 | 
						|
                       end;
 | 
						|
                     '"' :
 | 
						|
                       begin
 | 
						|
                         c:=current_scanner.asmgetchar;
 | 
						|
                         break;
 | 
						|
                       end;
 | 
						|
                     #10,#13:
 | 
						|
                       Message(scan_f_string_exceeds_line);
 | 
						|
                     else
 | 
						|
                       actasmpattern:=actasmpattern+c;
 | 
						|
                   end;
 | 
						|
                 until false;
 | 
						|
                 actasmpattern:=EscapeToPascal(actasmpattern);
 | 
						|
                 actasmtoken:=AS_STRING;
 | 
						|
                 current_scanner.in_asm_string:=false;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '$' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_DOLLAR;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '#' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_HASH;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '[' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_LBRACKET;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             ']' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_RBRACKET;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
{$ifdef arm}
 | 
						|
             // the arm assembler uses { ... } for register sets
 | 
						|
             '{' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_LSBRACKET;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '}' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_RSBRACKET;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
{$endif arm}
 | 
						|
 | 
						|
             ',' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_COMMA;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '<' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_SHL;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 if c = '<' then
 | 
						|
                  c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '>' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_SHL;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 if c = '>' then
 | 
						|
                  c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '|' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_OR;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '^' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_XOR;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
 | 
						|
             '(' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_LPAREN;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             ')' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_RPAREN;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             ':' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_COLON;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '+' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_PLUS;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '-' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_MINUS;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '*' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_STAR;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '/' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_SLASH;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '!' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_NOT;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             '@' :
 | 
						|
               begin
 | 
						|
                 actasmtoken:=AS_AT;
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
{$ifndef arm}
 | 
						|
             '{',
 | 
						|
{$endif arm}
 | 
						|
             #13,#10,';' :
 | 
						|
               begin
 | 
						|
                 { the comment is read by asmgetchar }
 | 
						|
                 c:=current_scanner.asmgetchar;
 | 
						|
                 firsttoken:=TRUE;
 | 
						|
                 actasmtoken:=AS_SEPARATOR;
 | 
						|
                 exit;
 | 
						|
               end;
 | 
						|
 | 
						|
             else
 | 
						|
               current_scanner.illegal_char(c);
 | 
						|
           end;
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tattreader.consume(t : tasmtoken):boolean;
 | 
						|
      begin
 | 
						|
        Consume:=true;
 | 
						|
        if t<>actasmtoken then
 | 
						|
         begin
 | 
						|
           Message2(scan_f_syn_expected,token2str[t],token2str[actasmtoken]);
 | 
						|
           Consume:=false;
 | 
						|
         end;
 | 
						|
        repeat
 | 
						|
          gettoken;
 | 
						|
        until actasmtoken<>AS_NONE;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tattreader.RecoverConsume(allowcomma:boolean);
 | 
						|
      begin
 | 
						|
        While not (actasmtoken in [AS_SEPARATOR,AS_END]) do
 | 
						|
         begin
 | 
						|
           if allowcomma and (actasmtoken=AS_COMMA) then
 | 
						|
            break;
 | 
						|
           Consume(actasmtoken);
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    Procedure tattreader.BuildConstant(constsize: byte);
 | 
						|
      var
 | 
						|
       asmsymtyp : TAsmSymType;
 | 
						|
       asmsym,
 | 
						|
       expr: string;
 | 
						|
       value : aint;
 | 
						|
      Begin
 | 
						|
        Repeat
 | 
						|
          Case actasmtoken of
 | 
						|
            AS_STRING:
 | 
						|
              Begin
 | 
						|
                expr:=actasmpattern;
 | 
						|
                if length(expr) > 1 then
 | 
						|
                 Message(asmr_e_string_not_allowed_as_const);
 | 
						|
                Consume(AS_STRING);
 | 
						|
                Case actasmtoken of
 | 
						|
                  AS_COMMA: Consume(AS_COMMA);
 | 
						|
                  AS_END,
 | 
						|
                  AS_SEPARATOR: ;
 | 
						|
                else
 | 
						|
                  Message(asmr_e_invalid_string_expression);
 | 
						|
                end; { end case }
 | 
						|
                ConcatString(curlist,expr);
 | 
						|
              end;
 | 
						|
            AS_INTNUM,
 | 
						|
            AS_PLUS,
 | 
						|
            AS_MINUS,
 | 
						|
            AS_LPAREN,
 | 
						|
            AS_TYPE,
 | 
						|
            AS_SIZEOF,
 | 
						|
            AS_NOT,
 | 
						|
            AS_ID :
 | 
						|
              Begin
 | 
						|
                BuildConstSymbolExpression(false,false,false,value,asmsym,asmsymtyp);
 | 
						|
                if asmsym<>'' then
 | 
						|
                 begin
 | 
						|
                   if constsize<>sizeof(aint) then
 | 
						|
                    Message(asmr_w_32bit_const_for_address);
 | 
						|
                   ConcatConstSymbol(curlist,asmsym,asmsymtyp,value)
 | 
						|
                 end
 | 
						|
                else
 | 
						|
                 ConcatConstant(curlist,value,constsize);
 | 
						|
              end;
 | 
						|
            AS_COMMA:
 | 
						|
              Consume(AS_COMMA);
 | 
						|
            AS_END,
 | 
						|
            AS_SEPARATOR:
 | 
						|
              break;
 | 
						|
            else
 | 
						|
              begin
 | 
						|
                Message(asmr_e_syn_constant);
 | 
						|
                RecoverConsume(false);
 | 
						|
              end
 | 
						|
         end; { end case }
 | 
						|
       Until false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    Procedure tattreader.BuildRealConstant(typ : tfloattype);
 | 
						|
      var
 | 
						|
        expr : string;
 | 
						|
        r : bestreal;
 | 
						|
        code : integer;
 | 
						|
        negativ : boolean;
 | 
						|
        errorflag: boolean;
 | 
						|
      Begin
 | 
						|
        errorflag:=FALSE;
 | 
						|
        Repeat
 | 
						|
          negativ:=false;
 | 
						|
          expr:='';
 | 
						|
          if actasmtoken=AS_PLUS then
 | 
						|
            Consume(AS_PLUS)
 | 
						|
          else
 | 
						|
           if actasmtoken=AS_MINUS then
 | 
						|
            begin
 | 
						|
              negativ:=true;
 | 
						|
              consume(AS_MINUS);
 | 
						|
            end;
 | 
						|
          Case actasmtoken of
 | 
						|
            AS_INTNUM:
 | 
						|
              Begin
 | 
						|
                expr:=actasmpattern;
 | 
						|
                Consume(AS_INTNUM);
 | 
						|
                if negativ then
 | 
						|
                 expr:='-'+expr;
 | 
						|
                val(expr,r,code);
 | 
						|
                if code<>0 then
 | 
						|
                 Begin
 | 
						|
                   r:=0;
 | 
						|
                   Message(asmr_e_invalid_float_expr);
 | 
						|
                 End;
 | 
						|
                ConcatRealConstant(curlist,r,typ);
 | 
						|
              end;
 | 
						|
            AS_REALNUM:
 | 
						|
              Begin
 | 
						|
                expr:=actasmpattern;
 | 
						|
                Consume(AS_REALNUM);
 | 
						|
                { in ATT syntax you have 0d in front of the real }
 | 
						|
                { should this be forced ?  yes i think so, as to }
 | 
						|
                { conform to gas as much as possible.            }
 | 
						|
                if (expr[1]='0') and (upper(expr[2])='D') then
 | 
						|
                 Delete(expr,1,2);
 | 
						|
                if negativ then
 | 
						|
                 expr:='-'+expr;
 | 
						|
                val(expr,r,code);
 | 
						|
                if code<>0 then
 | 
						|
                 Begin
 | 
						|
                   r:=0;
 | 
						|
                   Message(asmr_e_invalid_float_expr);
 | 
						|
                 End;
 | 
						|
                ConcatRealConstant(curlist,r,typ);
 | 
						|
              end;
 | 
						|
            AS_COMMA:
 | 
						|
              begin
 | 
						|
                Consume(AS_COMMA);
 | 
						|
              end;
 | 
						|
            AS_END,
 | 
						|
            AS_SEPARATOR:
 | 
						|
              begin
 | 
						|
                break;
 | 
						|
              end;
 | 
						|
         else
 | 
						|
           Begin
 | 
						|
             Consume(actasmtoken);
 | 
						|
             if not errorflag then
 | 
						|
              Message(asmr_e_invalid_float_expr);
 | 
						|
             errorflag:=TRUE;
 | 
						|
           end;
 | 
						|
         end;
 | 
						|
       Until false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    Procedure tattreader.BuildStringConstant(asciiz: boolean);
 | 
						|
      var
 | 
						|
        expr: string;
 | 
						|
        errorflag : boolean;
 | 
						|
      Begin
 | 
						|
        errorflag:=FALSE;
 | 
						|
        Repeat
 | 
						|
          Case actasmtoken of
 | 
						|
            AS_STRING:
 | 
						|
              Begin
 | 
						|
                expr:=actasmpattern;
 | 
						|
                if asciiz then
 | 
						|
                  expr:=expr+#0;
 | 
						|
                ConcatPasString(curlist,expr);
 | 
						|
                Consume(AS_STRING);
 | 
						|
              end;
 | 
						|
            AS_COMMA:
 | 
						|
              begin
 | 
						|
                Consume(AS_COMMA);
 | 
						|
              end;
 | 
						|
            AS_END,
 | 
						|
            AS_SEPARATOR:
 | 
						|
              begin
 | 
						|
                break;
 | 
						|
              end;
 | 
						|
         else
 | 
						|
           Begin
 | 
						|
             Consume(actasmtoken);
 | 
						|
             if not errorflag then
 | 
						|
              Message(asmr_e_invalid_string_expression);
 | 
						|
             errorflag:=TRUE;
 | 
						|
           end;
 | 
						|
         end;
 | 
						|
       Until false;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
   Function tattreader.Assemble: tlinkedlist;
 | 
						|
     Var
 | 
						|
       hl         : tasmlabel;
 | 
						|
       commname   : string;
 | 
						|
       lasTSec    : TAsmSectiontype;
 | 
						|
       l1,l2      : longint;
 | 
						|
     Begin
 | 
						|
       Message1(asmr_d_start_reading,'GNU AS');
 | 
						|
       firsttoken:=TRUE;
 | 
						|
       { sets up all opcode and register tables in uppercase }
 | 
						|
       if not _asmsorted then
 | 
						|
        Begin
 | 
						|
          SetupTables;
 | 
						|
          _asmsorted:=TRUE;
 | 
						|
        end;
 | 
						|
       curlist:=TAsmList.Create;
 | 
						|
       lasTSec:=sec_code;
 | 
						|
       { setup label linked list }
 | 
						|
       LocalLabelList:=TLocalLabelList.Create;
 | 
						|
       { start tokenizer }
 | 
						|
       c:=current_scanner.asmgetcharstart;
 | 
						|
       gettoken;
 | 
						|
       { main loop }
 | 
						|
       repeat
 | 
						|
         case actasmtoken of
 | 
						|
           AS_LLABEL:
 | 
						|
             Begin
 | 
						|
               if CreateLocalLabel(actasmpattern,hl,true) then
 | 
						|
                 ConcatLabel(curlist,hl);
 | 
						|
               Consume(AS_LLABEL);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_LABEL:
 | 
						|
             Begin
 | 
						|
               if SearchLabel(upper(actasmpattern),hl,true) then
 | 
						|
                ConcatLabel(curlist,hl)
 | 
						|
               else
 | 
						|
                Message1(asmr_e_unknown_label_identifier,actasmpattern);
 | 
						|
               Consume(AS_LABEL);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_DW:
 | 
						|
             Begin
 | 
						|
               Consume(AS_DW);
 | 
						|
               BuildConstant(2);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_DATA:
 | 
						|
             Begin
 | 
						|
               new_section(curList,sec_data,lower(current_procinfo.procdef.mangledname),0);
 | 
						|
               lasTSec:=sec_data;
 | 
						|
               Consume(AS_DATA);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_TEXT:
 | 
						|
             Begin
 | 
						|
               new_section(curList,sec_code,lower(current_procinfo.procdef.mangledname),0);
 | 
						|
               lasTSec:=sec_code;
 | 
						|
               Consume(AS_TEXT);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_DB:
 | 
						|
             Begin
 | 
						|
               Consume(AS_DB);
 | 
						|
               BuildConstant(1);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_DD:
 | 
						|
             Begin
 | 
						|
               Consume(AS_DD);
 | 
						|
               BuildConstant(4);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_DQ:
 | 
						|
             Begin
 | 
						|
               Consume(AS_DQ);
 | 
						|
{$ifdef cpu64bit}
 | 
						|
               BuildConstant(8);
 | 
						|
{$else cpu64bit}
 | 
						|
               BuildRealConstant(s64comp);
 | 
						|
{$endif cpu64bit}
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_SINGLE:
 | 
						|
             Begin
 | 
						|
               Consume(AS_SINGLE);
 | 
						|
               BuildRealConstant(s32real);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_DOUBLE:
 | 
						|
             Begin
 | 
						|
               Consume(AS_DOUBLE);
 | 
						|
               BuildRealConstant(s64real);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_EXTENDED:
 | 
						|
             Begin
 | 
						|
               Consume(AS_EXTENDED);
 | 
						|
               BuildRealConstant(s80real);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_GLOBAL:
 | 
						|
             Begin
 | 
						|
               Consume(AS_GLOBAL);
 | 
						|
               if actasmtoken=AS_ID then
 | 
						|
                 ConcatPublic(curlist,actasmpattern);
 | 
						|
               Consume(AS_ID);
 | 
						|
               if actasmtoken<>AS_SEPARATOR then
 | 
						|
                Consume(AS_SEPARATOR);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_ALIGN:
 | 
						|
             Begin
 | 
						|
               Consume(AS_ALIGN);
 | 
						|
               l1:=BuildConstExpression(false,false);
 | 
						|
               if (target_info.system in [system_i386_GO32V2]) then
 | 
						|
                 begin
 | 
						|
                    l2:=1;
 | 
						|
                    if (l1>=0) and (l1<=16) then
 | 
						|
                      while (l1>0) do
 | 
						|
                        begin
 | 
						|
                          l2:=2*l2;
 | 
						|
                          dec(l1);
 | 
						|
                        end;
 | 
						|
                    l1:=l2;
 | 
						|
                 end;
 | 
						|
               ConcatAlign(curlist,l1);
 | 
						|
               Message(asmr_n_align_is_target_specific);
 | 
						|
               if actasmtoken<>AS_SEPARATOR then
 | 
						|
                Consume(AS_SEPARATOR);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_BALIGN:
 | 
						|
             Begin
 | 
						|
               Consume(AS_BALIGN);
 | 
						|
               ConcatAlign(curlist,BuildConstExpression(false,false));
 | 
						|
               if actasmtoken<>AS_SEPARATOR then
 | 
						|
                Consume(AS_SEPARATOR);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_P2ALIGN:
 | 
						|
             Begin
 | 
						|
               Consume(AS_P2ALIGN);
 | 
						|
               l1:=BuildConstExpression(false,false);
 | 
						|
               l2:=1;
 | 
						|
               if (l1>=0) and (l1<=16) then
 | 
						|
                 while (l1>0) do
 | 
						|
                   begin
 | 
						|
                      l2:=2*l2;
 | 
						|
                      dec(l1);
 | 
						|
                   end;
 | 
						|
               l1:=l2;
 | 
						|
               ConcatAlign(curlist,l1);
 | 
						|
               if actasmtoken<>AS_SEPARATOR then
 | 
						|
                Consume(AS_SEPARATOR);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_ASCIIZ:
 | 
						|
             Begin
 | 
						|
               Consume(AS_ASCIIZ);
 | 
						|
               BuildStringConstant(TRUE);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_ASCII:
 | 
						|
             Begin
 | 
						|
               Consume(AS_ASCII);
 | 
						|
               BuildStringConstant(FALSE);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_LCOMM:
 | 
						|
             Begin
 | 
						|
               Consume(AS_LCOMM);
 | 
						|
               commname:=actasmpattern;
 | 
						|
               Consume(AS_ID);
 | 
						|
               Consume(AS_COMMA);
 | 
						|
               curList.concat(Tai_datablock.Create(commname,BuildConstExpression(false,false)));
 | 
						|
               if actasmtoken<>AS_SEPARATOR then
 | 
						|
                Consume(AS_SEPARATOR);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_COMM:
 | 
						|
             Begin
 | 
						|
               Consume(AS_COMM);
 | 
						|
               commname:=actasmpattern;
 | 
						|
               Consume(AS_ID);
 | 
						|
               Consume(AS_COMMA);
 | 
						|
               curList.concat(Tai_datablock.Create_global(commname,BuildConstExpression(false,false)));
 | 
						|
               if actasmtoken<>AS_SEPARATOR then
 | 
						|
                Consume(AS_SEPARATOR);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_OPCODE:
 | 
						|
             Begin
 | 
						|
               HandleOpCode;
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_SEPARATOR:
 | 
						|
             Begin
 | 
						|
               Consume(AS_SEPARATOR);
 | 
						|
             end;
 | 
						|
 | 
						|
           AS_END:
 | 
						|
             begin
 | 
						|
               break; { end assembly block }
 | 
						|
             end;
 | 
						|
 | 
						|
           else
 | 
						|
             Begin
 | 
						|
               Message(asmr_e_syntax_error);
 | 
						|
               RecoverConsume(false);
 | 
						|
             end;
 | 
						|
         end;
 | 
						|
       until false;
 | 
						|
       { Check LocalLabelList }
 | 
						|
       LocalLabelList.CheckEmitted;
 | 
						|
       LocalLabelList.Free;
 | 
						|
       { are we back in the code section? }
 | 
						|
       if lasTSec<>sec_code then
 | 
						|
        begin
 | 
						|
          Message(asmr_w_assembler_code_not_returned_to_text);
 | 
						|
          new_section(curList,sec_code,lower(current_procinfo.procdef.mangledname),0);
 | 
						|
        end;
 | 
						|
       { Return the list in an asmnode }
 | 
						|
       assemble:=curlist;
 | 
						|
       Message1(asmr_d_finish_reading,'GNU AS');
 | 
						|
     end;
 | 
						|
 | 
						|
 | 
						|
{*****************************************************************************
 | 
						|
                               Parsing Helpers
 | 
						|
*****************************************************************************}
 | 
						|
 | 
						|
    Procedure tattreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint);
 | 
						|
      { Description: This routine builds up a record offset after a AS_DOT }
 | 
						|
      { token is encountered.                                              }
 | 
						|
      { On entry actasmtoken should be equal to AS_DOT                     }
 | 
						|
      var
 | 
						|
        s : string;
 | 
						|
      Begin
 | 
						|
        offset:=0;
 | 
						|
        size:=0;
 | 
						|
        s:=expr;
 | 
						|
        while (actasmtoken=AS_DOT) do
 | 
						|
         begin
 | 
						|
           Consume(AS_DOT);
 | 
						|
           if actasmtoken=AS_ID then
 | 
						|
            s:=s+'.'+actasmpattern;
 | 
						|
           if not Consume(AS_ID) then
 | 
						|
            begin
 | 
						|
              RecoverConsume(true);
 | 
						|
              break;
 | 
						|
            end;
 | 
						|
         end;
 | 
						|
        if not GetRecordOffsetSize(s,offset,size) then
 | 
						|
         Message(asmr_e_building_record_offset);
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    procedure tattreader.BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
 | 
						|
      var
 | 
						|
        hssymtyp : TAsmSymType;
 | 
						|
        hs,tempstr,expr : string;
 | 
						|
        parenlevel : longint;
 | 
						|
        l,k : aint;
 | 
						|
        errorflag : boolean;
 | 
						|
        prevtok : tasmtoken;
 | 
						|
        sym : tsym;
 | 
						|
        srsymtable : tsymtable;
 | 
						|
        hl  : tasmlabel;
 | 
						|
      Begin
 | 
						|
        asmsym:='';
 | 
						|
        asmsymtyp:=AT_DATA;
 | 
						|
        value:=0;
 | 
						|
        errorflag:=FALSE;
 | 
						|
        tempstr:='';
 | 
						|
        expr:='';
 | 
						|
        parenlevel:=0;
 | 
						|
        Repeat
 | 
						|
          Case actasmtoken of
 | 
						|
            AS_LPAREN:
 | 
						|
              Begin
 | 
						|
                { Exit if ref? }
 | 
						|
                if allowref and (prevasmtoken in [AS_INTNUM,AS_ID]) then
 | 
						|
                 break;
 | 
						|
                Consume(AS_LPAREN);
 | 
						|
                expr:=expr + '(';
 | 
						|
                inc(parenlevel);
 | 
						|
              end;
 | 
						|
            AS_RBRACKET:
 | 
						|
              begin
 | 
						|
                if betweenbracket then
 | 
						|
                  break;
 | 
						|
                { write error only once. }
 | 
						|
                if not errorflag then
 | 
						|
                  Message(asmr_e_invalid_constant_expression);
 | 
						|
                { consume tokens until we find COMMA or SEPARATOR }
 | 
						|
                Consume(actasmtoken);
 | 
						|
                errorflag:=TRUE;
 | 
						|
              end;
 | 
						|
            AS_RPAREN:
 | 
						|
              Begin
 | 
						|
                { end of ref ? }
 | 
						|
                if (parenlevel=0) and betweenbracket then
 | 
						|
                 break;
 | 
						|
                Consume(AS_RPAREN);
 | 
						|
                expr:=expr + ')';
 | 
						|
                dec(parenlevel);
 | 
						|
              end;
 | 
						|
            AS_SHL:
 | 
						|
              Begin
 | 
						|
                Consume(AS_SHL);
 | 
						|
                expr:=expr + '<';
 | 
						|
              end;
 | 
						|
            AS_SHR:
 | 
						|
              Begin
 | 
						|
                Consume(AS_SHR);
 | 
						|
                expr:=expr + '>';
 | 
						|
              end;
 | 
						|
            AS_SLASH:
 | 
						|
              Begin
 | 
						|
                Consume(AS_SLASH);
 | 
						|
                expr:=expr + '/';
 | 
						|
              end;
 | 
						|
            AS_MOD:
 | 
						|
              Begin
 | 
						|
                Consume(AS_MOD);
 | 
						|
                expr:=expr + '%';
 | 
						|
              end;
 | 
						|
            AS_STAR:
 | 
						|
              Begin
 | 
						|
                Consume(AS_STAR);
 | 
						|
                expr:=expr + '*';
 | 
						|
              end;
 | 
						|
            AS_PLUS:
 | 
						|
              Begin
 | 
						|
                Consume(AS_PLUS);
 | 
						|
                expr:=expr + '+';
 | 
						|
              end;
 | 
						|
            AS_MINUS:
 | 
						|
              Begin
 | 
						|
                Consume(AS_MINUS);
 | 
						|
                expr:=expr + '-';
 | 
						|
              end;
 | 
						|
            AS_AND:
 | 
						|
              Begin
 | 
						|
                Consume(AS_AND);
 | 
						|
                expr:=expr + '&';
 | 
						|
              end;
 | 
						|
            AS_NOT:
 | 
						|
              Begin
 | 
						|
                Consume(AS_NOT);
 | 
						|
                expr:=expr + '~';
 | 
						|
              end;
 | 
						|
            AS_XOR:
 | 
						|
              Begin
 | 
						|
                Consume(AS_XOR);
 | 
						|
                expr:=expr + '^';
 | 
						|
              end;
 | 
						|
            AS_OR:
 | 
						|
              Begin
 | 
						|
                Consume(AS_OR);
 | 
						|
                expr:=expr + '|';
 | 
						|
              end;
 | 
						|
            AS_INTNUM:
 | 
						|
              Begin
 | 
						|
                expr:=expr + actasmpattern;
 | 
						|
                Consume(AS_INTNUM);
 | 
						|
              end;
 | 
						|
            AS_DOLLAR:
 | 
						|
              begin
 | 
						|
                Consume(AS_DOLLAR);
 | 
						|
                if actasmtoken<>AS_ID then
 | 
						|
                 Message(asmr_e_dollar_without_identifier);
 | 
						|
              end;
 | 
						|
            AS_STRING:
 | 
						|
              Begin
 | 
						|
                l:=0;
 | 
						|
                case Length(actasmpattern) of
 | 
						|
                 1 :
 | 
						|
                  l:=ord(actasmpattern[1]);
 | 
						|
                 2 :
 | 
						|
                  l:=ord(actasmpattern[2]) + ord(actasmpattern[1]) shl 8;
 | 
						|
                 3 :
 | 
						|
                  l:=ord(actasmpattern[3]) +
 | 
						|
                     Ord(actasmpattern[2]) shl 8 + ord(actasmpattern[1]) shl 16;
 | 
						|
                 4 :
 | 
						|
                  l:=ord(actasmpattern[4]) + ord(actasmpattern[3]) shl 8 +
 | 
						|
                     Ord(actasmpattern[2]) shl 16 + ord(actasmpattern[1]) shl 24;
 | 
						|
                else
 | 
						|
                  Message1(asmr_e_invalid_string_as_opcode_operand,actasmpattern);
 | 
						|
                end;
 | 
						|
                str(l, tempstr);
 | 
						|
                expr:=expr + tempstr;
 | 
						|
                Consume(AS_STRING);
 | 
						|
              end;
 | 
						|
            AS_SIZEOF,
 | 
						|
            AS_TYPE:
 | 
						|
              begin
 | 
						|
                l:=0;
 | 
						|
                Consume(actasmtoken);
 | 
						|
                if actasmtoken<>AS_ID then
 | 
						|
                 Message(asmr_e_type_without_identifier)
 | 
						|
                else
 | 
						|
                 begin
 | 
						|
                   tempstr:=actasmpattern;
 | 
						|
                   Consume(AS_ID);
 | 
						|
                   if actasmtoken=AS_DOT then
 | 
						|
                    BuildRecordOffsetSize(tempstr,k,l)
 | 
						|
                   else
 | 
						|
                    begin
 | 
						|
                      searchsym(tempstr,sym,srsymtable);
 | 
						|
                      if assigned(sym) then
 | 
						|
                       begin
 | 
						|
                         case sym.typ of
 | 
						|
                           globalvarsym,
 | 
						|
                           localvarsym,
 | 
						|
                           paravarsym :
 | 
						|
                             l:=tabstractvarsym(sym).getsize;
 | 
						|
                           typedconstsym :
 | 
						|
                             l:=ttypedconstsym(sym).getsize;
 | 
						|
                           typesym :
 | 
						|
                             l:=ttypesym(sym).typedef.size;
 | 
						|
                           else
 | 
						|
                             Message(asmr_e_wrong_sym_type);
 | 
						|
                         end;
 | 
						|
                       end
 | 
						|
                      else
 | 
						|
                       Message1(sym_e_unknown_id,tempstr);
 | 
						|
                    end;
 | 
						|
                 end;
 | 
						|
                str(l, tempstr);
 | 
						|
                expr:=expr + tempstr;
 | 
						|
              end;
 | 
						|
            AS_ID:
 | 
						|
              Begin
 | 
						|
                hs:='';
 | 
						|
                hssymtyp:=AT_DATA;
 | 
						|
                tempstr:=actasmpattern;
 | 
						|
                prevtok:=prevasmtoken;
 | 
						|
                consume(AS_ID);
 | 
						|
                if SearchIConstant(tempstr,l) then
 | 
						|
                 begin
 | 
						|
                   str(l, tempstr);
 | 
						|
                   expr:=expr + tempstr;
 | 
						|
                 end
 | 
						|
                else
 | 
						|
                 begin
 | 
						|
                   if is_locallabel(tempstr) then
 | 
						|
                    begin
 | 
						|
                      CreateLocalLabel(tempstr,hl,false);
 | 
						|
                      hs:=hl.name;
 | 
						|
                      hssymtyp:=AT_LABEL;
 | 
						|
                    end
 | 
						|
                   else
 | 
						|
                    if SearchLabel(tempstr,hl,false) then
 | 
						|
                      begin
 | 
						|
                        hs:=hl.name;
 | 
						|
                        hssymtyp:=AT_FUNCTION;
 | 
						|
                      end
 | 
						|
                   else
 | 
						|
                    begin
 | 
						|
                      searchsym(tempstr,sym,srsymtable);
 | 
						|
                      if assigned(sym) then
 | 
						|
                       begin
 | 
						|
                         case sym.typ of
 | 
						|
                           globalvarsym :
 | 
						|
                             hs:=tglobalvarsym(sym).mangledname;
 | 
						|
                           localvarsym,
 | 
						|
                           paravarsym :
 | 
						|
                             Message(asmr_e_no_local_or_para_allowed);
 | 
						|
                           typedconstsym :
 | 
						|
                             hs:=ttypedconstsym(sym).mangledname;
 | 
						|
                           procsym :
 | 
						|
                             with Tprocsym(sym) do
 | 
						|
                               begin
 | 
						|
                                 if procdef_count>1 then
 | 
						|
                                   message(asmr_w_calling_overload_func);
 | 
						|
                                 hs:=first_procdef.mangledname;
 | 
						|
                                 hssymtyp:=AT_FUNCTION;
 | 
						|
                               end;
 | 
						|
                           typesym :
 | 
						|
                             begin
 | 
						|
                               if not(ttypesym(sym).typedef.deftype in [recorddef,objectdef]) then
 | 
						|
                                Message(asmr_e_wrong_sym_type);
 | 
						|
                             end;
 | 
						|
                           else
 | 
						|
                             Message(asmr_e_wrong_sym_type);
 | 
						|
                         end;
 | 
						|
                       end
 | 
						|
                      else
 | 
						|
                       Message1(sym_e_unknown_id,tempstr);
 | 
						|
                    end;
 | 
						|
                   { symbol found? }
 | 
						|
                   if hs<>'' then
 | 
						|
                    begin
 | 
						|
                      if needofs and (prevtok<>AS_DOLLAR) then
 | 
						|
                       Message(asmr_e_need_dollar);
 | 
						|
                      if asmsym='' then
 | 
						|
                        begin
 | 
						|
                          asmsym:=hs;
 | 
						|
                          asmsymtyp:=hssymtyp;
 | 
						|
                        end
 | 
						|
                      else
 | 
						|
                        Message(asmr_e_cant_have_multiple_relocatable_symbols);
 | 
						|
                      if (expr='') or (expr[length(expr)]='+') then
 | 
						|
                       begin
 | 
						|
                         { don't remove the + if there could be a record field }
 | 
						|
                         if actasmtoken<>AS_DOT then
 | 
						|
                          delete(expr,length(expr),1);
 | 
						|
                       end
 | 
						|
                      else
 | 
						|
                       Message(asmr_e_only_add_relocatable_symbol);
 | 
						|
                    end;
 | 
						|
                   if actasmtoken=AS_DOT then
 | 
						|
                    begin
 | 
						|
                      BuildRecordOffsetSize(tempstr,l,k);
 | 
						|
                      str(l, tempstr);
 | 
						|
                      expr:=expr + tempstr;
 | 
						|
                    end
 | 
						|
                   else
 | 
						|
                    begin
 | 
						|
                      if (expr='') or (expr[length(expr)] in ['+','-','/','*']) then
 | 
						|
                       delete(expr,length(expr),1);
 | 
						|
                    end;
 | 
						|
                 end;
 | 
						|
                { check if there are wrong operator used like / or mod etc. }
 | 
						|
                if (hs<>'') and
 | 
						|
                   not(actasmtoken in [AS_MINUS,AS_PLUS,AS_COMMA,AS_SEPARATOR,
 | 
						|
                                       AS_LPAREN,AS_RPAREN,AS_RBRACKET,AS_END]) then
 | 
						|
                 Message(asmr_e_only_add_relocatable_symbol);
 | 
						|
              end;
 | 
						|
            AS_END,
 | 
						|
            AS_SEPARATOR,
 | 
						|
            AS_COMMA:
 | 
						|
              break;
 | 
						|
          else
 | 
						|
            Begin
 | 
						|
              { write error only once. }
 | 
						|
              if not errorflag then
 | 
						|
                Message(asmr_e_invalid_constant_expression);
 | 
						|
              { consume tokens until we find COMMA or SEPARATOR }
 | 
						|
              Consume(actasmtoken);
 | 
						|
              errorflag:=TRUE;
 | 
						|
            end;
 | 
						|
          end;
 | 
						|
        Until false;
 | 
						|
        { calculate expression }
 | 
						|
        if not ErrorFlag then
 | 
						|
          value:=CalculateExpression(expr)
 | 
						|
        else
 | 
						|
          value:=0;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    function tattreader.BuildConstExpression(allowref,betweenbracket:boolean): aint;
 | 
						|
      var
 | 
						|
        l : aint;
 | 
						|
        hs : string;
 | 
						|
        hssymtyp : TAsmSymType;
 | 
						|
      begin
 | 
						|
        BuildConstSymbolExpression(allowref,betweenbracket,false,l,hs,hssymtyp);
 | 
						|
        if hs<>'' then
 | 
						|
         Message(asmr_e_relocatable_symbol_not_allowed);
 | 
						|
        BuildConstExpression:=l;
 | 
						|
      end;
 | 
						|
 | 
						|
 | 
						|
    Procedure tattreader.BuildConstantOperand(oper : toperand);
 | 
						|
      var
 | 
						|
        l : aint;
 | 
						|
        tempstr : string;
 | 
						|
        tempsymtyp : TAsmSymType;
 | 
						|
      begin
 | 
						|
        BuildConstSymbolExpression(false,false,true,l,tempstr,tempsymtyp);
 | 
						|
        if tempstr<>'' then
 | 
						|
         begin
 | 
						|
           oper.opr.typ:=OPR_SYMBOL;
 | 
						|
           oper.opr.symofs:=l;
 | 
						|
           oper.opr.symbol:=current_asmdata.RefAsmSymbol(tempstr);
 | 
						|
         end
 | 
						|
        else
 | 
						|
         begin
 | 
						|
           oper.opr.typ:=OPR_CONSTANT;
 | 
						|
           oper.opr.val:=l;
 | 
						|
         end;
 | 
						|
      end;
 | 
						|
 | 
						|
end.
 |