Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 1e4be4f6cca2c9a2bfc532dbed99ff6a > files > 31

aikido-1.40-6mdv2010.0.i586.rpm

/*
 * types.aikido
 *
 * Aikido Language System,
 * export version: 1.00
 * Copyright (c) 2002-2003 Sun Microsystems, Inc.
 *
 * Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License Version 1.0 (the "License"). You
 * may not use this file except in compliance with the License. A copy of the License is available
 * at http://www.opensource.org/licenses/sunpublic.php
 * 
 * The Original Code is Aikido. 
 * The Initial Developer of the Original Code is David Allison on behalf of Sun Microsystems, Inc. 
 * Copyright (C) Sun Microsystems, Inc. 2000-2003. All Rights Reserved.
 * 
 * 
 * Contributor(s): dallison
 *
 * Version:  1.2
 * Created by dallison on 4/19/2002
 * Last modified by dallison on 03/07/29
 */



package CParser {
    extend Parser {
        class TypeRecord extends ParseNode {
            protected var size = 0          // size of this type
            var qualifiers = 0

        public:
            function addQualifiers (q) {
                qualifiers |= q
            }


            function getSize() {
                return size
            }


            function isPointer() {
                return false
            }

            function isArray() {
                return false
            }

            function isFunction() {
                return false
            }

            function isScalar() {
                return false
            }

            function isReal() {
                return false
            }

            function isIntegral() {
                return false
            }

            function isStruct() {
                return false
            }

            function print (s, indent) {
            }

            function getPrimitiveType {
                return 0
            }

            function dump (stream) extends dump (stream) {
                [size, ' '] -> stream
            }
        }

        class ScalarTypeRecord (public type) extends TypeRecord {
            if (type & CLONGLONG) {
               size = 8
            } elif (type & CSHORT) {
               size = 2
            } elif (type & CINT) {
                if (type & CLONGLONG) {
                    size = 8
                } elif (type & CSHORT) {
                    size = 2
                } else {
                    size = 4
                }
            } elif (type & CCHAR) {
                size = 1
            }

        public:
            function isScalar() {
                return true
            }

            function isReal() {
                return (type & (CFLOAT|CDOUBLE)) != 0
            }

            function isIntegral() {
                return !isReal()
            }

            function getPrimitiveType {
                return type
            }

            operator== (t) {
                return t.isScalar() && type == t.type
            }

            operator!= (t) {
                return !(this == t)
            }

            function print (s, indent) {
                if (type & CUNSIGNED) {
                    "unsigned " -> s
                } 
                if (type & CSIGNED) {
                    "signed " -> s
                } 
                if (type & CLONGLONG) {
                    "long long " -> s
                }
                if (type & CLONG) {
                    "long " -> s
                }
                if (type & CSHORT) {
                    "short " -> s
                }
                if (type & CCONST) {
                    "const " -> s
                }
                if (type & CVOLATILE) {
                    "volatile " -> s
                }
                if (type & CCHAR) {
                    "char " -> s
                }
                if (type & CINT) {
                    "int " -> s
                }
                if (type & CFLOAT) {
                    "float " -> s
                }
                if (type & CDOUBLE) {
                    "double " -> s
                }
                if (type & CVOID) {
                    "void " -> s
                }
            }

            public function dump (stream) extends dump (stream) {
                format ("%08x", type) -> stream
            }
        }

        class StructTypeRecord (public tag) extends TypeRecord {
            protected var members = []
            var bit = 0

         public:
            function numMembers {
                return sizeof (members)
            }

            function getMember (i) {
                return members[i]
            }

            function getMemberNumber (name) : int {
               var i = 0
               foreach m members {
                   if (m.getName() == name) {
                       return i
                   }
                   i++
               }
               return -1
            }

            function findMember (name) : Symbol {
               foreach m members {
                   if (m.getName() == name) {
                       return m
                   }
               }
               return null
            }

            function addMember (member) {
                bit = 0                         // reset bitfield offset
                if (findMember (member.getName()) != null) {
                    error ("Duplicate definition of struct member " + member.getName())
                } else {
                    var offset = size
                    var msize = member.getSize()
                    var mtype = member.getType()
                    if (mtype.isScalar()) {
                        offset = (offset + (msize - 1)) & ~(msize - 1)
                    } elif (mtype.isArray()) {
                        var arrayof = mtype.dereference()
                        if (arrayof.isScalar() && arrayof.type & CCHAR) {
                        } else {
                            offset = (offset + 3) & ~3
                        }
                    } else {
                        offset = (offset + 3) & ~3
                    }
                    member.setOffset (offset) 
                    size += member.getSize()
                    append (members, member)
                }
            }

            function addBitfield (member, width) {
                if (findMember (member.getName()) != null) {
                    error ("Duplicate definition of struct member " + member.getName())
                } else {
                    var topbit = bit + width
                    if (topbit > 31) {
                        size++
                        bit = 0
                    }
                    member.setOffset (topbit << 32 | size) 
                    bit += width
                    append (members, member)
                }
            
            }

            function isStruct() {
                return true
            }

            operator== (t) {
                return t instanceof StructTypeRecord && tag == t.tag
            }

            operator!= (t) {
                return !(this == t)
            }

            function print (s, indent) {
                ["struct ", tag.getName(), ' '] -> s
            }

            function dump (stream) {
               tag.dump (stream)
               foreach mem members {
                   mem.dump (stream)
               }
               ParseNode.dump (stream)
               [tag.id, ' '] -> stream
               foreach mem members {
                   [mem.id, ' '] -> stream
               }
               
            }
        }

        class UnionTypeRecord (public tag) extends StructTypeRecord (tag) {
        public:
            function addMember (member) {
                if (findMember (member.getName()) != null) {
                    error ("Duplicate definition of union member " + member.getName())
                } else {
                    var s = member.getSize()
                    if (s > size) {
                        size = s
                    }
                    append (members, member)
                }
            }

            operator== (t) {
                return t instanceof UnionTypeRecord && tag == t.tag
            }

            operator!= (t) {
                return !(this == t)
            }

            function print (s, indent) {
                ["union ", tag.getName(), ' '] -> s
            }
        }

        class EnumTypeRecord (public tag) extends TypeRecord  {
            size = 4
            var initval = 0

        public:
            function addMember (member, generic val) {
                if (typeof (val) == "none") {
                    val = initval
                }
                member.setDetails (val)
                insertSymbol (member)
                initval = val + 1
            }
           
            function isIntegral {
                return true
            }


            operator== (t) {
                return t instanceof EnumTypeRecord && tag == t.tag
            }

            operator!= (t) {
                return !(this == t)
            }

            function print (s, indent) {
                ["enum ", tag.getName(), ' '] -> s
            }

            function dump (stream) {
               tag.dump (stream)
               ParseNode.dump (stream)
               tag.id -> stream
            }
        }

        class ExtendedTypeRecord (protected type) extends TypeRecord {
            public function setStorage (s) {
                type.setStorage (s)
            }

            public function setsubtype (t) {
                type = t
            }

            public function dump (stream) {
               type.dump (stream)
               ParseNode.dump (stream)
               [type.id, ' '] -> stream
            }
        }

        class PointerTypeRecord (t = null) extends ExtendedTypeRecord (t)  {
            size = 4

        public:
            function isPointer {
                return true
            }

            function dereference {
                return type
            }

            operator== (t) {
                if (!t.isPointer()) {
                    return false
                }
                return type == t.dereference()
            }

            operator!= (t) {
                return !(this == t) 
            }

            function print (s, indent) {
                '*' -> s
                type.print (s, indent)
            }
        }

        class ArrayTypeRecord (public arraysize, t = null) extends ExtendedTypeRecord (t) {

        public:
            function setsubtype (t) extends setsubtype (t) {
                size = arraysize * t.getSize()
            }

            function isPointer {
                return true
            }

            function isArray() {
                return true
            }

            function dereference {
                return type
            }
            operator== (t) {
                if (!t.isPointer()) {
                    return false
                }
                return type == t.dereference()
            }

            operator!= (t) {
                return !(this == t) 
            }

            function print (s, indent) {
                type.print (s, indent)
                ['[', arraysize, ']'] -> s
            }

            function dump (stream) extends dump (stream) {
                arraysize -> stream
            }
        }

        class FunctionTypeRecord (proto, varargs, t = null) extends ExtendedTypeRecord (t) {
        public:
            function isFunction {
                return true
            }

            function dereference {
                return type
            }
            operator== (t) {
                if (!t.isFunction()) {
                    return false
                }
                return type == t.dereference()
            }

            operator!= (t) {
                return !(this == t) 
            }

            function getPrototype {
                return proto
            }

            function isVarArgs {
                return varargs
            }

            function print (s, indent) {
                type.print (s, indent)
                '(' -> s
                var comma = false
                foreach p proto {
                    if (comma) {
                        ',' -> s
                    }
                    comma = true
                    p.getType().print (s, indent)
                }
                if (varargs) {
                    if (comma) {
                        ',' -> s
                    }
                    "..." -> s
                }
                ')' -> s
            }
        }


        function constantExpression...
        function expression...

        function storage : int {
            switch (lex.currentToken) {
            case T_STATIC:
                lex.nextToken()
                return sSTATIC
                break
            case T_AUTO:
                lex.nextToken()
                return sAUTO
                break
            case T_EXTERN:
                lex.nextToken()
                return sEXTERN
                break
            case T_TYPEDEF:
                lex.nextToken()
                return sTYPEDEF
                break
            case T_AUTO:
                lex.nextToken()
                return sAUTO
            case T_REGISTER:
                lex.nextToken()
                return sREGISTER
            default:
                return 0
            }
        }

        function structunionType (isstruct) : TypeRecord {
            var tagname = ""
            if (lex.currentToken == IDENTIFIER) {
                tagname = lex.spelling
                lex.nextToken()
            } else {
                tagname = fakename()
            }
            if (lex.match (T_LBRACE)) {         // definition of a new struct?
                var tag = findTopTag (tagname)             
                if (tag != null) {
                    if (tag.isPredefined()) {
                        tag.define()
                    } else {
                        error ("Multiple definition of struct/union tag " + tagname)
                    }
                } else {
                    tag = new Symbol (tagname)
                    insertTag (tag)
                    var t = isstruct ? new StructTypeRecord (tag) : new UnionTypeRecord (tag)
                    tag.setType (t)
                }
                var t = tag.getType()
                while (!lex.match (T_RBRACE)) {
                    var tp = type()
                    for (;;) {
                        var decl = declaration (0, tp)
                        if (decl == null) {
                            error ("struct/union member expected")
                            lex.nextToken()
                        } else {
                            if (lex.match (T_COLON)) {              // bitfield?
                               var width = constantExpression()
                               t.addBitfield (decl, width)
                            } else {
                                t.addMember (decl)
                            }
                        }
                        if (!lex.match (T_COMMA)) {
                            break
                        }
                    }
                    needsemi()
                }
                return t
            } else {
                var tag = findTag (tagname)
                var t = null
                if (tag == null) {
                    tag = new Symbol (tagname)
                    tag.predefine()
                    t = isstruct ? new StructTypeRecord (tag) : new UnionTypeRecord (tag)
                    tag.setType (t)
                    insertTag (tag)
                } else {
                    t = tag.getType()
                }
                return t
            }
        }

        function enumType {
            var tagname = ""
            if (lex.currentToken == IDENTIFIER) {
                tagname = lex.spelling
                lex.nextToken()
            } else {
                tagname = fakename()
            }
            if (lex.match (T_LBRACE)) {         // definition of a new enum?
                var tag = findTopTag (tagname)             
                if (tag != null) {
                    if (tag.isPredefined()) {
                        tag.define()
                    } else {
                        error ("Multiple definition of enum tag " + tagname)
                    }
                } else {
                    tag = new Symbol (tagname)
                    insertTag (tag)
                    var t = new EnumTypeRecord (tag)
                    tag.setType (t)
                }
                var t = tag.getType()
                while (lex.currentToken != T_RBRACE) {
                    generic val = none
                    var name = lex.getIdentifier()
                    if (lex.match (T_ASSIGN)) {
                        val = constantExpression()
                    }
                    var member = new Symbol (name, sENUMCONST)
                    member.setType (new ScalarTypeRecord (CINT))
                    t.addMember (member, val)
                    if (!lex.match (T_COMMA)) {
                        break
                    }
                }
                needbrack (T_RBRACE)
                return t
            } else {
                var tag = findTag (tagname)
                var t = null
                if (tag == null) {
                    tag = new Symbol (tagname)
                    tag.predefine()
                    t = new EnumTypeRecord (tag)
                    tag.setType (t)
                    insertTag (tag)
                } else {
                    t = tag.getType()
                }
                return t
            }
        }

        function type: TypeRecord {
            var type = 0
            var done = false
            while (!done) {
                switch (lex.currentToken) {
                case IDENTIFIER:
                    var sym = findSymbol (lex.spelling)
                    if (sym == null) {
                        done = true
                    } else {
                        if (sym.getStorage() == sTYPEDEF) {
                            var copy = clone (sym.getType(), true)
                            lex.nextToken()
                            if ((type & ~(CCONST|CVOLATILE)) != 0) {
                                error ("Invalid modifier for typedef")
                            }
                            copy.addQualifiers (type)         // add in modifiers
                            return copy
                        }
                        done = true
                    }
                    break
                case T_UNSIGNED:
                    type |= CUNSIGNED
                    lex.nextToken()
                    break
                case T_SIGNED:
                    type |= CSIGNED
                    lex.nextToken()
                case T_INT:
                    type |= CINT
                    lex.nextToken()
                    break
                case T_CHAR:
                    type |= CCHAR
                    lex.nextToken()
                    break
                case T_LONG:
                    if (type & CLONG) {
                       type |= CLONGLONG
                    }
                    type |= CLONG | CINT
                    lex.nextToken()
                    break
                case T_SHORT:
                    type |= CSHORT | CINT
                    lex.nextToken()
                    break
                case T_FLOAT:
                    type |= CFLOAT
                    lex.nextToken()
                    break
                case T_DOUBLE:
                    type |= CDOUBLE
                    lex.nextToken()
                    break
                case T_CONST:
                    type |= CCONST
                    lex.nextToken()
                    break
                case T_VOLATILE:
                    type |= CVOLATILE
                    lex.nextToken()
                    break
                case T_VOID:
                    type |= CVOID
                    lex.nextToken()
                    break
                case T_STRUCT:
                    lex.nextToken()
                    return structunionType (true)
                case T_UNION:
                    lex.nextToken()
                    return structunionType (false)
                case T_ENUM:
                    lex.nextToken()
                    return enumType()
                    break
                default:
                   done = true
                   break
                }
            }
            if (type == 0) {
                return null
            }
            return new ScalarTypeRecord (type)
        }

        function declaration (store, t): Symbol {
            if (t == null) {
                return null
            }
            if (store == 0) {
                store = sEXTERN
            }
            var symbol = null
            var stack = new Stack()

            function pointer...

            function base {
                if (lex.match (T_LPAREN)) {
                    pointer()
                    needbrack (T_RPAREN)
                } else {
                    if (lex.currentToken == IDENTIFIER) {
                        if (symbol != null) {
                            error ("Multiple identifiers in declaration")
                        }
                        var name = lex.spelling
                        lex.nextToken()
                        symbol = new Symbol (name)
                    }
                }
            }

            function funcarray {
                base()
                if (lex.match (T_LPAREN)) {               // function
                    var proto = []
                    var varargs = false

                    function declarevarargs {
                        var builtinvalist = new Symbol ("__builtin_va_alist")

                        // declared as void *__builtin_va_alist[]

                        builtinvalist.setType (new ArrayTypeRecord (0, new PointerTypeRecord (new ScalarTypeRecord (CVOID))))
                        append (proto, builtinvalist)
                    }

                    if (lex.currentToken == T_RPAREN) {                 // empty?
                        declarevarargs()
                        varargs = true
                    } else {
                        while (lex.currentToken != T_RPAREN) {
                            if (lex.match (T_ELLIPSIS)) {
                                declarevarargs()
                                varargs = true
                                break
                            }
                            var st = storage()
                            var tp = type()
                            var decl = declaration (st == 0 ? sARGUMENT : st, tp)
                            if (decl != null) {
                                if (decl.getType() instanceof ScalarTypeRecord && decl.getType().type == CVOID) {   // (void)
                                    if (lex.currentToken == T_RPAREN) {
                                        break
                                    } else {
                                        error ("Illegal use of void in function prototype")
                                    }
                                }
                                append (proto, decl)
                            }
                            if (!lex.match (T_COMMA)) {
                                break
                            }
                        }
                    }
                    needbrack (T_RPAREN)
                    stack.push (new FunctionTypeRecord (proto, varargs))
                } else {
                    while (lex.match (T_LSQUARE)) {
                        var size = 0
                        if (lex.currentToken != T_RSQUARE) {
                            size = constantExpression()
                            // check the expression
                        }
                        stack.push (new ArrayTypeRecord (size))
                        needbrack (T_RSQUARE)
                    }
                }
            }

            function pointer {
                if (lex.match (T_STAR)) {
                    var qual = 0
                    if (lex.match (T_CONST)) {
                        qual |= CCONST
                    }
                    if (lex.match (T_VOLATILE)) {
                        qual |= CVOLATILE
                    }
                    pointer()
                    var p = new PointerTypeRecord()
                    p.addQualifiers(qual)
                    stack.push (p)
                } else {
                    funcarray()
                }
            }

           pointer()
           while (!stack.empty()) {
               var decl = stack.top()
               decl.setsubtype (t)
               t = decl
               stack.pop()
           }
           if (symbol != null) {
               symbol.setType (t)
               symbol.setStorage (store)
           } else {
               symbol = new Symbol (fakename())
               symbol.setType (t)
           }
           return symbol
           
        }
        
        // for an external declaration, the implicit type is an int
        function implicitType {
            return new ScalarTypeRecord (CINT)
        }

        // declared as typedef void *__builtin_va_alist[]
        public function declarevarargs {
            var builtinvalist = new Symbol ("__builtin_va_list")
            builtinvalist.setType (new ArrayTypeRecord (0, new PointerTypeRecord (new ScalarTypeRecord (CVOID))))
            builtinvalist.setStorage (sTYPEDEF) 
            insertGlobalSymbol (builtinvalist)
        }

    }


}