Exemple #1
0
def main():
    # Reset arguments
    mode = None
    destdir = None
    localdir = None
    modcache = None
    verbose = None
    auxdir = None
    modules = None
    avoids = None
    sourcebase = None
    m4base = None
    pobase = None
    docbase = None
    testsbase = None
    tests = None
    libname = None
    lgpl = None
    makefile = None
    libtool = None
    conddeps = None
    macro_prefix = None
    podomain = None
    witness_c_macro = None
    vc_files = None
    dryrun = None
    errors = None

    info = classes.GLInfo()
    parser = argparse.ArgumentParser(prog=constants.APP['name'],
                                     usage='gnulib-tool.py --help',
                                     add_help=False)
    # help
    parser.add_argument('-h',
                        '--help',
                        '--hel',
                        '--he',
                        '--h',
                        dest='help',
                        default=None,
                        action='store_true')
    # version
    parser.add_argument('--version',
                        '--versio',
                        '--versi',
                        '--vers',
                        dest='version',
                        default=None,
                        action='store_true')
    # list
    parser.add_argument('-l',
                        '--list',
                        '--lis',
                        dest='mode_list',
                        default=None,
                        action='store_true')
    # find
    parser.add_argument('-f',
                        '--find',
                        '--fin',
                        '--fi',
                        '--f',
                        dest='mode_find',
                        default=None,
                        nargs='*')
    # import
    parser.add_argument('-i',
                        '--import',
                        dest='mode_import',
                        default=None,
                        nargs='*')
    # add-import
    parser.add_argument('-a',
                        '--add-import',
                        dest='mode_add_import',
                        default=None,
                        nargs='+')
    # remove-import
    parser.add_argument('-r',
                        '--remove-import',
                        dest='mode_remove_import',
                        default=None,
                        nargs='+')
    # update
    parser.add_argument('-u',
                        '--update',
                        dest='mode_update',
                        default=None,
                        action='store_true')
    # create-testdir
    parser.add_argument('-td',
                        '--create-testdir',
                        dest='mode_create_testdir',
                        default=None,
                        nargs='*')
    # create-megatestdir
    parser.add_argument('-mtd',
                        '--create-megatestdir',
                        dest='mode_create_megatestdir',
                        default=None,
                        nargs='*')
    # test
    parser.add_argument('-t',
                        '--test',
                        dest='mode_test',
                        default=None,
                        nargs='*')
    # megatest
    parser.add_argument('-mt',
                        '--megatest',
                        '--megates',
                        '--megate',
                        '--megat',
                        '--mega',
                        '--meg',
                        '--me',
                        '--m',
                        dest='mode_megatest',
                        default=None,
                        nargs='*')
    # copy-file
    parser.add_argument('-c',
                        '--copy-file',
                        dest='mode_copy_file',
                        default=None,
                        nargs='+')
    # extract-*
    parser.add_argument('-xD',
                        '--extract-description',
                        dest='mode_xdescription',
                        default=None,
                        nargs='*')
    parser.add_argument('-xc',
                        '--extract-comment',
                        dest='mode_xcomment',
                        default=None,
                        nargs='*')
    parser.add_argument('-xs',
                        '--extract-status',
                        dest='mode_xstatus',
                        default=None,
                        nargs='*')
    parser.add_argument('-xn',
                        '--extract-notice',
                        dest='mode_xnotice',
                        default=None,
                        nargs='*')
    parser.add_argument('-xa',
                        '--extract-applicability',
                        dest='mode_xapplicability',
                        default=None,
                        nargs='*')
    parser.add_argument('-xf',
                        '--extract-filelist',
                        dest='mode_xfilelist',
                        default=None,
                        nargs='*')
    parser.add_argument('-xd',
                        '--extract-dependencies',
                        dest='mode_xdependencies',
                        default=None,
                        nargs='*')
    parser.add_argument('-xac',
                        '--extract-autoconf-snippet',
                        dest='mode_xautoconf',
                        default=None,
                        nargs='*')
    parser.add_argument('-xam',
                        '--extract-automake-snippet',
                        dest='mode_xautomake',
                        default=None,
                        nargs='*')
    parser.add_argument('-xi',
                        '--extract-include-directive',
                        dest='mode_xinclude',
                        default=None,
                        nargs='*')
    parser.add_argument('-xl',
                        '--extract-link-directive',
                        dest='mode_xlink',
                        default=None,
                        nargs='*')
    parser.add_argument('-xL',
                        '--extract-license',
                        dest='mode_xlicense',
                        default=None,
                        nargs='*')
    parser.add_argument('-xm',
                        '--extract-maintainer',
                        dest='mode_xmaintainer',
                        default=None,
                        nargs='*')
    # no-changelog: a no-op for backward compatibility
    parser.add_argument('--no-changelog',
                        dest='changelog',
                        default=None,
                        action='store_false')
    # destdir
    parser.add_argument('-d', '--dir', dest='destdir', default=None, nargs=1)
    # localdir
    parser.add_argument('-ld',
                        '--local-dir',
                        dest='localdir',
                        default=None,
                        nargs=1)
    # verbose
    parser.add_argument('-v', '--verbose', default=0, action='count')
    # quiet
    parser.add_argument('-q', '--quiet', default=0, action='count')
    # dryrun
    parser.add_argument('--dry-run',
                        dest='dryrun',
                        default=None,
                        action='store_true')
    # inctests
    parser.add_argument('--with-tests',
                        dest='inctests',
                        default=None,
                        action='store_true')
    # makefile
    parser.add_argument("--makefile-name",
                        dest="makefile",
                        default=None,
                        type=str)
    # obsolete
    parser.add_argument('--with-obsolete',
                        dest='obsolete',
                        default=None,
                        action='store_true')
    # c++-tests
    parser.add_argument('--with-c++-tests',
                        dest='cxx',
                        default=None,
                        action='store_true')
    # longrunning-tests
    parser.add_argument('--with-longrunning-tests',
                        dest='longrunning',
                        default=None,
                        action='store_true')
    # privileged-tests
    parser.add_argument('--with-privileged-tests',
                        dest='privileged',
                        default=None,
                        action='store_true')
    # unportable-tests
    parser.add_argument('--with-unportable-tests',
                        dest='unportable',
                        default=None,
                        action='store_true')
    # all-tests
    parser.add_argument('--with-all-tests',
                        dest='alltests',
                        default=None,
                        action='store_true')
    # auxdir
    parser.add_argument('--aux-dir', dest='auxdir', default=None, nargs=1)
    # libname
    parser.add_argument('--lib', dest='libname', default=None, nargs=1)
    # libtool
    parser.add_argument("--libtool",
                        dest=libtool,
                        default=False,
                        action="store_true")
    # sourcebase
    parser.add_argument('-sb',
                        '--source-base',
                        dest='sourcebase',
                        default=None,
                        nargs=1)
    # m4base
    parser.add_argument('-mb',
                        '--m4-base',
                        dest='m4base',
                        default=None,
                        nargs=1)
    # pobase
    parser.add_argument('-pb',
                        '--po-base',
                        dest='pobase',
                        default=None,
                        nargs=1)
    # docbase
    parser.add_argument('-db',
                        '--doc-base',
                        dest='docbase',
                        default=None,
                        nargs=1)
    # testsbase
    parser.add_argument('-tb',
                        '--tests-base',
                        dest='testsbase',
                        default=None,
                        nargs=1)
    # lgpl
    parser.add_argument('--lgpl',
                        dest='lgpl',
                        default=False,
                        type=int,
                        nargs='?')
    # avoids
    parser.add_argument('--avoid', dest='avoids', default=None, nargs='+')

    # Parse the given arguments.
    cmdargs = parser.parse_args()

    # Determine when user tries to combine modes.
    args = [
        cmdargs.mode_list,
        cmdargs.mode_import,
        cmdargs.mode_add_import,
        cmdargs.mode_remove_import,
        cmdargs.mode_update,
        cmdargs.mode_create_testdir,
        cmdargs.mode_create_megatestdir,
        cmdargs.mode_test,
        cmdargs.mode_megatest,
        cmdargs.mode_copy_file,
        cmdargs.mode_xdescription,
        cmdargs.mode_xcomment,
        cmdargs.mode_xstatus,
        cmdargs.mode_xnotice,
        cmdargs.mode_xapplicability,
        cmdargs.mode_xfilelist,
        cmdargs.mode_xdependencies,
        cmdargs.mode_xautoconf,
        cmdargs.mode_xautomake,
        cmdargs.mode_xinclude,
        cmdargs.mode_xlink,
        cmdargs.mode_xlicense,
        cmdargs.mode_xmaintainer,
    ]
    overflow = [arg for arg in args if arg]
    if len(overflow) > 1:
        message = 'gnulib-tool: Unable to combine different modes of work.\n'
        message += 'Try \'gnulib-tool --help\' for more information.\n'
        sys.stderr.write(message)
        sys.exit(1)

    # Determine selected mode.
    if cmdargs.help != None:
        print(info.usage())
        sys.exit(0)
    if cmdargs.version != None:
        message = '''gnulib-tool (%s %s)%s\n%s\n%s\n\nWritten by %s.''' % \
            (info.package(), info.date(), info.version(), info.copyright(),
             info.license(), info.authors())
        print(message)
        sys.exit(0)
    if cmdargs.mode_list != None:
        mode = 'list'
    if cmdargs.mode_import != None:
        mode = 'import'
        modules = list(cmdargs.mode_import)
    if cmdargs.mode_add_import != None:
        mode = 'add-import'
        modules = list(cmdargs.mode_add_import)
    if cmdargs.mode_remove_import != None:
        mode = 'remove-import'
        modules = list(cmdargs.mode_remove_import)
    if cmdargs.mode_update != None:
        mode = 'update'
    if cmdargs.mode_create_testdir != None:
        mode = 'create-testdir'
        modules = list(cmdargs.mode_create_testdir)
    if cmdargs.mode_create_megatestdir != None:
        mode = 'create-megatestdir'
        modules = list(cmdargs.mode_create_megatestdir)
    if cmdargs.mode_test != None:
        mode = 'test'
        modules = list(cmdargs.mode_test)
    if cmdargs.mode_megatest != None:
        mode = 'megatest'
        modules = list(cmdargs.mode_megatest)
    if cmdargs.mode_xdescription != None:
        mode = 'extract-description'
        modules = list(cmdargs.mode_xdescription)
    if cmdargs.mode_xcomment != None:
        mode = 'extract-comment'
        modules = list(cmdargs.mode_xcomment)
    if cmdargs.mode_xstatus != None:
        mode = 'extract-status'
        modules = list(cmdargs.mode_xstatus)
    if cmdargs.mode_xnotice != None:
        mode = 'extract-notice'
        modules = list(cmdargs.mode_xnotice)
    if cmdargs.mode_xapplicability != None:
        mode = 'extract-applicability'
        modules = list(cmdargs.mode_xapplicability)
    if cmdargs.mode_xfilelist != None:
        mode = 'extract-filelist'
        modules = list(cmdargs.mode_xfilelist)
    if cmdargs.mode_xautoconf != None:
        mode = 'extract-autoconf-snippet'
        modules = list(cmdargs.mode_xautoconf)
    if cmdargs.mode_xautomake != None:
        mode = 'extract-automake-snippet'
        modules = list(cmdargs.mode_xautomake)
    if cmdargs.mode_xdependencies != None:
        mode = 'extract-dependencies'
        modules = list(cmdargs.mode_xdependencies)
    if cmdargs.mode_xinclude != None:
        mode = 'extract-include-directive'
        modules = list(cmdargs.mode_xinclude)
    if cmdargs.mode_xlink != None:
        mode = 'extract-link-directive'
        modules = list(cmdargs.mode_xlink)
    if cmdargs.mode_xlicense != None:
        mode = 'extract-license'
        modules = list(cmdargs.mode_xlicense)
    if cmdargs.mode_xmaintainer != None:
        mode = 'extract-maintainer'
        modules = list(cmdargs.mode_xmaintainer)
    if cmdargs.mode_copy_file != None:
        mode = 'copy-file'
        if len(cmdargs.mode_copy_file) > 2:
            message = '%s: *** ' % constants.APP['name']
            message += 'invalid number of arguments for --%s' % mode
            message += '\n%s: *** Exit.\n' % constants.APP['name']
            sys.stderr.write(message)
            sys.exit(1)
        files = list(cmdargs.mode_copy_file)

    # Determine specific settings.
    destdir = cmdargs.destdir
    if destdir != None:
        destdir = cmdargs.destdir[0]
    localdir = cmdargs.localdir
    if localdir != None:
        localdir = cmdargs.localdir[0]
    libname = cmdargs.libname
    if libname != None:
        libname = cmdargs.libname[0]
    auxdir = cmdargs.auxdir
    if auxdir != None:
        auxdir = cmdargs.auxdir[0]
    sourcebase = cmdargs.sourcebase
    if sourcebase != None:
        sourcebase = cmdargs.sourcebase[0]
    m4base = cmdargs.m4base
    if m4base != None:
        m4base = cmdargs.m4base[0]
    pobase = cmdargs.pobase
    if pobase != None:
        pobase = cmdargs.pobase[0]
    testsbase = cmdargs.testsbase
    if testsbase != None:
        testsbase = cmdargs.testsbase[0]
    dryrun = cmdargs.dryrun
    verbose = -cmdargs.quiet + cmdargs.verbose
    inctests = cmdargs.inctests
    flags = [
        cmdargs.inctests, cmdargs.obsolete, cmdargs.cxx, cmdargs.longrunning,
        cmdargs.privileged, cmdargs.unportable, cmdargs.alltests
    ]
    testflags = list()
    for flag in flags:
        index = flags.index(flag)
        if flag != None:
            if flag:
                if index == 0:
                    testflags += [constants.TESTS['tests']]
                elif index == 1:
                    testflags += [constants.TESTS['obsolete']]
                elif index == 2:
                    testflags += [constants.TESTS['cxx-tests']]
                elif index == 3:
                    testflags += [constants.TESTS['longrunning-tests']]
                elif index == 4:
                    testflags += [constants.TESTS['privileged-tests']]
                elif index == 5:
                    testflags += [constants.TESTS['unportable-tests']]
                elif index == 6:
                    testflags += [constants.TESTS['all-tests']]
    lgpl = cmdargs.lgpl
    libtool = cmdargs.libtool
    makefile = cmdargs.makefile
    if lgpl == None:
        lgpl = True
    avoids = cmdargs.avoids

    # Create pygnulib configuration.
    config = classes.GLConfig(
        destdir=destdir,
        localdir=localdir,
        m4base=m4base,
        auxdir=auxdir,
        modules=modules,
        avoids=avoids,
        sourcebase=sourcebase,
        pobase=pobase,
        docbase=docbase,
        testsbase=testsbase,
        testflags=testflags,
        libname=libname,
        lgpl=lgpl,
        makefile=makefile,
        libtool=libtool,
        conddeps=conddeps,
        macro_prefix=macro_prefix,
        podomain=podomain,
        witness_c_macro=witness_c_macro,
        vc_files=vc_files,
        modcache=modcache,
        verbose=verbose,
        dryrun=dryrun,
    )

    # Canonicalize the inctests variable.
    if inctests == None:
        if mode in ['import', 'add-import', 'remove-import', 'update']:
            config.disableTestFlag(TESTS['tests'])
        elif mode in [
                'create-testdir', 'create-megatestdir', 'test', 'megatest'
        ]:
            config.enableTestFlag(TESTS['tests'])

    # Work in the given mode.
    if mode in ['list']:
        modulesystem = classes.GLModuleSystem(config)
        listing = modulesystem.list()
        result = '\n'.join(listing)
        os.rmdir(config['tempdir'])
        print(result)

    elif mode in ['import', 'add-import', 'remove-import', 'update']:
        mode = MODES[mode]
        if not destdir:
            destdir = '.'
        config.setDestDir(destdir)

        if mode == MODES['import']:
            # Set variables to default values.
            if not sourcebase:
                sourcebase = 'lib'
            if not m4base:
                m4base = 'm4'
            if not docbase:
                docbase = 'doc'
            if not testsbase:
                testsbase = 'tests'
            if not macro_prefix:
                macro_prefix = 'gl'
            config.setSourceBase(sourcebase)
            config.setM4Base(m4base)
            config.setDocBase(docbase)
            config.setTestsBase(testsbase)
            config.setMacroPrefix(macro_prefix)

            # Perform GLImport actions.
            importer = classes.GLImport(config, mode)
            filetable, transformers = importer.prepare()
            importer.execute(filetable, transformers)

        else:  # if mode != MODE['--import']
            if m4base:
                if not isfile(joinpath(destdir, m4base, 'gnulib-cache.m4')):
                    if not sourcebase:
                        sourcebase = 'lib'
                    if not docbase:
                        docbase = 'doc'
                    if not testsbase:
                        testsbase = 'tests'
                    if not macro_prefix:
                        macro_prefix = 'gl'
                    config.setSourceBase(sourcebase)
                    config.setM4Base(m4base)
                    config.setDocBase(docbase)
                    config.setTestsBase(testsbase)
                    config.setMacroPrefix(macro_prefix)
                # Perform GLImport actions.
                importer = classes.GLImport(config, mode)
                filetable, transformers = importer.prepare()
                importer.execute(filetable, transformers)
            else:  # if not m4base
                m4dirs = list()
                dirisnext = bool()
                filepath = joinpath(destdir, 'Makefile.am')
                if isfile(filepath):
                    with codecs.open(filepath, 'rb', 'UTF-8') as file:
                        data = file.read()
                        data = data.split('ACLOCAL_AMFLAGS')[1]
                        data = data[data.find('=') + 1:data.find('\n')]
                    aclocal_amflags = data.split()
                    for aclocal_amflag in aclocal_amflags:
                        if dirisnext:
                            if not isabs(aclocal_amflag):
                                m4dirs += [aclocal_amflag]
                        else:  # if not dirisnext
                            if aclocal_amflag == '-I':
                                dirisnext = True
                            else:  # if aclocal_amflag != '-I'
                                dirisnext = False
                else:  # if not isfile(filepath)
                    filepath = joinpath(destdir, 'aclocal.m4')
                    if isfile(filepath):
                        pattern = constants.compiler(
                            r'm4_include\(\[(.*?)\]\)')
                        with codecs.open(filepath, 'rb', 'UTF-8') as file:
                            m4dirs = pattern.findall(file.read())
                        m4dirs = [os.path.dirname(m4dir) for m4dir in m4dirs]
                        m4dirs = \
                            [  # Begin filtering
                                m4dir for m4dir in m4dirs \
                                if isfile(joinpath(destdir, m4dir, 'gnulib-cache.m4'))
                            ]  # Finish filtering
                        m4dirs = sorted(set(m4dirs))
                if len(m4dirs) == 0:
                    # First use of gnulib in a package.
                    # Any number of additional modules can be given.
                    if not sourcebase:
                        sourcebase = 'lib'
                    m4base = 'm4'
                    if not docbase:
                        docbase = 'doc'
                    if not testsbase:
                        testsbase = 'tests'
                    if not macro_prefix:
                        macro_prefix = 'gl'
                    config.setSourceBase(sourcebase)
                    config.setM4Base(m4base)
                    config.setDocBase(docbase)
                    config.setTestsBase(testsbase)
                    config.setMacroPrefix(macro_prefix)
                    # Perform GLImport actions.
                    importer = classes.GLImport(config, mode)
                    filetable, transformers = importer.prepare()
                    importer.execute(filetable, transformers)
                elif len(m4dirs) == 1:
                    m4base = m4dirs[-1]
                    config.setM4Base(m4base)
                    # Perform GLImport actions.
                    importer = classes.GLImport(config, mode)
                    filetable, transformers = importer.prepare()
                    importer.execute(filetable, transformers)
                else:  # if len(m4dirs) > 1
                    for m4base in m4dirs:
                        config.setM4Base(m4base)
                        # Perform GLImport actions.
                        importer = classes.GLImport(config, mode)
                        filetable, transformers = importer.prepare()
                        importer.execute(filetable, transformers)

    elif mode == 'create-testdir':
        if not destdir:
            message = '%s: *** ' % constants.APP['name']
            message += 'please specify --dir option'
            message += '\n%s: *** Exit.\n' % constants.APP['name']
            sys.stderr.write(message)
            sys.exit(1)
        if not auxdir:
            auxdir = 'build-aux'
        config.setAuxDir(auxdir)
        testdir = classes.GLTestDir(config, destdir)
        testdir.execute()

    elif mode == 'create-megatestdir':
        if not destdir:
            message = '%s: *** ' % constants.APP['name']
            message += 'please specify --dir option'
            message += '\n%s: *** Exit.\n' % constants.APP['name']
            sys.stderr.write(message)
            sys.exit(1)
        if not auxdir:
            auxdir = 'build-aux'
        config.setAuxDir(auxdir)
        testdir = classes.GLMegaTestDir(config, destdir)
        testdir.execute()

    elif mode == 'test':
        if not destdir:
            destdir = 'testdir %04d' % random.randrange(0, 9999)
        if not auxdir:
            auxdir = 'build-aux'
        config.setAuxDir(auxdir)
        testdir = classes.GLTestDir(config, destdir)
        testdir.execute()
        os.chdir(destdir)
        os.mkdir('build')
        os.chdir('build')
        try:  # Try to execute commands
            sp.call(['../configure'])
            sp.call([UTILS['make']])
            sp.call([UTILS['make'], 'check'])
            sp.call([UTILS['make'], 'distclean'])
        except Exception as error:
            sys.exit(1)
        args = ['find', '.', '-type', 'f', '-print']
        remaining = sp.check_output(args).decode(ENCS['shell'])
        lines = [
            line.strip() for line in remaining.split('\n') if line.strip()
        ]
        remaining = ' '.join(lines)
        if remaining:
            message = 'Remaining files: %s\n' % remaining
            message += 'gnulib-tool: *** Stop.\n'
            sys.stderr.write(message)
            sys.exit(1)
        os.chdir('../..')
        sp.call(['rm', '-rf', destdir], shell=False)

    elif mode == 'megatest':
        if not destdir:
            destdir = 'testdir %04d' % random.randrange(0, 9999)
        if not auxdir:
            auxdir = 'build-aux'
        config.setAuxDir(auxdir)
        testdir = classes.GLMegaTestDir(config, destdir)
        testdir.execute()
        os.chdir(destdir)
        os.mkdir('build')
        os.chdir('build')
        sp.call(['../configure'])
        sp.call([UTILS['make']])
        sp.call([UTILS['make'], 'check'])
        sp.call([UTILS['make'], 'distclean'])
        args = ['find', '.', '-type', 'f', '-print']
        remaining = sp.check_output(args).decode(ENCS['shell'])
        lines = [
            line.strip() for line in remaining.split('\n') if line.strip()
        ]
        remaining = ' '.join(lines)
        if remaining:
            message = 'Remaining files: %s\n' % remaining
            message += 'gnulib-tool: *** Stop.\n'
            sys.stderr.write(message)
            sys.exit(1)
        os.chdir('../..')
        sp.call(['rm', '-rf', destdir], shell=False)

    elif mode == 'extract-description':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getDescription())

    elif mode == 'extract-comment':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getComment())

    elif mode == 'extract-status':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            status = module.getStatus()
            print('\n'.join(status))

    elif mode == 'extract-notice':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getNotice())

    elif mode == 'extract-applicability':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getApplicability())

    elif mode == 'extract-filelist':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            files = module.getFiles()
            print('\n'.join(files))

    elif mode == 'extract-dependencies':
        result = string()
        if avoids:
            message = '%s: *** ' % constants.APP['name']
            message += 'cannot combine --avoid and --extract-dependencies\n'
            message += '%s: *** Exit.\n' % constants.APP['name']
            sys.stderr.write(message)
            sys.exit(1)
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            dependencies = module.getDependencies()
            if dependencies:
                for depmodule, condition in dependencies:
                    if condition == None:
                        result += '%s\n' % str(depmodule)
                    else:  # if condition != None
                        result += '%s\t%s' % (str(depmodule), condition)
        print(result)

    elif mode == 'extract-autoconf-snippet':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getAutoconfSnippet())

    elif mode == 'extract-automake-snippet':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getAutomakeSnippet())

    elif mode == 'extract-include-directive':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getInclude())

    elif mode == 'extract-link-directive':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getLink())

    elif mode == 'extract-license':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getLicense())

    elif mode == 'extract-maintainer':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            print(module.getMaintainer())

    elif mode == 'extract-tests-module':
        modulesystem = classes.GLModuleSystem(config)
        modules = [modulesystem.find(module) for module in modules]
        for module in modules:
            if module.getTestsModule():
                print(module.getTestsName())

    elif mode == 'copy-file':
        srcpath = files[0]
        if len(files) == 2:
            dest = files[1]
        else:  # if len(files) != 2
            dest = '.'
        if type(srcpath) is bytes:
            srcpath = srcpath.decode(ENCS['default'])
        if type(dest) is bytes:
            dest = dest.decode(ENCS['default'])
        if not auxdir:
            auxdir = 'build-aux'
        if not sourcebase:
            sourcebase = 'lib'
        if not m4base:
            m4base = 'm4'
        if not docbase:
            docbase = 'doc'
        if not testsbase:
            testsbase = 'tests'
        config.setAuxDir(auxdir)
        config.setSourceBase(sourcebase)
        config.setM4Base(m4base)
        config.setDocBase(docbase)
        config.setTestsBase(testsbase)
        filesystem = classes.GLFileSystem(config)
        lookedup, flag = filesystem.lookup(srcpath)
        if isdir(dest):
            destdir = string(dest)
            if srcpath.startswith('build-aux/'):
                destpath = constants.substart('build-aux/', '%s/' % auxdir,
                                              srcpath)
            elif srcpath.startswith('doc/'):
                destpath = constants.substart('doc/', '%s/' % docbase, srcpath)
            elif srcpath.startswith('lib/'):
                destpath = constants.substart('lib/', '%s/' % sourcebase,
                                              srcpath)
            elif srcpath.startswith('m4/'):
                destpath = constants.substart('m4/', '%s/' % m4base, srcpath)
            elif srcpath.startswith('tests/'):
                destpath = constants.substart('tests/', '%s/' % testsbase,
                                              srcpath)
            elif srcpath.startswith('tests=lib/'):
                destpath = constants.substart('tests=lib/', '%s/' % testsbase,
                                              srcpath)
            elif srcpath.startswith('top/'):
                destpath = constants.substart('top/', '', srcpath)
            else:  # either case
                destpath = srcpath
        else:  # if not isdir(destpath)
            destdir = os.path.dirname(destpath)
            destpath = os.path.basename(destpath)
        # Create the directory for destfile.
        dirname = os.path.dirname(joinpath(destdir, destpath))
        if not config['dryrun']:
            if dirname and not isdir(dirname):
                try:  # Try to create directories
                    os.makedirs(dirname)
                except Exception as error:
                    pass
        # Copy the file.
        assistant = classes.GLFileAssistant(config)
        tmpfile = assistant.tmpfilename(destpath)
        shutil.copy(lookedup, tmpfile)
        already_present = True
        assistant.setOriginal(srcpath)
        assistant.setRewritten(destpath)
        if isfile(joinpath(destdir, destpath)):
            # The file already exists.
            assistant.update(lookedup, flag, tmpfile, already_present)
        else:  # if not isfile(joinpath(destdir, destpath))
            # Install the file.
            # Don't protest if the file should be there but isn't: it happens
            # frequently that developers don't put autogenerated files under version
            # control.
            assistant.add(lookedup, flag, tmpfile)
        if isfile(tmpfile):
            os.remove(tmpfile)

    else:
        message = '%s: *** ' % constants.APP['name']
        message += 'no mode specified'
        message += '\n%s: *** Exit.\n' % constants.APP['name']
        sys.stderr.write(message)
        sys.exit(1)
def main():
  # Reset arguments
  mode = None
  destdir = None
  localdir = None
  modcache = None
  verbose = None
  auxdir = None
  modules = None
  avoids = None
  sourcebase = None
  m4base = None
  pobase = None
  docbase = None
  testsbase = None
  tests = None
  libname = None
  lgpl = None
  makefile = None
  libtool = None
  conddeps = None
  macro_prefix = None
  podomain = None
  witness_c_macro = None
  vc_files = None
  dryrun = None
  errors = None
  
  info = classes.GLInfo()
  parser = argparse.ArgumentParser(
    prog=constants.APP['name'],
    usage='gnulib-tool.py --help',
    add_help=False)
  # help
  parser.add_argument('-h', '--help', '--hel', '--he', '--h',
    dest='help',
    default=None,
    action='store_true')
  # version
  parser.add_argument('--version', '--versio', '--versi', '--vers',
    dest='version',
    default=None,
    action='store_true')
  # list
  parser.add_argument('-l', '--list', '--lis',
    dest='mode_list',
    default=None,
    action='store_true')
  # find
  parser.add_argument('-f', '--find', '--fin', '--fi', '--f',
    dest='mode_find',
    default=None,
    nargs='*')
  # import
  parser.add_argument('-i', '--import',
    dest='mode_import',
    default=None,
    nargs='+')
  # add-import
  parser.add_argument('-a', '--add-import',
    dest='mode_add_import',
    default=None,
    nargs='+')
  # remove-import
  parser.add_argument('-r', '--remove-import',
    dest='mode_remove_import',
    default=None,
    nargs='+')
  # update
  parser.add_argument('-u', '--update',
    dest='mode_update',
    default=None,
    action='store_true')
  # create-testdir
  parser.add_argument('-td', '--create-testdir',
    dest='mode_create_testdir',
    default=None,
    nargs='*')
  # create-megatestdir
  parser.add_argument('-mtd', '--create-megatestdir',
    dest='mode_create_megatestdir',
    default=None,
    nargs='*')
  # test
  parser.add_argument('-t', '--test',
    dest='mode_test',
    default=None,
    nargs='*')
  # megatest
  parser.add_argument('-mt', '--megatest', '--megates', '--megate', '--megat',
    '--mega', '--meg', '--me', '--m',
    dest='mode_megatest',
    default=None,
    nargs='*')
  # copy-file
  parser.add_argument('-c', '--copy-file',
    dest='mode_copy_file',
    default=None,
    nargs='+')
  # extract-*
  parser.add_argument('-xD', '--extract-description',
    dest='mode_xdescription',
    default=None,
    nargs='*')
  parser.add_argument('-xc', '--extract-comment',
    dest='mode_xcomment',
    default=None,
    nargs='*')
  parser.add_argument('-xs', '--extract-status',
    dest='mode_xstatus',
    default=None,
    nargs='*')
  parser.add_argument('-xn', '--extract-notice',
    dest='mode_xnotice',
    default=None,
    nargs='*')
  parser.add_argument('-xa', '--extract-applicability',
    dest='mode_xapplicability',
    default=None,
    nargs='*')
  parser.add_argument('-xf', '--extract-filelist',
    dest='mode_xfilelist',
    default=None,
    nargs='*')
  parser.add_argument('-xd', '--extract-dependencies',
    dest='mode_xdependencies',
    default=None,
    nargs='*')
  parser.add_argument('-xac', '--extract-autoconf-snippet',
    dest='mode_xautoconf',
    default=None,
    nargs='*')
  parser.add_argument('-xam', '--extract-automake-snippet',
    dest='mode_xautomake',
    default=None,
    nargs='*')
  parser.add_argument('-xi', '--extract-include-directive',
    dest='mode_xinclude',
    default=None,
    nargs='*')
  parser.add_argument('-xl', '--extract-link-directive',
    dest='mode_xlink',
    default=None,
    nargs='*')
  parser.add_argument('-xL', '--extract-license',
    dest='mode_xlicense',
    default=None,
    nargs='*')
  parser.add_argument('-xm', '--extract-maintainer',
    dest='mode_xmaintainer',
    default=None,
    nargs='*')
  # destdir
  parser.add_argument('-d', '--destdir',
    dest='destdir',
    default=None,
    nargs=1)
  # localdir
  parser.add_argument('-ld', '--local-dir',
    dest='localdir',
    default=None,
    nargs=1)
  # verbose
  parser.add_argument('-v', '--verbose',
    default=0,
    action='count')
  # quiet
  parser.add_argument('-q', '--quiet',
    default=0,
    action='count')
  # dryrun
  parser.add_argument('--dry-run',
    dest='dryrun',
    default=None,
    action='store_true')
  # inctests
  parser.add_argument('--with-tests',
    dest='inctests',
    default=None,
    action='store_true')
  # obsolete
  parser.add_argument('--with-obsolete',
    dest='obsolete',
    default=None,
    action='store_true')
  # c++-tests
  parser.add_argument('--with-c++-tests',
    dest='cxx',
    default=None,
    action='store_true')
  # longrunning-tests
  parser.add_argument('--with-longrunning-tests',
    dest='longrunning',
    default=None,
    action='store_true')
  # privileged-tests
  parser.add_argument('--with-privileged-tests',
    dest='privileged',
    default=None,
    action='store_true')
  # unportable-tests
  parser.add_argument('--with-unportable-tests',
    dest='unportable',
    default=None,
    action='store_true')
  # all-tests
  parser.add_argument('--with-all-tests',
    dest='alltests',
    default=None,
    action='store_true')
  # auxdir
  parser.add_argument('--aux-dir',
    dest='auxdir',
    default=None,
    nargs=1)
  # libname
  parser.add_argument('--lib',
    dest='libname',
    default=None,
    nargs=1)
  # sourcebase
  parser.add_argument('-sb', '--source-base',
    dest='sourcebase',
    default=None,
    nargs=1)
  # m4base
  parser.add_argument('-mb', '--m4-base',
    dest='m4base',
    default=None,
    nargs=1)
  # pobase
  parser.add_argument('-pb', '--po-base',
    dest='pobase',
    default=None,
    nargs=1)
  # docbase
  parser.add_argument('-db', '--doc-base',
    dest='docbase',
    default=None,
    nargs=1)
  # testsbase
  parser.add_argument('-tb', '--tests-base',
    dest='testsbase',
    default=None,
    nargs=1)
  # lgpl
  parser.add_argument('--lgpl',
    dest='lgpl',
    default=False,
    type=int,
    nargs='?')
  # avoids
  parser.add_argument('--avoid',
    dest='avoids',
    default=None,
    nargs='+')
  
  # Parse the given arguments.
  cmdargs = parser.parse_args()
  
  # Determine when user tries to combine modes.
  args = [
    cmdargs.mode_list,
    cmdargs.mode_import,
    cmdargs.mode_add_import,
    cmdargs.mode_remove_import,
    cmdargs.mode_update,
    cmdargs.mode_create_testdir,
    cmdargs.mode_create_megatestdir,
    cmdargs.mode_test,
    cmdargs.mode_megatest,
    cmdargs.mode_copy_file,
    cmdargs.mode_xdescription,
    cmdargs.mode_xcomment,
    cmdargs.mode_xstatus,
    cmdargs.mode_xnotice,
    cmdargs.mode_xapplicability,
    cmdargs.mode_xfilelist,
    cmdargs.mode_xdependencies,
    cmdargs.mode_xautoconf,
    cmdargs.mode_xautomake,
    cmdargs.mode_xinclude,
    cmdargs.mode_xlink,
    cmdargs.mode_xlicense,
    cmdargs.mode_xmaintainer,
  ]
  overflow = [arg for arg in args if arg]
  if len(overflow) > 1:
    message = 'gnulib-tool: Unable to combine different modes of work.\n'
    message += 'Try \'gnulib-tool --help\' for more information.\n'
    sys.stderr.write(message)
    sys.exit(1)
  
  # Determine selected mode.
  if cmdargs.help != None:
    print(info.usage())
    sys.exit(0)
  if cmdargs.version != None:
    message = '''gnulib-tool (%s %s)%s\n%s\n%s\n\nWritten by %s.''' % \
      (info.package(), info.date(), info.version(), info.copyright(),
        info.license(), info.authors())
    print(message)
    sys.exit(0)
  if cmdargs.mode_list != None:
    mode = 'list'
  if cmdargs.mode_import != None:
    mode = 'import'
    modules = list(cmdargs.mode_import)
  if cmdargs.mode_add_import != None:
    mode = 'add-import'
    modules = list(cmdargs.mode_add_import)
  if cmdargs.mode_remove_import != None:
    mode = 'remove-import'
    modules = list(cmdargs.mode_remove_import)
  if cmdargs.mode_update != None:
    mode = 'update'
  if cmdargs.mode_create_testdir != None:
    mode = 'create-testdir'
    modules = list(cmdargs.mode_create_testdir)
  if cmdargs.mode_create_megatestdir != None:
    mode = 'create-megatestdir'
    modules = list(cmdargs.mode_create_megatestdir)
  if cmdargs.mode_test != None:
    mode = 'test'
    modules = list(cmdargs.mode_test)
  if cmdargs.mode_megatest != None:
    mode = 'megatest'
    modules = list(cmdargs.mode_megatest)
  if cmdargs.mode_xdescription != None:
    mode = 'extract-description'
    modules = list(cmdargs.mode_xdescription)
  if cmdargs.mode_xcomment != None:
    mode = 'extract-comment'
    modules = list(cmdargs.mode_xcomment)
  if cmdargs.mode_xstatus != None:
    mode = 'extract-status'
    modules = list(cmdargs.mode_xstatus)
  if cmdargs.mode_xnotice != None:
    mode = 'extract-notice'
    modules = list(cmdargs.mode_xnotice)
  if cmdargs.mode_xapplicability != None:
    mode = 'extract-applicability'
    modules = list(cmdargs.mode_xapplicability)
  if cmdargs.mode_xfilelist != None:
    mode = 'extract-filelist'
    modules = list(cmdargs.mode_xfilelist)
  if cmdargs.mode_xautoconf != None:
    mode = 'extract-autoconf-snippet'
    modules = list(cmdargs.mode_xautoconf)
  if cmdargs.mode_xautomake != None:
    mode = 'extract-automake-snippet'
    modules = list(cmdargs.mode_xautomake)
  if cmdargs.mode_xdependencies != None:
    mode = 'extract-dependencies'
    modules = list(cmdargs.mode_xdependencies)
  if cmdargs.mode_xinclude != None:
    mode = 'extract-include-directive'
    modules = list(cmdargs.mode_xinclude)
  if cmdargs.mode_xlink != None:
    mode = 'extract-link-directive'
    modules = list(cmdargs.mode_xlink)
  if cmdargs.mode_xlicense != None:
    mode = 'extract-license'
    modules = list(cmdargs.mode_xlicense)
  if cmdargs.mode_xmaintainer != None:
    mode = 'extract-maintainer'
    modules = list(cmdargs.mode_xmaintainer)
  if cmdargs.mode_copy_file != None:
    mode = 'copy-file'
    if len(cmdargs.mode_copy_file) > 2:
      message = '%s: *** ' % constants.APP['name']
      message += 'invalid number of arguments for --%s' % mode
      message += '\n%s: *** Exit.\n' % constants.APP['name']
      sys.stderr.write(message)
      sys.exit(1)
    files = list(cmdargs.mode_copy_file)
  
  # Determine specific settings.
  destdir = cmdargs.destdir
  if destdir != None:
    destdir = cmdargs.destdir[0]
  localdir = cmdargs.localdir
  if localdir != None:
    localdir = cmdargs.localdir[0]
  libname = cmdargs.libname
  if libname != None:
    libname = cmdargs.libname[0]
  auxdir = cmdargs.auxdir
  if auxdir != None:
    auxdir = cmdargs.auxdir[0]
  sourcebase = cmdargs.sourcebase
  if sourcebase != None:
    sourcebase = cmdargs.sourcebase[0]
  m4base = cmdargs.m4base
  if m4base != None:
    m4base = cmdargs.m4base[0]
  pobase = cmdargs.pobase
  if pobase != None:
    pobase = cmdargs.pobase[0]
  testsbase = cmdargs.testsbase
  if testsbase != None:
    testsbase = cmdargs.testsbase[0]
  dryrun = cmdargs.dryrun
  verbose = -cmdargs.quiet +cmdargs.verbose
  inctests = cmdargs.inctests
  flags = [cmdargs.inctests, cmdargs.obsolete, cmdargs.cxx,
    cmdargs.longrunning, cmdargs.privileged, cmdargs.unportable,
    cmdargs.alltests]
  testflags = list()
  for flag in flags:
    index = flags.index(flag)
    if flag != None:
      if flag:
        if index == 0:
          testflags += [constants.TESTS['tests']]
        elif index == 1:
          testflags += [constants.TESTS['obsolete']]
        elif index == 2:
          testflags += [constants.TESTS['cxx-tests']]
        elif index == 3:
          testflags += [constants.TESTS['longrunning-tests']]
        elif index == 4:
          testflags += [constants.TESTS['privileged-tests']]
        elif index == 5:
          testflags += [constants.TESTS['unportable-tests']]
        elif index == 6:
          testflags += [constants.TESTS['all-tests']]
  lgpl = cmdargs.lgpl
  if lgpl == None:
    lgpl = True
  avoids = cmdargs.avoids
  
  # Create pygnulib configuration.
  config = classes.GLConfig\
  (
    destdir=destdir,
    localdir=localdir,
    m4base=m4base,
    auxdir=auxdir,
    modules=modules,
    avoids=avoids,
    sourcebase=sourcebase,
    pobase=pobase,
    docbase=docbase,
    testsbase=testsbase,
    testflags=testflags,
    libname=libname,
    lgpl=lgpl,
    makefile=makefile,
    libtool=libtool,
    conddeps=conddeps,
    macro_prefix=macro_prefix,
    podomain=podomain,
    witness_c_macro=witness_c_macro,
    vc_files=vc_files,
    modcache=modcache,
    verbose=verbose,
    dryrun=dryrun,
  )
  
  # Canonicalize the inctests variable.
  if inctests == None:
    if mode in ['import', 'add-import', 'remove-import', 'update']:
      config.disableTestFlag(TESTS['tests'])
    elif mode in ['create-testdir', 'create-megatestdir', 'test', 'megatest']:
      config.enableTestFlag(TESTS['tests'])
  
  # Work in the given mode.
  if mode in ['list']:
    modulesystem = classes.GLModuleSystem(config)
    listing = modulesystem.list()
    result = '\n'.join(listing)
    os.rmdir(config['tempdir'])
    print(result)
    
  elif mode in ['import', 'add-import', 'remove-import', 'update']:
    mode = MODES[mode]
    if not destdir:
      destdir = '.'
    config.setDestDir(destdir)
    
    if mode == MODES['import']:
      # Set variables to default values.
      if not sourcebase:
        sourcebase = 'lib'
      if not m4base:
        m4base = 'm4'
      if not docbase:
        docbase = 'doc'
      if not testsbase:
        testsbase = 'tests'
      if not macro_prefix:
        macro_prefix = 'gl'
      config.setSourceBase(sourcebase)
      config.setM4Base(m4base)
      config.setDocBase(docbase)
      config.setTestsBase(testsbase)
      config.setMacroPrefix(macro_prefix)
      
      # Perform GLImport actions.
      importer = classes.GLImport(config, mode)
      filetable, transformers = importer.prepare()
      importer.execute(filetable, transformers)
    
    else: # if mode != MODE['--import']
      if m4base:
        if not isfile(joinpath(destdir, m4base, 'gnulib-cache.m4')):
          if not sourcebase:
            sourcebase = 'lib'
          if not docbase:
            docbase = 'doc'
          if not testsbase:
            testsbase = 'tests'
          if not macro_prefix:
            macro_prefix = 'gl'
          config.setSourceBase(sourcebase)
          config.setM4Base(m4base)
          config.setDocBase(docbase)
          config.setTestsBase(testsbase)
          config.setMacroPrefix(macro_prefix)
        # Perform GLImport actions.
        importer = classes.GLImport(config, mode)
        filetable, transformers = importer.prepare()
        importer.execute(filetable, transformers)
      else: # if not m4base
        m4dirs = list()
        dirisnext = bool()
        filepath = joinpath(destdir, 'Makefile.am')
        if isfile(filepath):
          with codecs.open(filepath, 'rb', 'UTF-8') as file:
            data = file.read()
            data = data.split('ACLOCAL_AMFLAGS')[1]
            data = data[data.find('=')+1:data.find('\n')]
          aclocal_amflags = data.split()
          for aclocal_amflag in aclocal_amflags:
            if dirisnext:
              if not isabs(aclocal_amflag):
                m4dirs += [aclocal_amflag]
            else: # if not dirisnext
              if aclocal_amflag == '-I':
                dirisnext = True
              else: # if aclocal_amflag != '-I'
                dirisnext = False
        else: # if not isfile(filepath)
          filepath = joinpath(destdir, 'aclocal.m4')
          if isfile(filepath):
            pattern = constants.compiler(r'm4_include\(\[(.*?)\]\)')
            with codecs.open(filepath, 'rb', 'UTF-8') as file:
              m4dirs = pattern.findall(file.read())
            m4dirs = [os.path.dirname(m4dir) for m4dir in m4dirs]
            m4dirs = \
            [ # Begin filtering
              m4dir for m4dir in m4dirs \
              if isfile(joinpath(destdir, m4dir, 'gnulib-cache.m4'))
            ] # Finish filtering
            m4dirs = sorted(set(m4dirs))
        if len(m4dirs) == 0:
          # First use of gnulib in a package.
          # Any number of additional modules can be given.
          if not sourcebase:
            sourcebase = 'lib'
          m4base = 'm4'
          if not docbase:
            docbase = 'doc'
          if not testsbase:
            testsbase = 'tests'
          if not macro_prefix:
            macro_prefix = 'gl'
          config.setSourceBase(sourcebase)
          config.setM4Base(m4base)
          config.setDocBase(docbase)
          config.setTestsBase(testsbase)
          config.setMacroPrefix(macro_prefix)
          # Perform GLImport actions.
          importer = classes.GLImport(config, mode)
          filetable, transformers = importer.prepare()
          importer.execute(filetable, transformers)
        elif len(m4dirs) == 1:
          m4base = m4dirs[-1]
          config.setM4Base(m4base)
          # Perform GLImport actions.
          importer = classes.GLImport(config, mode)
          filetable, transformers = importer.prepare()
          importer.execute(filetable, transformers)
        else: # if len(m4dirs) > 1
          for m4base in m4dirs:
            config.setM4Base(m4base)
            # Perform GLImport actions.
            importer = classes.GLImport(config, mode)
            filetable, transformers = importer.prepare()
            importer.execute(filetable, transformers)
  
  elif mode == 'create-testdir':
    if not destdir:
      message = '%s: *** ' % constants.APP['name']
      message += 'please specify --dir option'
      message += '\n%s: *** Exit.\n' % constants.APP['name']
      sys.stderr.write(message)
      sys.exit(1)
    if not auxdir:
      auxdir = 'build-aux'
    config.setAuxDir(auxdir)
    testdir = classes.GLTestDir(config, destdir)
    testdir.execute()
  
  elif mode == 'create-megatestdir':
    if not destdir:
      message = '%s: *** ' % constants.APP['name']
      message += 'please specify --dir option'
      message += '\n%s: *** Exit.\n' % constants.APP['name']
      sys.stderr.write(message)
      sys.exit(1)
    if not auxdir:
      auxdir = 'build-aux'
    config.setAuxDir(auxdir)
    testdir = classes.GLMegaTestDir(config, destdir)
    testdir.execute()
  
  elif mode == 'test':
    if not destdir:
      destdir = 'testdir %04d' % random.randrange(0, 9999)
    if not auxdir:
      auxdir = 'build-aux'
    config.setAuxDir(auxdir)
    testdir = classes.GLTestDir(config, destdir)
    testdir.execute()
    os.chdir(destdir)
    os.mkdir('build')
    os.chdir('build')
    try: # Try to execute commands
      sp.call(['../configure'])
      sp.call([UTILS['make']])
      sp.call([UTILS['make'], 'check'])
      sp.call([UTILS['make'], 'distclean'])
    except Exception as error:
      sys.exit(1)
    args = ['find', '.', '-type', 'f', '-print']
    remaining = sp.check_output(args).decode(ENCS['shell'])
    lines = [line.strip() for line in remaining.split('\n') if line.strip()]
    remaining = ' '.join(lines)
    if remaining:
      message = 'Remaining files: %s\n' % remaining
      message += 'gnulib-tool: *** Stop.\n'
      sys.stderr.write(message)
      sys.exit(1)
    os.chdir('../..')
    sp.call(['rm', '-rf', destdir], shell=False)
    
  elif mode == 'megatest':
    if not destdir:
      destdir = 'testdir %04d' % random.randrange(0, 9999)
    if not auxdir:
      auxdir = 'build-aux'
    config.setAuxDir(auxdir)
    testdir = classes.GLMegaTestDir(config, destdir)
    testdir.execute()
    os.chdir(destdir)
    os.mkdir('build')
    os.chdir('build')
    sp.call(['../configure'])
    sp.call([UTILS['make']])
    sp.call([UTILS['make'], 'check'])
    sp.call([UTILS['make'], 'distclean'])
    args = ['find', '.', '-type', 'f', '-print']
    remaining = sp.check_output(args).decode(ENCS['shell'])
    lines = [line.strip() for line in remaining.split('\n') if line.strip()]
    remaining = ' '.join(lines)
    if remaining:
      message = 'Remaining files: %s\n' % remaining
      message += 'gnulib-tool: *** Stop.\n'
      sys.stderr.write(message)
      sys.exit(1)
    os.chdir('../..')
    sp.call(['rm', '-rf', destdir], shell=False)
  
  elif mode == 'extract-description':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getDescription())
    
  elif mode == 'extract-comment':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getComment())
    
  elif mode == 'extract-status':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      status = module.getStatus()
      print('\n'.join(status))
    
  elif mode == 'extract-notice':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getNotice())
    
  elif mode == 'extract-applicability':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getApplicability())
    
  elif mode == 'extract-filelist':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      files = module.getFiles()
      print('\n'.join(files))
    
  elif mode == 'extract-dependencies':
    result = string()
    if avoids:
      message = '%s: *** ' % constants.APP['name']
      message += 'cannot combine --avoid and --extract-dependencies\n'
      message += '%s: *** Exit.\n' % constants.APP['name']
      sys.stderr.write(message)
      sys.exit(1)
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      dependencies = module.getDependencies()
      if dependencies:
        for depmodule, condition in dependencies:
          if condition == None:
            result += '%s\n' % str(depmodule)
          else: # if condition != None
            result += '%s\t%s' % (str(depmodule), condition)
    print(result)
    
  elif mode == 'extract-autoconf-snippet':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getAutoconfSnippet())
    
  elif mode == 'extract-automake-snippet':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getAutomakeSnippet())
    
  elif mode == 'extract-include-directive':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getInclude())
    
  elif mode == 'extract-link-directive':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getLink())
    
  elif mode == 'extract-license':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getLicense())
    
  elif mode == 'extract-maintainer':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      print(module.getMaintainer())
    
  elif mode == 'extract-tests-module':
    modulesystem = classes.GLModuleSystem(config)
    modules = [modulesystem.find(module) for module in modules]
    for module in modules:
      if module.getTestsModule():
        print(module.getTestsName())
    
  elif mode == 'copy-file':
    srcpath = files[0]
    if len(files) == 2:
      dest = files[1]
    else: # if len(files) != 2
      dest = '.'
    if type(srcpath) is bytes:
      srcpath = srcpath.decode(ENCS['default'])
    if type(dest) is bytes:
      dest = dest.decode(ENCS['default'])
    if not auxdir:
      auxdir = 'build-aux'
    if not sourcebase:
      sourcebase = 'lib'
    if not m4base:
      m4base = 'm4'
    if not docbase:
      docbase = 'doc'
    if not testsbase:
      testsbase = 'tests'
    config.setAuxDir(auxdir)
    config.setSourceBase(sourcebase)
    config.setM4Base(m4base)
    config.setDocBase(docbase)
    config.setTestsBase(testsbase)
    filesystem = classes.GLFileSystem(config)
    lookedup, flag = filesystem.lookup(srcpath)
    if isdir(dest):
      destdir = string(dest)
      if srcpath.startswith('build-aux/'):
        destpath = constants.substart('build-aux/', '%s/' % auxdir, srcpath)
      elif srcpath.startswith('doc/'):
        destpath = constants.substart('doc/', '%s/' % docbase, srcpath)
      elif srcpath.startswith('lib/'):
        destpath = constants.substart('lib/', '%s/' % sourcebase, srcpath)
      elif srcpath.startswith('m4/'):
        destpath = constants.substart('m4/', '%s/' % m4base, srcpath)
      elif srcpath.startswith('tests/'):
        destpath = constants.substart('tests/', '%s/' % testsbase, srcpath)
      elif srcpath.startswith('tests=lib/'):
        destpath = constants.substart('tests=lib/', '%s/' % testsbase, srcpath)
      elif srcpath.startswith('top/'):
        destpath = constants.substart('top/', '', srcpath)
      else: # either case
        destpath = srcpath
    else: # if not isdir(destpath)
      destdir = os.path.dirname(destpath)
      destpath = os.path.basename(destpath)
    # Create the directory for destfile.
    dirname = os.path.dirname(joinpath(destdir, destpath))
    if not config['dryrun']:
      if dirname and not isdir(dirname):
        try: # Try to create directories
          os.makedirs(dirname)
        except Exception as error:
          pass
    # Copy the file.
    assistant = classes.GLFileAssistant(config)
    tmpfile = assistant.tmpfilename(destpath)
    shutil.copy(lookedup, tmpfile)
    already_present = True
    assistant.setOriginal(srcpath)
    assistant.setRewritten(destpath)
    if isfile(joinpath(destdir, destpath)):
      # The file already exists.
      assistant.update(lookedup, flag, tmpfile, already_present)
    else: # if not isfile(joinpath(destdir, destpath))
      # Install the file.
      # Don't protest if the file should be there but isn't: it happens
      # frequently that developers don't put autogenerated files under version
      # control.
      assistant.add(lookedup, flag, tmpfile)
    if isfile(tmpfile):
      os.remove(tmpfile)
    
  else:
    message = '%s: *** ' % constants.APP['name']
    message += 'no mode specified'
    message += '\n%s: *** Exit.\n' % constants.APP['name']
    sys.stderr.write(message)
    sys.exit(1)