OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [tools/] [cml2-tools/] [kxref.py] - Blame information for rev 3

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
#!/usr/bin/env python
2
"""
3
kxref.py -- generate configuration symbol cross-reference for the kernel tree
4
 
5
This is a report generator intended to catch problems and inconsistencies
6
in the configuration-symbol namespace.  It uses information generated by
7
the CML2 compiler -- notably, it relies on the compiler's scanning of
8
help files.
9
 
10
All this does is generate cross-reference reports on configuration
11
symbols.  But they can be filtered and presented in various
12
interesting ways.  Basic usage is like this:
13
 
14
        kxref.py [-f filter | -h] [-l] [-x symbol] [-n re] [sourcetree]
15
 
16
You can set a filter using a boolean-expression minilanguage.  The predicates
17
available are as follows:
18
 
19
        c -- select all symbols present in code (.c, .h, .S files)
20
        m -- select all symbols present in makefiles
21
        n -- select all symbols defined in CML2 rulesfiles
22
        h -- select all symbols for which help is available (CMl1 convention)
23
        H -- select all symbols for which help is available (CML2 convention)
24
        d -- select all symbols that occur in defconfigs
25
        x -- select all symbols that are derived in CML2.
26
        o -- select all symbols present in CML1 configuration files
27
        a -- select all symbols declared in CML1 configuration files
28
        p -- select all symbols for which autoconfigure.py has a probe
29
 
30
        D(name) -- select all symbols transitively dependent on name
31
        A(name) -- select all symbols transitively ancestral to name
32
        T(type) -- select type (trit, bool, string, decimal, hexadecimal)
33
        P(property) -- select all symbols with given property
34
        V(symbol) -- select all symbols with given symbol in their
35
                        visibility guard.
36
 
37
Operations available are as follows:
38
 
39
        & -- and (set intersection)
40
        | -- or (set intersection)
41
        ~ -- not (set complement).
42
 
43
You may use parentheses for expression grouping.
44
 
45
This program caches a cross-reference database in a file named
46
xref.out, so all reports after the first are generated really fast.
47
You should remove this file whenever you apply a patch.
48
 
49
The -i option inverts the report so it's keyed by file, rather than
50
by symbol.
51
 
52
The -g option generates a patch removing file lines containing the
53
reported (presumably orphaned) symbols.  Use with caution...it's
54
really only safe for hacking defconfigs.
55
 
56
The -x option is for debugging.  It generates a report on an individual
57
symbol specified as an argument to the option.  Flag letters are as
58
above, with f= giving the value of the computed filter predicate.
59
 
60
The -h option checks for duplicate or superfluous file inclusions
61
in the source tree.
62
 
63
The -l switch suppresses printing printing of cross-references;
64
only symbols matching the given filter(s) are listed.
65
 
66
The -n suppresses listing of files with names matching the given regexp.
67
If all the files a symbol occurs in are excluded, it will be omitted
68
from the listings.
69
 
70
The -t option produces a listing of symbols which either have
71
inconsistent CML1 types or types that differ between CML1 and CML2.
72
 
73
The -k option accepts a file of kill-list symbols to be ignored.
74
 
75
The program has some knowledge of file syntax.  It ignores the
76
contents of comments in C, CML1, and CML2 files (e.g. does not
77
cross-reference symbols in such comments).
78
 
79
Some interesting reports:
80
 
81
n&~p&~a -- identifies CML2 symbols no longer declared or defined in CML1
82
 
83
"""
84
import sys, os, re, getopt, cPickle, cml, cmlsystem
85
 
86
xrefs = None
87
rulebase = None
88
typefind = choicere = configre = definere = mycml1types = None
89
 
90
def suffix(haystack, *needle):
91
    "Does a filename have any of the given suffixes?"
92
    for suf in needle:
93
        if haystack[-len(suf):] == suf:
94
            return 1
95
    return 0
96
 
97
def prefix(haystack, *needle):
98
    "Does a filename have any of the given prefixes?"
99
    for pre in needle:
100
        if haystack[len(pre):] == pre:
101
            return 1
102
    return 0
103
 
104
# Code for recognizing symbols and stripping out comments
105
 
106
# It's OK that this matches _MODULE symbols, we'll filter those out later.
107
configpref = re.compile("(?<![A-Z0-9_])(CONFIG_[a-zA-Z0-9_][a-zA-Z0-9_]+)")
108
 
109
# Regular expressions for stripping out C comments.  We're aided here by the
110
# fact that we don't care about the contents of most of the file.  So by
111
# first stripping out / and characters that are not part of comment
112
# delimiter pairs, we can make detecting comments pretty trivial.  This won't
113
# completely strip comments of the form /* aaaa /* bbbb */, but for this
114
# application that's OK -- we don't have to be perfect, just reduce the
115
# exception cases to the point where eyeball checking is feasible.  Use
116
# of lookaheads and lookbehinds avoids nipping off anything that might
117
# be a nearby bit of symbol.
118
#
119
randomslash = re.compile("(?<=[^*])/(?=[^*])")
120
randomstar  = re.compile("(?<=[^/])\*(?=[^/])")
121
c_comment = re.compile("/\*[^*]*\*/")
122
 
123
def c_comment_strip(str):
124
    str = randomslash.sub("", str,)
125
    str = randomstar.sub("", str)
126
    return c_comment.sub("", str)
127
 
128
# Shell, config-file, and Makefile-style comments.
129
#
130
hashcomment = re.compile("#.*\n", re.MULTILINE)
131
 
132
def hash_comment_strip(str):
133
    return hashcomment.sub("", str)
134
 
135
# Code for generating the cross-reference
136
 
137
def ignore(file):
138
    "Return 1 if the file should be ignored for cross-referencing purposes."
139
    # Ignore CML files because we look symbols up directly in the rulebase.
140
    return suffix(file, ".bak", ".orig", ".rej", ".cml", ".o", ".a", ".out", "log", "Log", ",v", "~")
141
 
142
# These are used in the language documentation
143
kill_list = {"CHEER":1, "BOOM":1, "BOGUS":1}
144
 
145
def makexref(tree):
146
    "Generate a cross-reference dictionary for the given source tree."
147
    global typefind, choicere, configre, definere, mycml1types
148
    typefind = re.compile(r"(?<!define_)(bool|tristate|int|hex|string)\s+'.*'\s+CONFIG_(\w+)")
149
    choicere = re.compile(r"^\s*choice")
150
    configre = re.compile(rulebase.prefix + r"(\w*)")
151
    definere = re.compile(r"^\s+define_([a-z]*)\s+(\w*)")
152
    mycml1types = {}
153
    def xrefvisit(dict, dir, files):
154
        "Visit a directory on behalf of the cross-referencer."
155
        def filevisitor(dict, file):
156
            "Visit a file on behalf of the cross-referencer."
157
            if file[0] == '.':
158
                return
159
            fp = open(file)
160
            contents = fp.read()
161
            fp.close()
162
            if suffix(file, ".c", ".h", ".S"):
163
                contents = c_comment_strip(contents)
164
            elif suffix(file, ".in", ".cml"):
165
                contents = hash_comment_strip(contents)
166
            for match in configpref.findall(contents):
167
                if suffix(match, "_MODULE"):
168
                    continue
169
                match = namestrip(match)
170
                if kill_list.has_key(match):
171
                    continue
172
                elif not dict.has_key(match):
173
                    dict[match] = []
174
                if file not in dict[match]:
175
                    dict[match].append(file)
176
            # Parse file contents for choice symbols
177
            if suffix(file, ".in"):
178
                lines = contents.split("\n")
179
                while lines:
180
                    if not choicere.match(lines[0]):
181
                        # First extract type info for ordinary symbols
182
                        m = typefind.search(lines[0])
183
                        if m:
184
                            symtype = m.group(1)
185
                            symname = m.group(2)
186
                            if not mycml1types.has_key(symname):
187
                                mycml1types[symname] = []
188
                            if (symtype, file) not in mycml1types[symname]:
189
                                mycml1types[symname].append((symtype, file))
190
                        # CML1 defines count with other symbols of their type 
191
                        symdef = definere.search(lines[0])
192
                        if symdef:
193
                            symbol = namestrip(symdef.group(2))
194
                            type = symdef.group(1)
195
                            if not mycml1types.has_key(symbol):
196
                                mycml1types[symbol] = []
197
                            if (type, file) not in mycml1types[symbol]:
198
                                mycml1types[symbol].append((type, file))
199
                        lines.pop(0)
200
                        continue
201
                    else:
202
                        lines.pop(0)
203
                        while lines[0].find(rulebase.prefix) > -1:
204
                            findit = configre.search(lines[0])
205
                            symbol = namestrip(findit.group(0))
206
                            if not mycml1types.has_key(symbol):
207
                                mycml1types[symbol] = []
208
                            mycml1types[symbol].append(("choice", file))
209
                            if lines[0].find('" ') > -1:
210
                                break
211
                            lines.pop(0)
212
 
213
        for file in files:
214
            node = os.path.join(dir, file)[2:]
215
            if os.path.isfile(node) and not ignore(node):
216
                filevisitor(dict, node)
217
 
218
    xrefdict = {}
219
    here = os.getcwd()
220
    os.chdir(sourcetree)
221
    os.path.walk(".", xrefvisit, xrefdict)
222
    os.chdir(here)
223
    # Data reduction -- collapse CML1 cross references of identical type
224
    for (key, value) in mycml1types.items():
225
        if len(value) <= 1:
226
            continue            # Only interested in the multiples
227
        else:
228
            tdict = {}
229
            for (type, file) in value:
230
                tdict[type] = []
231
            for (type, file) in value:
232
                tdict[type].append(file)
233
            reslist = []
234
            for type in tdict.keys():
235
                reslist.append((type, tdict[type]))
236
            mycml1types[key] = reslist
237
    # Second stage of data reduction -- if a symbol has both a choice
238
    # declaration and another of a different type, suppress the non-choice
239
    # declaration -- we can assume it came from a CML1 define.
240
    for (key, value) in mycml1types.items():
241
        if "choice" in map(lambda x: x[0], value):
242
            mycml1types[key]=filter(lambda x: x[0]=="choice", mycml1types[key])
243
    return (xrefdict, mycml1types)
244
 
245
probe_table = {}
246
 
247
def load_probe_table():
248
    "Build a table of symbols for qhich we have probes."
249
    from autoconfigure import get_arch
250
    (ARCH, ARCHSYMBOL) = get_arch()
251
 
252
    TRUE = 1
253
    FALSE = 0
254
    PRESENT = 1
255
    ABSENT = 0
256
    y = m = n = 0
257
 
258
    def DEBUG(str):
259
        pass
260
 
261
    def PCI(prefix, symbol):
262
        probe_table[symbol] = 1
263
 
264
    def PCI_CLASS(match, symbol):
265
        probe_table[symbol] = 1
266
 
267
    def PNP(match, symbol):
268
        probe_table[symbol] = 1
269
 
270
    def MCA(match, symbol):
271
        probe_table[symbol] = 1
272
 
273
    def USBP(match, symbol):
274
        probe_table[symbol] = 1
275
 
276
    def USBC(match, symbol):
277
        probe_table[symbol] = 1
278
 
279
    def USBI(match, symbol):
280
        probe_table[symbol] = 1
281
 
282
    def FS(match, symbol):
283
        probe_table[symbol] = 1
284
 
285
    def DEV(match, symbol):
286
        probe_table[symbol] = 1
287
 
288
    def DEVM(match, symbol):
289
        probe_table[symbol] = 1
290
 
291
    def CONS(match, symbol):
292
        probe_table[symbol] = 1
293
 
294
    def DMESG(match, symbol, truthval=None):
295
        probe_table[symbol] = 1
296
 
297
    def NET(match, symbol):
298
        probe_table[symbol] = 1
299
 
300
    def IDE(match, symbol):
301
        probe_table[symbol] = 1
302
 
303
    def REQ(match, symbol):
304
        probe_table[symbol] = 1
305
 
306
    def CPUTYPE(match, symbol):
307
        probe_table[symbol] = 1
308
 
309
    def CPUINFO(match, symbol, present=None, truthval=None):
310
        probe_table[symbol] = 1
311
 
312
    def EXISTS(procfile, symbol):
313
        probe_table[symbol] = 1
314
 
315
    def MODULE(name, symbol):
316
        probe_table[symbol] = 1
317
 
318
    def GREP(pattern, file, symbol):
319
        probe_table[symbol] = 1
320
 
321
    execfile(rulesfile)
322
 
323
# Predicates for filtering the reports
324
 
325
def namestrip(name):
326
    if rulebase.prefix and name[:len(rulebase.prefix)] == rulebase.prefix:
327
        return name[len(rulebase.prefix):]
328
    else:
329
        return name
330
 
331
def in_code(name):
332
    "Does a name occur in code?"
333
    if not xrefs.has_key(name):
334
        return 0
335
    for file in xrefs[name]:
336
        if suffix(file, ".c", ".S") or (suffix(file, ".h") and not suffix(file, "autoconf.h")):
337
            return 1
338
    return 0
339
 
340
def in_help(name):
341
    "Is there help for a symbol (CML1 convention)?"
342
    # Catch choice names that aren't in Configure.help directly.
343
    entry = rulebase.dictionary.get(namestrip(name))
344
    if entry and entry.help():
345
        return 1
346
    # This catches names that are in a helpfile but not known to CML2.
347
    if not xrefs.has_key(name):
348
        return 0
349
    for file in xrefs[name]:
350
        if suffix(file, ".help"):
351
            return 1
352
    # False negative if there is ever a choice name that CML2
353
    # doesn't know about.
354
    return 0
355
 
356
def in_cml2_help(name):
357
    "Does a name occur in some help file (CML2 rules)?"
358
    entry = rulebase.dictionary.get(namestrip(name))
359
    if entry and entry.helptext:
360
        return 1
361
    # This catches names that are in a helpfile but not known to CML2.
362
    if not xrefs.has_key(name):
363
        return 0
364
    for file in xrefs[name]:
365
        if suffix(file, ".help"):
366
            return 1
367
    # False negative if there is ever a choice name that CML2
368
    # doesn't know about.
369
    return 0
370
 
371
def in_makefile(name):
372
    "Does a name occur in a makefile?"
373
    if not xrefs.has_key(name):
374
        return 0
375
    for file in xrefs[name]:
376
        if suffix(file, "akefile"):
377
            return 1
378
    return 0
379
 
380
def in_cml1(name):
381
    "Does a name occur in a CML1 file?"
382
    if not xrefs.has_key(name):
383
        return 0
384
    for file in xrefs[name]:
385
        if suffix(file, "onfig.in"):
386
            return 1
387
    return 0
388
 
389
def cml1_declared(name):
390
    "Is a name declared (assigned a type) in a CML1 file?"
391
    return mycml1types.has_key(name)
392
 
393
def in_defconfig(name):
394
    if not xrefs.has_key(name):
395
        return 0
396
    "Does a this symbol occur in a defconfig?"
397
    for file in xrefs[name]:
398
        if file.find("defconfig") > -1 or file.find("configs/") > -1:
399
            return 1
400
    return 0
401
 
402
def in_cml2(name):
403
    "Is this a valid CML2 symbol?"
404
    return rulebase.dictionary.has_key(namestrip(name))
405
 
406
def is_derived(name):
407
    "Is this a CML2 derived name?"
408
    entry = rulebase.dictionary.get(namestrip(name))
409
    if entry and entry.is_derived():
410
        return 1
411
    else:
412
        return 0
413
 
414
def dependent_of(ancestor, name):
415
    "Is given symbol a dependent of given ancestor?"
416
    ancestor = rulebase.dictionary.get(namestrip(ancestor))
417
    entry = rulebase.dictionary.get(namestrip(name))
418
    if entry and ancestor.ancestor_of(entry):
419
        return 1
420
    else:
421
        return 0
422
 
423
def ancestor_of(dependent, name):
424
    "Is given symbol a an ancestor of given dependent?"
425
    dependent = rulebase.dictionary.get(namestrip(dependent))
426
    entry = rulebase.dictionary.get(namestrip(name))
427
    if entry and entry.ancestor_of(dependent):
428
        return 1
429
    else:
430
        return 0
431
 
432
def type_of(typename, name):
433
    "Is given symbol of given tyoe?"
434
    entry = rulebase.dictionary.get(namestrip(name))
435
    if entry and entry.type == typename:
436
        return 1
437
    else:
438
        return 0
439
 
440
def has_property(property, name):
441
    "Does given symbol have given property?"
442
    entry = rulebase.dictionary.get(namestrip(name))
443
    if entry and property in entry.properties:
444
        return 1
445
    else:
446
        return 0
447
 
448
def is_probed(name):
449
    "Does given symbol have a probe?"
450
    entry = rulebase.dictionary.get(namestrip(name))
451
    if not probe_table:
452
        load_probe_table()
453
    return entry and probe_table.has_key(entry.name)
454
 
455
def in_visibility(guard, name):
456
    "Does the symbol GUARD occur in the visibility predicate of NAME?"
457
    entry = rulebase.dictionary.get(namestrip(name))
458
    if not entry:
459
        return 0
460
    guard = rulebase.dictionary.get(namestrip(guard))
461
    return entry.visibility and guard in cml.flatten_expr(entry.visibility)
462
 
463
# Report generation
464
 
465
def setfilter(filterspec):
466
    "Set the filter function."
467
    if not filterspec:
468
        function = "def myfilter(name): return 1"
469
    else:
470
        state = 0
471
        expression = ""
472
        for c in filterspec:
473
            if state == 0:
474
                if c == "(" or c == ")":
475
                    expression += c
476
                elif c == " " or c == "\t":
477
                    pass
478
                elif c == "a":
479
                    expression += " cml1_declared(name)"
480
                elif c == "c":
481
                    expression += " in_code(name)"
482
                elif c == "h":
483
                    expression += " in_help(name)"
484
                elif c == "H":
485
                    expression += " in_cml2_help(name)"
486
                elif c == 'm':
487
                    expression += " in_makefile(name)"
488
                elif c == "o":
489
                    expression += " in_cml1(name)"
490
                elif c == "n":
491
                    expression += " in_cml2(name)"
492
                elif c == "d":
493
                    expression += " in_defconfig(name)"
494
                elif c == "x":
495
                    expression += " is_derived(name)"
496
                elif c == "~":
497
                    expression += " not"
498
                elif c == "&":
499
                    expression += " and"
500
                elif c == "|":
501
                    expression += " or"
502
                elif c == "p":
503
                    expression += " is_probed(name)"
504
                elif c == "D":
505
                    expression += " dependent_of"
506
                    state = 1
507
                elif c == "A":
508
                    expression += " ancestor_of"
509
                    state = 1
510
                elif c == "T":
511
                    expression += " type_of"
512
                    state = 1
513
                elif c == "P":
514
                    expression += " has_property"
515
                    state = 1
516
                elif c == "V":
517
                    expression += " in_visibility"
518
                    state = 1
519
            elif state == 1:
520
                if c == ')':
521
                    expression += '", name)'
522
                    state = 0
523
                elif c == '(':
524
                    expression += '("'
525
                else:
526
                    expression += c
527
        function = "def myfilter(name): return " + expression
528
    #sys.stderr.write("Filter function: " +  function + "\n")
529
    exec function in globals()
530
 
531
def report(keys, norefs=0):
532
    "Generate a filtered report on the cross-references."
533
    for symbol in keys:
534
        refs = filter(lambda x: not (suppress and suppress.search(x)), xrefs[symbol])
535
        if refs:
536
            if norefs:
537
                print symbol
538
            else:
539
                sys.stdout.write(symbol + ":")
540
                for file in refs:
541
                    sys.stdout.write(" " + file)
542
                sys.stdout.write("\n")
543
 
544
def generate_patch(file, symbols):
545
    "Generate a patch deleting the given symbols from the given file."
546
    pfp = open(file, "rb")
547
    contents = pfp.read()
548
    pfp.close()
549
    for symbol in symbols:
550
        contents = re.compile("^.*" + symbol + "[^A-Z0-9].*\n", re.M).sub("", contents)
551
    pfp = open(file + ".tweaked", "wb")
552
    pfp.write(contents)
553
    pfp.close()
554
    os.system("diff -u %s %s.tweaked; rm %s.tweaked" % (file, file, file))
555
 
556
# Inclusion checking.  This lives here because we use the CML2 rulebase to
557
# check which CONFIG_ symbols are defined (just checking for a CONFIG_ stem
558
# isn't reliable as CML2 doesn't completely own that namespace).
559
 
560
includere = re.compile(r'^\s*#\s*include\s*[<"](\S*)[>"]', re.M)
561
 
562
def includecheck(sourcetree):
563
    "Check the inclusion structure of a source tree."
564
    def includevisit(dummy, dir, files):
565
        "Visit a directory on behalf of the inclusion checker."
566
        def filevisitor(dummy, file):
567
            "Visit a file on behalf of the inclusion checker."
568
            fp = open(file)
569
            contents = fp.read()
570
            fp.close()
571
            # First get the list of included files
572
            inclusions = includere.findall(contents)
573
            # This strips slashes, so it has to be done after
574
            contents = c_comment_strip(contents)
575
            # Check to see if we have defined CONFIG_ symbols in the file
576
            matched = []
577
            for match in configpref.findall(contents):
578
                if suffix(match, "_MODULE"):
579
                    match = match[:-7]
580
                match = namestrip(match)                # Strip prefix
581
                if rulebase.dictionary.has_key(match) and match not in matched:
582
                    matched.append(match)
583
            # Check for duplicates
584
            dups = {}
585
            for header in inclusions:
586
                dups[header] = 0
587
            for header in inclusions:
588
                dups[header] += 1
589
            for header in inclusions:
590
                if dups[header] > 1:
591
                    print "%s: %s is included %d times" % (file, header, dups[header])
592
            # OK, check to see if we have autoconf inclusion.
593
            have_autoconf = 0
594
            for header in inclusions:
595
                if header == "autoconf.h" or header == "linux/config.h":
596
                    have_autoconf = 1
597
                    break
598
            if not matched and have_autoconf:
599
                print "%s: has unnecessary configure file inclusion" % file
600
            elif matched and not have_autoconf:
601
                print "%s: needs configure file inclusion for %s" % (file, matched)
602
 
603
        for file in files:
604
            if suffix(file, ".c", ".h", ".S"):
605
                node = os.path.join(dir, file)[2:]
606
                if os.path.isfile(node) and not ignore(node):
607
                    filevisitor(None, node)
608
 
609
    here = os.getcwd()
610
    os.chdir(sourcetree)
611
    os.path.walk(".", includevisit, None)
612
    os.chdir(here)
613
 
614
# The main program
615
 
616
def load_context(tree):
617
    "Load context, including CML2 rulebase and cross-reference database."
618
    global rulebase, xrefs, mycml1types
619
 
620
    # Get a CML2 rulebase.
621
    if not os.path.exists(os.path.join(tree, "rules.out")):
622
        print "This program requires a CML2 rulebase in the source tree."
623
        raise SystemExit, 1
624
    else:
625
        rulebase = cmlsystem.CMLSystem(os.path.join(tree, "rules.out"))
626
 
627
    # Try to find a saved cross-reference database.  If no such database
628
    # exists, generate one and cache it.
629
    xref_file = os.path.join(tree, "xref.out")
630
    if os.path.exists(xref_file):
631
        sys.stderr.write("Reading cross-reference database...")
632
        ifp = open(xref_file, "rb")
633
        (xrefs, mycml1types) = cPickle.load(ifp)
634
        ifp.close()
635
        sys.stderr.write("done.\n")
636
    else:
637
        sys.stderr.write("Regenerating cross-reference database...")
638
        (xrefs, mycml1types) = makexref(tree)
639
        ofp = open(xref_file, "w")
640
        cPickle.dump((xrefs, mycml1types), ofp, 1)
641
        ofp.close()
642
        sys.stderr.write("done.\n")
643
 
644
if __name__ == "__main__":
645
    setfilter(None)
646
    examine = ""
647
    norefs = 0
648
    typecheck = 0
649
    suppress = None
650
    rulesfile = None
651
    invert = genpatch = checkincludes = 0
652
    (options, arguments) = getopt.getopt(sys.argv[1:], "ef:ghik:ln:r:tx:")
653
    for (switch, val) in options:
654
        if switch == '-f':
655
            setfilter(val)
656
        elif switch == '-i':
657
            invert = 1
658
        elif switch == '-g':
659
            invert = genpatch = 1
660
        elif switch == '-h':
661
            checkincludes = 1
662
        elif switch == '-k':
663
            fp = open(val, "r")
664
            while 1:
665
                line = fp.readline()
666
                if not line:
667
                    break
668
                kill_list[line.strip()] = 1
669
        elif switch == '-l':
670
            norefs = 1
671
        elif switch == '-n':
672
            suppress = re.compile(val)
673
        elif switch == '-r':
674
            rulesfile = val
675
        elif switch == '-t':
676
            typecheck = 1
677
        elif switch == '-x':
678
            examine = val
679
 
680
    if len(arguments) < 1:
681
        sourcetree = "."
682
    else:
683
        sourcetree = arguments[0]
684
 
685
    # Load or regenerate the cross-reference database
686
    load_context(sourcetree)
687
 
688
    if not checkincludes:
689
        # OK, now filter the database
690
        keys = filter(myfilter, xrefs.keys())
691
        keys.sort()
692
 
693
        # If invert was specified, invert the database so it's keyed by file
694
        if invert:
695
            inverted = {}
696
            for key in keys:
697
                for file in xrefs[key]:
698
                    if not inverted.has_key(file):
699
                        inverted[file] = []
700
                    if key not in inverted[file]:
701
                        inverted[file].append(key)
702
            xrefs = inverted
703
            keys = inverted.keys()
704
            keys.sort()
705
 
706
    if genpatch:
707
        for file in keys:
708
            generate_patch(file, xrefs[file])
709
    elif checkincludes:
710
        includecheck(sourcetree)
711
    elif examine:
712
        shortname = namestrip(examine)
713
        if not rulebase.dictionary.has_key(shortname) and not mycml1types.has_key(examine):
714
            print "%s: no such symbol" % examine
715
        else:
716
            print "%s: a=%d c=%d h=%d o=%d n=%d m=%d d=%d x=%s f=%d" % (examine, cml1_declared(examine), in_code(examine), in_help(examine), in_cml1(examine), in_cml2(examine), in_makefile(examine), in_defconfig(examine), is_derived(examine), myfilter(examine))
717
    elif typecheck:
718
        print "CML1 type consistency report:"
719
        hits = []
720
        ok = 0
721
        for (key, item) in mycml1types.items():
722
            if len(item) == 1:
723
                ok += 1
724
            else:
725
                hits.append(key)
726
        print "%d symbols have consistent type declarations." % ok
727
        if hits:
728
            print "Non-declared or multiply-declared symbols:"
729
            for symbol in hits:
730
                print "%s:" % symbol
731
                for (type, locs) in mycml1types[symbol]:
732
                    print "    %-8s: %s" % (type, " ".join(locs))
733
        print "CML2 type cross-check:"
734
        typematch = 0
735
        missing = 0
736
        matching = 0
737
        typemap = {"bool":"bool", "trit":"tristate", "string":"string", "decimal":"int", "hexadecimal":"hex"}
738
        for (key, item) in mycml1types.items():
739
            if not rulebase.dictionary.has_key(namestrip(key)):
740
                missing += 1
741
                continue
742
            elif len(item) != 1:
743
                continue
744
            cml2symbol = rulebase.dictionary[namestrip(key)]
745
            cml1type = item[0][0]
746
            if typemap[cml2symbol.type] == cml1type:
747
                matching += 1
748
            elif cml2symbol.menu and cml2symbol.menu.type=="choices" and cml1type=="choice":
749
                matching += 1
750
            else:
751
                if cml2symbol.is_derived():
752
                    derived = "(derived)"
753
                else:
754
                    derived = ""
755
                print '"%s", line %d: %s, %s -> %s %s' % (cml2symbol.file, cml2symbol.lineno, key, item[0][0], cml2symbol.type, derived)
756
        print "%d CML1 symbols missing, %d type matches" % (missing, matching)
757
    else:
758
        # OK, list the filtered symbols
759
        try:
760
            report(keys, norefs)
761
        except (KeyboardInterrupt, IOError):
762
            pass        # In case we break a pipe by interrupting
763
 
764
# That's all, folks!

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.