Annotation of embedaddon/libxml2/doc/apibuild.py, revision 1.1

1.1     ! misho       1: #!/usr/bin/python -u
        !             2: #
        !             3: # This is the API builder, it parses the C sources and build the
        !             4: # API formal description in XML.
        !             5: #
        !             6: # See Copyright for the status of this software.
        !             7: #
        !             8: # daniel@veillard.com
        !             9: #
        !            10: import os, sys
        !            11: import string
        !            12: import glob
        !            13: 
        !            14: debug=0
        !            15: #debugsym='ignorableWhitespaceSAXFunc'
        !            16: debugsym=None
        !            17: 
        !            18: #
        !            19: # C parser analysis code
        !            20: #
        !            21: ignored_files = {
        !            22:   "trio": "too many non standard macros",
        !            23:   "trio.c": "too many non standard macros",
        !            24:   "trionan.c": "too many non standard macros",
        !            25:   "triostr.c": "too many non standard macros",
        !            26:   "acconfig.h": "generated portability layer",
        !            27:   "config.h": "generated portability layer",
        !            28:   "libxml.h": "internal only",
        !            29:   "testOOM.c": "out of memory tester",
        !            30:   "testOOMlib.h": "out of memory tester",
        !            31:   "testOOMlib.c": "out of memory tester",
        !            32:   "rngparser.c": "not yet integrated",
        !            33:   "rngparser.h": "not yet integrated",
        !            34:   "elfgcchack.h": "not a normal header",
        !            35:   "testHTML.c": "test tool",
        !            36:   "testReader.c": "test tool",
        !            37:   "testSchemas.c": "test tool",
        !            38:   "testXPath.c": "test tool",
        !            39:   "testAutomata.c": "test tool",
        !            40:   "testModule.c": "test tool",
        !            41:   "testRegexp.c": "test tool",
        !            42:   "testThreads.c": "test tool",
        !            43:   "testC14N.c": "test tool",
        !            44:   "testRelax.c": "test tool",
        !            45:   "testThreadsWin32.c": "test tool",
        !            46:   "testSAX.c": "test tool",
        !            47:   "testURI.c": "test tool",
        !            48:   "testapi.c": "generated regression tests",
        !            49:   "runtest.c": "regression tests program",
        !            50:   "runsuite.c": "regression tests program",
        !            51:   "tst.c": "not part of the library",
        !            52:   "test.c": "not part of the library",
        !            53:   "testdso.c": "test for dynamid shared libraries",
        !            54:   "testrecurse.c": "test for entities recursions",
        !            55: }
        !            56: 
        !            57: ignored_words = {
        !            58:   "WINAPI": (0, "Windows keyword"),
        !            59:   "LIBXML_DLL_IMPORT": (0, "Special macro to flag external keywords"),
        !            60:   "XMLPUBVAR": (0, "Special macro for extern vars for win32"),
        !            61:   "XSLTPUBVAR": (0, "Special macro for extern vars for win32"),
        !            62:   "EXSLTPUBVAR": (0, "Special macro for extern vars for win32"),
        !            63:   "XMLPUBFUN": (0, "Special macro for extern funcs for win32"),
        !            64:   "XSLTPUBFUN": (0, "Special macro for extern funcs for win32"),
        !            65:   "EXSLTPUBFUN": (0, "Special macro for extern funcs for win32"),
        !            66:   "XMLCALL": (0, "Special macro for win32 calls"),
        !            67:   "XSLTCALL": (0, "Special macro for win32 calls"),
        !            68:   "XMLCDECL": (0, "Special macro for win32 calls"),
        !            69:   "EXSLTCALL": (0, "Special macro for win32 calls"),
        !            70:   "__declspec": (3, "Windows keyword"),
        !            71:   "__stdcall": (0, "Windows keyword"),
        !            72:   "ATTRIBUTE_UNUSED": (0, "macro keyword"),
        !            73:   "LIBEXSLT_PUBLIC": (0, "macro keyword"),
        !            74:   "X_IN_Y": (5, "macro function builder"),
        !            75:   "ATTRIBUTE_ALLOC_SIZE": (3, "macro for gcc checking extension"),
        !            76:   "ATTRIBUTE_PRINTF": (5, "macro for gcc printf args checking extension"),
        !            77:   "LIBXML_ATTR_FORMAT": (5, "macro for gcc printf args checking extension"),
        !            78:   "LIBXML_ATTR_ALLOC_SIZE": (3, "macro for gcc checking extension"),
        !            79: }
        !            80: 
        !            81: def escape(raw):
        !            82:     raw = string.replace(raw, '&', '&')
        !            83:     raw = string.replace(raw, '<', '&lt;')
        !            84:     raw = string.replace(raw, '>', '&gt;')
        !            85:     raw = string.replace(raw, "'", '&apos;')
        !            86:     raw = string.replace(raw, '"', '&quot;')
        !            87:     return raw
        !            88: 
        !            89: def uniq(items):
        !            90:     d = {}
        !            91:     for item in items:
        !            92:         d[item]=1
        !            93:     return d.keys()
        !            94: 
        !            95: class identifier:
        !            96:     def __init__(self, name, header=None, module=None, type=None, lineno = 0,
        !            97:                  info=None, extra=None, conditionals = None):
        !            98:         self.name = name
        !            99:        self.header = header
        !           100:        self.module = module
        !           101:        self.type = type
        !           102:        self.info = info
        !           103:        self.extra = extra
        !           104:        self.lineno = lineno
        !           105:        self.static = 0
        !           106:        if conditionals == None or len(conditionals) == 0:
        !           107:            self.conditionals = None
        !           108:        else:
        !           109:            self.conditionals = conditionals[:]
        !           110:        if self.name == debugsym:
        !           111:            print "=> define %s : %s" % (debugsym, (module, type, info,
        !           112:                                         extra, conditionals))
        !           113: 
        !           114:     def __repr__(self):
        !           115:         r = "%s %s:" % (self.type, self.name)
        !           116:        if self.static:
        !           117:            r = r + " static"
        !           118:        if self.module != None:
        !           119:            r = r + " from %s" % (self.module)
        !           120:        if self.info != None:
        !           121:            r = r + " " +  `self.info`
        !           122:        if self.extra != None:
        !           123:            r = r + " " + `self.extra`
        !           124:        if self.conditionals != None:
        !           125:            r = r + " " + `self.conditionals`
        !           126:        return r
        !           127: 
        !           128: 
        !           129:     def set_header(self, header):
        !           130:         self.header = header
        !           131:     def set_module(self, module):
        !           132:         self.module = module
        !           133:     def set_type(self, type):
        !           134:         self.type = type
        !           135:     def set_info(self, info):
        !           136:         self.info = info
        !           137:     def set_extra(self, extra):
        !           138:         self.extra = extra
        !           139:     def set_lineno(self, lineno):
        !           140:         self.lineno = lineno
        !           141:     def set_static(self, static):
        !           142:         self.static = static
        !           143:     def set_conditionals(self, conditionals):
        !           144:        if conditionals == None or len(conditionals) == 0:
        !           145:            self.conditionals = None
        !           146:        else:
        !           147:            self.conditionals = conditionals[:]
        !           148: 
        !           149:     def get_name(self):
        !           150:         return self.name
        !           151:     def get_header(self):
        !           152:         return self.module
        !           153:     def get_module(self):
        !           154:         return self.module
        !           155:     def get_type(self):
        !           156:         return self.type
        !           157:     def get_info(self):
        !           158:         return self.info
        !           159:     def get_lineno(self):
        !           160:         return self.lineno
        !           161:     def get_extra(self):
        !           162:         return self.extra
        !           163:     def get_static(self):
        !           164:         return self.static
        !           165:     def get_conditionals(self):
        !           166:         return self.conditionals
        !           167: 
        !           168:     def update(self, header, module, type = None, info = None, extra=None,
        !           169:                conditionals=None):
        !           170:        if self.name == debugsym:
        !           171:            print "=> update %s : %s" % (debugsym, (module, type, info,
        !           172:                                         extra, conditionals))
        !           173:         if header != None and self.header == None:
        !           174:            self.set_header(module)
        !           175:         if module != None and (self.module == None or self.header == self.module):
        !           176:            self.set_module(module)
        !           177:         if type != None and self.type == None:
        !           178:            self.set_type(type)
        !           179:         if info != None:
        !           180:            self.set_info(info)
        !           181:         if extra != None:
        !           182:            self.set_extra(extra)
        !           183:         if conditionals != None:
        !           184:            self.set_conditionals(conditionals)
        !           185: 
        !           186: class index:
        !           187:     def __init__(self, name = "noname"):
        !           188:         self.name = name
        !           189:         self.identifiers = {}
        !           190:         self.functions = {}
        !           191:        self.variables = {}
        !           192:        self.includes = {}
        !           193:        self.structs = {}
        !           194:        self.enums = {}
        !           195:        self.typedefs = {}
        !           196:        self.macros = {}
        !           197:        self.references = {}
        !           198:        self.info = {}
        !           199: 
        !           200:     def add_ref(self, name, header, module, static, type, lineno, info=None, extra=None, conditionals = None):
        !           201:         if name[0:2] == '__':
        !           202:            return None
        !           203:         d = None
        !           204:         try:
        !           205:           d = self.identifiers[name]
        !           206:           d.update(header, module, type, lineno, info, extra, conditionals)
        !           207:        except:
        !           208:           d = identifier(name, header, module, type, lineno, info, extra, conditionals)
        !           209:           self.identifiers[name] = d
        !           210: 
        !           211:        if d != None and static == 1:
        !           212:            d.set_static(1)
        !           213: 
        !           214:        if d != None and name != None and type != None:
        !           215:            self.references[name] = d
        !           216: 
        !           217:        if name == debugsym:
        !           218:            print "New ref: %s" % (d)
        !           219: 
        !           220:        return d
        !           221: 
        !           222:     def add(self, name, header, module, static, type, lineno, info=None, extra=None, conditionals = None):
        !           223:         if name[0:2] == '__':
        !           224:            return None
        !           225:         d = None
        !           226:         try:
        !           227:           d = self.identifiers[name]
        !           228:           d.update(header, module, type, lineno, info, extra, conditionals)
        !           229:        except:
        !           230:           d = identifier(name, header, module, type, lineno, info, extra, conditionals)
        !           231:           self.identifiers[name] = d
        !           232: 
        !           233:        if d != None and static == 1:
        !           234:            d.set_static(1)
        !           235: 
        !           236:        if d != None and name != None and type != None:
        !           237:            if type == "function":
        !           238:                self.functions[name] = d
        !           239:            elif type == "functype":
        !           240:                self.functions[name] = d
        !           241:            elif type == "variable":
        !           242:                self.variables[name] = d
        !           243:            elif type == "include":
        !           244:                self.includes[name] = d
        !           245:            elif type == "struct":
        !           246:                self.structs[name] = d
        !           247:            elif type == "enum":
        !           248:                self.enums[name] = d
        !           249:            elif type == "typedef":
        !           250:                self.typedefs[name] = d
        !           251:            elif type == "macro":
        !           252:                self.macros[name] = d
        !           253:            else:
        !           254:                print "Unable to register type ", type
        !           255: 
        !           256:        if name == debugsym:
        !           257:            print "New symbol: %s" % (d)
        !           258: 
        !           259:        return d
        !           260: 
        !           261:     def merge(self, idx):
        !           262:         for id in idx.functions.keys():
        !           263:               #
        !           264:               # macro might be used to override functions or variables
        !           265:               # definitions
        !           266:               #
        !           267:             if self.macros.has_key(id):
        !           268:                 del self.macros[id]
        !           269:             if self.functions.has_key(id):
        !           270:                 print "function %s from %s redeclared in %s" % (
        !           271:                    id, self.functions[id].header, idx.functions[id].header)
        !           272:             else:
        !           273:                 self.functions[id] = idx.functions[id]
        !           274:                 self.identifiers[id] = idx.functions[id]
        !           275:         for id in idx.variables.keys():
        !           276:               #
        !           277:               # macro might be used to override functions or variables
        !           278:               # definitions
        !           279:               #
        !           280:             if self.macros.has_key(id):
        !           281:                 del self.macros[id]
        !           282:             if self.variables.has_key(id):
        !           283:                 print "variable %s from %s redeclared in %s" % (
        !           284:                    id, self.variables[id].header, idx.variables[id].header)
        !           285:             else:
        !           286:                 self.variables[id] = idx.variables[id]
        !           287:                 self.identifiers[id] = idx.variables[id]
        !           288:         for id in idx.structs.keys():
        !           289:             if self.structs.has_key(id):
        !           290:                 print "struct %s from %s redeclared in %s" % (
        !           291:                    id, self.structs[id].header, idx.structs[id].header)
        !           292:             else:
        !           293:                 self.structs[id] = idx.structs[id]
        !           294:                 self.identifiers[id] = idx.structs[id]
        !           295:         for id in idx.typedefs.keys():
        !           296:             if self.typedefs.has_key(id):
        !           297:                 print "typedef %s from %s redeclared in %s" % (
        !           298:                    id, self.typedefs[id].header, idx.typedefs[id].header)
        !           299:             else:
        !           300:                 self.typedefs[id] = idx.typedefs[id]
        !           301:                 self.identifiers[id] = idx.typedefs[id]
        !           302:         for id in idx.macros.keys():
        !           303:               #
        !           304:               # macro might be used to override functions or variables
        !           305:               # definitions
        !           306:               #
        !           307:              if self.variables.has_key(id):
        !           308:                  continue
        !           309:              if self.functions.has_key(id):
        !           310:                  continue
        !           311:              if self.enums.has_key(id):
        !           312:                  continue
        !           313:             if self.macros.has_key(id):
        !           314:                 print "macro %s from %s redeclared in %s" % (
        !           315:                    id, self.macros[id].header, idx.macros[id].header)
        !           316:             else:
        !           317:                 self.macros[id] = idx.macros[id]
        !           318:                 self.identifiers[id] = idx.macros[id]
        !           319:         for id in idx.enums.keys():
        !           320:             if self.enums.has_key(id):
        !           321:                 print "enum %s from %s redeclared in %s" % (
        !           322:                    id, self.enums[id].header, idx.enums[id].header)
        !           323:             else:
        !           324:                 self.enums[id] = idx.enums[id]
        !           325:                 self.identifiers[id] = idx.enums[id]
        !           326: 
        !           327:     def merge_public(self, idx):
        !           328:         for id in idx.functions.keys():
        !           329:             if self.functions.has_key(id):
        !           330:                 # check that function condition agrees with header
        !           331:                 if idx.functions[id].conditionals != \
        !           332:                    self.functions[id].conditionals:
        !           333:                     print "Header condition differs from Function for %s:" \
        !           334:                        % id
        !           335:                     print "  H: %s" % self.functions[id].conditionals
        !           336:                     print "  C: %s" % idx.functions[id].conditionals
        !           337:                 up = idx.functions[id]
        !           338:                 self.functions[id].update(None, up.module, up.type, up.info, up.extra)
        !           339:         #     else:
        !           340:         #         print "Function %s from %s is not declared in headers" % (
        !           341:         #              id, idx.functions[id].module)
        !           342:         # TODO: do the same for variables.
        !           343: 
        !           344:     def analyze_dict(self, type, dict):
        !           345:         count = 0
        !           346:        public = 0
        !           347:         for name in dict.keys():
        !           348:            id = dict[name]
        !           349:            count = count + 1
        !           350:            if id.static == 0:
        !           351:                public = public + 1
        !           352:         if count != public:
        !           353:            print "  %d %s , %d public" % (count, type, public)
        !           354:        elif count != 0:
        !           355:            print "  %d public %s" % (count, type)
        !           356: 
        !           357: 
        !           358:     def analyze(self):
        !           359:        self.analyze_dict("functions", self.functions)
        !           360:        self.analyze_dict("variables", self.variables)
        !           361:        self.analyze_dict("structs", self.structs)
        !           362:        self.analyze_dict("typedefs", self.typedefs)
        !           363:        self.analyze_dict("macros", self.macros)
        !           364: 
        !           365: class CLexer:
        !           366:     """A lexer for the C language, tokenize the input by reading and
        !           367:        analyzing it line by line"""
        !           368:     def __init__(self, input):
        !           369:         self.input = input
        !           370:        self.tokens = []
        !           371:        self.line = ""
        !           372:        self.lineno = 0
        !           373: 
        !           374:     def getline(self):
        !           375:         line = ''
        !           376:        while line == '':
        !           377:            line = self.input.readline()
        !           378:            if not line:
        !           379:                return None
        !           380:            self.lineno = self.lineno + 1
        !           381:            line = string.lstrip(line)
        !           382:            line = string.rstrip(line)
        !           383:            if line == '':
        !           384:                continue
        !           385:            while line[-1] == '\\':
        !           386:                line = line[:-1]
        !           387:                n = self.input.readline()
        !           388:                self.lineno = self.lineno + 1
        !           389:                n = string.lstrip(n)
        !           390:                n = string.rstrip(n)
        !           391:                if not n:
        !           392:                    break
        !           393:                else:
        !           394:                    line = line + n
        !           395:         return line
        !           396: 
        !           397:     def getlineno(self):
        !           398:         return self.lineno
        !           399: 
        !           400:     def push(self, token):
        !           401:         self.tokens.insert(0, token);
        !           402: 
        !           403:     def debug(self):
        !           404:         print "Last token: ", self.last
        !           405:        print "Token queue: ", self.tokens
        !           406:        print "Line %d end: " % (self.lineno), self.line
        !           407: 
        !           408:     def token(self):
        !           409:         while self.tokens == []:
        !           410:            if self.line == "":
        !           411:                line = self.getline()
        !           412:            else:
        !           413:                line = self.line
        !           414:                self.line = ""
        !           415:            if line == None:
        !           416:                return None
        !           417: 
        !           418:            if line[0] == '#':
        !           419:                self.tokens = map((lambda x: ('preproc', x)),
        !           420:                                  string.split(line))
        !           421:                break;
        !           422:            l = len(line)
        !           423:            if line[0] == '"' or line[0] == "'":
        !           424:                end = line[0]
        !           425:                line = line[1:]
        !           426:                found = 0
        !           427:                tok = ""
        !           428:                while found == 0:
        !           429:                    i = 0
        !           430:                    l = len(line)
        !           431:                    while i < l:
        !           432:                        if line[i] == end:
        !           433:                            self.line = line[i+1:]
        !           434:                            line = line[:i]
        !           435:                            l = i
        !           436:                            found = 1
        !           437:                            break
        !           438:                        if line[i] == '\\':
        !           439:                            i = i + 1
        !           440:                        i = i + 1
        !           441:                    tok = tok + line
        !           442:                    if found == 0:
        !           443:                        line = self.getline()
        !           444:                        if line == None:
        !           445:                            return None
        !           446:                self.last = ('string', tok)
        !           447:                return self.last
        !           448: 
        !           449:            if l >= 2 and line[0] == '/' and line[1] == '*':
        !           450:                line = line[2:]
        !           451:                found = 0
        !           452:                tok = ""
        !           453:                while found == 0:
        !           454:                    i = 0
        !           455:                    l = len(line)
        !           456:                    while i < l:
        !           457:                        if line[i] == '*' and i+1 < l and line[i+1] == '/':
        !           458:                            self.line = line[i+2:]
        !           459:                            line = line[:i-1]
        !           460:                            l = i
        !           461:                            found = 1
        !           462:                            break
        !           463:                        i = i + 1
        !           464:                    if tok != "":
        !           465:                        tok = tok + "\n"
        !           466:                    tok = tok + line
        !           467:                    if found == 0:
        !           468:                        line = self.getline()
        !           469:                        if line == None:
        !           470:                            return None
        !           471:                self.last = ('comment', tok)
        !           472:                return self.last
        !           473:            if l >= 2 and line[0] == '/' and line[1] == '/':
        !           474:                line = line[2:]
        !           475:                self.last = ('comment', line)
        !           476:                return self.last
        !           477:            i = 0
        !           478:            while i < l:
        !           479:                if line[i] == '/' and i+1 < l and line[i+1] == '/':
        !           480:                    self.line = line[i:]
        !           481:                    line = line[:i]
        !           482:                    break
        !           483:                if line[i] == '/' and i+1 < l and line[i+1] == '*':
        !           484:                    self.line = line[i:]
        !           485:                    line = line[:i]
        !           486:                    break
        !           487:                if line[i] == '"' or line[i] == "'":
        !           488:                    self.line = line[i:]
        !           489:                    line = line[:i]
        !           490:                    break
        !           491:                i = i + 1
        !           492:            l = len(line)
        !           493:            i = 0
        !           494:            while i < l:
        !           495:                if line[i] == ' ' or line[i] == '\t':
        !           496:                    i = i + 1
        !           497:                    continue
        !           498:                o = ord(line[i])
        !           499:                if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \
        !           500:                   (o >= 48 and o <= 57):
        !           501:                    s = i
        !           502:                    while i < l:
        !           503:                        o = ord(line[i])
        !           504:                        if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \
        !           505:                           (o >= 48 and o <= 57) or string.find(
        !           506:                               " \t(){}:;,+-*/%&!|[]=><", line[i]) == -1:
        !           507:                            i = i + 1
        !           508:                        else:
        !           509:                            break
        !           510:                    self.tokens.append(('name', line[s:i]))
        !           511:                    continue
        !           512:                if string.find("(){}:;,[]", line[i]) != -1:
        !           513: #                 if line[i] == '(' or line[i] == ')' or line[i] == '{' or \
        !           514: #                  line[i] == '}' or line[i] == ':' or line[i] == ';' or \
        !           515: #                  line[i] == ',' or line[i] == '[' or line[i] == ']':
        !           516:                    self.tokens.append(('sep', line[i]))
        !           517:                    i = i + 1
        !           518:                    continue
        !           519:                if string.find("+-*><=/%&!|.", line[i]) != -1:
        !           520: #                 if line[i] == '+' or line[i] == '-' or line[i] == '*' or \
        !           521: #                  line[i] == '>' or line[i] == '<' or line[i] == '=' or \
        !           522: #                  line[i] == '/' or line[i] == '%' or line[i] == '&' or \
        !           523: #                  line[i] == '!' or line[i] == '|' or line[i] == '.':
        !           524:                    if line[i] == '.' and  i + 2 < l and \
        !           525:                       line[i+1] == '.' and line[i+2] == '.':
        !           526:                        self.tokens.append(('name', '...'))
        !           527:                        i = i + 3
        !           528:                        continue
        !           529: 
        !           530:                    j = i + 1
        !           531:                    if j < l and (
        !           532:                       string.find("+-*><=/%&!|", line[j]) != -1):
        !           533: #                      line[j] == '+' or line[j] == '-' or line[j] == '*' or \
        !           534: #                      line[j] == '>' or line[j] == '<' or line[j] == '=' or \
        !           535: #                      line[j] == '/' or line[j] == '%' or line[j] == '&' or \
        !           536: #                      line[j] == '!' or line[j] == '|'):
        !           537:                        self.tokens.append(('op', line[i:j+1]))
        !           538:                        i = j + 1
        !           539:                    else:
        !           540:                        self.tokens.append(('op', line[i]))
        !           541:                        i = i + 1
        !           542:                    continue
        !           543:                s = i
        !           544:                while i < l:
        !           545:                    o = ord(line[i])
        !           546:                    if (o >= 97 and o <= 122) or (o >= 65 and o <= 90) or \
        !           547:                       (o >= 48 and o <= 57) or (
        !           548:                        string.find(" \t(){}:;,+-*/%&!|[]=><", line[i]) == -1):
        !           549: #                       line[i] != ' ' and line[i] != '\t' and
        !           550: #                       line[i] != '(' and line[i] != ')' and
        !           551: #                       line[i] != '{'  and line[i] != '}' and
        !           552: #                       line[i] != ':' and line[i] != ';' and
        !           553: #                       line[i] != ',' and line[i] != '+' and
        !           554: #                       line[i] != '-' and line[i] != '*' and
        !           555: #                       line[i] != '/' and line[i] != '%' and
        !           556: #                       line[i] != '&' and line[i] != '!' and
        !           557: #                       line[i] != '|' and line[i] != '[' and
        !           558: #                       line[i] != ']' and line[i] != '=' and
        !           559: #                       line[i] != '*' and line[i] != '>' and
        !           560: #                       line[i] != '<'):
        !           561:                        i = i + 1
        !           562:                    else:
        !           563:                        break
        !           564:                self.tokens.append(('name', line[s:i]))
        !           565: 
        !           566:        tok = self.tokens[0]
        !           567:        self.tokens = self.tokens[1:]
        !           568:        self.last = tok
        !           569:        return tok
        !           570: 
        !           571: class CParser:
        !           572:     """The C module parser"""
        !           573:     def __init__(self, filename, idx = None):
        !           574:         self.filename = filename
        !           575:        if len(filename) > 2 and filename[-2:] == '.h':
        !           576:            self.is_header = 1
        !           577:        else:
        !           578:            self.is_header = 0
        !           579:         self.input = open(filename)
        !           580:        self.lexer = CLexer(self.input)
        !           581:        if idx == None:
        !           582:            self.index = index()
        !           583:        else:
        !           584:            self.index = idx
        !           585:        self.top_comment = ""
        !           586:        self.last_comment = ""
        !           587:        self.comment = None
        !           588:        self.collect_ref = 0
        !           589:        self.no_error = 0
        !           590:        self.conditionals = []
        !           591:        self.defines = []
        !           592: 
        !           593:     def collect_references(self):
        !           594:         self.collect_ref = 1
        !           595: 
        !           596:     def stop_error(self):
        !           597:         self.no_error = 1
        !           598: 
        !           599:     def start_error(self):
        !           600:         self.no_error = 0
        !           601: 
        !           602:     def lineno(self):
        !           603:         return self.lexer.getlineno()
        !           604: 
        !           605:     def index_add(self, name, module, static, type, info=None, extra = None):
        !           606:        if self.is_header == 1:
        !           607:            self.index.add(name, module, module, static, type, self.lineno(),
        !           608:                           info, extra, self.conditionals)
        !           609:        else:
        !           610:            self.index.add(name, None, module, static, type, self.lineno(),
        !           611:                           info, extra, self.conditionals)
        !           612: 
        !           613:     def index_add_ref(self, name, module, static, type, info=None,
        !           614:                       extra = None):
        !           615:        if self.is_header == 1:
        !           616:            self.index.add_ref(name, module, module, static, type,
        !           617:                               self.lineno(), info, extra, self.conditionals)
        !           618:        else:
        !           619:            self.index.add_ref(name, None, module, static, type, self.lineno(),
        !           620:                               info, extra, self.conditionals)
        !           621: 
        !           622:     def warning(self, msg):
        !           623:         if self.no_error:
        !           624:            return
        !           625:        print msg
        !           626: 
        !           627:     def error(self, msg, token=-1):
        !           628:         if self.no_error:
        !           629:            return
        !           630: 
        !           631:         print "Parse Error: " + msg
        !           632:        if token != -1:
        !           633:            print "Got token ", token
        !           634:        self.lexer.debug()
        !           635:        sys.exit(1)
        !           636: 
        !           637:     def debug(self, msg, token=-1):
        !           638:         print "Debug: " + msg
        !           639:        if token != -1:
        !           640:            print "Got token ", token
        !           641:        self.lexer.debug()
        !           642: 
        !           643:     def parseTopComment(self, comment):
        !           644:        res = {}
        !           645:        lines = string.split(comment, "\n")
        !           646:        item = None
        !           647:        for line in lines:
        !           648:            while line != "" and (line[0] == ' ' or line[0] == '\t'):
        !           649:                line = line[1:]
        !           650:            while line != "" and line[0] == '*':
        !           651:                line = line[1:]
        !           652:            while line != "" and (line[0] == ' ' or line[0] == '\t'):
        !           653:                line = line[1:]
        !           654:            try:
        !           655:                (it, line) = string.split(line, ":", 1)
        !           656:                item = it
        !           657:                while line != "" and (line[0] == ' ' or line[0] == '\t'):
        !           658:                    line = line[1:]
        !           659:                if res.has_key(item):
        !           660:                    res[item] = res[item] + " " + line
        !           661:                else:
        !           662:                    res[item] = line
        !           663:            except:
        !           664:                if item != None:
        !           665:                    if res.has_key(item):
        !           666:                        res[item] = res[item] + " " + line
        !           667:                    else:
        !           668:                        res[item] = line
        !           669:        self.index.info = res
        !           670: 
        !           671:     def parseComment(self, token):
        !           672:         if self.top_comment == "":
        !           673:            self.top_comment = token[1]
        !           674:        if self.comment == None or token[1][0] == '*':
        !           675:            self.comment = token[1];
        !           676:        else:
        !           677:            self.comment = self.comment + token[1]
        !           678:        token = self.lexer.token()
        !           679: 
        !           680:         if string.find(self.comment, "DOC_DISABLE") != -1:
        !           681:            self.stop_error()
        !           682: 
        !           683:         if string.find(self.comment, "DOC_ENABLE") != -1:
        !           684:            self.start_error()
        !           685: 
        !           686:        return token
        !           687: 
        !           688:     #
        !           689:     # Parse a comment block associate to a typedef
        !           690:     #
        !           691:     def parseTypeComment(self, name, quiet = 0):
        !           692:         if name[0:2] == '__':
        !           693:            quiet = 1
        !           694: 
        !           695:         args = []
        !           696:        desc = ""
        !           697: 
        !           698:         if self.comment == None:
        !           699:            if not quiet:
        !           700:                self.warning("Missing comment for type %s" % (name))
        !           701:            return((args, desc))
        !           702:         if self.comment[0] != '*':
        !           703:            if not quiet:
        !           704:                self.warning("Missing * in type comment for %s" % (name))
        !           705:            return((args, desc))
        !           706:        lines = string.split(self.comment, '\n')
        !           707:        if lines[0] == '*':
        !           708:            del lines[0]
        !           709:        if lines[0] != "* %s:" % (name):
        !           710:            if not quiet:
        !           711:                self.warning("Misformatted type comment for %s" % (name))
        !           712:                self.warning("  Expecting '* %s:' got '%s'" % (name, lines[0]))
        !           713:            return((args, desc))
        !           714:        del lines[0]
        !           715:        while len(lines) > 0 and lines[0] == '*':
        !           716:            del lines[0]
        !           717:        desc = ""
        !           718:        while len(lines) > 0:
        !           719:            l = lines[0]
        !           720:            while len(l) > 0 and l[0] == '*':
        !           721:                l = l[1:]
        !           722:            l = string.strip(l)
        !           723:            desc = desc + " " + l
        !           724:            del lines[0]
        !           725: 
        !           726:        desc = string.strip(desc)
        !           727: 
        !           728:        if quiet == 0:
        !           729:            if desc == "":
        !           730:                self.warning("Type comment for %s lack description of the macro" % (name))
        !           731: 
        !           732:        return(desc)
        !           733:     #
        !           734:     # Parse a comment block associate to a macro
        !           735:     #
        !           736:     def parseMacroComment(self, name, quiet = 0):
        !           737:         if name[0:2] == '__':
        !           738:            quiet = 1
        !           739: 
        !           740:         args = []
        !           741:        desc = ""
        !           742: 
        !           743:         if self.comment == None:
        !           744:            if not quiet:
        !           745:                self.warning("Missing comment for macro %s" % (name))
        !           746:            return((args, desc))
        !           747:         if self.comment[0] != '*':
        !           748:            if not quiet:
        !           749:                self.warning("Missing * in macro comment for %s" % (name))
        !           750:            return((args, desc))
        !           751:        lines = string.split(self.comment, '\n')
        !           752:        if lines[0] == '*':
        !           753:            del lines[0]
        !           754:        if lines[0] != "* %s:" % (name):
        !           755:            if not quiet:
        !           756:                self.warning("Misformatted macro comment for %s" % (name))
        !           757:                self.warning("  Expecting '* %s:' got '%s'" % (name, lines[0]))
        !           758:            return((args, desc))
        !           759:        del lines[0]
        !           760:        while lines[0] == '*':
        !           761:            del lines[0]
        !           762:        while len(lines) > 0 and lines[0][0:3] == '* @':
        !           763:            l = lines[0][3:]
        !           764:            try:
        !           765:                (arg, desc) = string.split(l, ':', 1)
        !           766:                desc=string.strip(desc)
        !           767:                arg=string.strip(arg)
        !           768:             except:
        !           769:                if not quiet:
        !           770:                    self.warning("Misformatted macro comment for %s" % (name))
        !           771:                    self.warning("  problem with '%s'" % (lines[0]))
        !           772:                del lines[0]
        !           773:                continue
        !           774:            del lines[0]
        !           775:            l = string.strip(lines[0])
        !           776:            while len(l) > 2 and l[0:3] != '* @':
        !           777:                while l[0] == '*':
        !           778:                    l = l[1:]
        !           779:                desc = desc + ' ' + string.strip(l)
        !           780:                del lines[0]
        !           781:                if len(lines) == 0:
        !           782:                    break
        !           783:                l = lines[0]
        !           784:             args.append((arg, desc))
        !           785:        while len(lines) > 0 and lines[0] == '*':
        !           786:            del lines[0]
        !           787:        desc = ""
        !           788:        while len(lines) > 0:
        !           789:            l = lines[0]
        !           790:            while len(l) > 0 and l[0] == '*':
        !           791:                l = l[1:]
        !           792:            l = string.strip(l)
        !           793:            desc = desc + " " + l
        !           794:            del lines[0]
        !           795: 
        !           796:        desc = string.strip(desc)
        !           797: 
        !           798:        if quiet == 0:
        !           799:            if desc == "":
        !           800:                self.warning("Macro comment for %s lack description of the macro" % (name))
        !           801: 
        !           802:        return((args, desc))
        !           803: 
        !           804:      #
        !           805:      # Parse a comment block and merge the informations found in the
        !           806:      # parameters descriptions, finally returns a block as complete
        !           807:      # as possible
        !           808:      #
        !           809:     def mergeFunctionComment(self, name, description, quiet = 0):
        !           810:         if name == 'main':
        !           811:            quiet = 1
        !           812:         if name[0:2] == '__':
        !           813:            quiet = 1
        !           814: 
        !           815:        (ret, args) = description
        !           816:        desc = ""
        !           817:        retdesc = ""
        !           818: 
        !           819:         if self.comment == None:
        !           820:            if not quiet:
        !           821:                self.warning("Missing comment for function %s" % (name))
        !           822:            return(((ret[0], retdesc), args, desc))
        !           823:         if self.comment[0] != '*':
        !           824:            if not quiet:
        !           825:                self.warning("Missing * in function comment for %s" % (name))
        !           826:            return(((ret[0], retdesc), args, desc))
        !           827:        lines = string.split(self.comment, '\n')
        !           828:        if lines[0] == '*':
        !           829:            del lines[0]
        !           830:        if lines[0] != "* %s:" % (name):
        !           831:            if not quiet:
        !           832:                self.warning("Misformatted function comment for %s" % (name))
        !           833:                self.warning("  Expecting '* %s:' got '%s'" % (name, lines[0]))
        !           834:            return(((ret[0], retdesc), args, desc))
        !           835:        del lines[0]
        !           836:        while lines[0] == '*':
        !           837:            del lines[0]
        !           838:        nbargs = len(args)
        !           839:        while len(lines) > 0 and lines[0][0:3] == '* @':
        !           840:            l = lines[0][3:]
        !           841:            try:
        !           842:                (arg, desc) = string.split(l, ':', 1)
        !           843:                desc=string.strip(desc)
        !           844:                arg=string.strip(arg)
        !           845:             except:
        !           846:                if not quiet:
        !           847:                    self.warning("Misformatted function comment for %s" % (name))
        !           848:                    self.warning("  problem with '%s'" % (lines[0]))
        !           849:                del lines[0]
        !           850:                continue
        !           851:            del lines[0]
        !           852:            l = string.strip(lines[0])
        !           853:            while len(l) > 2 and l[0:3] != '* @':
        !           854:                while l[0] == '*':
        !           855:                    l = l[1:]
        !           856:                desc = desc + ' ' + string.strip(l)
        !           857:                del lines[0]
        !           858:                if len(lines) == 0:
        !           859:                    break
        !           860:                l = lines[0]
        !           861:            i = 0
        !           862:            while i < nbargs:
        !           863:                if args[i][1] == arg:
        !           864:                    args[i] = (args[i][0], arg, desc)
        !           865:                    break;
        !           866:                i = i + 1
        !           867:            if i >= nbargs:
        !           868:                if not quiet:
        !           869:                    self.warning("Unable to find arg %s from function comment for %s" % (
        !           870:                       arg, name))
        !           871:        while len(lines) > 0 and lines[0] == '*':
        !           872:            del lines[0]
        !           873:        desc = ""
        !           874:        while len(lines) > 0:
        !           875:            l = lines[0]
        !           876:            while len(l) > 0 and l[0] == '*':
        !           877:                l = l[1:]
        !           878:            l = string.strip(l)
        !           879:            if len(l) >= 6 and  l[0:6] == "return" or l[0:6] == "Return":
        !           880:                try:
        !           881:                    l = string.split(l, ' ', 1)[1]
        !           882:                except:
        !           883:                    l = ""
        !           884:                retdesc = string.strip(l)
        !           885:                del lines[0]
        !           886:                while len(lines) > 0:
        !           887:                    l = lines[0]
        !           888:                    while len(l) > 0 and l[0] == '*':
        !           889:                        l = l[1:]
        !           890:                    l = string.strip(l)
        !           891:                    retdesc = retdesc + " " + l
        !           892:                    del lines[0]
        !           893:            else:
        !           894:                desc = desc + " " + l
        !           895:                del lines[0]
        !           896: 
        !           897:        retdesc = string.strip(retdesc)
        !           898:        desc = string.strip(desc)
        !           899: 
        !           900:        if quiet == 0:
        !           901:             #
        !           902:             # report missing comments
        !           903:             #
        !           904:            i = 0
        !           905:            while i < nbargs:
        !           906:                if args[i][2] == None and args[i][0] != "void" and \
        !           907:                   ((args[i][1] != None) or (args[i][1] == '')):
        !           908:                    self.warning("Function comment for %s lacks description of arg %s" % (name, args[i][1]))
        !           909:                i = i + 1
        !           910:            if retdesc == "" and ret[0] != "void":
        !           911:                self.warning("Function comment for %s lacks description of return value" % (name))
        !           912:            if desc == "":
        !           913:                self.warning("Function comment for %s lacks description of the function" % (name))
        !           914: 
        !           915:        return(((ret[0], retdesc), args, desc))
        !           916: 
        !           917:     def parsePreproc(self, token):
        !           918:        if debug:
        !           919:            print "=> preproc ", token, self.lexer.tokens
        !           920:         name = token[1]
        !           921:        if name == "#include":
        !           922:            token = self.lexer.token()
        !           923:            if token == None:
        !           924:                return None
        !           925:            if token[0] == 'preproc':
        !           926:                self.index_add(token[1], self.filename, not self.is_header,
        !           927:                                "include")
        !           928:                return self.lexer.token()
        !           929:            return token
        !           930:        if name == "#define":
        !           931:            token = self.lexer.token()
        !           932:            if token == None:
        !           933:                return None
        !           934:            if token[0] == 'preproc':
        !           935:                 # TODO macros with arguments
        !           936:                name = token[1]
        !           937:                lst = []
        !           938:                token = self.lexer.token()
        !           939:                while token != None and token[0] == 'preproc' and \
        !           940:                      token[1][0] != '#':
        !           941:                    lst.append(token[1])
        !           942:                    token = self.lexer.token()
        !           943:                 try:
        !           944:                    name = string.split(name, '(') [0]
        !           945:                 except:
        !           946:                     pass
        !           947:                 info = self.parseMacroComment(name, not self.is_header)
        !           948:                self.index_add(name, self.filename, not self.is_header,
        !           949:                                "macro", info)
        !           950:                return token
        !           951: 
        !           952:        #
        !           953:        # Processing of conditionals modified by Bill 1/1/05
        !           954:        #
        !           955:        # We process conditionals (i.e. tokens from #ifdef, #ifndef,
        !           956:        # #if, #else and #endif) for headers and mainline code,
        !           957:        # store the ones from the header in libxml2-api.xml, and later
        !           958:        # (in the routine merge_public) verify that the two (header and
        !           959:        # mainline code) agree.
        !           960:        #
        !           961:        # There is a small problem with processing the headers. Some of
        !           962:        # the variables are not concerned with enabling / disabling of
        !           963:        # library functions (e.g. '__XML_PARSER_H__'), and we don't want
        !           964:        # them to be included in libxml2-api.xml, or involved in
        !           965:        # the check between the header and the mainline code.  To
        !           966:        # accomplish this, we ignore any conditional which doesn't include
        !           967:        # the string 'ENABLED'
        !           968:        #
        !           969:        if name == "#ifdef":
        !           970:            apstr = self.lexer.tokens[0][1]
        !           971:            try:
        !           972:                self.defines.append(apstr)
        !           973:                if string.find(apstr, 'ENABLED') != -1:
        !           974:                    self.conditionals.append("defined(%s)" % apstr)
        !           975:            except:
        !           976:                pass
        !           977:        elif name == "#ifndef":
        !           978:            apstr = self.lexer.tokens[0][1]
        !           979:            try:
        !           980:                self.defines.append(apstr)
        !           981:                if string.find(apstr, 'ENABLED') != -1:
        !           982:                    self.conditionals.append("!defined(%s)" % apstr)
        !           983:            except:
        !           984:                pass
        !           985:        elif name == "#if":
        !           986:            apstr = ""
        !           987:            for tok in self.lexer.tokens:
        !           988:                if apstr != "":
        !           989:                    apstr = apstr + " "
        !           990:                apstr = apstr + tok[1]
        !           991:            try:
        !           992:                self.defines.append(apstr)
        !           993:                if string.find(apstr, 'ENABLED') != -1:
        !           994:                    self.conditionals.append(apstr)
        !           995:            except:
        !           996:                pass
        !           997:        elif name == "#else":
        !           998:            if self.conditionals != [] and \
        !           999:               string.find(self.defines[-1], 'ENABLED') != -1:
        !          1000:                self.conditionals[-1] = "!(%s)" % self.conditionals[-1]
        !          1001:        elif name == "#endif":
        !          1002:            if self.conditionals != [] and \
        !          1003:               string.find(self.defines[-1], 'ENABLED') != -1:
        !          1004:                self.conditionals = self.conditionals[:-1]
        !          1005:            self.defines = self.defines[:-1]
        !          1006:        token = self.lexer.token()
        !          1007:        while token != None and token[0] == 'preproc' and \
        !          1008:            token[1][0] != '#':
        !          1009:            token = self.lexer.token()
        !          1010:        return token
        !          1011: 
        !          1012:      #
        !          1013:      # token acquisition on top of the lexer, it handle internally
        !          1014:      # preprocessor and comments since they are logically not part of
        !          1015:      # the program structure.
        !          1016:      #
        !          1017:     def token(self):
        !          1018:         global ignored_words
        !          1019: 
        !          1020:         token = self.lexer.token()
        !          1021:        while token != None:
        !          1022:            if token[0] == 'comment':
        !          1023:                token = self.parseComment(token)
        !          1024:                continue
        !          1025:            elif token[0] == 'preproc':
        !          1026:                token = self.parsePreproc(token)
        !          1027:                continue
        !          1028:            elif token[0] == "name" and token[1] == "__const":
        !          1029:                token = ("name", "const")
        !          1030:                return token
        !          1031:            elif token[0] == "name" and token[1] == "__attribute":
        !          1032:                token = self.lexer.token()
        !          1033:                while token != None and token[1] != ";":
        !          1034:                    token = self.lexer.token()
        !          1035:                return token
        !          1036:            elif token[0] == "name" and ignored_words.has_key(token[1]):
        !          1037:                (n, info) = ignored_words[token[1]]
        !          1038:                i = 0
        !          1039:                while i < n:
        !          1040:                    token = self.lexer.token()
        !          1041:                    i = i + 1
        !          1042:                token = self.lexer.token()
        !          1043:                continue
        !          1044:            else:
        !          1045:                if debug:
        !          1046:                    print "=> ", token
        !          1047:                return token
        !          1048:        return None
        !          1049: 
        !          1050:      #
        !          1051:      # Parse a typedef, it records the type and its name.
        !          1052:      #
        !          1053:     def parseTypedef(self, token):
        !          1054:         if token == None:
        !          1055:            return None
        !          1056:        token = self.parseType(token)
        !          1057:        if token == None:
        !          1058:            self.error("parsing typedef")
        !          1059:            return None
        !          1060:        base_type = self.type
        !          1061:        type = base_type
        !          1062:         #self.debug("end typedef type", token)
        !          1063:        while token != None:
        !          1064:            if token[0] == "name":
        !          1065:                name = token[1]
        !          1066:                signature = self.signature
        !          1067:                if signature != None:
        !          1068:                    type = string.split(type, '(')[0]
        !          1069:                    d = self.mergeFunctionComment(name,
        !          1070:                            ((type, None), signature), 1)
        !          1071:                    self.index_add(name, self.filename, not self.is_header,
        !          1072:                                    "functype", d)
        !          1073:                else:
        !          1074:                    if base_type == "struct":
        !          1075:                        self.index_add(name, self.filename, not self.is_header,
        !          1076:                                        "struct", type)
        !          1077:                        base_type = "struct " + name
        !          1078:                    else:
        !          1079:                        # TODO report missing or misformatted comments
        !          1080:                        info = self.parseTypeComment(name, 1)
        !          1081:                        self.index_add(name, self.filename, not self.is_header,
        !          1082:                                    "typedef", type, info)
        !          1083:                token = self.token()
        !          1084:            else:
        !          1085:                self.error("parsing typedef: expecting a name")
        !          1086:                return token
        !          1087:             #self.debug("end typedef", token)
        !          1088:            if token != None and token[0] == 'sep' and token[1] == ',':
        !          1089:                type = base_type
        !          1090:                token = self.token()
        !          1091:                while token != None and token[0] == "op":
        !          1092:                    type = type + token[1]
        !          1093:                    token = self.token()
        !          1094:            elif token != None and token[0] == 'sep' and token[1] == ';':
        !          1095:                break;
        !          1096:            elif token != None and token[0] == 'name':
        !          1097:                type = base_type
        !          1098:                continue;
        !          1099:            else:
        !          1100:                self.error("parsing typedef: expecting ';'", token)
        !          1101:                return token
        !          1102:        token = self.token()
        !          1103:        return token
        !          1104: 
        !          1105:      #
        !          1106:      # Parse a C code block, used for functions it parse till
        !          1107:      # the balancing } included
        !          1108:      #
        !          1109:     def parseBlock(self, token):
        !          1110:         while token != None:
        !          1111:            if token[0] == "sep" and token[1] == "{":
        !          1112:                token = self.token()
        !          1113:                token = self.parseBlock(token)
        !          1114:            elif token[0] == "sep" and token[1] == "}":
        !          1115:                self.comment = None
        !          1116:                token = self.token()
        !          1117:                return token
        !          1118:            else:
        !          1119:                if self.collect_ref == 1:
        !          1120:                    oldtok = token
        !          1121:                    token = self.token()
        !          1122:                    if oldtok[0] == "name" and oldtok[1][0:3] == "xml":
        !          1123:                        if token[0] == "sep" and token[1] == "(":
        !          1124:                            self.index_add_ref(oldtok[1], self.filename,
        !          1125:                                                0, "function")
        !          1126:                            token = self.token()
        !          1127:                        elif token[0] == "name":
        !          1128:                            token = self.token()
        !          1129:                            if token[0] == "sep" and (token[1] == ";" or
        !          1130:                               token[1] == "," or token[1] == "="):
        !          1131:                                self.index_add_ref(oldtok[1], self.filename,
        !          1132:                                                    0, "type")
        !          1133:                    elif oldtok[0] == "name" and oldtok[1][0:4] == "XML_":
        !          1134:                        self.index_add_ref(oldtok[1], self.filename,
        !          1135:                                            0, "typedef")
        !          1136:                    elif oldtok[0] == "name" and oldtok[1][0:7] == "LIBXML_":
        !          1137:                        self.index_add_ref(oldtok[1], self.filename,
        !          1138:                                            0, "typedef")
        !          1139: 
        !          1140:                else:
        !          1141:                    token = self.token()
        !          1142:        return token
        !          1143: 
        !          1144:      #
        !          1145:      # Parse a C struct definition till the balancing }
        !          1146:      #
        !          1147:     def parseStruct(self, token):
        !          1148:         fields = []
        !          1149:         #self.debug("start parseStruct", token)
        !          1150:         while token != None:
        !          1151:            if token[0] == "sep" and token[1] == "{":
        !          1152:                token = self.token()
        !          1153:                token = self.parseTypeBlock(token)
        !          1154:            elif token[0] == "sep" and token[1] == "}":
        !          1155:                self.struct_fields = fields
        !          1156:                 #self.debug("end parseStruct", token)
        !          1157:                 #print fields
        !          1158:                token = self.token()
        !          1159:                return token
        !          1160:            else:
        !          1161:                base_type = self.type
        !          1162:                 #self.debug("before parseType", token)
        !          1163:                token = self.parseType(token)
        !          1164:                 #self.debug("after parseType", token)
        !          1165:                if token != None and token[0] == "name":
        !          1166:                    fname = token[1]
        !          1167:                    token = self.token()
        !          1168:                    if token[0] == "sep" and token[1] == ";":
        !          1169:                        self.comment = None
        !          1170:                        token = self.token()
        !          1171:                        fields.append((self.type, fname, self.comment))
        !          1172:                        self.comment = None
        !          1173:                    else:
        !          1174:                        self.error("parseStruct: expecting ;", token)
        !          1175:                elif token != None and token[0] == "sep" and token[1] == "{":
        !          1176:                    token = self.token()
        !          1177:                    token = self.parseTypeBlock(token)
        !          1178:                    if token != None and token[0] == "name":
        !          1179:                        token = self.token()
        !          1180:                    if token != None and token[0] == "sep" and token[1] == ";":
        !          1181:                        token = self.token()
        !          1182:                    else:
        !          1183:                        self.error("parseStruct: expecting ;", token)
        !          1184:                else:
        !          1185:                    self.error("parseStruct: name", token)
        !          1186:                    token = self.token()
        !          1187:                self.type = base_type;
        !          1188:         self.struct_fields = fields
        !          1189:         #self.debug("end parseStruct", token)
        !          1190:         #print fields
        !          1191:        return token
        !          1192: 
        !          1193:      #
        !          1194:      # Parse a C enum block, parse till the balancing }
        !          1195:      #
        !          1196:     def parseEnumBlock(self, token):
        !          1197:         self.enums = []
        !          1198:        name = None
        !          1199:        self.comment = None
        !          1200:        comment = ""
        !          1201:        value = "0"
        !          1202:         while token != None:
        !          1203:            if token[0] == "sep" and token[1] == "{":
        !          1204:                token = self.token()
        !          1205:                token = self.parseTypeBlock(token)
        !          1206:            elif token[0] == "sep" and token[1] == "}":
        !          1207:                if name != None:
        !          1208:                    if self.comment != None:
        !          1209:                        comment = self.comment
        !          1210:                        self.comment = None
        !          1211:                    self.enums.append((name, value, comment))
        !          1212:                token = self.token()
        !          1213:                return token
        !          1214:            elif token[0] == "name":
        !          1215:                    if name != None:
        !          1216:                        if self.comment != None:
        !          1217:                            comment = string.strip(self.comment)
        !          1218:                            self.comment = None
        !          1219:                        self.enums.append((name, value, comment))
        !          1220:                    name = token[1]
        !          1221:                    comment = ""
        !          1222:                    token = self.token()
        !          1223:                    if token[0] == "op" and token[1][0] == "=":
        !          1224:                        value = ""
        !          1225:                        if len(token[1]) > 1:
        !          1226:                            value = token[1][1:]
        !          1227:                        token = self.token()
        !          1228:                        while token[0] != "sep" or (token[1] != ',' and
        !          1229:                              token[1] != '}'):
        !          1230:                            value = value + token[1]
        !          1231:                            token = self.token()
        !          1232:                    else:
        !          1233:                        try:
        !          1234:                            value = "%d" % (int(value) + 1)
        !          1235:                        except:
        !          1236:                            self.warning("Failed to compute value of enum %s" % (name))
        !          1237:                            value=""
        !          1238:                    if token[0] == "sep" and token[1] == ",":
        !          1239:                        token = self.token()
        !          1240:            else:
        !          1241:                token = self.token()
        !          1242:        return token
        !          1243: 
        !          1244:      #
        !          1245:      # Parse a C definition block, used for structs it parse till
        !          1246:      # the balancing }
        !          1247:      #
        !          1248:     def parseTypeBlock(self, token):
        !          1249:         while token != None:
        !          1250:            if token[0] == "sep" and token[1] == "{":
        !          1251:                token = self.token()
        !          1252:                token = self.parseTypeBlock(token)
        !          1253:            elif token[0] == "sep" and token[1] == "}":
        !          1254:                token = self.token()
        !          1255:                return token
        !          1256:            else:
        !          1257:                token = self.token()
        !          1258:        return token
        !          1259: 
        !          1260:      #
        !          1261:      # Parse a type: the fact that the type name can either occur after
        !          1262:      #    the definition or within the definition makes it a little harder
        !          1263:      #    if inside, the name token is pushed back before returning
        !          1264:      #
        !          1265:     def parseType(self, token):
        !          1266:         self.type = ""
        !          1267:        self.struct_fields = []
        !          1268:         self.signature = None
        !          1269:        if token == None:
        !          1270:            return token
        !          1271: 
        !          1272:        while token[0] == "name" and (
        !          1273:              token[1] == "const" or \
        !          1274:              token[1] == "unsigned" or \
        !          1275:              token[1] == "signed"):
        !          1276:            if self.type == "":
        !          1277:                self.type = token[1]
        !          1278:            else:
        !          1279:                self.type = self.type + " " + token[1]
        !          1280:            token = self.token()
        !          1281: 
        !          1282:         if token[0] == "name" and (token[1] == "long" or token[1] == "short"):
        !          1283:            if self.type == "":
        !          1284:                self.type = token[1]
        !          1285:            else:
        !          1286:                self.type = self.type + " " + token[1]
        !          1287:            if token[0] == "name" and token[1] == "int":
        !          1288:                if self.type == "":
        !          1289:                    self.type = tmp[1]
        !          1290:                else:
        !          1291:                    self.type = self.type + " " + tmp[1]
        !          1292: 
        !          1293:         elif token[0] == "name" and token[1] == "struct":
        !          1294:            if self.type == "":
        !          1295:                self.type = token[1]
        !          1296:            else:
        !          1297:                self.type = self.type + " " + token[1]
        !          1298:            token = self.token()
        !          1299:            nametok = None
        !          1300:            if token[0] == "name":
        !          1301:                nametok = token
        !          1302:                token = self.token()
        !          1303:            if token != None and token[0] == "sep" and token[1] == "{":
        !          1304:                token = self.token()
        !          1305:                token = self.parseStruct(token)
        !          1306:            elif token != None and token[0] == "op" and token[1] == "*":
        !          1307:                self.type = self.type + " " + nametok[1] + " *"
        !          1308:                token = self.token()
        !          1309:                while token != None and token[0] == "op" and token[1] == "*":
        !          1310:                    self.type = self.type + " *"
        !          1311:                    token = self.token()
        !          1312:                if token[0] == "name":
        !          1313:                    nametok = token
        !          1314:                    token = self.token()
        !          1315:                else:
        !          1316:                    self.error("struct : expecting name", token)
        !          1317:                    return token
        !          1318:            elif token != None and token[0] == "name" and nametok != None:
        !          1319:                self.type = self.type + " " + nametok[1]
        !          1320:                return token
        !          1321: 
        !          1322:            if nametok != None:
        !          1323:                self.lexer.push(token)
        !          1324:                token = nametok
        !          1325:            return token
        !          1326: 
        !          1327:         elif token[0] == "name" and token[1] == "enum":
        !          1328:            if self.type == "":
        !          1329:                self.type = token[1]
        !          1330:            else:
        !          1331:                self.type = self.type + " " + token[1]
        !          1332:            self.enums = []
        !          1333:            token = self.token()
        !          1334:            if token != None and token[0] == "sep" and token[1] == "{":
        !          1335:                token = self.token()
        !          1336:                token = self.parseEnumBlock(token)
        !          1337:            else:
        !          1338:                self.error("parsing enum: expecting '{'", token)
        !          1339:            enum_type = None
        !          1340:            if token != None and token[0] != "name":
        !          1341:                self.lexer.push(token)
        !          1342:                token = ("name", "enum")
        !          1343:            else:
        !          1344:                enum_type = token[1]
        !          1345:            for enum in self.enums:
        !          1346:                self.index_add(enum[0], self.filename,
        !          1347:                               not self.is_header, "enum",
        !          1348:                               (enum[1], enum[2], enum_type))
        !          1349:            return token
        !          1350: 
        !          1351:        elif token[0] == "name":
        !          1352:            if self.type == "":
        !          1353:                self.type = token[1]
        !          1354:            else:
        !          1355:                self.type = self.type + " " + token[1]
        !          1356:        else:
        !          1357:            self.error("parsing type %s: expecting a name" % (self.type),
        !          1358:                       token)
        !          1359:            return token
        !          1360:        token = self.token()
        !          1361:         while token != None and (token[0] == "op" or
        !          1362:              token[0] == "name" and token[1] == "const"):
        !          1363:            self.type = self.type + " " + token[1]
        !          1364:            token = self.token()
        !          1365: 
        !          1366:         #
        !          1367:         # if there is a parenthesis here, this means a function type
        !          1368:         #
        !          1369:        if token != None and token[0] == "sep" and token[1] == '(':
        !          1370:            self.type = self.type + token[1]
        !          1371:            token = self.token()
        !          1372:            while token != None and token[0] == "op" and token[1] == '*':
        !          1373:                self.type = self.type + token[1]
        !          1374:                token = self.token()
        !          1375:            if token == None or token[0] != "name" :
        !          1376:                self.error("parsing function type, name expected", token);
        !          1377:                return token
        !          1378:            self.type = self.type + token[1]
        !          1379:            nametok = token
        !          1380:            token = self.token()
        !          1381:            if token != None and token[0] == "sep" and token[1] == ')':
        !          1382:                self.type = self.type + token[1]
        !          1383:                token = self.token()
        !          1384:                if token != None and token[0] == "sep" and token[1] == '(':
        !          1385:                    token = self.token()
        !          1386:                    type = self.type;
        !          1387:                    token = self.parseSignature(token);
        !          1388:                    self.type = type;
        !          1389:                else:
        !          1390:                    self.error("parsing function type, '(' expected", token);
        !          1391:                    return token
        !          1392:            else:
        !          1393:                self.error("parsing function type, ')' expected", token);
        !          1394:                return token
        !          1395:            self.lexer.push(token)
        !          1396:            token = nametok
        !          1397:            return token
        !          1398: 
        !          1399:          #
        !          1400:         # do some lookahead for arrays
        !          1401:         #
        !          1402:        if token != None and token[0] == "name":
        !          1403:            nametok = token
        !          1404:            token = self.token()
        !          1405:            if token != None and token[0] == "sep" and token[1] == '[':
        !          1406:                self.type = self.type + nametok[1]
        !          1407:                while token != None and token[0] == "sep" and token[1] == '[':
        !          1408:                    self.type = self.type + token[1]
        !          1409:                    token = self.token()
        !          1410:                    while token != None and token[0] != 'sep' and \
        !          1411:                          token[1] != ']' and token[1] != ';':
        !          1412:                        self.type = self.type + token[1]
        !          1413:                        token = self.token()
        !          1414:                if token != None and token[0] == 'sep' and token[1] == ']':
        !          1415:                    self.type = self.type + token[1]
        !          1416:                    token = self.token()
        !          1417:                else:
        !          1418:                    self.error("parsing array type, ']' expected", token);
        !          1419:                    return token
        !          1420:            elif token != None and token[0] == "sep" and token[1] == ':':
        !          1421:                 # remove :12 in case it's a limited int size
        !          1422:                token = self.token()
        !          1423:                token = self.token()
        !          1424:            self.lexer.push(token)
        !          1425:            token = nametok
        !          1426: 
        !          1427:        return token
        !          1428: 
        !          1429:      #
        !          1430:      # Parse a signature: '(' has been parsed and we scan the type definition
        !          1431:      #    up to the ')' included
        !          1432:     def parseSignature(self, token):
        !          1433:         signature = []
        !          1434:        if token != None and token[0] == "sep" and token[1] == ')':
        !          1435:            self.signature = []
        !          1436:            token = self.token()
        !          1437:            return token
        !          1438:        while token != None:
        !          1439:            token = self.parseType(token)
        !          1440:            if token != None and token[0] == "name":
        !          1441:                signature.append((self.type, token[1], None))
        !          1442:                token = self.token()
        !          1443:            elif token != None and token[0] == "sep" and token[1] == ',':
        !          1444:                token = self.token()
        !          1445:                continue
        !          1446:            elif token != None and token[0] == "sep" and token[1] == ')':
        !          1447:                 # only the type was provided
        !          1448:                if self.type == "...":
        !          1449:                    signature.append((self.type, "...", None))
        !          1450:                else:
        !          1451:                    signature.append((self.type, None, None))
        !          1452:            if token != None and token[0] == "sep":
        !          1453:                if token[1] == ',':
        !          1454:                    token = self.token()
        !          1455:                    continue
        !          1456:                elif token[1] == ')':
        !          1457:                    token = self.token()
        !          1458:                    break
        !          1459:        self.signature = signature
        !          1460:        return token
        !          1461: 
        !          1462:      #
        !          1463:      # Parse a global definition, be it a type, variable or function
        !          1464:      # the extern "C" blocks are a bit nasty and require it to recurse.
        !          1465:      #
        !          1466:     def parseGlobal(self, token):
        !          1467:         static = 0
        !          1468:         if token[1] == 'extern':
        !          1469:            token = self.token()
        !          1470:            if token == None:
        !          1471:                return token
        !          1472:            if token[0] == 'string':
        !          1473:                if token[1] == 'C':
        !          1474:                    token = self.token()
        !          1475:                    if token == None:
        !          1476:                        return token
        !          1477:                    if token[0] == 'sep' and token[1] == "{":
        !          1478:                        token = self.token()
        !          1479: #                       print 'Entering extern "C line ', self.lineno()
        !          1480:                        while token != None and (token[0] != 'sep' or
        !          1481:                              token[1] != "}"):
        !          1482:                            if token[0] == 'name':
        !          1483:                                token = self.parseGlobal(token)
        !          1484:                            else:
        !          1485:                                self.error(
        !          1486:                                 "token %s %s unexpected at the top level" % (
        !          1487:                                        token[0], token[1]))
        !          1488:                                token = self.parseGlobal(token)
        !          1489: #                       print 'Exiting extern "C" line', self.lineno()
        !          1490:                        token = self.token()
        !          1491:                        return token
        !          1492:                else:
        !          1493:                    return token
        !          1494:        elif token[1] == 'static':
        !          1495:            static = 1
        !          1496:            token = self.token()
        !          1497:            if token == None or  token[0] != 'name':
        !          1498:                return token
        !          1499: 
        !          1500:        if token[1] == 'typedef':
        !          1501:            token = self.token()
        !          1502:            return self.parseTypedef(token)
        !          1503:        else:
        !          1504:            token = self.parseType(token)
        !          1505:            type_orig = self.type
        !          1506:        if token == None or token[0] != "name":
        !          1507:            return token
        !          1508:        type = type_orig
        !          1509:        self.name = token[1]
        !          1510:        token = self.token()
        !          1511:        while token != None and (token[0] == "sep" or token[0] == "op"):
        !          1512:            if token[0] == "sep":
        !          1513:                if token[1] == "[":
        !          1514:                    type = type + token[1]
        !          1515:                    token = self.token()
        !          1516:                    while token != None and (token[0] != "sep" or \
        !          1517:                          token[1] != ";"):
        !          1518:                        type = type + token[1]
        !          1519:                        token = self.token()
        !          1520: 
        !          1521:            if token != None and token[0] == "op" and token[1] == "=":
        !          1522:                 #
        !          1523:                 # Skip the initialization of the variable
        !          1524:                 #
        !          1525:                token = self.token()
        !          1526:                if token[0] == 'sep' and token[1] == '{':
        !          1527:                    token = self.token()
        !          1528:                    token = self.parseBlock(token)
        !          1529:                else:
        !          1530:                    self.comment = None
        !          1531:                    while token != None and (token[0] != "sep" or \
        !          1532:                          (token[1] != ';' and token[1] != ',')):
        !          1533:                            token = self.token()
        !          1534:                self.comment = None
        !          1535:                if token == None or token[0] != "sep" or (token[1] != ';' and
        !          1536:                   token[1] != ','):
        !          1537:                    self.error("missing ';' or ',' after value")
        !          1538: 
        !          1539:            if token != None and token[0] == "sep":
        !          1540:                if token[1] == ";":
        !          1541:                    self.comment = None
        !          1542:                    token = self.token()
        !          1543:                    if type == "struct":
        !          1544:                        self.index_add(self.name, self.filename,
        !          1545:                             not self.is_header, "struct", self.struct_fields)
        !          1546:                    else:
        !          1547:                        self.index_add(self.name, self.filename,
        !          1548:                             not self.is_header, "variable", type)
        !          1549:                    break
        !          1550:                elif token[1] == "(":
        !          1551:                    token = self.token()
        !          1552:                    token = self.parseSignature(token)
        !          1553:                    if token == None:
        !          1554:                        return None
        !          1555:                    if token[0] == "sep" and token[1] == ";":
        !          1556:                        d = self.mergeFunctionComment(self.name,
        !          1557:                                ((type, None), self.signature), 1)
        !          1558:                        self.index_add(self.name, self.filename, static,
        !          1559:                                        "function", d)
        !          1560:                        token = self.token()
        !          1561:                    elif token[0] == "sep" and token[1] == "{":
        !          1562:                        d = self.mergeFunctionComment(self.name,
        !          1563:                                ((type, None), self.signature), static)
        !          1564:                        self.index_add(self.name, self.filename, static,
        !          1565:                                        "function", d)
        !          1566:                        token = self.token()
        !          1567:                        token = self.parseBlock(token);
        !          1568:                elif token[1] == ',':
        !          1569:                    self.comment = None
        !          1570:                    self.index_add(self.name, self.filename, static,
        !          1571:                                    "variable", type)
        !          1572:                    type = type_orig
        !          1573:                    token = self.token()
        !          1574:                    while token != None and token[0] == "sep":
        !          1575:                        type = type + token[1]
        !          1576:                        token = self.token()
        !          1577:                    if token != None and token[0] == "name":
        !          1578:                        self.name = token[1]
        !          1579:                        token = self.token()
        !          1580:                else:
        !          1581:                    break
        !          1582: 
        !          1583:        return token
        !          1584: 
        !          1585:     def parse(self):
        !          1586:         self.warning("Parsing %s" % (self.filename))
        !          1587:         token = self.token()
        !          1588:        while token != None:
        !          1589:             if token[0] == 'name':
        !          1590:                token = self.parseGlobal(token)
        !          1591:             else:
        !          1592:                self.error("token %s %s unexpected at the top level" % (
        !          1593:                       token[0], token[1]))
        !          1594:                token = self.parseGlobal(token)
        !          1595:                return
        !          1596:        self.parseTopComment(self.top_comment)
        !          1597:         return self.index
        !          1598: 
        !          1599: 
        !          1600: class docBuilder:
        !          1601:     """A documentation builder"""
        !          1602:     def __init__(self, name, directories=['.'], excludes=[]):
        !          1603:         self.name = name
        !          1604:         self.directories = directories
        !          1605:        self.excludes = excludes + ignored_files.keys()
        !          1606:        self.modules = {}
        !          1607:        self.headers = {}
        !          1608:        self.idx = index()
        !          1609:         self.xref = {}
        !          1610:        self.index = {}
        !          1611:        if name == 'libxml2':
        !          1612:            self.basename = 'libxml'
        !          1613:        else:
        !          1614:            self.basename = name
        !          1615: 
        !          1616:     def indexString(self, id, str):
        !          1617:        if str == None:
        !          1618:            return
        !          1619:        str = string.replace(str, "'", ' ')
        !          1620:        str = string.replace(str, '"', ' ')
        !          1621:        str = string.replace(str, "/", ' ')
        !          1622:        str = string.replace(str, '*', ' ')
        !          1623:        str = string.replace(str, "[", ' ')
        !          1624:        str = string.replace(str, "]", ' ')
        !          1625:        str = string.replace(str, "(", ' ')
        !          1626:        str = string.replace(str, ")", ' ')
        !          1627:        str = string.replace(str, "<", ' ')
        !          1628:        str = string.replace(str, '>', ' ')
        !          1629:        str = string.replace(str, "&", ' ')
        !          1630:        str = string.replace(str, '#', ' ')
        !          1631:        str = string.replace(str, ",", ' ')
        !          1632:        str = string.replace(str, '.', ' ')
        !          1633:        str = string.replace(str, ';', ' ')
        !          1634:        tokens = string.split(str)
        !          1635:        for token in tokens:
        !          1636:            try:
        !          1637:                c = token[0]
        !          1638:                if string.find(string.letters, c) < 0:
        !          1639:                    pass
        !          1640:                elif len(token) < 3:
        !          1641:                    pass
        !          1642:                else:
        !          1643:                    lower = string.lower(token)
        !          1644:                    # TODO: generalize this a bit
        !          1645:                    if lower == 'and' or lower == 'the':
        !          1646:                        pass
        !          1647:                    elif self.xref.has_key(token):
        !          1648:                        self.xref[token].append(id)
        !          1649:                    else:
        !          1650:                        self.xref[token] = [id]
        !          1651:            except:
        !          1652:                pass
        !          1653: 
        !          1654:     def analyze(self):
        !          1655:         print "Project %s : %d headers, %d modules" % (self.name, len(self.headers.keys()), len(self.modules.keys()))
        !          1656:        self.idx.analyze()
        !          1657: 
        !          1658:     def scanHeaders(self):
        !          1659:        for header in self.headers.keys():
        !          1660:            parser = CParser(header)
        !          1661:            idx = parser.parse()
        !          1662:            self.headers[header] = idx;
        !          1663:            self.idx.merge(idx)
        !          1664: 
        !          1665:     def scanModules(self):
        !          1666:        for module in self.modules.keys():
        !          1667:            parser = CParser(module)
        !          1668:            idx = parser.parse()
        !          1669:            # idx.analyze()
        !          1670:            self.modules[module] = idx
        !          1671:            self.idx.merge_public(idx)
        !          1672: 
        !          1673:     def scan(self):
        !          1674:         for directory in self.directories:
        !          1675:            files = glob.glob(directory + "/*.c")
        !          1676:            for file in files:
        !          1677:                skip = 0
        !          1678:                for excl in self.excludes:
        !          1679:                    if string.find(file, excl) != -1:
        !          1680:                        skip = 1;
        !          1681:                        break
        !          1682:                if skip == 0:
        !          1683:                    self.modules[file] = None;
        !          1684:            files = glob.glob(directory + "/*.h")
        !          1685:            for file in files:
        !          1686:                skip = 0
        !          1687:                for excl in self.excludes:
        !          1688:                    if string.find(file, excl) != -1:
        !          1689:                        skip = 1;
        !          1690:                        break
        !          1691:                if skip == 0:
        !          1692:                    self.headers[file] = None;
        !          1693:        self.scanHeaders()
        !          1694:        self.scanModules()
        !          1695: 
        !          1696:     def modulename_file(self, file):
        !          1697:         module = os.path.basename(file)
        !          1698:        if module[-2:] == '.h':
        !          1699:            module = module[:-2]
        !          1700:        elif module[-2:] == '.c':
        !          1701:            module = module[:-2]
        !          1702:        return module
        !          1703: 
        !          1704:     def serialize_enum(self, output, name):
        !          1705:         id = self.idx.enums[name]
        !          1706:         output.write("    <enum name='%s' file='%s'" % (name,
        !          1707:                     self.modulename_file(id.header)))
        !          1708:        if id.info != None:
        !          1709:            info = id.info
        !          1710:            if info[0] != None and info[0] != '':
        !          1711:                try:
        !          1712:                    val = eval(info[0])
        !          1713:                except:
        !          1714:                    val = info[0]
        !          1715:                output.write(" value='%s'" % (val));
        !          1716:            if info[2] != None and info[2] != '':
        !          1717:                output.write(" type='%s'" % info[2]);
        !          1718:            if info[1] != None and info[1] != '':
        !          1719:                output.write(" info='%s'" % escape(info[1]));
        !          1720:         output.write("/>\n")
        !          1721: 
        !          1722:     def serialize_macro(self, output, name):
        !          1723:         id = self.idx.macros[name]
        !          1724:         output.write("    <macro name='%s' file='%s'>\n" % (name,
        !          1725:                     self.modulename_file(id.header)))
        !          1726:        if id.info != None:
        !          1727:             try:
        !          1728:                (args, desc) = id.info
        !          1729:                if desc != None and desc != "":
        !          1730:                    output.write("      <info>%s</info>\n" % (escape(desc)))
        !          1731:                    self.indexString(name, desc)
        !          1732:                for arg in args:
        !          1733:                    (name, desc) = arg
        !          1734:                    if desc != None and desc != "":
        !          1735:                        output.write("      <arg name='%s' info='%s'/>\n" % (
        !          1736:                                     name, escape(desc)))
        !          1737:                        self.indexString(name, desc)
        !          1738:                    else:
        !          1739:                        output.write("      <arg name='%s'/>\n" % (name))
        !          1740:             except:
        !          1741:                 pass
        !          1742:         output.write("    </macro>\n")
        !          1743: 
        !          1744:     def serialize_typedef(self, output, name):
        !          1745:         id = self.idx.typedefs[name]
        !          1746:        if id.info[0:7] == 'struct ':
        !          1747:            output.write("    <struct name='%s' file='%s' type='%s'" % (
        !          1748:                     name, self.modulename_file(id.header), id.info))
        !          1749:            name = id.info[7:]
        !          1750:            if self.idx.structs.has_key(name) and ( \
        !          1751:               type(self.idx.structs[name].info) == type(()) or
        !          1752:                type(self.idx.structs[name].info) == type([])):
        !          1753:                output.write(">\n");
        !          1754:                try:
        !          1755:                    for field in self.idx.structs[name].info:
        !          1756:                        desc = field[2]
        !          1757:                        self.indexString(name, desc)
        !          1758:                        if desc == None:
        !          1759:                            desc = ''
        !          1760:                        else:
        !          1761:                            desc = escape(desc)
        !          1762:                        output.write("      <field name='%s' type='%s' info='%s'/>\n" % (field[1] , field[0], desc))
        !          1763:                except:
        !          1764:                    print "Failed to serialize struct %s" % (name)
        !          1765:                output.write("    </struct>\n")
        !          1766:            else:
        !          1767:                output.write("/>\n");
        !          1768:        else :
        !          1769:            output.write("    <typedef name='%s' file='%s' type='%s'" % (
        !          1770:                         name, self.modulename_file(id.header), id.info))
        !          1771:             try:
        !          1772:                desc = id.extra
        !          1773:                if desc != None and desc != "":
        !          1774:                    output.write(">\n      <info>%s</info>\n" % (escape(desc)))
        !          1775:                    output.write("    </typedef>\n")
        !          1776:                else:
        !          1777:                    output.write("/>\n")
        !          1778:            except:
        !          1779:                output.write("/>\n")
        !          1780: 
        !          1781:     def serialize_variable(self, output, name):
        !          1782:         id = self.idx.variables[name]
        !          1783:        if id.info != None:
        !          1784:            output.write("    <variable name='%s' file='%s' type='%s'/>\n" % (
        !          1785:                    name, self.modulename_file(id.header), id.info))
        !          1786:        else:
        !          1787:            output.write("    <variable name='%s' file='%s'/>\n" % (
        !          1788:                    name, self.modulename_file(id.header)))
        !          1789: 
        !          1790:     def serialize_function(self, output, name):
        !          1791:         id = self.idx.functions[name]
        !          1792:        if name == debugsym:
        !          1793:            print "=>", id
        !          1794: 
        !          1795:         output.write("    <%s name='%s' file='%s' module='%s'>\n" % (id.type,
        !          1796:                     name, self.modulename_file(id.header),
        !          1797:                     self.modulename_file(id.module)))
        !          1798:        #
        !          1799:        # Processing of conditionals modified by Bill 1/1/05
        !          1800:        #
        !          1801:        if id.conditionals != None:
        !          1802:            apstr = ""
        !          1803:            for cond in id.conditionals:
        !          1804:                if apstr != "":
        !          1805:                    apstr = apstr + " &amp;&amp; "
        !          1806:                apstr = apstr + cond
        !          1807:            output.write("      <cond>%s</cond>\n"% (apstr));
        !          1808:        try:
        !          1809:            (ret, params, desc) = id.info
        !          1810:            if (desc == None or desc == '') and \
        !          1811:               name[0:9] != "xmlThrDef" and name != "xmlDllMain":
        !          1812:                print "%s %s from %s has no description" % (id.type, name,
        !          1813:                       self.modulename_file(id.module))
        !          1814: 
        !          1815:            output.write("      <info>%s</info>\n" % (escape(desc)))
        !          1816:            self.indexString(name, desc)
        !          1817:            if ret[0] != None:
        !          1818:                if ret[0] == "void":
        !          1819:                    output.write("      <return type='void'/>\n")
        !          1820:                else:
        !          1821:                    output.write("      <return type='%s' info='%s'/>\n" % (
        !          1822:                             ret[0], escape(ret[1])))
        !          1823:                    self.indexString(name, ret[1])
        !          1824:            for param in params:
        !          1825:                if param[0] == 'void':
        !          1826:                    continue
        !          1827:                if param[2] == None:
        !          1828:                    output.write("      <arg name='%s' type='%s' info=''/>\n" % (param[1], param[0]))
        !          1829:                else:
        !          1830:                    output.write("      <arg name='%s' type='%s' info='%s'/>\n" % (param[1], param[0], escape(param[2])))
        !          1831:                    self.indexString(name, param[2])
        !          1832:        except:
        !          1833:            print "Failed to save function %s info: " % name, `id.info`
        !          1834:         output.write("    </%s>\n" % (id.type))
        !          1835: 
        !          1836:     def serialize_exports(self, output, file):
        !          1837:         module = self.modulename_file(file)
        !          1838:        output.write("    <file name='%s'>\n" % (module))
        !          1839:        dict = self.headers[file]
        !          1840:        if dict.info != None:
        !          1841:            for data in ('Summary', 'Description', 'Author'):
        !          1842:                try:
        !          1843:                    output.write("     <%s>%s</%s>\n" % (
        !          1844:                                 string.lower(data),
        !          1845:                                 escape(dict.info[data]),
        !          1846:                                 string.lower(data)))
        !          1847:                except:
        !          1848:                    print "Header %s lacks a %s description" % (module, data)
        !          1849:            if dict.info.has_key('Description'):
        !          1850:                desc = dict.info['Description']
        !          1851:                if string.find(desc, "DEPRECATED") != -1:
        !          1852:                    output.write("     <deprecated/>\n")
        !          1853: 
        !          1854:         ids = dict.macros.keys()
        !          1855:        ids.sort()
        !          1856:        for id in uniq(ids):
        !          1857:            # Macros are sometime used to masquerade other types.
        !          1858:            if dict.functions.has_key(id):
        !          1859:                continue
        !          1860:            if dict.variables.has_key(id):
        !          1861:                continue
        !          1862:            if dict.typedefs.has_key(id):
        !          1863:                continue
        !          1864:            if dict.structs.has_key(id):
        !          1865:                continue
        !          1866:            if dict.enums.has_key(id):
        !          1867:                continue
        !          1868:            output.write("     <exports symbol='%s' type='macro'/>\n" % (id))
        !          1869:         ids = dict.enums.keys()
        !          1870:        ids.sort()
        !          1871:        for id in uniq(ids):
        !          1872:            output.write("     <exports symbol='%s' type='enum'/>\n" % (id))
        !          1873:         ids = dict.typedefs.keys()
        !          1874:        ids.sort()
        !          1875:        for id in uniq(ids):
        !          1876:            output.write("     <exports symbol='%s' type='typedef'/>\n" % (id))
        !          1877:         ids = dict.structs.keys()
        !          1878:        ids.sort()
        !          1879:        for id in uniq(ids):
        !          1880:            output.write("     <exports symbol='%s' type='struct'/>\n" % (id))
        !          1881:         ids = dict.variables.keys()
        !          1882:        ids.sort()
        !          1883:        for id in uniq(ids):
        !          1884:            output.write("     <exports symbol='%s' type='variable'/>\n" % (id))
        !          1885:         ids = dict.functions.keys()
        !          1886:        ids.sort()
        !          1887:        for id in uniq(ids):
        !          1888:            output.write("     <exports symbol='%s' type='function'/>\n" % (id))
        !          1889:        output.write("    </file>\n")
        !          1890: 
        !          1891:     def serialize_xrefs_files(self, output):
        !          1892:         headers = self.headers.keys()
        !          1893:         headers.sort()
        !          1894:         for file in headers:
        !          1895:            module = self.modulename_file(file)
        !          1896:            output.write("    <file name='%s'>\n" % (module))
        !          1897:            dict = self.headers[file]
        !          1898:            ids = uniq(dict.functions.keys() + dict.variables.keys() + \
        !          1899:                  dict.macros.keys() + dict.typedefs.keys() + \
        !          1900:                  dict.structs.keys() + dict.enums.keys())
        !          1901:            ids.sort()
        !          1902:            for id in ids:
        !          1903:                output.write("      <ref name='%s'/>\n" % (id))
        !          1904:            output.write("    </file>\n")
        !          1905:         pass
        !          1906: 
        !          1907:     def serialize_xrefs_functions(self, output):
        !          1908:         funcs = {}
        !          1909:        for name in self.idx.functions.keys():
        !          1910:            id = self.idx.functions[name]
        !          1911:            try:
        !          1912:                (ret, params, desc) = id.info
        !          1913:                for param in params:
        !          1914:                    if param[0] == 'void':
        !          1915:                        continue
        !          1916:                    if funcs.has_key(param[0]):
        !          1917:                        funcs[param[0]].append(name)
        !          1918:                    else:
        !          1919:                        funcs[param[0]] = [name]
        !          1920:            except:
        !          1921:                pass
        !          1922:        typ = funcs.keys()
        !          1923:        typ.sort()
        !          1924:        for type in typ:
        !          1925:            if type == '' or type == 'void' or type == "int" or \
        !          1926:               type == "char *" or type == "const char *" :
        !          1927:                continue
        !          1928:            output.write("    <type name='%s'>\n" % (type))
        !          1929:            ids = funcs[type]
        !          1930:            ids.sort()
        !          1931:            pid = ''    # not sure why we have dups, but get rid of them!
        !          1932:            for id in ids:
        !          1933:                if id != pid:
        !          1934:                    output.write("      <ref name='%s'/>\n" % (id))
        !          1935:                    pid = id
        !          1936:            output.write("    </type>\n")
        !          1937: 
        !          1938:     def serialize_xrefs_constructors(self, output):
        !          1939:         funcs = {}
        !          1940:        for name in self.idx.functions.keys():
        !          1941:            id = self.idx.functions[name]
        !          1942:            try:
        !          1943:                (ret, params, desc) = id.info
        !          1944:                if ret[0] == "void":
        !          1945:                    continue
        !          1946:                if funcs.has_key(ret[0]):
        !          1947:                    funcs[ret[0]].append(name)
        !          1948:                else:
        !          1949:                    funcs[ret[0]] = [name]
        !          1950:            except:
        !          1951:                pass
        !          1952:        typ = funcs.keys()
        !          1953:        typ.sort()
        !          1954:        for type in typ:
        !          1955:            if type == '' or type == 'void' or type == "int" or \
        !          1956:               type == "char *" or type == "const char *" :
        !          1957:                continue
        !          1958:            output.write("    <type name='%s'>\n" % (type))
        !          1959:            ids = funcs[type]
        !          1960:            ids.sort()
        !          1961:            for id in ids:
        !          1962:                output.write("      <ref name='%s'/>\n" % (id))
        !          1963:            output.write("    </type>\n")
        !          1964: 
        !          1965:     def serialize_xrefs_alpha(self, output):
        !          1966:        letter = None
        !          1967:        ids = self.idx.identifiers.keys()
        !          1968:        ids.sort()
        !          1969:        for id in ids:
        !          1970:            if id[0] != letter:
        !          1971:                if letter != None:
        !          1972:                    output.write("    </letter>\n")
        !          1973:                letter = id[0]
        !          1974:                output.write("    <letter name='%s'>\n" % (letter))
        !          1975:            output.write("      <ref name='%s'/>\n" % (id))
        !          1976:        if letter != None:
        !          1977:            output.write("    </letter>\n")
        !          1978: 
        !          1979:     def serialize_xrefs_references(self, output):
        !          1980:         typ = self.idx.identifiers.keys()
        !          1981:        typ.sort()
        !          1982:        for id in typ:
        !          1983:            idf = self.idx.identifiers[id]
        !          1984:            module = idf.header
        !          1985:            output.write("    <reference name='%s' href='%s'/>\n" % (id,
        !          1986:                         'html/' + self.basename + '-' +
        !          1987:                         self.modulename_file(module) + '.html#' +
        !          1988:                         id))
        !          1989: 
        !          1990:     def serialize_xrefs_index(self, output):
        !          1991:         index = self.xref
        !          1992:        typ = index.keys()
        !          1993:        typ.sort()
        !          1994:        letter = None
        !          1995:        count = 0
        !          1996:        chunk = 0
        !          1997:        chunks = []
        !          1998:        for id in typ:
        !          1999:            if len(index[id]) > 30:
        !          2000:                continue
        !          2001:            if id[0] != letter:
        !          2002:                if letter == None or count > 200:
        !          2003:                    if letter != None:
        !          2004:                        output.write("      </letter>\n")
        !          2005:                        output.write("    </chunk>\n")
        !          2006:                        count = 0
        !          2007:                        chunks.append(["chunk%s" % (chunk -1), first_letter, letter])
        !          2008:                    output.write("    <chunk name='chunk%s'>\n" % (chunk))
        !          2009:                    first_letter = id[0]
        !          2010:                    chunk = chunk + 1
        !          2011:                elif letter != None:
        !          2012:                    output.write("      </letter>\n")
        !          2013:                letter = id[0]
        !          2014:                output.write("      <letter name='%s'>\n" % (letter))
        !          2015:            output.write("        <word name='%s'>\n" % (id))
        !          2016:            tokens = index[id];
        !          2017:            tokens.sort()
        !          2018:            tok = None
        !          2019:            for token in tokens:
        !          2020:                if tok == token:
        !          2021:                    continue
        !          2022:                tok = token
        !          2023:                output.write("          <ref name='%s'/>\n" % (token))
        !          2024:                count = count + 1
        !          2025:            output.write("        </word>\n")
        !          2026:        if letter != None:
        !          2027:            output.write("      </letter>\n")
        !          2028:            output.write("    </chunk>\n")
        !          2029:            if count != 0:
        !          2030:                chunks.append(["chunk%s" % (chunk -1), first_letter, letter])
        !          2031:            output.write("    <chunks>\n")
        !          2032:            for ch in chunks:
        !          2033:                output.write("      <chunk name='%s' start='%s' end='%s'/>\n" % (
        !          2034:                             ch[0], ch[1], ch[2]))
        !          2035:            output.write("    </chunks>\n")
        !          2036: 
        !          2037:     def serialize_xrefs(self, output):
        !          2038:        output.write("  <references>\n")
        !          2039:        self.serialize_xrefs_references(output)
        !          2040:        output.write("  </references>\n")
        !          2041:        output.write("  <alpha>\n")
        !          2042:        self.serialize_xrefs_alpha(output)
        !          2043:        output.write("  </alpha>\n")
        !          2044:        output.write("  <constructors>\n")
        !          2045:        self.serialize_xrefs_constructors(output)
        !          2046:        output.write("  </constructors>\n")
        !          2047:        output.write("  <functions>\n")
        !          2048:        self.serialize_xrefs_functions(output)
        !          2049:        output.write("  </functions>\n")
        !          2050:        output.write("  <files>\n")
        !          2051:        self.serialize_xrefs_files(output)
        !          2052:        output.write("  </files>\n")
        !          2053:        output.write("  <index>\n")
        !          2054:        self.serialize_xrefs_index(output)
        !          2055:        output.write("  </index>\n")
        !          2056: 
        !          2057:     def serialize(self):
        !          2058:         filename = "%s-api.xml" % self.name
        !          2059:         print "Saving XML description %s" % (filename)
        !          2060:         output = open(filename, "w")
        !          2061:         output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
        !          2062:         output.write("<api name='%s'>\n" % self.name)
        !          2063:         output.write("  <files>\n")
        !          2064:         headers = self.headers.keys()
        !          2065:         headers.sort()
        !          2066:         for file in headers:
        !          2067:             self.serialize_exports(output, file)
        !          2068:         output.write("  </files>\n")
        !          2069:         output.write("  <symbols>\n")
        !          2070:         macros = self.idx.macros.keys()
        !          2071:         macros.sort()
        !          2072:         for macro in macros:
        !          2073:             self.serialize_macro(output, macro)
        !          2074:         enums = self.idx.enums.keys()
        !          2075:         enums.sort()
        !          2076:         for enum in enums:
        !          2077:             self.serialize_enum(output, enum)
        !          2078:         typedefs = self.idx.typedefs.keys()
        !          2079:         typedefs.sort()
        !          2080:         for typedef in typedefs:
        !          2081:             self.serialize_typedef(output, typedef)
        !          2082:         variables = self.idx.variables.keys()
        !          2083:         variables.sort()
        !          2084:         for variable in variables:
        !          2085:             self.serialize_variable(output, variable)
        !          2086:         functions = self.idx.functions.keys()
        !          2087:         functions.sort()
        !          2088:         for function in functions:
        !          2089:             self.serialize_function(output, function)
        !          2090:         output.write("  </symbols>\n")
        !          2091:         output.write("</api>\n")
        !          2092:         output.close()
        !          2093: 
        !          2094:         filename = "%s-refs.xml" % self.name
        !          2095:         print "Saving XML Cross References %s" % (filename)
        !          2096:         output = open(filename, "w")
        !          2097:         output.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
        !          2098:         output.write("<apirefs name='%s'>\n" % self.name)
        !          2099:         self.serialize_xrefs(output)
        !          2100:         output.write("</apirefs>\n")
        !          2101:         output.close()
        !          2102: 
        !          2103: 
        !          2104: def rebuild():
        !          2105:     builder = None
        !          2106:     if glob.glob("parser.c") != [] :
        !          2107:         print "Rebuilding API description for libxml2"
        !          2108:        builder = docBuilder("libxml2", [".", "."],
        !          2109:                             ["xmlwin32version.h", "tst.c"])
        !          2110:     elif glob.glob("../parser.c") != [] :
        !          2111:         print "Rebuilding API description for libxml2"
        !          2112:        builder = docBuilder("libxml2", ["..", "../include/libxml"],
        !          2113:                             ["xmlwin32version.h", "tst.c"])
        !          2114:     elif glob.glob("../libxslt/transform.c") != [] :
        !          2115:         print "Rebuilding API description for libxslt"
        !          2116:        builder = docBuilder("libxslt", ["../libxslt"],
        !          2117:                             ["win32config.h", "libxslt.h", "tst.c"])
        !          2118:     else:
        !          2119:         print "rebuild() failed, unable to guess the module"
        !          2120:        return None
        !          2121:     builder.scan()
        !          2122:     builder.analyze()
        !          2123:     builder.serialize()
        !          2124:     if glob.glob("../libexslt/exslt.c") != [] :
        !          2125:         extra = docBuilder("libexslt", ["../libexslt"], ["libexslt.h"])
        !          2126:        extra.scan()
        !          2127:        extra.analyze()
        !          2128:        extra.serialize()
        !          2129:     return builder
        !          2130: 
        !          2131: #
        !          2132: # for debugging the parser
        !          2133: #
        !          2134: def parse(filename):
        !          2135:     parser = CParser(filename)
        !          2136:     idx = parser.parse()
        !          2137:     return idx
        !          2138: 
        !          2139: if __name__ == "__main__":
        !          2140:     if len(sys.argv) > 1:
        !          2141:         debug = 1
        !          2142:         parse(sys.argv[1])
        !          2143:     else:
        !          2144:        rebuild()

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>