#!/usr/bin/env python """\ deheader -- find (optionally remove) unneeded includes in C or C++ sourcefiles. Usage: deheader [-h] [-v] [-r] [-i pattern] [-x pattern] [sourcefiles] -h, --help Emit this help message and quit. -m, --maker Set the build command (by default "make") -i, --ignore Ignore (don't remove) headers matching the argument regexp -r, --remove Remove the final set of unneeded headers -o, --options Options to pass to the compiler -w, --where-to-run The home directory from where it should start the compilation -v, --verbose Be chatty about what you're doing. -x, --exclude Exclude files matching regexp -V, --version Emit version and exit. This tool takes a list of C or C++ sourcefiles and generates a report on which #includes can be omitted from them -- the test, for each foo.c or foo.cc or foo.cpp, is simply whether 'rm foo.o; make foo.o' returns a zero status. Optionally, with the -r option, the unneeded headers are removed. The tool also reports on headers required for strict portability. If a sourcefile argument is a directory, the report is generated on all source files beneath it. Subdirectories beginning with a dot are ignored. If no arguments are given, the program runs as if the name of the current directory had been passed to it. The original sourcefile is moved to a name with an .orig suffix and restored on interrupt or after processing with its original timestamp, unless the -r option was given and headers removed. The last line of the output is a statistical summary of operations. """ import sys, os, getopt, time, re, operator, commands, datetime import datetime as dt BATON_DEBUG = 1 PROGRESS_DEBUG = 2 COMMAND_DEBUG = 3 version = "0.6" # Difference in various compiler implementations and OSes mean that for cross- # platform compatibility you sometimes want to leave "unneeded" headers alone # because they're required in order to satify dependencies on other platforms. # Note: This table is not yet complete. requirements = ( # Headers mandated by SuS Version 2 System Interfaces. # a64l, l64a - convert between a 32-bit integer and a radix-64 ASCII string (r"a64l()", [""]), (r"l64a()", [""]), # abort - generate an abnormal process abort (r"abort()", [""]), # abs - return an integer absolute value (r"abs()", [""]), # access - determine accessibility of a file (r"access()", [""]), # acos - arc cosine function (r"acos()", [""]), # acosh, asinh, atanh - inverse hyperbolic functions (r"acosh()", [""]), (r"asinh()", [""]), (r"atanh()", [""]), # advance - pattern match given a compiled regular expression (r"advance()", [""]), # aio.h - asynchronous input and output (r"aio_cancel()", [""]), (r"aio_error()", [""]), (r"aio_fsync()", [""]), (r"aio_read()", [""]), (r"aio_return()", [""]), (r"aio_suspend()", [""]), (r"aio_write()", [""]), (r"lio_listio()", [""]), # alarm - schedule an alarm signal (r"alarm()", [""]), # asctime, asctime_r - convert date and time to a string (r"asctime()", [""]), (r"asctime_r()", [""]), # asin - arc sine function (r"asin()", [""]), # atan - arc tangent function (r"atan()", [""]), # atan2 - arc tangent function (r"atanh()", [""]), # atanh - hyperbolic arc tangent (r"atan2()", [""]), # atexit - register a function to run at process termination (r"atexit()", [""]), # atof - convert a string to double-precision number (r"atof()", [""]), # atoi - convert a string to integer (r"atol()", [""]), # atol - convert a string to long integer (r"atol()", [""]), # basename - return the last component of a pathname (r"basename()", [""]), # bcmp - memory operations (r"bcmp()", [""]), # bcopy - memory operations (r"bcopy()", [""]), # brk, sbrk - change space allocation (LEGACY) (r"brk()", [""]), (r"sbrk()", [""]), # bsearch - binary search a sorted table (r"bsort()", [""]), # btowc - single-byte to wide-character conversion (r"btowc()", ["", ""]), # bzero - memory operations (r"bzero()", [""]), # calloc - a memory allocator (r"calloc()", [""]), # catclose - close a message catalogue descriptor (r"catclose()", [""]), # catgets - read a program message (r"catgets()", [""]), # catopen - open a message catalogue (r"catopen()", [""]), # cbrt - cube root function (r"cbrt()", [""]), # ceil - ceiling value function (r"ceil()", [""]), # chdir - change working directory (r"chdir()", [""]), # chmod - change mode of a file (r"chmod()", ["", ""]), # chown - change owner and group of a file (r"chown()", ["", ""]), # chroot - change root directory (LEGACY) (r"chroot()", [""]), # clearerr - clear indicators on a stream (r"clearerr()", [""]), # clock - report CPU time used (r"clock()", [""]), # clock_settime, clock_gettime, clock_getres - clock and timer functions (r"clock_settime()", [""]), (r"clock_gettime()", [""]), (r"clock_getres()", [""]), # close - close a file descriptor (r"close()", [""]), # closedir - close a directory stream (r"closedir()", ["", ""]), # closelog, openlog, setlogmask, syslog - control system log (r"closelog()", [""]), (r"openlog()", [""]), (r"setlogmask()", [""]), (r"syslog()", [""]), # compile - produce a compiled regular expression (r"compile()", [""]), # confstr - get configurable variables (r"confstr()", [""]), # cos - cosine function (r"cos()", [""]), # cosh - hyperbolic cosine function (r"cosh()", [""]), # creat - create a new file or rewrite an existing one (r"creat()", ["", "", ""]), # crypt - string encoding function (r"crypt()", [""]), # ctermid - generate a pathname for controlling terminal (r"ctermid()", [""]), # ctime, ctime_r - convert a time value to date and time string (r"ctime()", [""]), (r"ctime_r()", [""]), # ctype.h - character types (r"isalnum()", [""]), (r"isalpha()", [""]), (r"isascii()", [""]), (r"iscntrl()", [""]), (r"isdigit()", [""]), (r"isgraph()", [""]), (r"islower()", [""]), (r"isprint()", [""]), (r"ispunct()", [""]), (r"isspace()", [""]), (r"isupper()", [""]), (r"isxdigit()", [""]), (r"toascii()", [""]), (r"tolower()", [""]), (r"toupper()", [""]), (r"_tolower()", [""]), (r"_toupper()", [""]), # cuserid - character login name of the user (r"cuserid()", [""]), # daylight - daylight savings time flag (r"extern\s+int\s+daylight;", [""]), # dbm_clearerr, dbm_close, dbm_delete, dbm_error, dbm_fetch, dbm_firstkey, dbm_nextkey, dbm_open, dbm_store - database functions (r"dbm_clearerr()", [""]), (r"dbm_close()", [""]), (r"dbm_delete()", [""]), (r"dbm_error()", [""]), (r"dbm_fetch()", [""]), (r"dbm_firstkey()", [""]), (r"dbm_nextkey()", [""]), (r"dbm_open()", [""]), (r"dbm_store()", [""]), # difftime - compute the difference between two calendar time values (r"difftime()", [""]), # dirname - report the parent directory name of a file pathname (r"dirname()", [""]), # div - compute the quotient and remainder of an integer division (r"div()", [""]), # dlclose - close a dlopen() object (r"dlclose()", [""]), # dlerror - get diagnostic information (r"dlerror()", [""]), # dlsym - obtain the address of a symbol from a dlopen() object (r"dlsym()", [""]), # drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, seed48, srand48 - generate uniformly distributed pseudo-random numbers (r"drand48()", [""]), (r"erand48()", [""]), (r"jrand48()", [""]), (r"lcong48()", [""]), (r"lrand48()", [""]), (r"mrand48()", [""]), (r"nrand48()", [""]), (r"seed48()", [""]), (r"srand48()", [""]), # dup, dup2 - duplicate an open file descriptor (r"dup()", [""]), (r"dup2()", [""]), # exit, _exit - terminate a process (r"exit()", [""]), (r"_exit()", [""]), # ecvt, fcvt, gcvt - convert a floating-point number to a string (r"ecvt()", [""]), (r"fcvt()", [""]), (r"gcvt()", [""]), # encrypt - encoding function (r"encrypt()", [""]), # endgrent, getgrent, setgrent - group database entry functions (r"endgrent()", [""]), (r"getgrent()", [""]), (r"setgrent()", [""]), (r"getgrnam()", [""]), (r"getgrgid()", [""]), (r"getgrnam_r()", [""]), (r"getgrgid_r()", [""]), # endpwent, getpwent, setpwent - user database functions (r"endpwent()", [""]), (r"getpwent()", [""]), (r"setpwent()", [""]), (r"getpwnam()", [""]), (r"getpwuid()", [""]), (r"getpwnam_r()", [""]), (r"getpwuid_r()", [""]), # endutxent, getutxent, getutxid, getutxline, pututxline, setutxent - user accounting database functions (r"endutxent()", [""]), (r"getutxent()", [""]), (r"getutxid()", [""]), (r"getutxline()", [""]), (r"pututxline()", [""]), (r"setutxent()", [""]), # erf, erfc - error and complementary error functions (r"erf()", [""]), (r"erfc()", [""]), # environ, execl, execv, execle, execve, execlp, execvp - execute a file (r"extern\s+char\s+\*\*environ;", [""]), (r"execl()", [""]), (r"execv()", [""]), (r"execle()", [""]), (r"execve()", [""]), (r"execlp()", [""]), (r"execvp()", [""]), # exp - exponential function (r"exp()", [""]), # expm1 - compute exponential functions (r"expm1()", [""]), # FD_CLR - macros for synchronous I/O multiplexing (r"FD_CLR()", [""]), (r"FD_ISSET()", [""]), (r"FD_SET()", [""]), (r"FD_ZERO()", [""]), # fabs - absolute value function (r"fabs()", [""]), # fattach - attach a STREAMS-based file descriptor to a file in the file system name space (r"fattach()", [""]), # fchdir - change working directory (r"fchdir()", [""]), # fchmod - change mode of a file (r"fchmod()", [""]), # fchown - change owner and group of a file (r"fchown()", [""]), # fdopen - associate a stream with a file descriptor (r"fdopen()", [""]), # fclose - close a stream (r"fclose()", [""]), # fdatasync - synchronise the data of a file (r"fdatasync()", [""]), # fdetach - detach a name from a STREAMS-based file descriptor (r"fdetach()", [""]), # fdopen - associate a stream with a file descriptor (r"fdopen()", [""]), # ferror - test error indicator on a stream (r"ferror()", [""]), # feof - test end-of-file indicator on a stream (r"feof()", [""]), # fflush - flush a stream (r"fflush()", [""]), # ffs - find first set bit (r"ffs()", [""]), # fgetc - get a byte from a stream (r"fgetc()", [""]), # fgetpos - get current file position information (r"fgetpos()", [""]), # fgets - get a string from a stream (r"fgets()", [""]), # fgetwc - get a wide-character code from a stream (r"fgetwc()", ["", ""]), # fgetws - get a wide-character string from a stream (r"fgetws()", ["", ""]), # fileno - map a stream pointer to a file descriptor (r"fileno()", [""]), # flockfile, ftrylockfile, funlockfile - stdio locking functions (r"flockfile()", [""]), (r"ftrylockfile()", [""]), (r"funlockfile()", [""]), # fmod - floating-point remainder value function (r"fmod()", [""]), # fmtmsg.h - message display structures (r"fmtmsg()", [""]), # fnmatch.h - filename-matching types (r"fnmatch()", [""]), # fopen - open a stream (r"fopen()", [""]), # fork - create a new process (r"fork()", ["", ""]), # fpathconf, pathconf - get configurable pathname variables (r"fpathconf()", [""]), (r"pathconf()", [""]), # fputc - put a byte on a stream (r"fputc()", [""]), # fputs - put a string on a stream (r"fputs()", [""]), # fputwc - put a wide-character code on a stream (r"fputwc()", [""]), # fputws - put a wide-character string on a stream (r"fputws()", [""]), # fread - binary input (r"fread()", [""]), # free - free allocated memory (r"free()", [""]), # freopen - open a stream (r"freopen()", [""]), # frexp - extract mantissa and exponent from a double precision number (r"frexp()", [""]), # fscanf, scanf, sscanf - convert formatted input (r"fscanf()", [""]), (r"scanf()", [""]), (r"sscanf()", [""]), # fseek, fseeko - reposition a file-position indicator in a stream (r"fseek()", [""]), (r"fseeko()", [""]), # fsetpos - set current file position (r"fsetpos()", [""]), # fstat - get file status (r"fstat()", ["", ""]), # fstatvfs, statvfs - get file system information (r"fstatvfs()", [""]), (r"statvfs()", [""]), # fsync - synchronise changes to a file (r"fsync()", [""]), # ftell, ftello - return a file offset in a stream (r"ftell()", [""]), (r"ftello()", [""]), # ftime - get date and time (r"ftime()", [""]), # ftok - generate an IPC key (r"ftok()", [""]), # ftruncate, truncate - truncate a file to a specified length (r"truncate()", [""]), (r"ftruncate()", [""]), # ftw - traverse (walk) a file tree (r"ftw()", [""]), (r"nftw()", [""]), # fwide - set stream orientation (r"fwide()", ["", ""]), # fwprintf, wprintf, swprintf - print formatted wide-character output (r"fwprintf()", ["", ""]), (r"wprintf()", ["", ""]), (r"swprintf()", ["", ""]), # fwrite - binary output (r"fwrite()", [""]), # fwscanf, wscanf, swscanf - convert formatted wide-character input (r"fwscanf()", ["", ""]), (r"wscanf()", ["", ""]), (r"swscanf()", ["", ""]), # gamma, signgam - log gamma function (r"gamma()", [""]), # getc - get a byte from a stream (r"getc()", [""]), # getc_unlocked, getchar_unlocked, putc_unlocked, putchar_unlocked - stdio with explicit client locking (r"getc_unlocked()", [""]), (r"getchar_unlocked()", [""]), (r"putc_unlocked()", [""]), (r"putchar_unlocked()", [""]), # getchar - get a byte from a stdin stream (r"getchar()", [""]), # getcontext, setcontext - get and set current user context (r"getcontext()", [""]), (r"setcontext()", [""]), # getcwd - get the pathname of the current working directory (r"getcwd()", [""]), # getdate - convert user format date and time (r"getdate()", [""]), # getdtablesize - get the file descriptor table size (r"getdtablesize()", [""]), # getegid - get the effective group ID (r"getegid()", ["", ""]), # getenv - get value of an environment variable (r"getenv()", [""]), # geteuid - get the effective user ID (r"geteuid()", ["", ""]), # getgid - get the real group ID (r"getgid()", ["", ""]), # getgrgid, getgrgid_r - get group database entry for a group ID (r"getgrgid()", ["", ""]), (r"getgrgid_r()", ["", ""]), # getgrnam, getgrnam_r - search group database for a name (r"getgrnam()", ["", ""]), (r"getgrnam_r()", ["", ""]), # getgroups - get supplementary group IDs (r"getgroups()", ["", ""]), # gethostid - get an identifier for the current host (r"gethostid()", [""]), # getitimer, setitimer - get or set value of interval timer (r"getitimer()", [""]), (r"setitimer()", [""]), # getlogin, getlogin_r - get login name (r"getlogin()", [""]), (r"getlogin_r()", [""]), # getmsg, getpmsg - receive next message from a STREAMS file (r"getmsg()", [""]), (r"getpmsg()", [""]), # getopt, optarg, optind, opterr, optopt - command option parsing (r"getopt()", [""]), (r"extern\s+char\s+\*\*optarg;", [""]), # getpagesize - get the current page size (r"getpagesize()", [""]), # getpass - read a string of characters without echo (r"getpass()", [""]), # getpgid - get the process group ID for a process (r"getpgid()", [""]), # getpgrp - get the process group ID of the calling process (r"getpgrp()", ["", ""]), # getpid - get the process ID (r"getpid()", ["", ""]), # getppid - get the parent process ID (r"getppid()", ["", ""]), # getpriority, setpriority - get or set the nice value (r"getpriority()", [""]), (r"setpriority()", [""]), # getpwnam, getpwnam_r - search user database for a name (r"getpwnam()", ["", ""]), (r"getpwnam_r()", ["", ""]), # getpwuid, getpwuid_r - search user database for a user ID (r"getpwuid()", ["", ""]), (r"getpwuid_r()", ["", ""]), # getrlimit, setrlimit - control maximum resource consumption (r"getrlimit()", [""]), (r"setrlimit()", [""]), # getrusage - get information about resource utilisation (r"getrusage()", [""]), # gets - get a string from a stdin stream (r"gets()", [""]), # getsid - get the process group ID of session leader (r"getsid()", [""]), # getsubopt - parse suboption arguments from a string (r"getsubopt()", [""]), # gettimeofday - get the date and time (r"gettimeofday()", [""]), # getuid - get a real user ID (r"getuid()", ["", ""]), # getw - get a word from a stream (r"getw()", [""]), # getwc - get a wide-character code from a stream (r"getwc()", ["", ""]), # getws - get a wide-character string from a stream (r"getws()", ["", ""]), # getwchar - get a wide character from a stdin stream (r"getwchar()", [""]), # getwd - get the current working directory pathname (r"getwd()", [""]), # glob.h - pathname pattern-matching types (r"glob()", [""]), (r"globfree()", [""]), # gmtime, gmtime_r - convert a time value to a broken-down UTC time (r"gmtime()", [""]), (r"gmtime_r()", [""]), # grantpt - grant access to the slave pseudo-terminal device (r"grantpt()", [""]), # hcreate, hdestroy, hsearch - manage hash search table (r"hcreate()", [""]), (r"hdestroy()", [""]), (r"hsearch ()", [""]), # hypot - Euclidean distance function (r"hypot()", [""]), # iconv.h - codeset conversion facility (r"iconv_open()", [""]), (r"iconv()", [""]), (r"iconv_close()", [""]), # ilogb - return an unbiased exponent (r"ilogb()", [""]), # index - character string operations (r"index()", [""]), # initstate, random, setstate, srandom - pseudorandom number functions (r"initstate()", [""]), (r"random()", [""]), (r"setstate()", [""]), (r"srandom()", [""]), # insque, remque - insert or remove an element in a queue (r"insque()", [""]), (r"remque()", [""]), # SuS ioctl specifies , but that's just wrong # isastream - test a file descriptor (r"isastream()", [""]), # isnan - test for a NaN (r"isnan()", [""]), # j0, j1, jn - Bessel functions of the first kind (r"j0()", [""]), (r"j1()", [""]), (r"jn()", [""]), # labs - return a long integer absolute value (r"labs()", [""]), # lchown - change the owner and group of a symbolic link (r"lchown()", [""]), # ldexp - load exponent of a floating point number (r"ldexp()", [""]), # ldiv - compute quotient and remainder of a long division (r"ldiv()", [""]), # lgamma - log gamma function (r"lgamma()", [""]), # libgen.h - definitions for pattern matching functions (r"regcmp()", [""]), (r"regex()", [""]), # link - link to a file (r"link()", [""]), # localeconv - determine the program locale (r"localeconv()", [""]), # localtime, localtime_r - convert a time value to a broken-down local time (r"localtime()", [""]), (r"localtime_r()", [""]), # lockf - record locking on files (r"lockf()", [""]), # log - natural logarithm function (r"log()", [""]), # log10 - base 10 logarithm function (r"log10()", [""]), # log1p - compute a natural logarithm (r"log1p()", [""]), # logb - radix-independent exponent (r"logb()", [""]), # lsearch, lfind - linear search and update (r"lfind()", [""]), (r"lsearch()", [""]), # lseek - move the read/write file offset (r"lseek()", ["", ""]), # lstat - get symbolic link status (r"lstat()", [""]), # makecontext, swapcontext - manipulate user contexts (r"makecontext()", [""]), (r"swapcontext()", [""]), # malloc - a memory allocator (r"malloc()", [""]), # mblen - get number of bytes in a character (r"mblen()", [""]), # mbrlen - get number of bytes in a character (restartable) (r"mblren()", [""]), # mbrtowc - convert a character to a wide-character code (restartable) (r"mbrtowc()", [""]), # mbsinit - determine conversion object status (r"mbsinit()", [""]), # mbsrtowcs - convert a character string to a wide-character string (restartable) (r"mbsrtowcs()", [""]), # mbstowcs - convert a character string to a wide-character string (r"mbstowcs()", [""]), # mbtowc - convert a character to a wide-character code (r"mbtowcs()", [""]), # mkdir - make a directory (r"mkdir()", ["", ""]), # mkfifo - make a FIFO special file (r"mkfifo()", ["", ""]), # mknod - make a directory, a special or regular file (r"mknod()", [""]), # mkstemp - make a unique file name (r"mkstemp()", [""]), # mktemp - make a unique filename (r"mktemp()", [""]), # convert broken-down time into time since the Epoch (r"mktime()", [""]), # sys/mman.h - memory management declarations (r"mlock()", [""]), (r"mlockall()", [""]), (r"mmap()", [""]), (r"mprotect()", [""]), (r"msync()", [""]), (r"munlock()", [""]), (r"munlockall()", [""]), (r"munmap()", [""]), (r"shm_open()", [""]), (r"shm_unlink()", [""]), # modf - decompose a floating-point number (r"modf()", [""]), # monetary.h - monetary types (r"strfmon()", [""]), # mqueue.h - message queues (r"mq_close()", [""]), (r"mq_getattr()", [""]), (r"mq_notify()", [""]), (r"mq_open()", [""]), (r"mq_receive()", [""]), (r"mq_send()", [""]), (r"mq_setattr()", [""]), (r"mq_unlink()", [""]), # sys/msg.h - message queue structures (r"msgctl()", [""]), (r"msgget()", [""]), (r"msgrcv()", [""]), (r"msgsnd()", [""]), # nanosleep - high resolution sleep (r"nanosleep()", [""]), # nextafter - next representable double-precision floating-point number (r"nextafter()", [""]), # change nice value of a process (r"nice()", [""]), # nl_langinfo - language information (r"nl_langinfo()", [""]), # open - open a file (r"open()", ["", "", ""]), # opendir - open a directory (r"opendir()", ["", ""]), # pause - suspend the thread until signal is received (r"pause()", [""]), # pclose - close a pipe stream to or from a process (r"pclose()", [""]), # perror - write error messages to standard error (r"perror()", [""]), # pipe - create an interprocess channel (r"pipe()", [""]), # poll - input/output multiplexing (r"poll()", [""]), # popen - initiate pipe streams to or from a process (r"popen()", [""]), # pow - power function (r"pow()", [""]), # pread - read from a file ("pread()", [""]), # pthread.h - threads (r"pthread_attr_destroy()", [""]), (r"pthread_attr_getdetachstate()", [""]), (r"pthread_attr_getguardsize()", [""]), (r"pthread_attr_getinheritsched()", [""]), (r"pthread_attr_getschedparam()", [""]), (r"pthread_attr_getschedpolicy()", [""]), (r"pthread_attr_getscope()", [""]), (r"pthread_attr_getstackaddr()", [""]), (r"pthread_attr_getstacksize()", [""]), (r"pthread_attr_init()", [""]), (r"pthread_attr_setdetachstate()", [""]), (r"pthread_attr_setguardsize()", [""]), (r"pthread_attr_setinheritsched()", [""]), (r"pthread_attr_setschedparam()", [""]), (r"pthread_attr_setschedpolicy()", [""]), (r"pthread_attr_setscope()", [""]), (r"pthread_attr_setstackaddr()", [""]), (r"pthread_attr_setstacksize()", [""]), (r"pthread_cancel()", [""]), (r"pthread_cleanup_push()", [""]), (r"pthread_cleanup_pop()", [""]), (r"pthread_cond_broadcast()", [""]), (r"pthread_cond_destroy()", [""]), (r"pthread_cond_init()", [""]), (r"pthread_cond_signal()", [""]), (r"pthread_cond_timedwait()", [""]), (r"pthread_cond_wait()", [""]), (r"pthread_condattr_destroy()", [""]), (r"pthread_condattr_getpshared()", [""]), (r"pthread_condattr_init()", [""]), (r"pthread_condattr_setpshared()", [""]), (r"pthread_create()", [""]), (r"pthread_detach()", [""]), (r"pthread_equal()", [""]), (r"pthread_exit()", [""]), (r"pthread_getconcurrency()", [""]), (r"pthread_getschedparam()", [""]), (r"pthread_getspecific()", [""]), (r"pthread_join()", [""]), (r"pthread_key_create()", [""]), (r"pthread_key_delete()", [""]), (r"pthread_mutex_destroy()", [""]), (r"pthread_mutex_getprioceiling()", [""]), (r"pthread_mutex_init()", [""]), (r"pthread_mutex_lock()", [""]), (r"pthread_mutex_setprioceiling()", [""]), (r"pthread_mutex_trylock()", [""]), (r"pthread_mutex_unlock()", [""]), (r"pthread_mutexattr_destroy()", [""]), (r"pthread_mutexattr_getprioceiling()",[""]), (r"pthread_mutexattr_getprotocol()", [""]), (r"pthread_mutexattr_getpshared()", [""]), (r"pthread_mutexattr_gettype()", [""]), (r"pthread_mutexattr_init()", [""]), (r"pthread_mutexattr_setprioceiling()",[""]), (r"pthread_mutexattr_setprotocol()", [""]), (r"pthread_mutexattr_setpshared()", [""]), (r"pthread_mutexattr_settype()", [""]), (r"pthread_once()", [""]), (r"pthread_rwlock_destroy()", [""]), (r"pthread_rwlock_init()", [""]), (r"pthread_rwlock_rdlock()", [""]), (r"pthread_rwlock_tryrdlock()", [""]), (r"pthread_rwlock_trywrlock()", [""]), (r"pthread_rwlock_unlock()", [""]), (r"pthread_rwlock_wrlock()", [""]), (r"pthread_rwlockattr_destroy()", [""]), (r"pthread_rwlockattr_getpshared()", [""]), (r"pthread_rwlockattr_init()", [""]), (r"pthread_rwlockattr_setpshared()", [""]), (r"pthread_self()", [""]), (r"pthread_setcancelstate()", [""]), (r"pthread_setcanceltype()", [""]), (r"pthread_setconcurrency()", [""]), (r"pthread_setschedparam()", [""]), (r"pthread_setspecific()", [""]), (r"pthread_testcancel()", [""]), # ptsname - get name of the slave pseudo-terminal device (r"ptsname()", [""]), # putc - put a byte on a stream (r"putc()", [""]), # putc_unlocked - stdio with explicit client locking (r"putc_unlocked()", [""]), # putchar - put byte on stdout stream (r"putchar()", [""]), # putchar_unlocked - stdio with explicit client locking (r"putchar_unlocked()", [""]), # putenv - change or add a value to environment (r"putenv()", [""]), # putmsg, putpmsg - send a message on a STREAM (r"putmsg()", [""]), (r"putpmsg()", [""]), # puts - put a string on standard output (r"puts()", [""]), # putw - put a word on a stream (r"putw()", [""]), # putwc - put a wide-character on a stream (r"putwc()", ["", ""]), # putwchar - put a wide character from a stdin stream (r"putwchar()", [""]), # qsort - sort a table of data (r"qsort()", [""]), # raise - send a signal to the executing process (r"raise()", [""]), # rand, rand_r - pseudo-random number generator (r"rand()", [""]), (r"srand()", [""]), (r"rand_r()", [""]), # random - generate pseudorandom number (r"random()", [""]), # re_comp.h - regular-expression-matching functions for re_comp() (r"re_comp()", [""]), (r"re_exec()", [""]), # read, readv, pread - read from a file ("read()", [""]), ("readv()", [""]), # readdir, readdir_r - read directory (r"readdir()", ["", ""]), (r"readdir_r()", ["", ""]), # readlink - read the contents of a symbolic link ("readlink()", [""]), # realloc - memory reallocator ("realloc()", [""]), # realpath - resolve a pathname ("realpath()", [""]), # regcomp, regexec, regerror, regfree - regular expression matching (r"regcomp()", ["", ""]), (r"regexec()", ["", ""]), (r"regerror()", ["", ""]), (r"regfree()", ["", ""]), # remainder - remainder function (r"remainder()", [""]), # remove - remove files (r"remove()", [""]), # rename - rename a file (r"rename()", [""]), # rewind - reset file position indicator in a stream (r"rewind()", [""]), # rewinddir - reset position of directory stream to the beginning of a directory (r"rewinddir()", ["", ""]), # rindex - character string operations (r"rindex()", [""]), # rint - round-to-nearest integral value (r"rint()", [""]), # rmdir - remove a directory ("rmdir()", [""]), # scalb - load exponent of a radix-independent floating-point number (r"scalb()", [""]), # scanf - convert formatted input (r"scanf()", [""]), # sched.h - execution scheduling (r"sched_get_priority_max()", [""]), (r"sched_get_priority_min()", [""]), (r"sched_getparam()", [""]), (r"sched_getscheduler()", [""]), (r"sched_rr_get_interval()", [""]), (r"sched_setparam()", [""]), (r"sched_setscheduler()", [""]), (r"sched_yield()", [""]), # seekdir - set position of directory stream (r"seekdir()", ["", ""]), # select - synchronous I/O multiplexing (r"select()", [""]), # semaphore.h - semaphores (r"sem_close()", [""]), (r"sem_destroy()", [""]), (r"sem_getvalue()", [""]), (r"sem_init()", [""]), (r"sem_open()", [""]), (r"sem_post()", [""]), (r"sem_trywait()", [""]), (r"sem_unlink()", [""]), (r"sem_wait()", [""]), # sys/sem.h - semaphore facility (r"semctl()", [""]), (r"semget()", [""]), (r"semop()", [""]), # setbuf - assign buffering to a stream (r"setbuf()", [""]), # setgid - set-group-ID (r"setgid()", ["", ""]), # setgrent - reset group database to first entry (r"setgrent()", [""]), # setkey - set encoding key (r"setkey()", [""]), # setpgid - set process group ID for job control (r"setpgid()", ["", ""]), # setpgrp - set process group ID (r"setpgrp()", [""]), # setregid - set real and effective group IDs (r"setregid()", [""]), # setreuid - set real and effective user IDs (r"setreuid()", [""]), # setsid - create session and set process group ID (r"setsid()", ["", ""]), # setuid - set-user-ID (r"setuid()", ["", ""]), # setvbuf - assign buffering to a stream (r"setvbuf()", [""]), # sys/shm.h - shared memory facility (r"shmat()", [""]), (r"shmctl()", [""]), (r"shmdt()", [""]), (r"shmget()", [""]), # setjmp.h - stack environment declarations (r"longjmp()", [""]), (r"siglongjmp()", [""]), (r"_longjmp()", [""]), (r"setjmp()", [""]), (r"sigsetjmp()", [""]), (r"_setjmp()", [""]), # signal.h - signals (r"bsd_signal()", [""]), (r"kill()", [""]), (r"killpg()", [""]), (r"pthread_kill()", [""]), (r"pthread_sigmask()", [""]), (r"raise()", [""]), (r"sigaction()", [""]), (r"sigaddset()", [""]), (r"sigaltstack()", [""]), (r"sigdelset()", [""]), (r"sigemptyset()", [""]), (r"sigfillset()", [""]), (r"sighold()", [""]), (r"sigignore()", [""]), (r"siginterrupt()", [""]), (r"sigismember()", [""]), (r"signal()", [""]), (r"sigpause()", [""]), (r"sigpending()", [""]), (r"sigprocmask()", [""]), (r"sigqueue()", [""]), (r"sigrelse()", [""]), (r"sigset()", [""]), (r"sigstack()", [""]), (r"sigsuspend()", [""]), (r"sigtimedwait()", [""]), (r"sigwait()", [""]), (r"sigwaitinfo()", [""]), # sin - sine function (r"sin()", [""]), # sinh - hyperbolic sine function (r"sinh()", [""]), # sleep - suspend execution for an interval of time (r"sleep()", [""]), # fprintf, printf, snprintf, sprintf - print formatted output (r"fprintf()", [""]), (r"printf()", [""]), (r"snprintf()", [""]), (r"sprintf()", [""]), # sqrt - square root function (r"sqrt()", [""]), # stat - get file status (r"stat()", ["", ""]), # stdarg.h - handle variable argument list (r"va_start()", [""]), (r"va_arg()", [""]), (r"va_end()", [""]), # stddef.h - standard type definitions (r"offsetof()", [""]), # step - pattern match with regular expressions (r"step()", [""]), # strcasecmp, strncasecmp - case-insensitive string comparisons (r"strcasecmp()", [""]), (r"strncasecmp()", [""]), # string.h - string operations (r"memccpy()", [""]), (r"memchr()", [""]), (r"memcmp()", [""]), (r"memcpy()", [""]), (r"memmove()", [""]), (r"memset()", [""]), (r"strcat()", [""]), (r"strchr()", [""]), (r"strcmp()", [""]), (r"strcoll()", [""]), (r"strcpy()", [""]), (r"strcspn()", [""]), (r"strdup()", [""]), (r"strerror()", [""]), (r"strlen()", [""]), (r"strncat()", [""]), (r"strncmp()", [""]), (r"strncpy()", [""]), (r"strpbrk()", [""]), (r"strrchr()", [""]), (r"strspn()", [""]), (r"strstr()", [""]), (r"strtok()", [""]), (r"strtok_r()", [""]), (r"strxfrm()", [""]), # wctype.h - wide-character classification and mapping utilities (r"iswalnum()", [""]), (r"iswalpha()", [""]), (r"iswascii()", [""]), (r"iswcntrl()", [""]), (r"iswdigit()", [""]), (r"iswgraph()", [""]), (r"iswlower()", [""]), (r"iswprint()", [""]), (r"iswpunct()", [""]), (r"iswspace()", [""]), (r"iswupper()", [""]), (r"iswxdigit()", [""]), (r"iswctype()", [""]), (r"towctrans()", [""]), (r"towlower()", [""]), (r"towupper()", [""]), (r"wctrans()", [""]), (r"wctype()", [""]), # strftime - convert date and time to a string (r"strftime()", [""]), # strptime - date and time conversion (r"strptime()", [""]), # strtod - convert string to a double-precision number (r"strtod()", [""]), # strtol - convert string to a long integer (r"strtol()", [""]), # strtoul - convert string to an unsigned long (r"strtoul()", [""]), # swab - swap bytes (r"swab()", [""]), # symlink - make symbolic link to a file (r"symlink()", [""]), # sync - schedule filesystem updates (r"sync()", [""]), # sysconf - get configurable system variables (r"sysconf()", [""]), # system - issue a command (r"system()", [""]), # sys/wait.h - declarations for waiting (r"wait()", ["", ""]), (r"wait3()", ["", ""]), (r"waitid()", ["", ""]), (r"waitpid()", ["", ""]), (r"WEXITSTATUS()", ["", ""]), (r"WIFCONTINUED()", ["", ""]), (r"WIFEXITED()", ["", ""]), (r"WIFSIGNALED()", ["", ""]), (r"WIFSTOPPED()", ["", ""]), (r"WSTOPSIG()", ["", ""]), (r"WTERMSIG()", ["", ""]), # tan - tangent function (r"tan()", [""]), # tanh - hyperbolic tangent function (r"tanh()", [""]), # tcgetpgrp - get the foreground process group ID (r"tcgetpgrp()", ["", ""]), # tcsetpgrp - set the foreground process group ID (r"tcsetpgrp()", ["", ""]), # tdelete - delete node from binary search tree (r"tdelete()", [""]), # telldir - current location of a named directory stream (r"telldir()", [""]), # tempnam - create a name for a temporary file (r"tempnam()", [""]), # termios.h - define values for termios (r"cfgetispeed()", [""]), (r"cfgetospeed()", [""]), (r"cfsetispeed()", [""]), (r"cfsetospeed()", [""]), (r"tcdrain()", [""]), (r"tcflow()", [""]), (r"tcflush()", [""]), (r"tcgetattr()", [""]), (r"tcgetsid()", [""]), (r"tcsendbreak()", [""]), (r"tcsetattr()", [""]), # tdelete, tfind, tsearch, twalk - manage a binary search tree (r"tsearch()", [""]), (r"tfind()", [""]), (r"tdelete()", [""]), (r"twalk()", [""]), # time - get time (r"time()", [""]), # timer_create - create a per-process timer (r"timer_create()", ["", ""]), # timer_delete - delete a per-process timer (r"timer_delete()", ["", ""]), # timer_settime, timer_gettime, timer_getoverrun - per-process timers (r"timer_settime()", [""]), (r"timer_gettime()", [""]), (r"timer_getoverrun()", [""]), # times - get process and waited-for child process times (r"times()", [""]), # tmpfile - create a temporary file (r"tmpfile()", [""]), # tmpnam - create a name for a temporary file (r"tmpnam()", [""]), # truncate - truncate a file to a specified length (r"truncate()", [""]), # ttyname, ttyname_r - find pathname of a terminal ("ttyname()", [""]), ("ttyname_r()", [""]), # ttyslot - find the slot of the current user in the user accounting database ("ttyslot()", [""]), # tzset - set time zone conversion information ("tzset()", [""]), # ualarm - set the interval timer ("ualarm()", [""]), # ulimit - get and set process limits ("ulimit()", [""]), # umask - set and get file mode creation mask (r"umask()", ["", ""]), # uname - get name of current system ("uname()", [""]), # ungetc - push byte back into input stream (r"ungetc()", [""]), # ungetwc - push wide-character code back into input stream (r"ungetwc()", ["", ""]), # unlink - remove a directory entry ("unlink()", [""]), # unlockpt - unlock a pseudo-terminal master/slave pair (r"unlockpt()", [""]), # usleep - suspend execution for an interval ("usleep()", [""]), # utime - set file access and modification times (r"utime()", ["", ""]), # utimes - set file access and modification times (r"utimes()", [""]), # valloc - page-aligned memory allocator (r"valloc()", [""]), # vfork - create new process; share virtual memory ("vfork()", [""]), # vfprintf, vprintf, vsnprintf, vsprintf - format output of a stdarg argument list (r"vfprintf()", ["", ""]), (r"vprintf()", ["", ""]), (r"vsnprintf()", ["", ""]), (r"vsprintf()", ["", ""]), # vfwprintf, vwprintf, vswprintf - wide-character formatted output of a stdarg argument list (r"vwprintf()", ["", "", ""]), (r"vfwprintf()", ["", "", ""]), (r"vswprintf()", ["", "", ""]), # wchar.h - wide-character types (r"wcrtomb()", [""]), # SuSv2 erroneously says (r"wcscat()", [""]), (r"wcschr()", [""]), (r"wcscmp()", [""]), (r"wcscoll()", [""]), (r"wcscpy()", [""]), (r"wcscpy()", [""]), (r"wcsftime()", [""]), (r"wcslen()", [""]), (r"wcsncat()", [""]), (r"wcsncmp()", [""]), (r"wcsncpy()", [""]), (r"wcspbrk()", [""]), (r"wcsrchr()", [""]), (r"wcsrtombs()", [""]), (r"wcsspn()", [""]), (r"wcsstr()", [""]), (r"wcstod()", [""]), (r"wcstok()", [""]), (r"wcstol()", [""]), (r"wcstoul()", [""]), (r"wcswcs()", [""]), (r"wcswidth()", [""]), (r"wcsxfrm()", [""]), (r"wctob()", [""]), (r"wctype()", [""]), (r"wcwidth()", [""]), (r"wmemchr()", [""]), (r"wmemcmp()", [""]), (r"wmemcpy()", [""]), (r"wmemmove()", [""]), (r"wmemset()", [""]), (r"wprintf()", [""]), (r"wscanf()", [""]), # wordexp.h - word-expansion types (r"wordexp()", [""]), (r"wordfree()", [""]), # write, writev, pwrite - write on a file (r"write()", [""]), (r"pwrite()", [""]), (r"writev()", [""]), # y0, y1, yn - Bessel functions of the second kind (r"y0()", [""]), (r"y1()", [""]), (r"yn()", [""]), # Headers mandated by SuS Version 2 Network Services. # sys/socket.h - Internet Protocol family (r"accept()", [""]), (r"bind()", [""]), (r"connect()", [""]), (r"getpeername()", [""]), (r"getsockname()", [""]), (r"getsockopt()", [""]), (r"listen()", [""]), (r"recv()", [""]), (r"recvfrom()", [""]), (r"recvmsg()", [""]), (r"send()", [""]), (r"sendmsg()", [""]), (r"sendto()", [""]), (r"setsockopt()", [""]), (r"shutdown()", [""]), (r"socket()", [""]), (r"socketpair()", [""]), # arpa/inet.h - definitions for internet operations (r"inet_addr()", [""]), (r"inet_lnaof()", [""]), (r"inet_makeaddr()", [""]), (r"inet_netof()", [""]), (r"inet_network()", [""]), (r"inet_ntoa()", [""]), (r"htonl()", [""]), (r"htons()", [""]), (r"ntohl()", [""]), (r"ntohs()", [""]), # netdb.h - definitions for network database operations (r"endhostent()", [""]), (r"endnetent()", [""]), (r"endprotoent()", [""]), (r"endservent()", [""]), (r"gethostbyaddr()", [""]), (r"gethostbyname()", [""]), (r"gethostent()", [""]), (r"getnetbyaddr()", [""]), (r"getnetbyname()", [""]), (r"getnetent()", [""]), (r"getprotobyname()", [""]), (r"getprotobynumber()",[""]), (r"getprotoent()", [""]), (r"getservbyname()", [""]), (r"getservbyport()", [""]), (r"getservent()", [""]), (r"sethostent()", [""]), (r"setnetent()", [""]), (r"setprotoent()", [""]), (r"setservent()", [""]), # unistd.h - standard symbolic constants and types (r"gethostname()", [""]), # stdbool.h - standard boolean type (r"=\s*true", [""]), (r"=\s*false", [""]), # Dependencies observed on systems other than the Linux this was # developed under. (r"", ["", ""]), (r"", [""]), ) class Baton: "Ship progress indications to stderr." def __init__(self, prompt, endmsg=None): self.stream = sys.stderr self.stream.write(prompt + "...") if os.isatty(self.stream.fileno()): self.stream.write(" \010") self.stream.flush() self.count = 0 self.endmsg = endmsg self.time = time.time() return def twirl(self, ch=None): if self.stream is None: return if os.isatty(self.stream.fileno()): if ch: self.stream.write(ch) else: self.stream.write("-/|\\"[self.count % 4]) self.stream.write("\010") self.stream.flush() self.count = self.count + 1 return def end(self, msg=None): if msg == None: msg = self.endmsg if self.stream: self.stream.write("...(%2.2f sec) %s.\n" % (time.time() - self.time, msg)) return class InclusionMap: "Map the inclusion dependencies of a set of files and directories." @staticmethod def c_source(filename): "Predicate: return true if the filename appears to be C or C++ source." return filename.endswith(".c") or filename.endswith(".cc") or filename.endswith(".cpp") def __init__(self, roots, ignore, excludes, verbosity): "Build the initial inclusion map." self.verbosity = verbosity self.files = [] compiled = [] for (r, h) in requirements: if r.endswith("()"): # The prefix is intended to exclude false suffix matches: # also, excluding : prevents matching on C++ method names. c = re.compile(r"[^a-zA-Z0-9:_]" + r.replace("()", r"\s*\(")) else: c = re.compile(r) compiled.append((r, c, h)) for root in roots: if not os.path.isdir(root): if excludes and excludes.search(root): if verbose > 1: print "deheader: %s excluded" % root elif InclusionMap.c_source(root): self.files.append(root) else: print >>sys.stderr, "deheader: can't analyze %s" % root else: for root, dirs, files in os.walk(root): dirs = filter(lambda x: not x.startswith("."), dirs) for name in files: path = os.path.join(root, name) if excludes and excludes.search(path): if verbose > 1: print "deheader: %s excluded" % root elif InclusionMap.c_source(path): self.files.append(path) self.depends_on = {} self.requires = {} for sourcefile in self.files: includes = [] requires = [] seen = [] conditions = [] for line in open(sourcefile): if line.startswith("#ifndef"): conditions.append(line[7:].strip()) elif line.startswith("#ifdef"): conditions.append(line[6:].strip()) elif line.startswith("#if"): conditions.append(line[3:].strip()) elif line.startswith("#endif"): conditions.pop() elif line.startswith("#include"): if verbosity >= PROGRESS_DEBUG: name = trim(line) print "deheader: %s includes %s" % (sourcefile, name) if ignore and ignore.search(line): if verbosity >= PROGRESS_DEBUG: print "deheader: ignoring %s (exclusion match with %s)." % (name, ignore.pattern) continue if not conditions or conditions == ["S_SPLINT_S"]: includes.append(line) elif verbose > 1: print "deheader: ignoring %s (conditional inclusion)" % name for (r, c, h) in compiled: if c.search(line): if not set(h).issubset(set(seen)): requires.append((h, r)) seen += h self.depends_on[sourcefile] = includes self.requires[sourcefile] = requires # Duplicate-header detection trimmedcount = {} for ref in map(trim, includes): trimmedcount[ref] = trimmedcount.get(ref, 0) + 1 for ref in trimmedcount: if trimmedcount[ref] > 1: print "deheader: %s has more than one inclusion of %s" % (sourcefile, ref) def forget(self, sourcefile, header): "Forget a header dependency." self.depends_on[sourcefile].remove(header) def remember(self, sourcefile, header): "Undo forgetting of a dependency." self.depends_on[sourcefile].append(header) class SaveForModification: "Prepare a file to be temporarily modified, with guaranteed reversion." def __init__(self, filename): self.filename = filename self.original = filename + "-orig" os.rename(self.filename, self.original) def remove_headers(self, removables): "Prepare a version with specified headers deleted." ofp = open(self.filename, "w") for line in open(self.original): if line not in removables: ofp.write(line) ofp.close() def forget(self): "Disable reversion." os.remove(self.original) def revert(self): "Revert modifications on the file at the end of this object's lifetime." if os.path.exists(self.original): try: os.remove(self.filename) except OSError: pass os.rename(self.original, self.filename) def trim(line): "Get file reference from an #include, retaining <> if a system header." trimmed = line[9:].strip() if trimmed[0] in '"': return '"' + trimmed.split('"')[1] + '"' elif trimmed[0] == '<': return trimmed.split('>')[0] + ">" else: return `line` def testcompile(source, maker, whereToRun, msg="", verbosity=0, showerrs=False): "Test-compile a sourcefile. Return the status and the compilation time" (stem, suffix) = os.path.splitext(source) derived = stem + ".o" if os.path.exists(derived): os.remove(derived) os.chdir(whereToRun) command = maker + " " + source+ " -c -o " + derived start = time.time() (status, output) = commands.getstatusoutput(command) end = time.time() if (os.WIFEXITED(status) and os.WEXITSTATUS(status) != 0 and showerrs) or verbosity >= COMMAND_DEBUG: sys.stdout.write(output) if status: explain = "failed" if verbosity >= PROGRESS_DEBUG: explain += " (%d)" % status else: explain = "succeeded" if verbosity >= PROGRESS_DEBUG: print "deheader: %s%s %s." \ % (sourcefile, msg, explain) if os.path.exists(derived): os.remove(derived) return (status, end - start) def getHeaderBaseName(header): if len( header.split("\"")) == 3 : return header.split("\"")[1].split(".")[0] elif len( header.split("<")) == 2 : return header.split("<")[1].split(".")[0] return header canRemoveSameNameHeader = [] def c_analyze(sourcefile, maker, includes, requires, verbosity, whereToRun): "Given a C file and a list of includes, return those that can be omitted." # We'll remove headers in reverse order, because later unnecessary # headers might depend on earlier ones includes.reverse() unneeded = [] if verbosity == BATON_DEBUG: baton = Baton(sourcefile + ": ", "Done") try: saveit = SaveForModification(sourcefile) while True: keepgoing = False for header in includes: if verbosity == BATON_DEBUG: baton.twirl() retain = 0 for (requirements, trigger) in requires: for required in requirements: if required in header: if verbosity >= PROGRESS_DEBUG: print "deheader: in %s, %s prevents uninclusion of %s" % (sourcefile, trigger, trim(header)) retain += 1 if not retain: saveit.remove_headers([header]) (st, t) = testcompile(sourcefile, maker, whereToRun, " without %s" % trim(header), verbosity, showerrs=False) if st == 0: # unneeded.append(header) # includes.remove(header) # keepgoing = True baseCFileName = os.path.basename(sourcefile).split(".")[0] baseHeaderName = getHeaderBaseName(header) if baseCFileName == baseHeaderName : if not sourcefile in canRemoveSameNameHeader : print "\nBAD Practice: I will not remove BUT, please, check this out!!!! Header with the same name of the code file can be removed without a problem." print " File %s does not need %s " % (sourcefile, header) else : unneeded.append(header) includes.remove(header) keepgoing = True if not keepgoing: break finally: saveit.revert() if verbosity == BATON_DEBUG: baton.end() # Tries to remove everyone that is assigned to be removed just to be sure!!! try: saveit = SaveForModification(sourcefile) saveit.remove_headers(unneeded) (st, t) = testcompile(sourcefile, maker, whereToRun, " without %s" % trim(str(unneeded)), verbosity, showerrs=False) saveit.revert() if st != 0: unneeded = getCombination(sourcefile, maker, unneeded, verbosity) except: unneeded = [] finally: saveit.revert() # Missing-require detection. Can't be merged with duplicate-header # detection because this has to be done after unneeded headers are removed. stillhere = map(trim, includes) for (requirement, trigger) in requires: if not set(requirement).issubset(stillhere): print "deheader: in %s, %s portability requires %s." % (sourcefile, trigger, ",".join(requirement)) return unneeded def getCombination(sourcefile, maker, unneeded, verbosity): reallyRemove = [] for element in unneeded: reallyRemove.append(element); try: saveit = SaveForModification(sourcefile) saveit.remove_headers(reallyRemove) (st, t) = testcompile(sourcefile, maker, whereToRun, " without %s" % trim(str(reallyRemove)), verbosity, showerrs=False) if st != 0: reallyRemove.pop() except: reallyRemove.pop() finally: saveit.revert() return reallyRemove def deheader(sourcefile, maker, includes, requires, remove, verbose, whereToRun ): # Sanity check against broken sourcefiles; we want this to # complain visibly if the sourcefile won't build at all. (st, t) = testcompile(sourcefile, maker, whereToRun, verbosity=max(1, verbose), showerrs=True) if st == 0: # Now do the analysis if sourcefile.endswith(".c") or sourcefile.endswith(".cc") or sourcefile.endswith(".cpp"): unneeded = c_analyze(sourcefile, maker, includes[:], requires, verbose, whereToRun) if unneeded: for line in unneeded: print "deheader: remove %s from %s" % (trim(line), sourcefile) if remove: remove_it = SaveForModification(sourcefile) remove_it.remove_headers(unneeded) remove_it.forget() del remove_it return Summary([sourcefile], includes, unneeded) else: print >>sys.stderr, "deheader: basic compilation failed on %s" % (sourcefile,) return Summary([sourcefile], includes, []) # After-action analysis starts here class Summary: "Summarize results from a deheading." def __init__(self, filenames=None, includes=None, unneeded=None): self.filenames = filenames or [] self.includes = includes or [] self.unneeded = unneeded or [] def __add__(self, other): result = Summary() result.filenames = self.filenames + other.filenames result.includes = self.includes + other.includes result.unneeded = self.unneeded + other.unneeded return result def __repr__(self): return "%d files, %d includes, %d removable" % \ (len(self.filenames), len(self.includes), len(self.unneeded)) if __name__ == "__main__": (options, arguments) = getopt.getopt(sys.argv[1:], "hi:m:rvxo:w:V", ["help", "ignore", "remove", "verbose","options","where-to-run"]) start1 = time.time() start12 = datetime.datetime.now() maker = "/usr/lib64/ccache/g++ -O0 -ggdb -g3 -Wall -Werror -Wno-error=deprecated-declarations -fstrict-aliasing -Wstrict-aliasing -fPIC -pthread -pthread -pthread -Ibuild -I. -Isrc -Ins3 -Ibuild -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/libxml2 -DNS3_ASSERT_ENABLE -DNS3_LOG_ENABLE -DSQLITE3=1 -DHAVE_IF_TUN_H=1 " verbose = 0 remove = False optTmp = "" whereToRun = "." ignores = [] excludes = [] for (switch, val) in options: if switch in ('-h', '--help'): sys.stderr.write(__doc__) sys.exit(0) elif switch in ('-i', '--ignore'): ignores.append(val) elif switch in ('-m', '--maker'): maker = val elif switch in ('-r', '--remove'): remove = True elif switch in ('-o', '--options'): optTmp = val elif switch in ('-w', '--where-to-run'): whereToRun = val elif switch in ('-v', '--verbose'): verbose += 1 elif switch in ('-V', '--version'): print "deheader", version raise SystemExit, 0 elif switch in ('-x', '--exclude'): excludes.append(val) maker = maker + " " + optTmp if not ignores: ignore = None else: ignore = re.compile("|".join(ignores)) if not excludes: excludes = None else: excludes = re.compile("|".join(excludes)) if not arguments: arguments = ["."] inclusion_map = InclusionMap(arguments, ignore, excludes, verbose) summaries = [] for sourcefile in inclusion_map.depends_on: summaries.append(deheader(sourcefile, maker, inclusion_map.depends_on[sourcefile], inclusion_map.requires[sourcefile], remove, verbose, whereToRun)) stats = Summary() for summary in summaries: stats = stats + summary print "deheader: saw", stats if canRemoveSameNameHeader: print "Bad Bad Practices: Files where the header with the same name of the code file could be removed" for headerTmp in canRemoveSameNameHeader : print " > %s" %(headerTmp) end1 = time.time() print "start: %s " % (time.strftime("%a %b %d, %Y %-I:%M:%S %p",time.localtime(start1))) print "end : %s " % (time.strftime("%a %b %d, %Y %-I:%M:%S %p",time.localtime(end1))) print "total: %s " % (datetime.datetime.now() - start12) raise SystemExit, 0 # End