17db96d56Sopenharmony_ci#! /usr/bin/env python3
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci"""finddiv - a grep-like tool that looks for division operators.
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ciUsage: finddiv [-l] file_or_directory ...
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ciFor directory arguments, all files in the directory whose name ends in
87db96d56Sopenharmony_ci.py are processed, and subdirectories are processed recursively.
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ciThis actually tokenizes the files to avoid false hits in comments or
117db96d56Sopenharmony_cistrings literals.
127db96d56Sopenharmony_ci
137db96d56Sopenharmony_ciBy default, this prints all lines containing a / or /= operator, in
147db96d56Sopenharmony_cigrep -n style.  With the -l option specified, it prints the filename
157db96d56Sopenharmony_ciof files that contain at least one / or /= operator.
167db96d56Sopenharmony_ci"""
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ciimport os
197db96d56Sopenharmony_ciimport sys
207db96d56Sopenharmony_ciimport getopt
217db96d56Sopenharmony_ciimport tokenize
227db96d56Sopenharmony_ci
237db96d56Sopenharmony_cidef main():
247db96d56Sopenharmony_ci    try:
257db96d56Sopenharmony_ci        opts, args = getopt.getopt(sys.argv[1:], "lh")
267db96d56Sopenharmony_ci    except getopt.error as msg:
277db96d56Sopenharmony_ci        usage(msg)
287db96d56Sopenharmony_ci        return 2
297db96d56Sopenharmony_ci    if not args:
307db96d56Sopenharmony_ci        usage("at least one file argument is required")
317db96d56Sopenharmony_ci        return 2
327db96d56Sopenharmony_ci    listnames = 0
337db96d56Sopenharmony_ci    for o, a in opts:
347db96d56Sopenharmony_ci        if o == "-h":
357db96d56Sopenharmony_ci            print(__doc__)
367db96d56Sopenharmony_ci            return
377db96d56Sopenharmony_ci        if o == "-l":
387db96d56Sopenharmony_ci            listnames = 1
397db96d56Sopenharmony_ci    exit = None
407db96d56Sopenharmony_ci    for filename in args:
417db96d56Sopenharmony_ci        x = process(filename, listnames)
427db96d56Sopenharmony_ci        exit = exit or x
437db96d56Sopenharmony_ci    return exit
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_cidef usage(msg):
467db96d56Sopenharmony_ci    sys.stderr.write("%s: %s\n" % (sys.argv[0], msg))
477db96d56Sopenharmony_ci    sys.stderr.write("Usage: %s [-l] file ...\n" % sys.argv[0])
487db96d56Sopenharmony_ci    sys.stderr.write("Try `%s -h' for more information.\n" % sys.argv[0])
497db96d56Sopenharmony_ci
507db96d56Sopenharmony_cidef process(filename, listnames):
517db96d56Sopenharmony_ci    if os.path.isdir(filename):
527db96d56Sopenharmony_ci        return processdir(filename, listnames)
537db96d56Sopenharmony_ci    try:
547db96d56Sopenharmony_ci        fp = open(filename)
557db96d56Sopenharmony_ci    except IOError as msg:
567db96d56Sopenharmony_ci        sys.stderr.write("Can't open: %s\n" % msg)
577db96d56Sopenharmony_ci        return 1
587db96d56Sopenharmony_ci    with fp:
597db96d56Sopenharmony_ci        g = tokenize.generate_tokens(fp.readline)
607db96d56Sopenharmony_ci        lastrow = None
617db96d56Sopenharmony_ci        for type, token, (row, col), end, line in g:
627db96d56Sopenharmony_ci            if token in ("/", "/="):
637db96d56Sopenharmony_ci                if listnames:
647db96d56Sopenharmony_ci                    print(filename)
657db96d56Sopenharmony_ci                    break
667db96d56Sopenharmony_ci                if row != lastrow:
677db96d56Sopenharmony_ci                    lastrow = row
687db96d56Sopenharmony_ci                    print("%s:%d:%s" % (filename, row, line), end=' ')
697db96d56Sopenharmony_ci
707db96d56Sopenharmony_cidef processdir(dir, listnames):
717db96d56Sopenharmony_ci    try:
727db96d56Sopenharmony_ci        names = os.listdir(dir)
737db96d56Sopenharmony_ci    except OSError as msg:
747db96d56Sopenharmony_ci        sys.stderr.write("Can't list directory: %s\n" % dir)
757db96d56Sopenharmony_ci        return 1
767db96d56Sopenharmony_ci    files = []
777db96d56Sopenharmony_ci    for name in names:
787db96d56Sopenharmony_ci        fn = os.path.join(dir, name)
797db96d56Sopenharmony_ci        if os.path.normcase(fn).endswith(".py") or os.path.isdir(fn):
807db96d56Sopenharmony_ci            files.append(fn)
817db96d56Sopenharmony_ci    files.sort(key=os.path.normcase)
827db96d56Sopenharmony_ci    exit = None
837db96d56Sopenharmony_ci    for fn in files:
847db96d56Sopenharmony_ci        x = process(fn, listnames)
857db96d56Sopenharmony_ci        exit = exit or x
867db96d56Sopenharmony_ci    return exit
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ciif __name__ == "__main__":
897db96d56Sopenharmony_ci    sys.exit(main())
90