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

1.1     ! misho       1: #!/usr/bin/python -u
        !             2: #
        !             3: # imports the API description and fills up a database with
        !             4: # name relevance to modules, functions or web pages
        !             5: #
        !             6: # Operation needed:
        !             7: # =================
        !             8: #
        !             9: # install mysqld, the python wrappers for mysql and libxml2, start mysqld
        !            10: # Change the root passwd of mysql:
        !            11: #    mysqladmin -u root password new_password
        !            12: # Create the new database xmlsoft
        !            13: #    mysqladmin -p create xmlsoft
        !            14: # Create a database user 'veillard' and give him passord access
        !            15: # change veillard and abcde with the right user name and passwd
        !            16: #    mysql -p
        !            17: #    password:
        !            18: #    mysql> GRANT ALL PRIVILEGES ON xmlsoft TO veillard@localhost
        !            19: #           IDENTIFIED BY 'abcde' WITH GRANT OPTION;
        !            20: #
        !            21: # As the user check the access:
        !            22: #    mysql -p xmlsoft
        !            23: #    Enter password:
        !            24: #    Welcome to the MySQL monitor....
        !            25: #    mysql> use xmlsoft
        !            26: #    Database changed
        !            27: #    mysql> quit
        !            28: #    Bye
        !            29: #
        !            30: # Then run the script in the doc subdir, it will create the symbols and
        !            31: # word tables and populate them with informations extracted from 
        !            32: # the libxml2-api.xml API description, and make then accessible read-only
        !            33: # by nobody@loaclhost the user expected to be Apache's one
        !            34: #
        !            35: # On the Apache configuration, make sure you have php support enabled
        !            36: #
        !            37: 
        !            38: import MySQLdb
        !            39: import libxml2
        !            40: import sys
        !            41: import string
        !            42: import os
        !            43: 
        !            44: #
        !            45: # We are not interested in parsing errors here
        !            46: #
        !            47: def callback(ctx, str):
        !            48:     return
        !            49: libxml2.registerErrorHandler(callback, None)
        !            50: 
        !            51: #
        !            52: # The dictionnary of tables required and the SQL command needed
        !            53: # to create them
        !            54: #
        !            55: TABLES={
        !            56:   "symbols" : """CREATE TABLE symbols (
        !            57:            name varchar(255) BINARY NOT NULL,
        !            58:           module varchar(255) BINARY NOT NULL,
        !            59:            type varchar(25) NOT NULL,
        !            60:           descr varchar(255),
        !            61:           UNIQUE KEY name (name),
        !            62:           KEY module (module))""",
        !            63:   "words" : """CREATE TABLE words (
        !            64:            name varchar(50) BINARY NOT NULL,
        !            65:           symbol varchar(255) BINARY NOT NULL,
        !            66:            relevance int,
        !            67:           KEY name (name),
        !            68:           KEY symbol (symbol),
        !            69:           UNIQUE KEY ID (name, symbol))""",
        !            70:   "wordsHTML" : """CREATE TABLE wordsHTML (
        !            71:            name varchar(50) BINARY NOT NULL,
        !            72:           resource varchar(255) BINARY NOT NULL,
        !            73:           section varchar(255),
        !            74:           id varchar(50),
        !            75:            relevance int,
        !            76:           KEY name (name),
        !            77:           KEY resource (resource),
        !            78:           UNIQUE KEY ref (name, resource))""",
        !            79:   "wordsArchive" : """CREATE TABLE wordsArchive (
        !            80:            name varchar(50) BINARY NOT NULL,
        !            81:           ID int(11) NOT NULL,
        !            82:            relevance int,
        !            83:           KEY name (name),
        !            84:           UNIQUE KEY ref (name, ID))""",
        !            85:   "pages" : """CREATE TABLE pages (
        !            86:            resource varchar(255) BINARY NOT NULL,
        !            87:           title varchar(255) BINARY NOT NULL,
        !            88:           UNIQUE KEY name (resource))""",
        !            89:   "archives" : """CREATE TABLE archives (
        !            90:            ID int(11) NOT NULL auto_increment,
        !            91:            resource varchar(255) BINARY NOT NULL,
        !            92:           title varchar(255) BINARY NOT NULL,
        !            93:           UNIQUE KEY id (ID,resource(255)),
        !            94:           INDEX (ID),
        !            95:           INDEX (resource))""",
        !            96:   "Queries" : """CREATE TABLE Queries (
        !            97:            ID int(11) NOT NULL auto_increment,
        !            98:           Value varchar(50) NOT NULL,
        !            99:           Count int(11) NOT NULL,
        !           100:           UNIQUE KEY id (ID,Value(35)),
        !           101:           INDEX (ID))""",
        !           102:   "AllQueries" : """CREATE TABLE AllQueries (
        !           103:            ID int(11) NOT NULL auto_increment,
        !           104:           Value varchar(50) NOT NULL,
        !           105:           Count int(11) NOT NULL,
        !           106:           UNIQUE KEY id (ID,Value(35)),
        !           107:           INDEX (ID))""",
        !           108: }
        !           109: 
        !           110: #
        !           111: # The XML API description file to parse
        !           112: #
        !           113: API="libxml2-api.xml"
        !           114: DB=None
        !           115: 
        !           116: #########################################################################
        !           117: #                                                                      #
        !           118: #                  MySQL database interfaces                           #
        !           119: #                                                                      #
        !           120: #########################################################################
        !           121: def createTable(db, name):
        !           122:     global TABLES
        !           123: 
        !           124:     if db == None:
        !           125:         return -1
        !           126:     if name == None:
        !           127:         return -1
        !           128:     c = db.cursor()
        !           129: 
        !           130:     ret = c.execute("DROP TABLE IF EXISTS %s" % (name))
        !           131:     if ret == 1:
        !           132:         print "Removed table %s" % (name)
        !           133:     print "Creating table %s" % (name)
        !           134:     try:
        !           135:         ret = c.execute(TABLES[name])
        !           136:     except:
        !           137:         print "Failed to create table %s" % (name)
        !           138:        return -1
        !           139:     return ret
        !           140: 
        !           141: def checkTables(db, verbose = 1):
        !           142:     global TABLES
        !           143: 
        !           144:     if db == None:
        !           145:         return -1
        !           146:     c = db.cursor()
        !           147:     nbtables = c.execute("show tables")
        !           148:     if verbose:
        !           149:        print "Found %d tables" % (nbtables)
        !           150:     tables = {}
        !           151:     i = 0
        !           152:     while i < nbtables:
        !           153:         l = c.fetchone()
        !           154:        name = l[0]
        !           155:        tables[name] = {}
        !           156:         i = i + 1
        !           157: 
        !           158:     for table in TABLES.keys():
        !           159:         if not tables.has_key(table):
        !           160:            print "table %s missing" % (table)
        !           161:            createTable(db, table)
        !           162:        try:
        !           163:            ret = c.execute("SELECT count(*) from %s" % table);
        !           164:            row = c.fetchone()
        !           165:            if verbose:
        !           166:                print "Table %s contains %d records" % (table, row[0])
        !           167:        except:
        !           168:            print "Troubles with table %s : repairing" % (table)
        !           169:            ret = c.execute("repair table %s" % table);
        !           170:            print "repairing returned %d" % (ret)
        !           171:            ret = c.execute("SELECT count(*) from %s" % table);
        !           172:            row = c.fetchone()
        !           173:            print "Table %s contains %d records" % (table, row[0])
        !           174:     if verbose:
        !           175:        print "checkTables finished"
        !           176: 
        !           177:     # make sure apache can access the tables read-only
        !           178:     try:
        !           179:        ret = c.execute("GRANT SELECT ON xmlsoft.* TO nobody@localhost")
        !           180:        ret = c.execute("GRANT INSERT,SELECT,UPDATE  ON xmlsoft.Queries TO nobody@localhost")
        !           181:     except:
        !           182:         pass
        !           183:     return 0
        !           184:     
        !           185: def openMySQL(db="xmlsoft", passwd=None, verbose = 1):
        !           186:     global DB
        !           187: 
        !           188:     if passwd == None:
        !           189:         try:
        !           190:            passwd = os.environ["MySQL_PASS"]
        !           191:        except:
        !           192:            print "No password available, set environment MySQL_PASS"
        !           193:            sys.exit(1)
        !           194: 
        !           195:     DB = MySQLdb.connect(passwd=passwd, db=db)
        !           196:     if DB == None:
        !           197:         return -1
        !           198:     ret = checkTables(DB, verbose)
        !           199:     return ret
        !           200: 
        !           201: def updateWord(name, symbol, relevance):
        !           202:     global DB
        !           203: 
        !           204:     if DB == None:
        !           205:         openMySQL()
        !           206:     if DB == None:
        !           207:         return -1
        !           208:     if name == None:
        !           209:         return -1
        !           210:     if symbol == None:
        !           211:         return -1
        !           212: 
        !           213:     c = DB.cursor()
        !           214:     try:
        !           215:        ret = c.execute(
        !           216: """INSERT INTO words (name, symbol, relevance) VALUES ('%s','%s', %d)""" %
        !           217:                (name, symbol, relevance))
        !           218:     except:
        !           219:         try:
        !           220:            ret = c.execute(
        !           221:     """UPDATE words SET relevance = %d where name = '%s' and symbol = '%s'""" %
        !           222:                    (relevance, name, symbol))
        !           223:        except:
        !           224:            print "Update word (%s, %s, %s) failed command" % (name, symbol, relevance)
        !           225:            print "UPDATE words SET relevance = %d where name = '%s' and symbol = '%s'" % (relevance, name, symbol)
        !           226:            print sys.exc_type, sys.exc_value
        !           227:            return -1
        !           228:             
        !           229:     return ret
        !           230: 
        !           231: def updateSymbol(name, module, type, desc):
        !           232:     global DB
        !           233: 
        !           234:     updateWord(name, name, 50)
        !           235:     if DB == None:
        !           236:         openMySQL()
        !           237:     if DB == None:
        !           238:         return -1
        !           239:     if name == None:
        !           240:         return -1
        !           241:     if module == None:
        !           242:         return -1
        !           243:     if type == None:
        !           244:         return -1
        !           245: 
        !           246:     try:
        !           247:        desc = string.replace(desc, "'", " ")
        !           248:        l = string.split(desc, ".")
        !           249:        desc = l[0]
        !           250:        desc = desc[0:99]
        !           251:     except:
        !           252:         desc = ""
        !           253: 
        !           254:     c = DB.cursor()
        !           255:     try:
        !           256:        ret = c.execute(
        !           257: """INSERT INTO symbols (name, module, type, descr) VALUES ('%s','%s', '%s', '%s')""" %
        !           258:                     (name, module, type, desc))
        !           259:     except:
        !           260:         try:
        !           261:            ret = c.execute(
        !           262: """UPDATE symbols SET module='%s', type='%s', descr='%s' where name='%s'""" %
        !           263:                     (module, type, desc, name))
        !           264:         except:
        !           265:            print "Update symbol (%s, %s, %s) failed command" % (name, module, type)
        !           266:            print """UPDATE symbols SET module='%s', type='%s', descr='%s' where name='%s'""" % (module, type, desc, name)
        !           267:            print sys.exc_type, sys.exc_value
        !           268:            return -1
        !           269:             
        !           270:     return ret
        !           271:         
        !           272: def addFunction(name, module, desc = ""):
        !           273:     return updateSymbol(name, module, 'function', desc)
        !           274: 
        !           275: def addMacro(name, module, desc = ""):
        !           276:     return updateSymbol(name, module, 'macro', desc)
        !           277: 
        !           278: def addEnum(name, module, desc = ""):
        !           279:     return updateSymbol(name, module, 'enum', desc)
        !           280: 
        !           281: def addStruct(name, module, desc = ""):
        !           282:     return updateSymbol(name, module, 'struct', desc)
        !           283: 
        !           284: def addConst(name, module, desc = ""):
        !           285:     return updateSymbol(name, module, 'const', desc)
        !           286: 
        !           287: def addType(name, module, desc = ""):
        !           288:     return updateSymbol(name, module, 'type', desc)
        !           289: 
        !           290: def addFunctype(name, module, desc = ""):
        !           291:     return updateSymbol(name, module, 'functype', desc)
        !           292: 
        !           293: def addPage(resource, title):
        !           294:     global DB
        !           295: 
        !           296:     if DB == None:
        !           297:         openMySQL()
        !           298:     if DB == None:
        !           299:         return -1
        !           300:     if resource == None:
        !           301:         return -1
        !           302: 
        !           303:     c = DB.cursor()
        !           304:     try:
        !           305:        ret = c.execute(
        !           306:            """INSERT INTO pages (resource, title) VALUES ('%s','%s')""" %
        !           307:                     (resource, title))
        !           308:     except:
        !           309:         try:
        !           310:            ret = c.execute(
        !           311:                """UPDATE pages SET title='%s' WHERE resource='%s'""" %
        !           312:                     (title, resource))
        !           313:         except:
        !           314:            print "Update symbol (%s, %s, %s) failed command" % (name, module, type)
        !           315:            print """UPDATE pages SET title='%s' WHERE resource='%s'""" % (title, resource)
        !           316:            print sys.exc_type, sys.exc_value
        !           317:            return -1
        !           318:             
        !           319:     return ret
        !           320: 
        !           321: def updateWordHTML(name, resource, desc, id, relevance):
        !           322:     global DB
        !           323: 
        !           324:     if DB == None:
        !           325:         openMySQL()
        !           326:     if DB == None:
        !           327:         return -1
        !           328:     if name == None:
        !           329:         return -1
        !           330:     if resource == None:
        !           331:         return -1
        !           332:     if id == None:
        !           333:         id = ""
        !           334:     if desc == None:
        !           335:         desc = ""
        !           336:     else:
        !           337:        try:
        !           338:            desc = string.replace(desc, "'", " ")
        !           339:            desc = desc[0:99]
        !           340:        except:
        !           341:            desc = ""
        !           342: 
        !           343:     c = DB.cursor()
        !           344:     try:
        !           345:        ret = c.execute(
        !           346: """INSERT INTO wordsHTML (name, resource, section, id, relevance) VALUES ('%s','%s', '%s', '%s', '%d')""" %
        !           347:                     (name, resource, desc, id, relevance))
        !           348:     except:
        !           349:         try:
        !           350:            ret = c.execute(
        !           351: """UPDATE wordsHTML SET section='%s', id='%s', relevance='%d' where name='%s' and resource='%s'""" %
        !           352:                     (desc, id, relevance, name, resource))
        !           353:         except:
        !           354:            print "Update symbol (%s, %s, %d) failed command" % (name, resource, relevance)
        !           355:            print """UPDATE wordsHTML SET section='%s', id='%s', relevance='%d' where name='%s' and resource='%s'""" % (desc, id, relevance, name, resource)
        !           356:            print sys.exc_type, sys.exc_value
        !           357:            return -1
        !           358:             
        !           359:     return ret
        !           360: 
        !           361: def checkXMLMsgArchive(url):
        !           362:     global DB
        !           363: 
        !           364:     if DB == None:
        !           365:         openMySQL()
        !           366:     if DB == None:
        !           367:         return -1
        !           368:     if url == None:
        !           369:         return -1
        !           370: 
        !           371:     c = DB.cursor()
        !           372:     try:
        !           373:        ret = c.execute(
        !           374:            """SELECT ID FROM archives WHERE resource='%s'""" % (url))
        !           375:        row = c.fetchone()
        !           376:        if row == None:
        !           377:            return -1
        !           378:     except:
        !           379:        return -1
        !           380:             
        !           381:     return row[0]
        !           382:     
        !           383: def addXMLMsgArchive(url, title):
        !           384:     global DB
        !           385: 
        !           386:     if DB == None:
        !           387:         openMySQL()
        !           388:     if DB == None:
        !           389:         return -1
        !           390:     if url == None:
        !           391:         return -1
        !           392:     if title == None:
        !           393:         title = ""
        !           394:     else:
        !           395:        title = string.replace(title, "'", " ")
        !           396:        title = title[0:99]
        !           397: 
        !           398:     c = DB.cursor()
        !           399:     try:
        !           400:         cmd = """INSERT INTO archives (resource, title) VALUES ('%s','%s')""" % (url, title)
        !           401:         ret = c.execute(cmd)
        !           402:        cmd = """SELECT ID FROM archives WHERE resource='%s'""" % (url)
        !           403:         ret = c.execute(cmd)
        !           404:        row = c.fetchone()
        !           405:        if row == None:
        !           406:            print "addXMLMsgArchive failed to get the ID: %s" % (url)
        !           407:            return -1
        !           408:     except:
        !           409:         print "addXMLMsgArchive failed command: %s" % (cmd)
        !           410:        return -1
        !           411:             
        !           412:     return((int)(row[0]))
        !           413: 
        !           414: def updateWordArchive(name, id, relevance):
        !           415:     global DB
        !           416: 
        !           417:     if DB == None:
        !           418:         openMySQL()
        !           419:     if DB == None:
        !           420:         return -1
        !           421:     if name == None:
        !           422:         return -1
        !           423:     if id == None:
        !           424:         return -1
        !           425: 
        !           426:     c = DB.cursor()
        !           427:     try:
        !           428:        ret = c.execute(
        !           429: """INSERT INTO wordsArchive (name, id, relevance) VALUES ('%s', '%d', '%d')""" %
        !           430:                     (name, id, relevance))
        !           431:     except:
        !           432:         try:
        !           433:            ret = c.execute(
        !           434: """UPDATE wordsArchive SET relevance='%d' where name='%s' and ID='%d'""" %
        !           435:                     (relevance, name, id))
        !           436:         except:
        !           437:            print "Update word archive (%s, %d, %d) failed command" % (name, id, relevance)
        !           438:            print """UPDATE wordsArchive SET relevance='%d' where name='%s' and ID='%d'""" % (relevance, name, id)
        !           439:            print sys.exc_type, sys.exc_value
        !           440:            return -1
        !           441:             
        !           442:     return ret
        !           443: 
        !           444: #########################################################################
        !           445: #                                                                      #
        !           446: #                  Word dictionnary and analysis routines              #
        !           447: #                                                                      #
        !           448: #########################################################################
        !           449: 
        !           450: #
        !           451: # top 100 english word without the one len < 3 + own set
        !           452: #
        !           453: dropWords = {
        !           454:     'the':0, 'this':0, 'can':0, 'man':0, 'had':0, 'him':0, 'only':0,
        !           455:     'and':0, 'not':0, 'been':0, 'other':0, 'even':0, 'are':0, 'was':0,
        !           456:     'new':0, 'most':0, 'but':0, 'when':0, 'some':0, 'made':0, 'from':0,
        !           457:     'who':0, 'could':0, 'after':0, 'that':0, 'will':0, 'time':0, 'also':0,
        !           458:     'have':0, 'more':0, 'these':0, 'did':0, 'was':0, 'two':0, 'many':0,
        !           459:     'they':0, 'may':0, 'before':0, 'for':0, 'which':0, 'out':0, 'then':0,
        !           460:     'must':0, 'one':0, 'through':0, 'with':0, 'you':0, 'said':0,
        !           461:     'first':0, 'back':0, 'were':0, 'what':0, 'any':0, 'years':0, 'his':0,
        !           462:     'her':0, 'where':0, 'all':0, 'its':0, 'now':0, 'much':0, 'she':0,
        !           463:     'about':0, 'such':0, 'your':0, 'there':0, 'into':0, 'like':0, 'may':0,
        !           464:     'would':0, 'than':0, 'our':0, 'well':0, 'their':0, 'them':0, 'over':0,
        !           465:     'down':0,
        !           466:     'net':0, 'www':0, 'bad':0, 'Okay':0, 'bin':0, 'cur':0,
        !           467: }
        !           468: 
        !           469: wordsDict = {}
        !           470: wordsDictHTML = {}
        !           471: wordsDictArchive = {}
        !           472: 
        !           473: def cleanupWordsString(str):
        !           474:     str = string.replace(str, ".", " ")
        !           475:     str = string.replace(str, "!", " ")
        !           476:     str = string.replace(str, "?", " ")
        !           477:     str = string.replace(str, ",", " ")
        !           478:     str = string.replace(str, "'", " ")
        !           479:     str = string.replace(str, '"', " ")
        !           480:     str = string.replace(str, ";", " ")
        !           481:     str = string.replace(str, "(", " ")
        !           482:     str = string.replace(str, ")", " ")
        !           483:     str = string.replace(str, "{", " ")
        !           484:     str = string.replace(str, "}", " ")
        !           485:     str = string.replace(str, "<", " ")
        !           486:     str = string.replace(str, ">", " ")
        !           487:     str = string.replace(str, "=", " ")
        !           488:     str = string.replace(str, "/", " ")
        !           489:     str = string.replace(str, "*", " ")
        !           490:     str = string.replace(str, ":", " ")
        !           491:     str = string.replace(str, "#", " ")
        !           492:     str = string.replace(str, "\\", " ")
        !           493:     str = string.replace(str, "\n", " ")
        !           494:     str = string.replace(str, "\r", " ")
        !           495:     str = string.replace(str, "\xc2", " ")
        !           496:     str = string.replace(str, "\xa0", " ")
        !           497:     return str
        !           498:     
        !           499: def cleanupDescrString(str):
        !           500:     str = string.replace(str, "'", " ")
        !           501:     str = string.replace(str, "\n", " ")
        !           502:     str = string.replace(str, "\r", " ")
        !           503:     str = string.replace(str, "\xc2", " ")
        !           504:     str = string.replace(str, "\xa0", " ")
        !           505:     l = string.split(str)
        !           506:     str = string.join(str)
        !           507:     return str
        !           508: 
        !           509: def splitIdentifier(str):
        !           510:     ret = []
        !           511:     while str != "":
        !           512:         cur = string.lower(str[0])
        !           513:        str = str[1:]
        !           514:        if ((cur < 'a') or (cur > 'z')):
        !           515:            continue
        !           516:        while (str != "") and (str[0] >= 'A') and (str[0] <= 'Z'):
        !           517:            cur = cur + string.lower(str[0])
        !           518:            str = str[1:]
        !           519:        while (str != "") and (str[0] >= 'a') and (str[0] <= 'z'):
        !           520:            cur = cur + str[0]
        !           521:            str = str[1:]
        !           522:        while (str != "") and (str[0] >= '0') and (str[0] <= '9'):
        !           523:            str = str[1:]
        !           524:        ret.append(cur)
        !           525:     return ret
        !           526: 
        !           527: def addWord(word, module, symbol, relevance):
        !           528:     global wordsDict
        !           529: 
        !           530:     if word == None or len(word) < 3:
        !           531:         return -1
        !           532:     if module == None or symbol == None:
        !           533:         return -1
        !           534:     if dropWords.has_key(word):
        !           535:         return 0
        !           536:     if ord(word[0]) > 0x80:
        !           537:         return 0
        !           538: 
        !           539:     if wordsDict.has_key(word):
        !           540:         d = wordsDict[word]
        !           541:        if d == None:
        !           542:            return 0
        !           543:        if len(d) > 500:
        !           544:            wordsDict[word] = None
        !           545:            return 0
        !           546:        try:
        !           547:            relevance = relevance + d[(module, symbol)]
        !           548:        except:
        !           549:            pass
        !           550:     else:
        !           551:         wordsDict[word] = {}
        !           552:     wordsDict[word][(module, symbol)] = relevance
        !           553:     return relevance
        !           554:     
        !           555: def addString(str, module, symbol, relevance):
        !           556:     if str == None or len(str) < 3:
        !           557:         return -1
        !           558:     ret = 0
        !           559:     str = cleanupWordsString(str)
        !           560:     l = string.split(str)
        !           561:     for word in l:
        !           562:        if len(word) > 2:
        !           563:            ret = ret + addWord(word, module, symbol, 5)
        !           564: 
        !           565:     return ret
        !           566: 
        !           567: def addWordHTML(word, resource, id, section, relevance):
        !           568:     global wordsDictHTML
        !           569: 
        !           570:     if word == None or len(word) < 3:
        !           571:         return -1
        !           572:     if resource == None or section == None:
        !           573:         return -1
        !           574:     if dropWords.has_key(word):
        !           575:         return 0
        !           576:     if ord(word[0]) > 0x80:
        !           577:         return 0
        !           578: 
        !           579:     section = cleanupDescrString(section)
        !           580: 
        !           581:     if wordsDictHTML.has_key(word):
        !           582:         d = wordsDictHTML[word]
        !           583:        if d == None:
        !           584:            print "skipped %s" % (word)
        !           585:            return 0
        !           586:        try:
        !           587:            (r,i,s) = d[resource]
        !           588:            if i != None:
        !           589:                id = i
        !           590:            if s != None:
        !           591:                section = s
        !           592:            relevance = relevance + r
        !           593:        except:
        !           594:            pass
        !           595:     else:
        !           596:         wordsDictHTML[word] = {}
        !           597:     d = wordsDictHTML[word];
        !           598:     d[resource] = (relevance, id, section)
        !           599:     return relevance
        !           600:     
        !           601: def addStringHTML(str, resource, id, section, relevance):
        !           602:     if str == None or len(str) < 3:
        !           603:         return -1
        !           604:     ret = 0
        !           605:     str = cleanupWordsString(str)
        !           606:     l = string.split(str)
        !           607:     for word in l:
        !           608:        if len(word) > 2:
        !           609:            try:
        !           610:                r = addWordHTML(word, resource, id, section, relevance)
        !           611:                if r < 0:
        !           612:                    print "addWordHTML failed: %s %s" % (word, resource)
        !           613:                ret = ret + r
        !           614:            except:
        !           615:                print "addWordHTML failed: %s %s %d" % (word, resource, relevance)
        !           616:                print sys.exc_type, sys.exc_value
        !           617: 
        !           618:     return ret
        !           619: 
        !           620: def addWordArchive(word, id, relevance):
        !           621:     global wordsDictArchive
        !           622: 
        !           623:     if word == None or len(word) < 3:
        !           624:         return -1
        !           625:     if id == None or id == -1:
        !           626:         return -1
        !           627:     if dropWords.has_key(word):
        !           628:         return 0
        !           629:     if ord(word[0]) > 0x80:
        !           630:         return 0
        !           631: 
        !           632:     if wordsDictArchive.has_key(word):
        !           633:         d = wordsDictArchive[word]
        !           634:        if d == None:
        !           635:            print "skipped %s" % (word)
        !           636:            return 0
        !           637:        try:
        !           638:            r = d[id]
        !           639:            relevance = relevance + r
        !           640:        except:
        !           641:            pass
        !           642:     else:
        !           643:         wordsDictArchive[word] = {}
        !           644:     d = wordsDictArchive[word];
        !           645:     d[id] = relevance
        !           646:     return relevance
        !           647:     
        !           648: def addStringArchive(str, id, relevance):
        !           649:     if str == None or len(str) < 3:
        !           650:         return -1
        !           651:     ret = 0
        !           652:     str = cleanupWordsString(str)
        !           653:     l = string.split(str)
        !           654:     for word in l:
        !           655:         i = len(word)
        !           656:        if i > 2:
        !           657:            try:
        !           658:                r = addWordArchive(word, id, relevance)
        !           659:                if r < 0:
        !           660:                    print "addWordArchive failed: %s %s" % (word, id)
        !           661:                else:
        !           662:                    ret = ret + r
        !           663:            except:
        !           664:                print "addWordArchive failed: %s %s %d" % (word, id, relevance)
        !           665:                print sys.exc_type, sys.exc_value
        !           666:     return ret
        !           667: 
        !           668: #########################################################################
        !           669: #                                                                      #
        !           670: #                  XML API description analysis                                #
        !           671: #                                                                      #
        !           672: #########################################################################
        !           673: 
        !           674: def loadAPI(filename):
        !           675:     doc = libxml2.parseFile(filename)
        !           676:     print "loaded %s" % (filename)
        !           677:     return doc
        !           678: 
        !           679: def foundExport(file, symbol):
        !           680:     if file == None:
        !           681:         return 0
        !           682:     if symbol == None:
        !           683:         return 0
        !           684:     addFunction(symbol, file)
        !           685:     l = splitIdentifier(symbol)
        !           686:     for word in l:
        !           687:        addWord(word, file, symbol, 10)
        !           688:     return 1
        !           689:      
        !           690: def analyzeAPIFile(top):
        !           691:     count = 0
        !           692:     name = top.prop("name")
        !           693:     cur = top.children
        !           694:     while cur != None:
        !           695:         if cur.type == 'text':
        !           696:            cur = cur.next
        !           697:            continue
        !           698:        if cur.name == "exports":
        !           699:            count = count + foundExport(name, cur.prop("symbol"))
        !           700:        else:
        !           701:            print "unexpected element %s in API doc <file name='%s'>" % (name)
        !           702:         cur = cur.next
        !           703:     return count
        !           704: 
        !           705: def analyzeAPIFiles(top):
        !           706:     count = 0
        !           707:     cur = top.children
        !           708:         
        !           709:     while cur != None:
        !           710:         if cur.type == 'text':
        !           711:            cur = cur.next
        !           712:            continue
        !           713:        if cur.name == "file":
        !           714:            count = count + analyzeAPIFile(cur)
        !           715:        else:
        !           716:            print "unexpected element %s in API doc <files>" % (cur.name)
        !           717:         cur = cur.next
        !           718:     return count
        !           719: 
        !           720: def analyzeAPIEnum(top):
        !           721:     file = top.prop("file")
        !           722:     if file == None:
        !           723:         return 0
        !           724:     symbol = top.prop("name")
        !           725:     if symbol == None:
        !           726:         return 0
        !           727: 
        !           728:     addEnum(symbol, file)
        !           729:     l = splitIdentifier(symbol)
        !           730:     for word in l:
        !           731:        addWord(word, file, symbol, 10)
        !           732: 
        !           733:     return 1
        !           734: 
        !           735: def analyzeAPIConst(top):
        !           736:     file = top.prop("file")
        !           737:     if file == None:
        !           738:         return 0
        !           739:     symbol = top.prop("name")
        !           740:     if symbol == None:
        !           741:         return 0
        !           742: 
        !           743:     addConst(symbol, file)
        !           744:     l = splitIdentifier(symbol)
        !           745:     for word in l:
        !           746:        addWord(word, file, symbol, 10)
        !           747: 
        !           748:     return 1
        !           749: 
        !           750: def analyzeAPIType(top):
        !           751:     file = top.prop("file")
        !           752:     if file == None:
        !           753:         return 0
        !           754:     symbol = top.prop("name")
        !           755:     if symbol == None:
        !           756:         return 0
        !           757: 
        !           758:     addType(symbol, file)
        !           759:     l = splitIdentifier(symbol)
        !           760:     for word in l:
        !           761:        addWord(word, file, symbol, 10)
        !           762:     return 1
        !           763: 
        !           764: def analyzeAPIFunctype(top):
        !           765:     file = top.prop("file")
        !           766:     if file == None:
        !           767:         return 0
        !           768:     symbol = top.prop("name")
        !           769:     if symbol == None:
        !           770:         return 0
        !           771: 
        !           772:     addFunctype(symbol, file)
        !           773:     l = splitIdentifier(symbol)
        !           774:     for word in l:
        !           775:        addWord(word, file, symbol, 10)
        !           776:     return 1
        !           777: 
        !           778: def analyzeAPIStruct(top):
        !           779:     file = top.prop("file")
        !           780:     if file == None:
        !           781:         return 0
        !           782:     symbol = top.prop("name")
        !           783:     if symbol == None:
        !           784:         return 0
        !           785: 
        !           786:     addStruct(symbol, file)
        !           787:     l = splitIdentifier(symbol)
        !           788:     for word in l:
        !           789:        addWord(word, file, symbol, 10)
        !           790: 
        !           791:     info = top.prop("info")
        !           792:     if info != None:
        !           793:        info = string.replace(info, "'", " ")
        !           794:        info = string.strip(info)
        !           795:        l = string.split(info)
        !           796:        for word in l:
        !           797:            if len(word) > 2:
        !           798:                addWord(word, file, symbol, 5)
        !           799:     return 1
        !           800: 
        !           801: def analyzeAPIMacro(top):
        !           802:     file = top.prop("file")
        !           803:     if file == None:
        !           804:         return 0
        !           805:     symbol = top.prop("name")
        !           806:     if symbol == None:
        !           807:         return 0
        !           808:     symbol = string.replace(symbol, "'", " ")
        !           809:     symbol = string.strip(symbol)
        !           810: 
        !           811:     info = None
        !           812:     cur = top.children
        !           813:     while cur != None:
        !           814:         if cur.type == 'text':
        !           815:            cur = cur.next
        !           816:            continue
        !           817:        if cur.name == "info":
        !           818:            info = cur.content
        !           819:            break
        !           820:         cur = cur.next
        !           821: 
        !           822:     l = splitIdentifier(symbol)
        !           823:     for word in l:
        !           824:        addWord(word, file, symbol, 10)
        !           825: 
        !           826:     if info == None:
        !           827:        addMacro(symbol, file)
        !           828:         print "Macro %s description has no <info>" % (symbol)
        !           829:         return 0
        !           830: 
        !           831:     info = string.replace(info, "'", " ")
        !           832:     info = string.strip(info)
        !           833:     addMacro(symbol, file, info)
        !           834:     l = string.split(info)
        !           835:     for word in l:
        !           836:        if len(word) > 2:
        !           837:            addWord(word, file, symbol, 5)
        !           838:     return 1
        !           839: 
        !           840: def analyzeAPIFunction(top):
        !           841:     file = top.prop("file")
        !           842:     if file == None:
        !           843:         return 0
        !           844:     symbol = top.prop("name")
        !           845:     if symbol == None:
        !           846:         return 0
        !           847: 
        !           848:     symbol = string.replace(symbol, "'", " ")
        !           849:     symbol = string.strip(symbol)
        !           850:     info = None
        !           851:     cur = top.children
        !           852:     while cur != None:
        !           853:         if cur.type == 'text':
        !           854:            cur = cur.next
        !           855:            continue
        !           856:        if cur.name == "info":
        !           857:            info = cur.content
        !           858:        elif cur.name == "return":
        !           859:            rinfo = cur.prop("info")
        !           860:            if rinfo != None:
        !           861:                rinfo = string.replace(rinfo, "'", " ")
        !           862:                rinfo = string.strip(rinfo)
        !           863:                addString(rinfo, file, symbol, 7)
        !           864:        elif cur.name == "arg":
        !           865:            ainfo = cur.prop("info")
        !           866:            if ainfo != None:
        !           867:                ainfo = string.replace(ainfo, "'", " ")
        !           868:                ainfo = string.strip(ainfo)
        !           869:                addString(ainfo, file, symbol, 5)
        !           870:            name = cur.prop("name")
        !           871:            if name != None:
        !           872:                name = string.replace(name, "'", " ")
        !           873:                name = string.strip(name)
        !           874:                addWord(name, file, symbol, 7)
        !           875:         cur = cur.next
        !           876:     if info == None:
        !           877:         print "Function %s description has no <info>" % (symbol)
        !           878:        addFunction(symbol, file, "")
        !           879:     else:
        !           880:         info = string.replace(info, "'", " ")
        !           881:        info = string.strip(info)
        !           882:        addFunction(symbol, file, info)
        !           883:         addString(info, file, symbol, 5)
        !           884: 
        !           885:     l = splitIdentifier(symbol)
        !           886:     for word in l:
        !           887:        addWord(word, file, symbol, 10)
        !           888: 
        !           889:     return 1
        !           890: 
        !           891: def analyzeAPISymbols(top):
        !           892:     count = 0
        !           893:     cur = top.children
        !           894:         
        !           895:     while cur != None:
        !           896:         if cur.type == 'text':
        !           897:            cur = cur.next
        !           898:            continue
        !           899:        if cur.name == "macro":
        !           900:            count = count + analyzeAPIMacro(cur)
        !           901:        elif cur.name == "function":
        !           902:            count = count + analyzeAPIFunction(cur)
        !           903:        elif cur.name == "const":
        !           904:            count = count + analyzeAPIConst(cur)
        !           905:        elif cur.name == "typedef":
        !           906:            count = count + analyzeAPIType(cur)
        !           907:        elif cur.name == "struct":
        !           908:            count = count + analyzeAPIStruct(cur)
        !           909:        elif cur.name == "enum":
        !           910:            count = count + analyzeAPIEnum(cur)
        !           911:        elif cur.name == "functype":
        !           912:            count = count + analyzeAPIFunctype(cur)
        !           913:        else:
        !           914:            print "unexpected element %s in API doc <files>" % (cur.name)
        !           915:         cur = cur.next
        !           916:     return count
        !           917: 
        !           918: def analyzeAPI(doc):
        !           919:     count = 0
        !           920:     if doc == None:
        !           921:         return -1
        !           922:     root = doc.getRootElement()
        !           923:     if root.name != "api":
        !           924:         print "Unexpected root name"
        !           925:         return -1
        !           926:     cur = root.children
        !           927:     while cur != None:
        !           928:         if cur.type == 'text':
        !           929:            cur = cur.next
        !           930:            continue
        !           931:        if cur.name == "files":
        !           932:            pass
        !           933: #          count = count + analyzeAPIFiles(cur)
        !           934:        elif cur.name == "symbols":
        !           935:            count = count + analyzeAPISymbols(cur)
        !           936:        else:
        !           937:            print "unexpected element %s in API doc" % (cur.name)
        !           938:         cur = cur.next
        !           939:     return count
        !           940: 
        !           941: #########################################################################
        !           942: #                                                                      #
        !           943: #                  Web pages parsing and analysis                      #
        !           944: #                                                                      #
        !           945: #########################################################################
        !           946: 
        !           947: import glob
        !           948: 
        !           949: def analyzeHTMLText(doc, resource, p, section, id):
        !           950:     words = 0
        !           951:     try:
        !           952:        content = p.content
        !           953:        words = words + addStringHTML(content, resource, id, section, 5)
        !           954:     except:
        !           955:         return -1
        !           956:     return words
        !           957: 
        !           958: def analyzeHTMLPara(doc, resource, p, section, id):
        !           959:     words = 0
        !           960:     try:
        !           961:        content = p.content
        !           962:        words = words + addStringHTML(content, resource, id, section, 5)
        !           963:     except:
        !           964:         return -1
        !           965:     return words
        !           966: 
        !           967: def analyzeHTMLPre(doc, resource, p, section, id):
        !           968:     words = 0
        !           969:     try:
        !           970:        content = p.content
        !           971:        words = words + addStringHTML(content, resource, id, section, 5)
        !           972:     except:
        !           973:         return -1
        !           974:     return words
        !           975: 
        !           976: def analyzeHTML(doc, resource, p, section, id):
        !           977:     words = 0
        !           978:     try:
        !           979:        content = p.content
        !           980:        words = words + addStringHTML(content, resource, id, section, 5)
        !           981:     except:
        !           982:         return -1
        !           983:     return words
        !           984: 
        !           985: def analyzeHTML(doc, resource):
        !           986:     para = 0;
        !           987:     ctxt = doc.xpathNewContext()
        !           988:     try:
        !           989:        res = ctxt.xpathEval("//head/title")
        !           990:        title = res[0].content
        !           991:     except:
        !           992:         title = "Page %s" % (resource)
        !           993:     addPage(resource, title)
        !           994:     try:
        !           995:        items = ctxt.xpathEval("//h1 | //h2 | //h3 | //text()")
        !           996:        section = title
        !           997:        id = ""
        !           998:        for item in items:
        !           999:            if item.name == 'h1' or item.name == 'h2' or item.name == 'h3':
        !          1000:                section = item.content
        !          1001:                if item.prop("id"):
        !          1002:                    id = item.prop("id")
        !          1003:                elif item.prop("name"):
        !          1004:                    id = item.prop("name")
        !          1005:            elif item.type == 'text':
        !          1006:                analyzeHTMLText(doc, resource, item, section, id)
        !          1007:                para = para + 1
        !          1008:            elif item.name == 'p':
        !          1009:                analyzeHTMLPara(doc, resource, item, section, id)
        !          1010:                para = para + 1
        !          1011:            elif item.name == 'pre':
        !          1012:                analyzeHTMLPre(doc, resource, item, section, id)
        !          1013:                para = para + 1
        !          1014:            else:
        !          1015:                print "Page %s, unexpected %s element" % (resource, item.name)
        !          1016:     except:
        !          1017:         print "Page %s: problem analyzing" % (resource)
        !          1018:        print sys.exc_type, sys.exc_value
        !          1019: 
        !          1020:     return para
        !          1021: 
        !          1022: def analyzeHTMLPages():
        !          1023:     ret = 0
        !          1024:     HTMLfiles = glob.glob("*.html") + glob.glob("tutorial/*.html")
        !          1025:     for html in HTMLfiles:
        !          1026:        if html[0:3] == "API":
        !          1027:            continue
        !          1028:        if html == "xml.html":
        !          1029:            continue
        !          1030:        try:
        !          1031:            doc = libxml2.parseFile(html)
        !          1032:        except:
        !          1033:            doc = libxml2.htmlParseFile(html, None)
        !          1034:        try:
        !          1035:            res = analyzeHTML(doc, html)
        !          1036:            print "Parsed %s : %d paragraphs" % (html, res)
        !          1037:            ret = ret + 1
        !          1038:        except:
        !          1039:            print "could not parse %s" % (html)
        !          1040:     return ret
        !          1041: 
        !          1042: #########################################################################
        !          1043: #                                                                      #
        !          1044: #                  Mail archives parsing and analysis                  #
        !          1045: #                                                                      #
        !          1046: #########################################################################
        !          1047: 
        !          1048: import time
        !          1049: 
        !          1050: def getXMLDateArchive(t = None):
        !          1051:     if t == None:
        !          1052:        t = time.time()
        !          1053:     T = time.gmtime(t)
        !          1054:     month = time.strftime("%B", T)
        !          1055:     year = T[0]
        !          1056:     url = "http://mail.gnome.org/archives/xml/%d-%s/date.html" % (year, month)
        !          1057:     return url
        !          1058: 
        !          1059: def scanXMLMsgArchive(url, title, force = 0):
        !          1060:     if url == None or title == None:
        !          1061:         return 0
        !          1062: 
        !          1063:     ID = checkXMLMsgArchive(url)
        !          1064:     if force == 0 and ID != -1:
        !          1065:         return 0
        !          1066: 
        !          1067:     if ID == -1:
        !          1068:        ID = addXMLMsgArchive(url, title)
        !          1069:        if ID == -1:
        !          1070:            return 0
        !          1071: 
        !          1072:     try:
        !          1073:         print "Loading %s" % (url)
        !          1074:         doc = libxml2.htmlParseFile(url, None);
        !          1075:     except:
        !          1076:         doc = None
        !          1077:     if doc == None:
        !          1078:         print "Failed to parse %s" % (url)
        !          1079:        return 0
        !          1080: 
        !          1081:     addStringArchive(title, ID, 20)
        !          1082:     ctxt = doc.xpathNewContext()
        !          1083:     texts = ctxt.xpathEval("//pre//text()")
        !          1084:     for text in texts:
        !          1085:         addStringArchive(text.content, ID, 5)
        !          1086: 
        !          1087:     return 1
        !          1088: 
        !          1089: def scanXMLDateArchive(t = None, force = 0):
        !          1090:     global wordsDictArchive
        !          1091: 
        !          1092:     wordsDictArchive = {}
        !          1093: 
        !          1094:     url = getXMLDateArchive(t)
        !          1095:     print "loading %s" % (url)
        !          1096:     try:
        !          1097:        doc = libxml2.htmlParseFile(url, None);
        !          1098:     except:
        !          1099:         doc = None
        !          1100:     if doc == None:
        !          1101:         print "Failed to parse %s" % (url)
        !          1102:        return -1
        !          1103:     ctxt = doc.xpathNewContext()
        !          1104:     anchors = ctxt.xpathEval("//a[@href]")
        !          1105:     links = 0
        !          1106:     newmsg = 0
        !          1107:     for anchor in anchors:
        !          1108:        href = anchor.prop("href")
        !          1109:        if href == None or href[0:3] != "msg":
        !          1110:            continue
        !          1111:         try:
        !          1112:            links = links + 1
        !          1113: 
        !          1114:            msg = libxml2.buildURI(href, url)
        !          1115:            title = anchor.content
        !          1116:            if title != None and title[0:4] == 'Re: ':
        !          1117:                title = title[4:]
        !          1118:            if title != None and title[0:6] == '[xml] ':
        !          1119:                title = title[6:]
        !          1120:            newmsg = newmsg + scanXMLMsgArchive(msg, title, force)
        !          1121: 
        !          1122:        except:
        !          1123:            pass
        !          1124: 
        !          1125:     return newmsg
        !          1126:     
        !          1127: 
        !          1128: #########################################################################
        !          1129: #                                                                      #
        !          1130: #          Main code: open the DB, the API XML and analyze it          #
        !          1131: #                                                                      #
        !          1132: #########################################################################
        !          1133: def analyzeArchives(t = None, force = 0):
        !          1134:     global wordsDictArchive
        !          1135: 
        !          1136:     ret = scanXMLDateArchive(t, force)
        !          1137:     print "Indexed %d words in %d archive pages" % (len(wordsDictArchive), ret)
        !          1138: 
        !          1139:     i = 0
        !          1140:     skipped = 0
        !          1141:     for word in wordsDictArchive.keys():
        !          1142:        refs = wordsDictArchive[word]
        !          1143:        if refs  == None:
        !          1144:            skipped = skipped + 1
        !          1145:            continue;
        !          1146:        for id in refs.keys():
        !          1147:            relevance = refs[id]
        !          1148:            updateWordArchive(word, id, relevance)
        !          1149:            i = i + 1
        !          1150: 
        !          1151:     print "Found %d associations in HTML pages" % (i)
        !          1152: 
        !          1153: def analyzeHTMLTop():
        !          1154:     global wordsDictHTML
        !          1155: 
        !          1156:     ret = analyzeHTMLPages()
        !          1157:     print "Indexed %d words in %d HTML pages" % (len(wordsDictHTML), ret)
        !          1158: 
        !          1159:     i = 0
        !          1160:     skipped = 0
        !          1161:     for word in wordsDictHTML.keys():
        !          1162:        refs = wordsDictHTML[word]
        !          1163:        if refs  == None:
        !          1164:            skipped = skipped + 1
        !          1165:            continue;
        !          1166:        for resource in refs.keys():
        !          1167:            (relevance, id, section) = refs[resource]
        !          1168:            updateWordHTML(word, resource, section, id, relevance)
        !          1169:            i = i + 1
        !          1170: 
        !          1171:     print "Found %d associations in HTML pages" % (i)
        !          1172: 
        !          1173: def analyzeAPITop():
        !          1174:     global wordsDict
        !          1175:     global API
        !          1176: 
        !          1177:     try:
        !          1178:        doc = loadAPI(API)
        !          1179:        ret = analyzeAPI(doc)
        !          1180:        print "Analyzed %d blocs" % (ret)
        !          1181:        doc.freeDoc()
        !          1182:     except:
        !          1183:        print "Failed to parse and analyze %s" % (API)
        !          1184:        print sys.exc_type, sys.exc_value
        !          1185:        sys.exit(1)
        !          1186: 
        !          1187:     print "Indexed %d words" % (len(wordsDict))
        !          1188:     i = 0
        !          1189:     skipped = 0
        !          1190:     for word in wordsDict.keys():
        !          1191:        refs = wordsDict[word]
        !          1192:        if refs  == None:
        !          1193:            skipped = skipped + 1
        !          1194:            continue;
        !          1195:        for (module, symbol) in refs.keys():
        !          1196:            updateWord(word, symbol, refs[(module, symbol)])
        !          1197:            i = i + 1
        !          1198: 
        !          1199:     print "Found %d associations, skipped %d words" % (i, skipped)
        !          1200: 
        !          1201: def usage():
        !          1202:     print "Usage index.py [--force] [--archive]  [--archive-year year] [--archive-month month] [--API] [--docs]"
        !          1203:     sys.exit(1)
        !          1204: 
        !          1205: def main():
        !          1206:     try:
        !          1207:        openMySQL()
        !          1208:     except:
        !          1209:        print "Failed to open the database"
        !          1210:        print sys.exc_type, sys.exc_value
        !          1211:        sys.exit(1)
        !          1212: 
        !          1213:     args = sys.argv[1:]
        !          1214:     force = 0
        !          1215:     if args:
        !          1216:         i = 0
        !          1217:        while i < len(args):
        !          1218:            if args[i] == '--force':
        !          1219:                force = 1
        !          1220:            elif args[i] == '--archive':
        !          1221:                analyzeArchives(None, force)
        !          1222:            elif args[i] == '--archive-year':
        !          1223:                i = i + 1;
        !          1224:                year = args[i]
        !          1225:                months = ["January" , "February", "March", "April", "May",
        !          1226:                          "June", "July", "August", "September", "October",
        !          1227:                          "November", "December"];
        !          1228:                for month in months:
        !          1229:                    try:
        !          1230:                        str = "%s-%s" % (year, month)
        !          1231:                        T = time.strptime(str, "%Y-%B")
        !          1232:                        t = time.mktime(T) + 3600 * 24 * 10;
        !          1233:                        analyzeArchives(t, force)
        !          1234:                    except:
        !          1235:                        print "Failed to index month archive:"
        !          1236:                        print sys.exc_type, sys.exc_value
        !          1237:            elif args[i] == '--archive-month':
        !          1238:                i = i + 1;
        !          1239:                month = args[i]
        !          1240:                try:
        !          1241:                    T = time.strptime(month, "%Y-%B")
        !          1242:                    t = time.mktime(T) + 3600 * 24 * 10;
        !          1243:                    analyzeArchives(t, force)
        !          1244:                except:
        !          1245:                    print "Failed to index month archive:"
        !          1246:                    print sys.exc_type, sys.exc_value
        !          1247:            elif args[i] == '--API':
        !          1248:                analyzeAPITop()
        !          1249:            elif args[i] == '--docs':
        !          1250:                analyzeHTMLTop()
        !          1251:            else:
        !          1252:                usage()
        !          1253:            i = i + 1
        !          1254:     else:
        !          1255:         usage()
        !          1256: 
        !          1257: if __name__ == "__main__":
        !          1258:     main()

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