"Fossies" - the Fresh Open Source Software Archive 
Member "deheader-1.10/deheader" (17 Feb 2023, 72250 Bytes) of package /linux/privat/deheader-1.10.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the latest
Fossies "Diffs" side-by-side code changes report for "deheader":
1.8_vs_1.10.
1 #!/usr/bin/env python3
2 """\
3 deheader -- find (optionally remove) unneeded includes in C or C++ sourcefiles.
4
5 Usage: deheader [-h] [-i pattern] [-m cmd] [-b dir] [-q] [-r] [-x pattern] [-v] [file...]
6 -h, --help Emit this help message and quit.
7 -m, --maker Set the build command (by default 'make %s')
8 -b, --builddir Set a build directory relative to where deheader is run
9 -i, --ignore Ignore (don't remove) headers matching the argument regexp
10 -q, --quiet Suppress statistical summary
11 -r, --remove Remove the final set of unneeded headers
12 -v, --verbose Be chatty about what you're doing.
13 -x, --exclude Exclude files matching regexp
14 -V, --version Emit version and exit.
15
16 This tool takes a list of C or C++ sourcefiles and generates a report
17 on which #includes can be omitted from them -- the test, for each foo.c
18 or foo.cc or foo.cpp, is simply whether 'rm foo.o; make foo.o' returns a
19 zero status. Optionally, with the -r option, the unneeded headers are removed.
20 The tool also reports on headers required for strict portability.
21
22 If a sourcefile argument is a directory, the report is generated on all source
23 files beneath it. Subdirectories beginning with a dot are ignored. If no
24 arguments are given, the program runs as if the name of the current directory
25 had been passed to it.
26
27 The original sourcefile is moved to a name with an .orig suffix and restored
28 on interrupt or after processing with its original timestamp, unless the
29 -r option was given and headers removed.
30
31 The last line of the output is a statistical summary of operations.
32 """
33 # SPDX-License-Identifier: BSD-2-Clause
34
35 # pylint: disable=line-too-long,invalid-name,redefined-outer-name,too-many-lines,missing-function-docstring,no-else-raise,no-else-return,consider-using-f-string,consider-using-dict-items,consider-using-with
36
37 # pylint: disable=multiple-imports
38 import sys, os, getopt, time, re, subprocess
39
40 version = "1.10"
41
42 try:
43 from subprocess import getstatusoutput
44 except ImportError:
45 from commands import getstatusoutput
46
47 BATON_DEBUG = 1
48 PROGRESS_DEBUG = 2
49 COMMAND_DEBUG = 3
50
51 # Difference in various compiler implementations and OSes mean that for cross-
52 # platform compatibility you sometimes want to leave "unneeded" headers alone
53 # because they're required in order to satisfy dependencies on other platforms.
54 requirements = (
55 # Headers mandated by SuS Version 2 System Interfaces.
56 # a64l, l64a - convert between a 32-bit integer and a radix-64 ASCII string
57 (r"a64l()", ["<stdlib.h>"]),
58 (r"l64a()", ["<stdlib.h>"]),
59 # abort - generate an abnormal process abort
60 (r"abort()", ["<stdlib.h>"]),
61 # abs - return an integer absolute value
62 (r"abs()", ["<stdlib.h>"]),
63 # access - determine accessibility of a file
64 (r"access()", ["<unistd.h>"]),
65 # acos - arc cosine function
66 (r"acos()", ["<math.h>"]),
67 # acosh, asinh, atanh - inverse hyperbolic functions
68 (r"acosh()", ["<math.h>"]),
69 (r"asinh()", ["<math.h>"]),
70 (r"atanh()", ["<math.h>"]),
71 # advance - pattern match given a compiled regular expression
72 (r"advance()", ["<regex.h>"]),
73 # aio.h - asynchronous input and output
74 (r"aio_cancel()", ["<aio.h>"]),
75 (r"aio_error()", ["<aio.h>"]),
76 (r"aio_fsync()", ["<aio.h>"]),
77 (r"aio_read()", ["<aio.h>"]),
78 (r"aio_return()", ["<aio.h>"]),
79 (r"aio_suspend()", ["<aio.h>"]),
80 (r"aio_write()", ["<aio.h>"]),
81 (r"lio_listio()", ["<aio.h>"]),
82 # alarm - schedule an alarm signal
83 (r"alarm()", ["<unistd.h>"]),
84 # asctime, asctime_r - convert date and time to a string
85 (r"asctime()", ["<time.h>"]),
86 (r"asctime_r()", ["<time.h>"]),
87 # asin - arc sine function
88 (r"asin()", ["<math.h>"]),
89 # assert - verify program assertion
90 (r"assert()", ["<assert.h>"]),
91 # atan - arc tangent function
92 (r"atan()", ["<math.h>"]),
93 # atan2 - arc tangent function
94 (r"atanh()", ["<math.h>"]),
95 # atanh - hyperbolic arc tangent
96 (r"atan2()", ["<math.h>"]),
97 # atexit - register a function to run at process termination
98 (r"atexit()", ["<stdlib.h>"]),
99 # atof - convert a string to double-precision number
100 (r"atof()", ["<stdlib.h>"]),
101 # atoi - convert a string to integer
102 (r"atoi()", ["<stdlib.h>"]),
103 # atol - convert a string to long integer
104 (r"atol()", ["<stdlib.h>"]),
105 # basename - return the last component of a pathname
106 (r"basename()", ["<libgen.h>"]),
107 # bcmp - memory operations
108 (r"bcmp()", ["<strings.h>"]),
109 # bcopy - memory operations
110 (r"bcopy()", ["<strings.h>"]),
111 # brk, sbrk - change space allocation (LEGACY)
112 (r"brk()", ["<unistd.h>"]),
113 (r"sbrk()", ["<unistd.h>"]),
114 # bsearch - binary search a sorted table
115 (r"bsort()", ["<stdlib.h>"]),
116 # btowc - single-byte to wide-character conversion
117 (r"btowc()", ["<stdio.h>", "<wchar.h>"]),
118 # bzero - memory operations
119 (r"bzero()", ["<strings.h>"]),
120 # calloc - a memory allocator
121 (r"calloc()", ["<stdlib.h>"]),
122 # catclose - close a message catalogue descriptor
123 (r"catclose()", ["<nl_types.h>"]),
124 # catgets - read a program message
125 (r"catgets()", ["<nl_types.h>"]),
126 # catopen - open a message catalogue
127 (r"catopen()", ["<nl_types.h>"]),
128 # cbrt - cube root function
129 (r"cbrt()", ["<math.h>"]),
130 # ceil - ceiling value function
131 (r"ceil()", ["<math.h>"]),
132 # chdir - change working directory
133 (r"chdir()", ["<unistd.h>"]),
134 # chmod - change mode of a file
135 (r"chmod()", ["<sys/stat.h>", "<sys/types.h>"]),
136 # chown - change owner and group of a file
137 (r"chown()", ["<sys/types.h>", "<unistd.h>"]),
138 # chroot - change root directory (LEGACY)
139 (r"chroot()", ["<unistd.h>"]),
140 # clearerr - clear indicators on a stream
141 (r"clearerr()", ["<stdio.h>"]),
142 # clock - report CPU time used
143 (r"clock()", ["<time.h>"]),
144 # clock_settime, clock_gettime, clock_getres - clock and timer functions
145 (r"clock_settime()", ["<time.h>"]),
146 (r"clock_gettime()", ["<time.h>"]),
147 (r"clock_getres()", ["<time.h>"]),
148 # close - close a file descriptor
149 (r"close()", ["<unistd.h>"]),
150 # closedir - close a directory stream
151 (r"closedir()", ["<sys/types.h>", "<dirent.h>"]),
152 # closelog, openlog, setlogmask, syslog - control system log
153 (r"closelog()", ["<syslog.h>"]),
154 (r"openlog()", ["<syslog.h>"]),
155 (r"setlogmask()", ["<syslog.h>"]),
156 (r"syslog()", ["<syslog.h>"]),
157 # compile - produce a compiled regular expression
158 (r"compile()", ["<regexp.h>"]),
159 # confstr - get configurable variables
160 (r"confstr()", ["<unistd.h>"]),
161 # cos - cosine function
162 (r"cos()", ["<math.h>"]),
163 # cosh - hyperbolic cosine function
164 (r"cosh()", ["<math.h>"]),
165 # creat - create a new file or rewrite an existing one
166 (r"creat()", ["<sys/types.h>", "<sys/stat.h>", "<fcntl.h>"]),
167 # crypt - string encoding function
168 (r"crypt()", ["<unistd.h>"]),
169 # ctermid - generate a pathname for controlling terminal
170 (r"ctermid()", ["<stdio.h>"]),
171 # ctime, ctime_r - convert a time value to date and time string
172 (r"ctime()", ["<time.h>"]),
173 (r"ctime_r()", ["<time.h>"]),
174 # ctype.h - character types
175 (r"isalnum()", ["<ctype.h>"]),
176 (r"isalpha()", ["<ctype.h>"]),
177 (r"isascii()", ["<ctype.h>"]),
178 (r"iscntrl()", ["<ctype.h>"]),
179 (r"isdigit()", ["<ctype.h>"]),
180 (r"isgraph()", ["<ctype.h>"]),
181 (r"islower()", ["<ctype.h>"]),
182 (r"isprint()", ["<ctype.h>"]),
183 (r"ispunct()", ["<ctype.h>"]),
184 (r"isspace()", ["<ctype.h>"]),
185 (r"isupper()", ["<ctype.h>"]),
186 (r"isxdigit()", ["<ctype.h>"]),
187 (r"toascii()", ["<ctype.h>"]),
188 (r"tolower()", ["<ctype.h>"]),
189 (r"toupper()", ["<ctype.h>"]),
190 (r"_tolower()", ["<ctype.h>"]),
191 (r"_toupper()", ["<ctype.h>"]),
192 # cuserid - character login name of the user
193 (r"cuserid()", ["<stdio.h>"]),
194 # daylight - daylight savings time flag
195 (r"extern\s+int\s+daylight;", ["<time.h>"]),
196 # dbm_clearerr, dbm_close, dbm_delete, dbm_error, dbm_fetch, dbm_firstkey, dbm_nextkey, dbm_open, dbm_store - database functions
197 (r"dbm_clearerr()", ["<ndbm.h>"]),
198 (r"dbm_close()", ["<ndbm.h>"]),
199 (r"dbm_delete()", ["<ndbm.h>"]),
200 (r"dbm_error()", ["<ndbm.h>"]),
201 (r"dbm_fetch()", ["<ndbm.h>"]),
202 (r"dbm_firstkey()", ["<ndbm.h>"]),
203 (r"dbm_nextkey()", ["<ndbm.h>"]),
204 (r"dbm_open()", ["<ndbm.h>"]),
205 (r"dbm_store()", ["<ndbm.h>"]),
206 # difftime - compute the difference between two calendar time values
207 (r"difftime()", ["<time.h>"]),
208 # dirname - report the parent directory name of a file pathname
209 (r"dirname()", ["<libgen.h>"]),
210 # div - compute the quotient and remainder of an integer division
211 (r"div()", ["<stdio.h>"]),
212 # dlclose - close a dlopen() object
213 (r"dlclose()", ["<dlfcn.h>"]),
214 # dlerror - get diagnostic information
215 (r"dlerror()", ["<dlfcn.h>"]),
216 # dlsym - obtain the address of a symbol from a dlopen() object
217 (r"dlsym()", ["<dlfcn.h>"]),
218 # drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, seed48, srand48 - generate uniformly distributed pseudo-random numbers
219 (r"drand48()", ["<stdlib.h>"]),
220 (r"erand48()", ["<stdlib.h>"]),
221 (r"jrand48()", ["<stdlib.h>"]),
222 (r"lcong48()", ["<stdlib.h>"]),
223 (r"lrand48()", ["<stdlib.h>"]),
224 (r"mrand48()", ["<stdlib.h>"]),
225 (r"nrand48()", ["<stdlib.h>"]),
226 (r"seed48()", ["<stdlib.h>"]),
227 (r"srand48()", ["<stdlib.h>"]),
228 # dup, dup2 - duplicate an open file descriptor
229 (r"dup()", ["<unistd.h>"]),
230 (r"dup2()", ["<unistd.h>"]),
231 # exit, _exit - terminate a process
232 (r"exit()", ["<stdlib.h>"]),
233 (r"_exit()", ["<unistd.h>"]),
234 # ecvt, fcvt, gcvt - convert a floating-point number to a string
235 (r"ecvt()", ["<stdlib.h>"]),
236 (r"fcvt()", ["<stdlib.h>"]),
237 (r"gcvt()", ["<stdlib.h>"]),
238 # encrypt - encoding function
239 (r"encrypt()", ["<unistd.h>"]),
240 # endgrent, getgrent, setgrent - group database entry functions
241 (r"endgrent()", ["<grp.h>"]),
242 (r"getgrent()", ["<grp.h>"]),
243 (r"setgrent()", ["<grp.h>"]),
244 (r"getgrnam()", ["<grp.h>"]),
245 (r"getgrgid()", ["<grp.h>"]),
246 (r"getgrnam_r()", ["<grp.h>"]),
247 (r"getgrgid_r()", ["<grp.h>"]),
248 # endpwent, getpwent, setpwent - user database functions
249 (r"endpwent()", ["<pwd.h>"]),
250 (r"getpwent()", ["<pwd.h>"]),
251 (r"setpwent()", ["<pwd.h>"]),
252 (r"getpwnam()", ["<pwd.h>"]),
253 (r"getpwuid()", ["<pwd.h>"]),
254 (r"getpwnam_r()", ["<pwd.h>"]),
255 (r"getpwuid_r()", ["<pwd.h>"]),
256 # endutxent, getutxent, getutxid, getutxline, pututxline, setutxent - user accounting database functions
257 (r"endutxent()", ["<utmpx.h>"]),
258 (r"getutxent()", ["<utmpx.h>"]),
259 (r"getutxid()", ["<utmpx.h>"]),
260 (r"getutxline()", ["<utmpx.h>"]),
261 (r"pututxline()", ["<utmpx.h>"]),
262 (r"setutxent()", ["<utmpx.h>"]),
263 # erf, erfc - error and complementary error functions
264 (r"erf()", ["<math.h>"]),
265 (r"erfc()", ["<math.h>"]),
266 # environ, execl, execv, execle, execve, execlp, execvp - execute a file
267 (r"extern\s+char\s+\*\*environ;", ["<unistd.h>"]),
268 (r"execl()", ["<unistd.h>"]),
269 (r"execv()", ["<unistd.h>"]),
270 (r"execle()", ["<unistd.h>"]),
271 (r"execve()", ["<unistd.h>"]),
272 (r"execlp()", ["<unistd.h>"]),
273 (r"execvp()", ["<unistd.h>"]),
274 # exp - exponential function
275 (r"exp()", ["<math.h>"]),
276 # expm1 - compute exponential functions
277 (r"expm1()", ["<math.h>"]),
278 # FD_CLR - macros for synchronous I/O multiplexing
279 (r"FD_CLR()", ["<sys/time.h>"]),
280 (r"FD_ISSET()", ["<sys/time.h>"]),
281 (r"FD_SET()", ["<sys/time.h>"]),
282 (r"FD_ZERO()", ["<sys/time.h>"]),
283 # fabs - absolute value function
284 (r"fabs()", ["<math.h>"]),
285 # fattach - attach a STREAMS-based file descriptor to a file in the file system name space
286 (r"fattach()", ["<stropts.h>"]),
287 # fchdir - change working directory
288 (r"fchdir()", ["<unistd.h>"]),
289 # fchmod - change mode of a file
290 (r"fchmod()", ["<sys/stat.h>"]),
291 # fchown - change owner and group of a file
292 (r"fchown()", ["<unistd.h>"]),
293 # fdopen - associate a stream with a file descriptor
294 (r"fdopen()", ["<stdio.h>"]),
295 # fclose - close a stream
296 (r"fclose()", ["<stdio.h>"]),
297 # fdatasync - synchronise the data of a file
298 (r"fdatasync()", ["<unistd.h>"]),
299 # fdetach - detach a name from a STREAMS-based file descriptor
300 (r"fdetach()", ["<stropts.h>"]),
301 # fdopen - associate a stream with a file descriptor
302 (r"fdopen()", ["<stdio.h>"]),
303 # ferror - test error indicator on a stream
304 (r"ferror()", ["<stdio.h>"]),
305 # feof - test end-of-file indicator on a stream
306 (r"feof()", ["<stdio.h>"]),
307 # fflush - flush a stream
308 (r"fflush()", ["<stdio.h>"]),
309 # ffs - find first set bit
310 (r"ffs()", ["<strings.h>"]),
311 # fgetc - get a byte from a stream
312 (r"fgetc()", ["<stdio.h>"]),
313 # fgetpos - get current file position information
314 (r"fgetpos()", ["<stdio.h>"]),
315 # fgets - get a string from a stream
316 (r"fgets()", ["<stdio.h>"]),
317 # fgetwc - get a wide-character code from a stream
318 (r"fgetwc()", ["<stdio.h>", "<wchar.h>"]),
319 # fgetws - get a wide-character string from a stream
320 (r"fgetws()", ["<stdio.h>", "<wchar.h>"]),
321 # fileno - map a stream pointer to a file descriptor
322 (r"fileno()", ["<stdio.h>"]),
323 # flockfile, ftrylockfile, funlockfile - stdio locking functions
324 (r"flockfile()", ["<stdio.h>"]),
325 (r"ftrylockfile()", ["<stdio.h>"]),
326 (r"funlockfile()", ["<stdio.h>"]),
327 # fmod - floating-point remainder value function
328 (r"fmod()", ["<math.h>"]),
329 # fmtmsg.h - message display structures
330 (r"fmtmsg()", ["<fmtmsg.h>"]),
331 # fnmatch.h - filename-matching types
332 (r"fnmatch()", ["<fnmatch.h>"]),
333 # fopen - open a stream
334 (r"fopen()", ["<stdio.h>"]),
335 # fork - create a new process
336 (r"fork()", ["<sys/types.h>", "<unistd.h>"]),
337 # fpathconf, pathconf - get configurable pathname variables
338 (r"fpathconf()", ["<unistd.h>"]),
339 (r"pathconf()", ["<unistd.h>"]),
340 # fputc - put a byte on a stream
341 (r"fputc()", ["<stdio.h>"]),
342 # fputs - put a string on a stream
343 (r"fputs()", ["<stdio.h>"]),
344 # fputwc - put a wide-character code on a stream
345 (r"fputwc()", ["<stdio.h>"]),
346 # fputws - put a wide-character string on a stream
347 (r"fputws()", ["<stdio.h>"]),
348 # fread - binary input
349 (r"fread()", ["<stdio.h>"]),
350 # free - free allocated memory
351 (r"free()", ["<stdlib.h>"]),
352 # freopen - open a stream
353 (r"freopen()", ["<stdio.h>"]),
354 # frexp - extract mantissa and exponent from a double precision number
355 (r"frexp()", ["<math.h>"]),
356 # fscanf, scanf, sscanf - convert formatted input
357 (r"fscanf()", ["<stdio.h>"]),
358 (r"scanf()", ["<stdio.h>"]),
359 (r"sscanf()", ["<stdio.h>"]),
360 # fseek, fseeko - reposition a file-position indicator in a stream
361 (r"fseek()", ["<stdio.h>"]),
362 (r"fseeko()", ["<stdio.h>"]),
363 # fsetpos - set current file position
364 (r"fsetpos()", ["<stdio.h>"]),
365 # fstat - get file status
366 (r"fstat()", ["<sys/types.h>", "<sys/stat.h>"]),
367 # fstatvfs, statvfs - get file system information
368 (r"fstatvfs()", ["<sys/statvfs.h>"]),
369 (r"statvfs()", ["<sys/statvfs.h>"]),
370 # fsync - synchronise changes to a file
371 (r"fsync()", ["<unistd.h>"]),
372 # ftell, ftello - return a file offset in a stream
373 (r"ftell()", ["<stdio.h>"]),
374 (r"ftello()", ["<stdio.h>"]),
375 # ftime - get date and time
376 (r"ftime()", ["<sys/timeb.h>"]),
377 # ftok - generate an IPC key
378 (r"ftok()", ["<sys/ipc.h>"]),
379 # ftruncate, truncate - truncate a file to a specified length
380 (r"truncate()", ["<unistd.h>"]),
381 (r"ftruncate()", ["<unistd.h>"]),
382 # ftw - traverse (walk) a file tree
383 (r"ftw()", ["<ftw.h>"]),
384 (r"nftw()", ["<ftw.h>"]),
385 # fwide - set stream orientation
386 (r"fwide()", ["<stdio.h>", "<wchar.h>"]),
387 # fwprintf, wprintf, swprintf - print formatted wide-character output
388 (r"fwprintf()", ["<stdio.h>", "<wchar.h>"]),
389 (r"wprintf()", ["<stdio.h>", "<wchar.h>"]),
390 (r"swprintf()", ["<stdio.h>", "<wchar.h>"]),
391 # fwrite - binary output
392 (r"fwrite()", ["<stdio.h>"]),
393 # fwscanf, wscanf, swscanf - convert formatted wide-character input
394 (r"fwscanf()", ["<stdio.h>", "<wchar.h>"]),
395 (r"wscanf()", ["<stdio.h>", "<wchar.h>"]),
396 (r"swscanf()", ["<stdio.h>", "<wchar.h>"]),
397 # gamma, signgam - log gamma function
398 (r"gamma()", ["<math.h>"]),
399 # getc - get a byte from a stream
400 (r"getc()", ["<stdio.h>"]),
401 # getc_unlocked, getchar_unlocked, putc_unlocked, putchar_unlocked - stdio with explicit client locking
402 (r"getc_unlocked()", ["<stdio.h>"]),
403 (r"getchar_unlocked()", ["<stdio.h>"]),
404 (r"putc_unlocked()", ["<stdio.h>"]),
405 (r"putchar_unlocked()", ["<stdio.h>"]),
406 # getchar - get a byte from a stdin stream
407 (r"getchar()", ["<stdio.h>"]),
408 # getcontext, setcontext - get and set current user context
409 (r"getcontext()", ["<ucontext.h>"]),
410 (r"setcontext()", ["<ucontext.h>"]),
411 # getcwd - get the pathname of the current working directory
412 (r"getcwd()", ["<unistd.h>"]),
413 # getdate - convert user format date and time
414 (r"getdate()", ["<time.h>"]),
415 # getdtablesize - get the file descriptor table size
416 (r"getdtablesize()", ["<unistd.h>"]),
417 # getegid - get the effective group ID
418 (r"getegid()", ["<unistd.h>", "<sys/types.h>"]),
419 # getenv - get value of an environment variable
420 (r"getenv()", ["<stdlib.h>"]),
421 # geteuid - get the effective user ID
422 (r"geteuid()", ["<unistd.h>", "<sys/types.h>"]),
423 # getgid - get the real group ID
424 (r"getgid()", ["<unistd.h>", "<sys/types.h>"]),
425 # getgrgid, getgrgid_r - get group database entry for a group ID
426 (r"getgrgid()", ["<sys/types.h>", "<grp.h>"]),
427 (r"getgrgid_r()", ["<sys/types.h>", "<grp.h>"]),
428 # getgrnam, getgrnam_r - search group database for a name
429 (r"getgrnam()", ["<sys/types.h>", "<pwd.h>"]),
430 (r"getgrnam_r()", ["<sys/types.h>", "<pwd.h>"]),
431 # getgroups - get supplementary group IDs
432 (r"getgroups()", ["<unistd.h>", "<sys/types.h>"]),
433 # gethostid - get an identifier for the current host
434 (r"gethostid()", ["<unistd.h>"]),
435 # getitimer, setitimer - get or set value of interval timer
436 (r"getitimer()", ["<sys/time.h>"]),
437 (r"setitimer()", ["<sys/time.h>"]),
438 # getlogin, getlogin_r - get login name
439 (r"getlogin()", ["<unistd.h>"]),
440 (r"getlogin_r()", ["<unistd.h>"]),
441 # getmsg, getpmsg - receive next message from a STREAMS file
442 (r"getmsg()", ["<stropts.h>"]),
443 (r"getpmsg()", ["<stropts.h>"]),
444 # getopt, optarg, optind, opterr, optopt - command option parsing
445 (r"getopt()", ["<unistd.h>"]),
446 (r"extern\s+char\s+\*\*optarg;", ["<unistd.h>"]),
447 # getpagesize - get the current page size
448 (r"getpagesize()", ["<unistd.h>"]),
449 # getpass - read a string of characters without echo
450 (r"getpass()", ["<unistd.h>"]),
451 # getpgid - get the process group ID for a process
452 (r"getpgid()", ["<unistd.h>"]),
453 # getpgrp - get the process group ID of the calling process
454 (r"getpgrp()", ["<sys/types.h>", "<unistd.h>"]),
455 # getpid - get the process ID
456 (r"getpid()", ["<sys/types.h>", "<unistd.h>"]),
457 # getppid - get the parent process ID
458 (r"getppid()", ["<sys/types.h>", "<unistd.h>"]),
459 # getpriority, setpriority - get or set the nice value
460 (r"getpriority()", ["<sys/resource.h>"]),
461 (r"setpriority()", ["<sys/resource.h>"]),
462 # getpwnam, getpwnam_r - search user database for a name
463 (r"getpwnam()", ["<sys/types.h>", "<pwd.h>"]),
464 (r"getpwnam_r()", ["<sys/types.h>", "<pwd.h>"]),
465 # getpwuid, getpwuid_r - search user database for a user ID
466 (r"getpwuid()", ["<sys/types.h>", "<pwd.h>"]),
467 (r"getpwuid_r()", ["<sys/types.h>", "<pwd.h>"]),
468 # getrlimit, setrlimit - control maximum resource consumption
469 (r"getrlimit()", ["<sys/resource.h>"]),
470 (r"setrlimit()", ["<sys/resource.h>"]),
471 # getrusage - get information about resource utilisation
472 (r"getrusage()", ["<sys/resource.h>"]),
473 # gets - get a string from a stdin stream
474 (r"gets()", ["<stdio.h>"]),
475 # getsid - get the process group ID of session leader
476 (r"getsid()", ["<unistd.h>"]),
477 # getsubopt - parse suboption arguments from a string
478 (r"getsubopt()", ["<stdlib.h>"]),
479 # gettimeofday - get the date and time
480 (r"gettimeofday()", ["<sys/time.h>"]),
481 # getuid - get a real user ID
482 (r"getuid()", ["<sys/types.h>", "<unistd.h>"]),
483 # getw - get a word from a stream
484 (r"getw()", ["<stdio.h>"]),
485 # getwc - get a wide-character code from a stream
486 (r"getwc()", ["<stdio.h>", "<wchar.h>"]),
487 # getws - get a wide-character string from a stream
488 (r"getws()", ["<stdio.h>", "<wchar.h>"]),
489 # getwchar - get a wide character from a stdin stream
490 (r"getwchar()", ["<wchar.h>"]),
491 # getwd - get the current working directory pathname
492 (r"getwd()", ["<unistd.h>"]),
493 # glob.h - pathname pattern-matching types
494 (r"glob()", ["<glob.h>"]),
495 (r"globfree()", ["<glob.h>"]),
496 # gmtime, gmtime_r - convert a time value to a broken-down UTC time
497 (r"gmtime()", ["<time.h>"]),
498 (r"gmtime_r()", ["<time.h>"]),
499 # grantpt - grant access to the slave pseudo-terminal device
500 (r"grantpt()", ["<stdlib.h>"]),
501 # hcreate, hdestroy, hsearch - manage hash search table
502 (r"hcreate()", ["<search.h>"]),
503 (r"hdestroy()", ["<search.h>"]),
504 (r"hsearch ()", ["<search.h>"]),
505 # hypot - Euclidean distance function
506 (r"hypot()", ["<math.h>"]),
507 # iconv.h - codeset conversion facility
508 (r"iconv_open()", ["<iconv.h>"]),
509 (r"iconv()", ["<iconv.h>"]),
510 (r"iconv_close()", ["<iconv.h>"]),
511 # ilogb - return an unbiased exponent
512 (r"ilogb()", ["<math.h>"]),
513 # index - character string operations
514 (r"index()", ["<strings.h>"]),
515 # initstate, random, setstate, srandom - pseudorandom number functions
516 (r"initstate()", ["<stdlib.h>"]),
517 (r"random()", ["<stdlib.h>"]),
518 (r"setstate()", ["<stdlib.h>"]),
519 (r"srandom()", ["<stdlib.h>"]),
520 # insque, remque - insert or remove an element in a queue
521 (r"insque()", ["<search.h>"]),
522 (r"remque()", ["<search.h>"]),
523 # SuS ioctl specifies <stropts.h>, but that's just wrong
524 # isastream - test a file descriptor
525 (r"isastream()", ["<stropts.h>"]),
526 # isnan - test for a NaN
527 (r"isnan()", ["<math.h>"]),
528 # j0, j1, jn - Bessel functions of the first kind
529 (r"j0()", ["<math.h>"]),
530 (r"j1()", ["<math.h>"]),
531 (r"jn()", ["<math.h>"]),
532 # labs - return a long integer absolute value
533 (r"labs()", ["<stdlib.h>"]),
534 # lchown - change the owner and group of a symbolic link
535 (r"lchown()", ["<unistd.h>"]),
536 # ldexp - load exponent of a floating point number
537 (r"ldexp()", ["<math.h>"]),
538 # ldiv - compute quotient and remainder of a long division
539 (r"ldiv()", ["<stdlib.h>"]),
540 # lgamma - log gamma function
541 (r"lgamma()", ["<math.h>"]),
542 # libgen.h - definitions for pattern matching functions
543 (r"regcmp()", ["<libgen.h>"]),
544 (r"regex()", ["<libgen.h>"]),
545 # link - link to a file
546 (r"link()", ["<unistd.h>"]),
547 # localeconv - determine the program locale
548 (r"localeconv()", ["<locale.h>"]),
549 # localtime, localtime_r - convert a time value to a broken-down local time
550 (r"localtime()", ["<time.h>"]),
551 (r"localtime_r()", ["<time.h>"]),
552 # lockf - record locking on files
553 (r"lockf()", ["<unistd.h>"]),
554 # log - natural logarithm function
555 (r"log()", ["<math.h>"]),
556 # log10 - base 10 logarithm function
557 (r"log10()", ["<math.h>"]),
558 # log1p - compute a natural logarithm
559 (r"log1p()", ["<math.h>"]),
560 # logb - radix-independent exponent
561 (r"logb()", ["<math.h>"]),
562 # lsearch, lfind - linear search and update
563 (r"lfind()", ["<search.h>"]),
564 (r"lsearch()", ["<search.h>"]),
565 # lseek - move the read/write file offset
566 (r"lseek()", ["<sys/types.h>", "<unistd.h>"]),
567 # lstat - get symbolic link status
568 (r"lstat()", ["<sys/stat.h>"]),
569 # makecontext, swapcontext - manipulate user contexts
570 (r"makecontext()", ["<ucontext.h>"]),
571 (r"swapcontext()", ["<ucontext.h>"]),
572 # malloc - a memory allocator
573 (r"malloc()", ["<stdlib.h>"]),
574 # mblen - get number of bytes in a character
575 (r"mblen()", ["<stdlib.h>"]),
576 # mbrlen - get number of bytes in a character (restartable)
577 (r"mblren()", ["<wchar.h>"]),
578 # mbrtowc - convert a character to a wide-character code (restartable)
579 (r"mbrtowc()", ["<wchar.h>"]),
580 # mbsinit - determine conversion object status
581 (r"mbsinit()", ["<wchar.h>"]),
582 # mbsrtowcs - convert a character string to a wide-character string (restartable)
583 (r"mbsrtowcs()", ["<wchar.h>"]),
584 # mbstowcs - convert a character string to a wide-character string
585 (r"mbstowcs()", ["<wchar.h>"]),
586 # mbtowc - convert a character to a wide-character code
587 (r"mbtowcs()", ["<stdlib.h>"]),
588 # mkdir - make a directory
589 (r"mkdir()", ["<sys/types.h>", "<sys/stat.h>"]),
590 # mkfifo - make a FIFO special file
591 (r"mkfifo()", ["<sys/types.h>", "<sys/stat.h>"]),
592 # mknod - make a directory, a special or regular file
593 (r"mknod()", ["<sys/stat.h>"]),
594 # mkstemp - make a unique file name
595 (r"mkstemp()", ["<stdlib.h>"]),
596 # mktemp - make a unique filename
597 (r"mktemp()", ["<stdlib.h>"]),
598 # convert broken-down time into time since the Epoch
599 (r"mktime()", ["<time.h>"]),
600 # sys/mman.h - memory management declarations
601 (r"mlock()", ["<sys/mman.h>"]),
602 (r"mlockall()", ["<sys/mman.h>"]),
603 (r"mmap()", ["<sys/mman.h>"]),
604 (r"mprotect()", ["<sys/mman.h>"]),
605 (r"msync()", ["<sys/mman.h>"]),
606 (r"munlock()", ["<sys/mman.h>"]),
607 (r"munlockall()", ["<sys/mman.h>"]),
608 (r"munmap()", ["<sys/mman.h>"]),
609 (r"shm_open()", ["<sys/mman.h>"]),
610 (r"shm_unlink()", ["<sys/mman.h>"]),
611 # modf - decompose a floating-point number
612 (r"modf()", ["<math.h>"]),
613 # monetary.h - monetary types
614 (r"strfmon()", ["<monetary.h>"]),
615 # mqueue.h - message queues
616 (r"mq_close()", ["<mqueue.h>"]),
617 (r"mq_getattr()", ["<mqueue.h>"]),
618 (r"mq_notify()", ["<mqueue.h>"]),
619 (r"mq_open()", ["<mqueue.h>"]),
620 (r"mq_receive()", ["<mqueue.h>"]),
621 (r"mq_send()", ["<mqueue.h>"]),
622 (r"mq_setattr()", ["<mqueue.h>"]),
623 (r"mq_unlink()", ["<mqueue.h>"]),
624 # sys/msg.h - message queue structures
625 (r"msgctl()", ["<sys/msg.h>"]),
626 (r"msgget()", ["<sys/msg.h>"]),
627 (r"msgrcv()", ["<sys/msg.h>"]),
628 (r"msgsnd()", ["<sys/msg.h>"]),
629 # nanosleep - high resolution sleep
630 (r"nanosleep()", ["<time.h>"]),
631 # nextafter - next representable double-precision floating-point number
632 (r"nextafter()", ["<math.h>"]),
633 # change nice value of a process
634 (r"nice()", ["<unistd.h>"]),
635 # nl_langinfo - language information
636 (r"nl_langinfo()", ["<langinfo.h>"]),
637 # open - open a file
638 (r"open()", ["<sys/types.h>", "<sys/stat.h>", "<fcntl.h>"]),
639 # opendir - open a directory
640 (r"opendir()", ["<sys/types.h>", "<dirent.h>"]),
641 # pause - suspend the thread until signal is received
642 (r"pause()", ["<unistd.h>"]),
643 # pclose - close a pipe stream to or from a process
644 (r"pclose()", ["<stdio.h>"]),
645 # perror - write error messages to standard error
646 (r"perror()", ["<stdio.h>"]),
647 # pipe - create an interprocess channel
648 (r"pipe()", ["<unistd.h>"]),
649 # poll - input/output multiplexing
650 (r"poll()", ["<poll.h>"]),
651 # popen - initiate pipe streams to or from a process
652 (r"popen()", ["<stdio.h>"]),
653 # pow - power function
654 (r"pow()", ["<math.h>"]),
655 # pread - read from a file
656 ("pread()", ["<unistd.h>"]),
657 # pthread.h - threads
658 (r"pthread_attr_destroy()", ["<pthread.h>"]),
659 (r"pthread_attr_getdetachstate()", ["<pthread.h>"]),
660 (r"pthread_attr_getguardsize()", ["<pthread.h>"]),
661 (r"pthread_attr_getinheritsched()", ["<pthread.h>"]),
662 (r"pthread_attr_getschedparam()", ["<pthread.h>"]),
663 (r"pthread_attr_getschedpolicy()", ["<pthread.h>"]),
664 (r"pthread_attr_getscope()", ["<pthread.h>"]),
665 (r"pthread_attr_getstackaddr()", ["<pthread.h>"]),
666 (r"pthread_attr_getstacksize()", ["<pthread.h>"]),
667 (r"pthread_attr_init()", ["<pthread.h>"]),
668 (r"pthread_attr_setdetachstate()", ["<pthread.h>"]),
669 (r"pthread_attr_setguardsize()", ["<pthread.h>"]),
670 (r"pthread_attr_setinheritsched()", ["<pthread.h>"]),
671 (r"pthread_attr_setschedparam()", ["<pthread.h>"]),
672 (r"pthread_attr_setschedpolicy()", ["<pthread.h>"]),
673 (r"pthread_attr_setscope()", ["<pthread.h>"]),
674 (r"pthread_attr_setstackaddr()", ["<pthread.h>"]),
675 (r"pthread_attr_setstacksize()", ["<pthread.h>"]),
676 (r"pthread_cancel()", ["<pthread.h>"]),
677 (r"pthread_cleanup_push()", ["<pthread.h>"]),
678 (r"pthread_cleanup_pop()", ["<pthread.h>"]),
679 (r"pthread_cond_broadcast()", ["<pthread.h>"]),
680 (r"pthread_cond_destroy()", ["<pthread.h>"]),
681 (r"pthread_cond_init()", ["<pthread.h>"]),
682 (r"pthread_cond_signal()", ["<pthread.h>"]),
683 (r"pthread_cond_timedwait()", ["<pthread.h>"]),
684 (r"pthread_cond_wait()", ["<pthread.h>"]),
685 (r"pthread_condattr_destroy()", ["<pthread.h>"]),
686 (r"pthread_condattr_getpshared()", ["<pthread.h>"]),
687 (r"pthread_condattr_init()", ["<pthread.h>"]),
688 (r"pthread_condattr_setpshared()", ["<pthread.h>"]),
689 (r"pthread_create()", ["<pthread.h>"]),
690 (r"pthread_detach()", ["<pthread.h>"]),
691 (r"pthread_equal()", ["<pthread.h>"]),
692 (r"pthread_exit()", ["<pthread.h>"]),
693 (r"pthread_getconcurrency()", ["<pthread.h>"]),
694 (r"pthread_getschedparam()", ["<pthread.h>"]),
695 (r"pthread_getspecific()", ["<pthread.h>"]),
696 (r"pthread_join()", ["<pthread.h>"]),
697 (r"pthread_key_create()", ["<pthread.h>"]),
698 (r"pthread_key_delete()", ["<pthread.h>"]),
699 (r"pthread_mutex_destroy()", ["<pthread.h>"]),
700 (r"pthread_mutex_getprioceiling()", ["<pthread.h>"]),
701 (r"pthread_mutex_init()", ["<pthread.h>"]),
702 (r"pthread_mutex_lock()", ["<pthread.h>"]),
703 (r"pthread_mutex_setprioceiling()", ["<pthread.h>"]),
704 (r"pthread_mutex_trylock()", ["<pthread.h>"]),
705 (r"pthread_mutex_unlock()", ["<pthread.h>"]),
706 (r"pthread_mutexattr_destroy()", ["<pthread.h>"]),
707 (r"pthread_mutexattr_getprioceiling()",["<pthread.h>"]),
708 (r"pthread_mutexattr_getprotocol()", ["<pthread.h>"]),
709 (r"pthread_mutexattr_getpshared()", ["<pthread.h>"]),
710 (r"pthread_mutexattr_gettype()", ["<pthread.h>"]),
711 (r"pthread_mutexattr_init()", ["<pthread.h>"]),
712 (r"pthread_mutexattr_setprioceiling()",["<pthread.h>"]),
713 (r"pthread_mutexattr_setprotocol()", ["<pthread.h>"]),
714 (r"pthread_mutexattr_setpshared()", ["<pthread.h>"]),
715 (r"pthread_mutexattr_settype()", ["<pthread.h>"]),
716 (r"pthread_once()", ["<pthread.h>"]),
717 (r"pthread_rwlock_destroy()", ["<pthread.h>"]),
718 (r"pthread_rwlock_init()", ["<pthread.h>"]),
719 (r"pthread_rwlock_rdlock()", ["<pthread.h>"]),
720 (r"pthread_rwlock_tryrdlock()", ["<pthread.h>"]),
721 (r"pthread_rwlock_trywrlock()", ["<pthread.h>"]),
722 (r"pthread_rwlock_unlock()", ["<pthread.h>"]),
723 (r"pthread_rwlock_wrlock()", ["<pthread.h>"]),
724 (r"pthread_rwlockattr_destroy()", ["<pthread.h>"]),
725 (r"pthread_rwlockattr_getpshared()", ["<pthread.h>"]),
726 (r"pthread_rwlockattr_init()", ["<pthread.h>"]),
727 (r"pthread_rwlockattr_setpshared()", ["<pthread.h>"]),
728 (r"pthread_self()", ["<pthread.h>"]),
729 (r"pthread_setcancelstate()", ["<pthread.h>"]),
730 (r"pthread_setcanceltype()", ["<pthread.h>"]),
731 (r"pthread_setconcurrency()", ["<pthread.h>"]),
732 (r"pthread_setschedparam()", ["<pthread.h>"]),
733 (r"pthread_setspecific()", ["<pthread.h>"]),
734 (r"pthread_testcancel()", ["<pthread.h>"]),
735 # ptsname - get name of the slave pseudo-terminal device
736 (r"ptsname()", ["<stdlib.h>"]),
737 # putc - put a byte on a stream
738 (r"putc()", ["<stdio.h>"]),
739 # putc_unlocked - stdio with explicit client locking
740 (r"putc_unlocked()", ["<stdio.h>"]),
741 # putchar - put byte on stdout stream
742 (r"putchar()", ["<stdio.h>"]),
743 # putchar_unlocked - stdio with explicit client locking
744 (r"putchar_unlocked()", ["<stdio.h>"]),
745 # putenv - change or add a value to environment
746 (r"putenv()", ["<stdlib.h>"]),
747 # putmsg, putpmsg - send a message on a STREAM
748 (r"putmsg()", ["<stropts.h>"]),
749 (r"putpmsg()", ["<stropts.h>"]),
750 # puts - put a string on standard output
751 (r"puts()", ["<stdio.h>"]),
752 # putw - put a word on a stream
753 (r"putw()", ["<stdio.h>"]),
754 # putwc - put a wide-character on a stream
755 (r"putwc()", ["<stdio.h>", "<wchar.h>"]),
756 # putwchar - put a wide character from a stdin stream
757 (r"putwchar()", ["<wchar.h>"]),
758 # qsort - sort a table of data
759 (r"qsort()", ["<stdlib.h>"]),
760 # raise - send a signal to the executing process
761 (r"raise()", ["<signal.h>"]),
762 # rand, rand_r - pseudo-random number generator
763 (r"rand()", ["<stdlib.h>"]),
764 (r"srand()", ["<stdlib.h>"]),
765 (r"rand_r()", ["<stdlib.h>"]),
766 # random - generate pseudorandom number
767 (r"random()", ["<stdlib.h>"]),
768 # re_comp.h - regular-expression-matching functions for re_comp()
769 (r"re_comp()", ["<re_comp.h>"]),
770 (r"re_exec()", ["<re_comp.h>"]),
771 # read, readv, pread - read from a file
772 ("read()", ["<unistd.h>"]),
773 ("readv()", ["<sys/uio.h>"]),
774 # readdir, readdir_r - read directory
775 (r"readdir()", ["<sys/types.h>", "<dirent.h>"]),
776 (r"readdir_r()", ["<sys/types.h>", "<dirent.h>"]),
777 # readlink - read the contents of a symbolic link
778 ("readlink()", ["<unistd.h>"]),
779 # realloc - memory reallocator
780 ("realloc()", ["<unistd.h>"]),
781 # realpath - resolve a pathname
782 ("realpath()", ["<stdlib.h>"]),
783 # regcomp, regexec, regerror, regfree - regular expression matching
784 (r"regcomp()", ["<sys/types.h>", "<regex.h>"]),
785 (r"regexec()", ["<sys/types.h>", "<regex.h>"]),
786 (r"regerror()", ["<sys/types.h>", "<regex.h>"]),
787 (r"regfree()", ["<sys/types.h>", "<regex.h>"]),
788 # remainder - remainder function
789 (r"remainder()", ["<math.h>"]),
790 # remove - remove files
791 (r"remove()", ["<stdio.h>"]),
792 # rename - rename a file
793 (r"rename()", ["<stdio.h>"]),
794 # rewind - reset file position indicator in a stream
795 (r"rewind()", ["<stdio.h>"]),
796 # rewinddir - reset position of directory stream to the beginning of a directory
797 (r"rewinddir()", ["<sys/types.h>", "<dirent.h>"]),
798 # rindex - character string operations
799 (r"rindex()", ["<strings.h>"]),
800 # rint - round-to-nearest integral value
801 (r"rint()", ["<math.h>"]),
802 # rmdir - remove a directory
803 ("rmdir()", ["<unistd.h>"]),
804 # scalb - load exponent of a radix-independent floating-point number
805 (r"scalb()", ["<math.h>"]),
806 # scanf - convert formatted input
807 (r"scanf()", ["<stdio.h>"]),
808 # sched.h - execution scheduling
809 (r"sched_get_priority_max()", ["<sched.h>"]),
810 (r"sched_get_priority_min()", ["<sched.h>"]),
811 (r"sched_getparam()", ["<sched.h>"]),
812 (r"sched_getscheduler()", ["<sched.h>"]),
813 (r"sched_rr_get_interval()", ["<sched.h>"]),
814 (r"sched_setparam()", ["<sched.h>"]),
815 (r"sched_setscheduler()", ["<sched.h>"]),
816 (r"sched_yield()", ["<sched.h>"]),
817 # seekdir - set position of directory stream
818 (r"seekdir()", ["<sys/types.h>", "<dirent.h>"]),
819 # select - synchronous I/O multiplexing
820 (r"select()", ["<sys/time.h>"]),
821 # semaphore.h - semaphores
822 (r"sem_close()", ["<semaphore.h>"]),
823 (r"sem_destroy()", ["<semaphore.h>"]),
824 (r"sem_getvalue()", ["<semaphore.h>"]),
825 (r"sem_init()", ["<semaphore.h>"]),
826 (r"sem_open()", ["<semaphore.h>"]),
827 (r"sem_post()", ["<semaphore.h>"]),
828 (r"sem_trywait()", ["<semaphore.h>"]),
829 (r"sem_unlink()", ["<semaphore.h>"]),
830 (r"sem_wait()", ["<semaphore.h>"]),
831 # sys/sem.h - semaphore facility
832 (r"semctl()", ["<sys/sem.h>"]),
833 (r"semget()", ["<sys/sem.h>"]),
834 (r"semop()", ["<sys/sem.h>"]),
835 # setbuf - assign buffering to a stream
836 (r"setbuf()", ["<stdio.h>"]),
837 # setgid - set-group-ID
838 (r"setgid()", ["<sys/types.h>", "<unistd.h>"]),
839 # setgrent - reset group database to first entry
840 (r"setgrent()", ["<grp.h>"]),
841 # setkey - set encoding key
842 (r"setkey()", ["<stdlib.h>"]),
843 # setpgid - set process group ID for job control
844 (r"setpgid()", ["<sys/types.h>", "<unistd.h>"]),
845 # setpgrp - set process group ID
846 (r"setpgrp()", ["<unistd.h>"]),
847 # setregid - set real and effective group IDs
848 (r"setregid()", ["<unistd.h>"]),
849 # setreuid - set real and effective user IDs
850 (r"setreuid()", ["<unistd.h>"]),
851 # setsid - create session and set process group ID
852 (r"setsid()", ["<sys/types.h>", "<unistd.h>"]),
853 # setuid - set-user-ID
854 (r"setuid()", ["<sys/types.h>", "<unistd.h>"]),
855 # setvbuf - assign buffering to a stream
856 (r"setvbuf()", ["<stdio.h>"]),
857 # sys/shm.h - shared memory facility
858 (r"shmat()", ["<sys/shm.h>"]),
859 (r"shmctl()", ["<sys/shm.h>"]),
860 (r"shmdt()", ["<sys/shm.h>"]),
861 (r"shmget()", ["<sys/shm.h>"]),
862 # setjmp.h - stack environment declarations
863 (r"longjmp()", ["<setjmp.h>"]),
864 (r"siglongjmp()", ["<setjmp.h>"]),
865 (r"_longjmp()", ["<setjmp.h>"]),
866 (r"setjmp()", ["<setjmp.h>"]),
867 (r"sigsetjmp()", ["<setjmp.h>"]),
868 (r"_setjmp()", ["<setjmp.h>"]),
869 # signal.h - signals
870 (r"bsd_signal()", ["<signal.h>"]),
871 (r"kill()", ["<signal.h>"]),
872 (r"killpg()", ["<signal.h>"]),
873 (r"pthread_kill()", ["<signal.h>"]),
874 (r"pthread_sigmask()", ["<signal.h>"]),
875 (r"raise()", ["<signal.h>"]),
876 (r"sigaction()", ["<signal.h>"]),
877 (r"sigaddset()", ["<signal.h>"]),
878 (r"sigaltstack()", ["<signal.h>"]),
879 (r"sigdelset()", ["<signal.h>"]),
880 (r"sigemptyset()", ["<signal.h>"]),
881 (r"sigfillset()", ["<signal.h>"]),
882 (r"sighold()", ["<signal.h>"]),
883 (r"sigignore()", ["<signal.h>"]),
884 (r"siginterrupt()", ["<signal.h>"]),
885 (r"sigismember()", ["<signal.h>"]),
886 (r"signal()", ["<signal.h>"]),
887 (r"sigpause()", ["<signal.h>"]),
888 (r"sigpending()", ["<signal.h>"]),
889 (r"sigprocmask()", ["<signal.h>"]),
890 (r"sigqueue()", ["<signal.h>"]),
891 (r"sigrelse()", ["<signal.h>"]),
892 (r"sigset()", ["<signal.h>"]),
893 (r"sigstack()", ["<signal.h>"]),
894 (r"sigsuspend()", ["<signal.h>"]),
895 (r"sigtimedwait()", ["<signal.h>"]),
896 (r"sigwait()", ["<signal.h>"]),
897 (r"sigwaitinfo()", ["<signal.h>"]),
898 # sin - sine function
899 (r"sin()", ["<math.h>"]),
900 # sinh - hyperbolic sine function
901 (r"sinh()", ["<math.h>"]),
902 # sleep - suspend execution for an interval of time
903 (r"sleep()", ["<unistd.h>"]),
904 # fprintf, printf, snprintf, sprintf - print formatted output
905 (r"fprintf()", ["<stdio.h>"]),
906 (r"printf()", ["<stdio.h>"]),
907 (r"snprintf()", ["<stdio.h>"]),
908 (r"sprintf()", ["<stdio.h>"]),
909 # sqrt - square root function
910 (r"sqrt()", ["<math.h>"]),
911 # stat - get file status
912 (r"stat()", ["<sys/types.h>", "<sys/stat.h>"]),
913 # stdarg.h - handle variable argument list
914 (r"va_start()", ["<stdarg.h>"]),
915 (r"va_arg()", ["<stdarg.h>"]),
916 (r"va_end()", ["<stdarg.h>"]),
917 # stddef.h - standard type definitions
918 (r"offsetof()", ["<stddef.h>"]),
919 # step - pattern match with regular expressions
920 (r"step()", ["<regexp.h>"]),
921 # strcasecmp, strncasecmp - case-insensitive string comparisons
922 (r"strcasecmp()", ["<strings.h>"]),
923 (r"strncasecmp()", ["<strings.h>"]),
924 # string.h - string operations
925 (r"memccpy()", ["<string.h>"]),
926 (r"memchr()", ["<string.h>"]),
927 (r"memcmp()", ["<string.h>"]),
928 (r"memcpy()", ["<string.h>"]),
929 (r"memmove()", ["<string.h>"]),
930 (r"memset()", ["<string.h>"]),
931 (r"strcat()", ["<string.h>"]),
932 (r"strchr()", ["<string.h>"]),
933 (r"strcmp()", ["<string.h>"]),
934 (r"strcoll()", ["<string.h>"]),
935 (r"strcpy()", ["<string.h>"]),
936 (r"strcspn()", ["<string.h>"]),
937 (r"strdup()", ["<string.h>"]),
938 (r"strerror()", ["<string.h>"]),
939 (r"strlen()", ["<string.h>"]),
940 (r"strncat()", ["<string.h>"]),
941 (r"strncmp()", ["<string.h>"]),
942 (r"strncpy()", ["<string.h>"]),
943 (r"strpbrk()", ["<string.h>"]),
944 (r"strrchr()", ["<string.h>"]),
945 (r"strspn()", ["<string.h>"]),
946 (r"strstr()", ["<string.h>"]),
947 (r"strtok()", ["<string.h>"]),
948 (r"strtok_r()", ["<string.h>"]),
949 (r"strxfrm()", ["<string.h>"]),
950 # wctype.h - wide-character classification and mapping utilities
951 (r"iswalnum()", ["<wctype.h>"]),
952 (r"iswalpha()", ["<wctype.h>"]),
953 (r"iswascii()", ["<wctype.h>"]),
954 (r"iswcntrl()", ["<wctype.h>"]),
955 (r"iswdigit()", ["<wctype.h>"]),
956 (r"iswgraph()", ["<wctype.h>"]),
957 (r"iswlower()", ["<wctype.h>"]),
958 (r"iswprint()", ["<wctype.h>"]),
959 (r"iswpunct()", ["<wctype.h>"]),
960 (r"iswspace()", ["<wctype.h>"]),
961 (r"iswupper()", ["<wctype.h>"]),
962 (r"iswxdigit()", ["<wctype.h>"]),
963 (r"iswctype()", ["<wctype.h>"]),
964 (r"towctrans()", ["<wctype.h>"]),
965 (r"towlower()", ["<wctype.h>"]),
966 (r"towupper()", ["<wctype.h>"]),
967 (r"wctrans()", ["<wctype.h>"]),
968 (r"wctype()", ["<wctype.h>"]),
969 # strftime - convert date and time to a string
970 (r"strftime()", ["<time.h>"]),
971 # strptime - date and time conversion
972 (r"strptime()", ["<time.h>"]),
973 # strtod - convert string to a double-precision number
974 (r"strtod()", ["<stdlib.h>"]),
975 # strtol - convert string to a long integer
976 (r"strtol()", ["<stdlib.h>"]),
977 # strtoul - convert string to an unsigned long
978 (r"strtoul()", ["<stdlib.h>"]),
979 # strtoull - convert string to an unsigned long qlong
980 (r"strtoull()", ["<stdlib.h>"]),
981 # swab - swap bytes
982 (r"swab()", ["<stdlib.h>"]),
983 # symlink - make symbolic link to a file
984 (r"symlink()", ["<stdlib.h>"]),
985 # sync - schedule filesystem updates
986 (r"sync()", ["<stdlib.h>"]),
987 # sysconf - get configurable system variables
988 (r"sysconf()", ["<unistd.h>"]),
989 # system - issue a command
990 (r"system()", ["<stdlib.h>"]),
991 # sys/wait.h - declarations for waiting
992 (r"wait()", ["<sys/types.h>", "<sys/wait.h>"]),
993 (r"wait3()", ["<sys/types.h>", "<sys/wait.h>"]),
994 (r"waitid()", ["<sys/types.h>", "<sys/wait.h>"]),
995 (r"waitpid()", ["<sys/types.h>", "<sys/wait.h>"]),
996 (r"WEXITSTATUS()", ["<sys/types.h>", "<sys/wait.h>"]),
997 (r"WIFCONTINUED()", ["<sys/types.h>", "<sys/wait.h>"]),
998 (r"WIFEXITED()", ["<sys/types.h>", "<sys/wait.h>"]),
999 (r"WIFSIGNALED()", ["<sys/types.h>", "<sys/wait.h>"]),
1000 (r"WIFSTOPPED()", ["<sys/types.h>", "<sys/wait.h>"]),
1001 (r"WSTOPSIG()", ["<sys/types.h>", "<sys/wait.h>"]),
1002 (r"WTERMSIG()", ["<sys/types.h>", "<sys/wait.h>"]),
1003 # tan - tangent function
1004 (r"tan()", ["<math.h>"]),
1005 # tanh - hyperbolic tangent function
1006 (r"tanh()", ["<math.h>"]),
1007 # tcgetpgrp - get the foreground process group ID
1008 (r"tcgetpgrp()", ["<sys/types.h>", "<unistd.h>"]),
1009 # tcsetpgrp - set the foreground process group ID
1010 (r"tcsetpgrp()", ["<sys/types.h>", "<unistd.h>"]),
1011 # tdelete - delete node from binary search tree
1012 (r"tdelete()", ["<search.h>"]),
1013 # telldir - current location of a named directory stream
1014 (r"telldir()", ["<dirent.h>"]),
1015 # tempnam - create a name for a temporary file
1016 (r"tempnam()", ["<stdio.h>"]),
1017 # termios.h - define values for termios
1018 (r"cfgetispeed()", ["<termios.h>"]),
1019 (r"cfgetospeed()", ["<termios.h>"]),
1020 (r"cfsetispeed()", ["<termios.h>"]),
1021 (r"cfsetospeed()", ["<termios.h>"]),
1022 (r"tcdrain()", ["<termios.h>"]),
1023 (r"tcflow()", ["<termios.h>"]),
1024 (r"tcflush()", ["<termios.h>"]),
1025 (r"tcgetattr()", ["<termios.h>"]),
1026 (r"tcgetsid()", ["<termios.h>"]),
1027 (r"tcsendbreak()", ["<termios.h>"]),
1028 (r"tcsetattr()", ["<termios.h>"]),
1029 # tdelete, tfind, tsearch, twalk - manage a binary search tree
1030 (r"tsearch()", ["<termios.h>"]),
1031 (r"tfind()", ["<termios.h>"]),
1032 (r"tdelete()", ["<termios.h>"]),
1033 (r"twalk()", ["<termios.h>"]),
1034 # time - get time
1035 (r"time()", ["<time.h>"]),
1036 # timer_create - create a per-process timer
1037 (r"timer_create()", ["<time.h>", "<signal.h>"]),
1038 # timer_delete - delete a per-process timer
1039 (r"timer_delete()", ["<time.h>", "<signal.h>"]),
1040 # timer_settime, timer_gettime, timer_getoverrun - per-process timers
1041 (r"timer_settime()", ["<time.h>"]),
1042 (r"timer_gettime()", ["<time.h>"]),
1043 (r"timer_getoverrun()", ["<time.h>"]),
1044 # times - get process and waited-for child process times
1045 (r"times()", ["<sys/time.h>"]),
1046 # tmpfile - create a temporary file
1047 (r"tmpfile()", ["<stdio.h>"]),
1048 # tmpnam - create a name for a temporary file
1049 (r"tmpnam()", ["<stdio.h>"]),
1050 # truncate - truncate a file to a specified length
1051 (r"truncate()", ["<stdio.h>"]),
1052 # ttyname, ttyname_r - find pathname of a terminal
1053 ("ttyname()", ["<unistd.h>"]),
1054 ("ttyname_r()", ["<unistd.h>"]),
1055 # ttyslot - find the slot of the current user in the user accounting database
1056 ("ttyslot()", ["<unistd.h>"]),
1057 # tzset - set time zone conversion information
1058 ("tzset()", ["<time.h>"]),
1059 # ualarm - set the interval timer
1060 ("ualarm()", ["<unistd.h>"]),
1061 # ulimit - get and set process limits
1062 ("ulimit()", ["<ulimit.h>"]),
1063 # umask - set and get file mode creation mask
1064 (r"umask()", ["<sys/stat.h>", "<sys/types.h>"]),
1065 # uname - get name of current system
1066 ("uname()", ["<sys/utsname.h>"]),
1067 # ungetc - push byte back into input stream
1068 (r"ungetc()", ["<stdio.h>"]),
1069 # ungetwc - push wide-character code back into input stream
1070 (r"ungetwc()", ["<stdio.h>", "<wchar.h>"]),
1071 # unlink - remove a directory entry
1072 ("unlink()", ["<unistd.h>"]),
1073 # unlockpt - unlock a pseudo-terminal master/slave pair
1074 (r"unlockpt()", ["<stdlib.h>"]),
1075 # usleep - suspend execution for an interval
1076 ("usleep()", ["<unistd.h>"]),
1077 # utime - set file access and modification times
1078 (r"utime()", ["<sys/types.h>", "<utime.h>"]),
1079 # utimes - set file access and modification times
1080 (r"utimes()", ["<sys/time.h>"]),
1081 # valloc - page-aligned memory allocator
1082 (r"valloc()", ["<stdlib.h>"]),
1083 # vfork - create new process; share virtual memory
1084 ("vfork()", ["<unistd.h>"]),
1085 # vfprintf, vprintf, vsnprintf, vsprintf - format output of a stdarg argument list
1086 (r"vfprintf()", ["<stdarg.h>", "<stdio.h>"]),
1087 (r"vprintf()", ["<stdarg.h>", "<stdio.h>"]),
1088 (r"vsnprintf()", ["<stdarg.h>", "<stdio.h>"]),
1089 (r"vsprintf()", ["<stdarg.h>", "<stdio.h>"]),
1090 # vfwprintf, vwprintf, vswprintf - wide-character formatted output of a stdarg argument list
1091 (r"vwprintf()", ["<stdarg.h>", "<stdio.h>", "<wchar.h>"]),
1092 (r"vfwprintf()", ["<stdarg.h>", "<stdio.h>", "<wchar.h>"]),
1093 (r"vswprintf()", ["<stdarg.h>", "<stdio.h>", "<wchar.h>"]),
1094 # wchar.h - wide-character types
1095 (r"wcrtomb()", ["<wchar.h>"]), # SuSv2 erroneously says <stdio.h>
1096 (r"wcscat()", ["<wchar.h>"]),
1097 (r"wcschr()", ["<wchar.h>"]),
1098 (r"wcscmp()", ["<wchar.h>"]),
1099 (r"wcscoll()", ["<wchar.h>"]),
1100 (r"wcscpy()", ["<wchar.h>"]),
1101 (r"wcscpy()", ["<wchar.h>"]),
1102 (r"wcsftime()", ["<wchar.h>"]),
1103 (r"wcslen()", ["<wchar.h>"]),
1104 (r"wcsncat()", ["<wchar.h>"]),
1105 (r"wcsncmp()", ["<wchar.h>"]),
1106 (r"wcsncpy()", ["<wchar.h>"]),
1107 (r"wcspbrk()", ["<wchar.h>"]),
1108 (r"wcsrchr()", ["<wchar.h>"]),
1109 (r"wcsrtombs()", ["<wchar.h>"]),
1110 (r"wcsspn()", ["<wchar.h>"]),
1111 (r"wcsstr()", ["<wchar.h>"]),
1112 (r"wcstod()", ["<wchar.h>"]),
1113 (r"wcstok()", ["<wchar.h>"]),
1114 (r"wcstol()", ["<wchar.h>"]),
1115 (r"wcstoul()", ["<wchar.h>"]),
1116 (r"wcswcs()", ["<wchar.h>"]),
1117 (r"wcswidth()", ["<wchar.h>"]),
1118 (r"wcsxfrm()", ["<wchar.h>"]),
1119 (r"wctob()", ["<wchar.h>"]),
1120 (r"wctype()", ["<wchar.h>"]),
1121 (r"wcwidth()", ["<wchar.h>"]),
1122 (r"wmemchr()", ["<wchar.h>"]),
1123 (r"wmemcmp()", ["<wchar.h>"]),
1124 (r"wmemcpy()", ["<wchar.h>"]),
1125 (r"wmemmove()", ["<wchar.h>"]),
1126 (r"wmemset()", ["<wchar.h>"]),
1127 (r"wprintf()", ["<wchar.h>"]),
1128 (r"wscanf()", ["<wchar.h>"]),
1129 # wordexp.h - word-expansion types
1130 (r"wordexp()", ["<wordexp.h>"]),
1131 (r"wordfree()", ["<wordexp.h>"]),
1132 # write, writev, pwrite - write on a file
1133 (r"write()", ["<unistd.h>"]),
1134 (r"pwrite()", ["<unistd.h>"]),
1135 (r"writev()", ["<sys/uio.h>"]),
1136 # y0, y1, yn - Bessel functions of the second kind
1137 (r"y0()", ["<math.h>"]),
1138 (r"y1()", ["<math.h>"]),
1139 (r"yn()", ["<math.h>"]),
1140 # stdbool.h - standard boolean type
1141 (r"=\s*true", ["<stdbool.h>"]),
1142 (r"=\s*false", ["<stdbool.h>"]),
1143
1144 # Headers mandated by SuS Version 2 Network Services.
1145 # sys/socket.h - Internet Protocol family
1146 (r"accept()", ["<sys/socket.h>"]),
1147 (r"bind()", ["<sys/socket.h>"]),
1148 (r"connect()", ["<sys/socket.h>"]),
1149 (r"getpeername()", ["<sys/socket.h>"]),
1150 (r"getsockname()", ["<sys/socket.h>"]),
1151 (r"getsockopt()", ["<sys/socket.h>"]),
1152 (r"listen()", ["<sys/socket.h>"]),
1153 (r"recv()", ["<sys/socket.h>"]),
1154 (r"recvfrom()", ["<sys/socket.h>"]),
1155 (r"recvmsg()", ["<sys/socket.h>"]),
1156 (r"send()", ["<sys/socket.h>"]),
1157 (r"sendmsg()", ["<sys/socket.h>"]),
1158 (r"sendto()", ["<sys/socket.h>"]),
1159 (r"setsockopt()", ["<sys/socket.h>"]),
1160 (r"shutdown()", ["<sys/socket.h>"]),
1161 (r"socket()", ["<sys/socket.h>"]),
1162 (r"socketpair()", ["<sys/socket.h>"]),
1163 # arpa/inet.h - definitions for internet operations
1164 (r"inet_addr()", ["<arpa/inet.h>"]),
1165 (r"inet_lnaof()", ["<arpa/inet.h>"]),
1166 (r"inet_makeaddr()", ["<arpa/inet.h>"]),
1167 (r"inet_netof()", ["<arpa/inet.h>"]),
1168 (r"inet_network()", ["<arpa/inet.h>"]),
1169 (r"inet_ntoa()", ["<arpa/inet.h>"]),
1170 (r"htonl()", ["<arpa/inet.h>"]),
1171 (r"htons()", ["<arpa/inet.h>"]),
1172 (r"ntohl()", ["<arpa/inet.h>"]),
1173 (r"ntohs()", ["<arpa/inet.h>"]),
1174 # netdb.h - definitions for network database operations
1175 (r"endhostent()", ["<netdb.h>"]),
1176 (r"endnetent()", ["<netdb.h>"]),
1177 (r"endprotoent()", ["<netdb.h>"]),
1178 (r"endservent()", ["<netdb.h>"]),
1179 (r"gethostbyaddr()", ["<netdb.h>"]),
1180 (r"gethostbyname()", ["<netdb.h>"]),
1181 (r"gethostent()", ["<netdb.h>"]),
1182 (r"getnetbyaddr()", ["<netdb.h>"]),
1183 (r"getnetbyname()", ["<netdb.h>"]),
1184 (r"getnetent()", ["<netdb.h>"]),
1185 (r"getprotobyname()", ["<netdb.h>"]),
1186 (r"getprotobynumber()",["<netdb.h>"]),
1187 (r"getprotoent()", ["<netdb.h>"]),
1188 (r"getservbyname()", ["<netdb.h>"]),
1189 (r"getservbyport()", ["<netdb.h>"]),
1190 (r"getservent()", ["<netdb.h>"]),
1191 (r"sethostent()", ["<netdb.h>"]),
1192 (r"setnetent()", ["<netdb.h>"]),
1193 (r"setprotoent()", ["<netdb.h>"]),
1194 (r"setservent()", ["<netdb.h>"]),
1195 # net/if.h - mappings between network interface names and indexes
1196 (r"if_nametoindex()", ["net/if.h"]),
1197 (r"if_indextoname()", ["net/if.h"]),
1198 (r"if_nameindex()", ["net/if.h"]),
1199 (r"if_freenameindex()",["net/if.h"]),
1200 # unistd.h - standard symbolic constants and types
1201 (r"gethostname()", ["<unistd.h>"]),
1202
1203 # Linux only
1204 (r"syscall()", ["<unistd.h>", "<sys/syscall.h>"]), # Originally from 4BSD
1205
1206 # Dependencies observed on systems other than the Linux this was
1207 # developed under.
1208 (r"<sys/socket.h>", ["<sys/stat.h>", "<sys/types.h>"]),
1209 (r"<arpa/inet.h>", ["<netinet/in.h>"]),
1210 )
1211
1212 class Baton:
1213 "Ship progress indications to stderr."
1214 def __init__(self, prompt, endmsg=None):
1215 self.stream = sys.stderr
1216 self.stream.write(prompt + "...")
1217 if os.isatty(self.stream.fileno()):
1218 self.stream.write(" \b")
1219 self.stream.flush()
1220 self.count = 0
1221 self.endmsg = endmsg
1222 self.time = time.time()
1223
1224 def twirl(self, ch=None):
1225 if self.stream is None:
1226 return
1227 if os.isatty(self.stream.fileno()):
1228 if ch:
1229 self.stream.write(ch)
1230 else:
1231 self.stream.write("-/|\\"[self.count % 4])
1232 self.stream.write("\b")
1233 self.stream.flush()
1234 self.count = self.count + 1
1235
1236 def end(self, msg=None):
1237 if msg is None:
1238 msg = self.endmsg
1239 if self.stream:
1240 self.stream.write("...(%2.2f sec) %s.\n" % (time.time() - self.time, msg))
1241
1242 class InclusionMap:
1243 "Map the inclusion dependencies of a set of files and directories."
1244 @staticmethod
1245 def c_source(filename):
1246 "Predicate: return true if the filename appears to be C or C++ source."
1247 return filename.endswith(".c") or filename.endswith(".cpp") or filename.endswith(".cc")
1248 # pylint: disable=too-many-locals,too-many-branches,too-many-statements
1249 def __init__(self, roots, ignore, excludes, verbosity):
1250 "Build the initial inclusion map."
1251 self.verbosity = verbosity
1252 self.files = []
1253 compiled = []
1254 for (r, h) in requirements:
1255 if r.endswith("()"):
1256 # The prefix is intended to exclude false suffix matches:
1257 # also, excluding : prevents matching on C++ method names.
1258 c = re.compile(r"[^a-zA-Z0-9:_]" + r.replace("()", r"\s*\("))
1259 else:
1260 c = re.compile(r)
1261 compiled.append((r, c, h))
1262 # pylint: disable=too-many-nested-blocks
1263 for root in roots:
1264 if not os.path.isdir(root):
1265 if excludes and excludes.search(root):
1266 if verbose > 1:
1267 print("deheader: %s excluded" % root)
1268 elif InclusionMap.c_source(root):
1269 self.files.append(root)
1270 else:
1271 sys.stderr.write("deheader: can't analyze %s\n" % root)
1272 else:
1273 sublist = []
1274 for root, dirs, files in os.walk(root):
1275 dirs = [x for x in dirs if not x.startswith(".")]
1276 for name in files:
1277 path = os.path.join(root, name)
1278 if excludes and excludes.search(path):
1279 if verbose > 1:
1280 print("deheader: %s excluded" % root)
1281 elif InclusionMap.c_source(path):
1282 sublist.append(path)
1283 self.files += sublist
1284 self.files.sort()
1285 self.depends_on = {}
1286 self.requires = {}
1287 # pylint: disable=too-many-nested-blocks
1288 for sourcefile in self.files:
1289 includes = []
1290 requires = []
1291 seen = []
1292 conditions = []
1293 with open(sourcefile, encoding='ascii', errors='surrogateescape') as rfp:
1294 for (i, line) in enumerate(rfp):
1295 c = match_preproc(["ifndef", "ifdef", "if"], line)
1296 if c is not False:
1297 conditions.append(c)
1298 elif match_preproc("endif", line) is not False:
1299 try:
1300 conditions.pop()
1301 except IndexError:
1302 sys.stderr.write('%s:%d: unbalanced #endif\n' % (sourcefile, i+1))
1303 sys.exit(1)
1304 else:
1305 f = match_preproc("include", line)
1306 if f is not False:
1307 if verbosity >= PROGRESS_DEBUG:
1308 name = trim(f)
1309 print("deheader: %s includes %s" % (sourcefile, name))
1310 if ignore and ignore.search(line):
1311 if verbosity >= PROGRESS_DEBUG:
1312 print("deheader: ignoring %s (exclusion match with %s)." % (name, ignore.pattern))
1313 continue
1314 if not conditions or conditions == ["S_SPLINT_S"]:
1315 includes.append(line)
1316 elif verbose > 1:
1317 print("deheader: ignoring %s (conditional inclusion)" % name)
1318 for (r, c, h) in compiled:
1319 if c.search(line):
1320 if not set(h).issubset(set(seen)):
1321 requires.append((h, r))
1322 seen += h
1323 self.depends_on[sourcefile] = includes
1324 self.requires[sourcefile] = requires
1325 # Duplicate-header detection
1326 trimmedcount = {}
1327 for ref in map(trim, includes):
1328 trimmedcount[ref] = trimmedcount.get(ref, 0) + 1
1329 for ref in trimmedcount:
1330 if trimmedcount[ref] > 1:
1331 print("deheader: %s has more than one inclusion of %s" % (sourcefile, ref))
1332 trimmedcount = {}
1333 for ref in map(supertrim, includes):
1334 trimmedcount[ref] = trimmedcount.get(ref, 0) + 1
1335 for ref in trimmedcount:
1336 if trimmedcount[ref] > 1:
1337 print("deheader: %s has duplicates or colliding inclusions of %s" % (sourcefile, ref))
1338 def forget(self, sourcefile, header):
1339 "Forget a header dependency."
1340 self.depends_on[sourcefile].remove(header)
1341 def remember(self, sourcefile, header):
1342 "Undo forgetting of a dependency."
1343 self.depends_on[sourcefile].append(header)
1344
1345 class SaveForModification:
1346 "Prepare a file to be temporarily modified, with guaranteed reversion."
1347 def __init__(self, filename):
1348 self.filename = filename
1349 self.original = filename + "-orig"
1350 os.rename(self.filename, self.original)
1351 def remove_headers(self, removables):
1352 "Prepare a version with specified headers deleted."
1353 ofp = open(self.filename, "w", encoding='ascii', errors='surrogateescape')
1354 for line in open(self.original, encoding='ascii', errors='surrogateescape'):
1355 if line not in removables:
1356 ofp.write(line)
1357 ofp.close()
1358 def forget(self):
1359 "Disable reversion."
1360 os.remove(self.original)
1361 def revert(self):
1362 "Revert modifications on the file at the end of this object's lifetime."
1363 if os.path.exists(self.original):
1364 try:
1365 os.remove(self.filename)
1366 except OSError:
1367 pass
1368 os.rename(self.original, self.filename)
1369
1370 def match_preproc(directives, line):
1371 if not isinstance(directives, list):
1372 directives = [directives]
1373 regexp = "|".join([r"#\s*" + d for d in directives])
1374 m = re.match(regexp, line)
1375 if m:
1376 return line[m.span()[1]:].strip()
1377 return False
1378
1379 def trim(line):
1380 "Get file reference from an #include, retaining <> if a system header."
1381 trimmed = re.sub(r"^#\s*include", "", line).strip()
1382 if trimmed[0] in '"':
1383 return '"' + trimmed.split('"')[1] + '"'
1384 elif trimmed[0] == '<':
1385 return trimmed.split('>')[0] + ">"
1386 else:
1387 return repr(line)
1388
1389 def supertrim(line):
1390 "Get file bare reference from an #include - used fr detecting duplicates/collisions."
1391 trimmed = re.sub(r"^#\s*include", "", line).strip()
1392 if trimmed[0] in '"':
1393 return trimmed.split('"')[1]
1394 elif trimmed[0] == '<':
1395 return trimmed.split('<')[1]
1396 else:
1397 return repr(line)
1398
1399 def clean(derived):
1400 "Clean a derived object file preparatory to test-compiling it"
1401 if os.path.exists(os.path.join(builddir, derived)):
1402 os.remove(os.path.join(builddir, derived))
1403 elif os.path.exists("CMakeList.txt"):
1404 subprocess.call(["make","clean"])
1405
1406 # pylint: disable=too-many-arguments,too-many-statements,too-many-locals
1407 def testcompile(source, maker, msg="", verbosity=0, showerrs=False, subdir=""):
1408 "Test-compile a sourcefile. Return the status and the compilation time"
1409 (stem, _suffix) = os.path.splitext(source)
1410 derived = stem + ".o"
1411 clean(os.path.join(subdir, derived))
1412 command = maker % derived
1413 olddir = os.getcwd()
1414 if len(subdir) > 0:
1415 os.chdir(subdir)
1416 start = time.time()
1417 (status, output) = getstatusoutput(command)
1418 end = time.time()
1419 os.chdir(olddir)
1420 if verbosity >= COMMAND_DEBUG or (showerrs and os.WIFEXITED(status) and os.WEXITSTATUS(status) != 0):
1421 sys.stdout.write(output + "\n")
1422 if status:
1423 explain = "failed"
1424 if verbosity >= PROGRESS_DEBUG:
1425 explain += " (%d)" % status
1426 else:
1427 explain = "succeeded"
1428 if verbosity >= PROGRESS_DEBUG:
1429 print("deheader: %s%s %s." % (source, msg, explain))
1430 clean(os.path.join(subdir, derived))
1431 return (status, end - start)
1432
1433 # pylint: disable=too-many-locals,too-many-nested-blocks,too-many-branches
1434 def c_analyze(sourcefile, maker, includes, requires, verbosity, subdir=""):
1435 "Given a C file and a list of includes, return those that can be omitted."
1436 # We'll remove headers in reverse order, because later unnecessary
1437 # headers might depend on earlier ones
1438 includes.reverse()
1439 unneeded = []
1440 if verbosity == BATON_DEBUG:
1441 baton = Baton(sourcefile + ": ", "Done")
1442 try:
1443 saveit = SaveForModification(os.path.join(subdir, sourcefile))
1444 while True:
1445 keepgoing = False
1446 for header in includes[:]:
1447 if verbosity == BATON_DEBUG:
1448 baton.twirl()
1449 retain = 0
1450 for (requirements, trigger) in requires:
1451 for required in requirements:
1452 if required in header:
1453 if verbosity >= PROGRESS_DEBUG:
1454 print("deheader: in %s, %s prevents uninclusion of %s" % (os.path.join(subdir, sourcefile), trigger, trim(header)))
1455 retain += 1
1456 if not retain:
1457 saveit.remove_headers(unneeded + [header])
1458 (st, _t) = testcompile(sourcefile, maker, " without %s" % trim(header), verbosity, showerrs=False, subdir=subdir)
1459 if st == 0:
1460 unneeded.append(header)
1461 includes.remove(header)
1462 keepgoing = True
1463 if not keepgoing:
1464 break
1465 finally:
1466 saveit.revert()
1467 if verbosity == BATON_DEBUG:
1468 baton.end()
1469 # Missing-require detection. Can't be merged with duplicate-header
1470 # detection because this has to be done after unneeded headers are removed.
1471 stillhere = list(map(trim, includes))
1472 for (requirement, trigger) in requires:
1473 if not set(requirement).issubset(stillhere):
1474 print("deheader: in %s, %s portability requires %s." % (os.path.join(subdir, sourcefile), trigger, ",".join(requirement)))
1475 return unneeded
1476
1477 def deheader(sourcefile, maker, includes, requires, remove, verbose):
1478 # Sanity check against broken sourcefiles; we want this to
1479 # complain visibly if the sourcefile won't build at all.
1480 subdir = ""
1481 (st, _t) = testcompile(sourcefile, maker, verbosity=max(1, verbose), showerrs=False)
1482 if st != 0:
1483 subdir = os.path.dirname(sourcefile)
1484 sourcefile = os.path.basename(sourcefile)
1485 (st, _t) = testcompile(sourcefile, maker, verbosity=max(1, verbose), showerrs=True, subdir=subdir)
1486 if st == 0:
1487 # Now do the analysis
1488 if sourcefile.endswith(".c") or sourcefile.endswith(".cpp") or sourcefile.endswith(".cc"):
1489 unneeded = c_analyze(sourcefile, maker,
1490 includes[:], requires, verbose, subdir=subdir)
1491 if unneeded:
1492 for line in unneeded:
1493 print("deheader: remove %s from %s" % (trim(line), os.path.join(subdir, sourcefile)))
1494 if remove:
1495 remove_it = SaveForModification(os.path.join(subdir, sourcefile))
1496 remove_it.remove_headers(unneeded)
1497 remove_it.forget()
1498 del remove_it
1499 return Summary([sourcefile], includes, unneeded)
1500 else:
1501 sys.stderr.write("deheader: basic compilation failed on %s\n" % (sourcefile,))
1502 return Summary([sourcefile], includes, [])
1503
1504 # After-action analysis starts here
1505
1506 class Summary:
1507 "Summarize results from a deheading."
1508 def __init__(self, filenames=None, includes=None, unneeded=None):
1509 self.filenames = filenames or []
1510 self.includes = includes or []
1511 self.unneeded = unneeded or []
1512 def __add__(self, other):
1513 result = Summary()
1514 result.filenames = self.filenames + other.filenames
1515 result.includes = self.includes + other.includes
1516 result.unneeded = self.unneeded + other.unneeded
1517 return result
1518 def has_unneeded_includes(self):
1519 return len(self.unneeded) > 0
1520 def __repr__(self):
1521 return "%d files, %d includes, %d removable" % \
1522 (len(self.filenames), len(self.includes), len(self.unneeded))
1523
1524 if __name__ == "__main__":
1525 (options, arguments) = getopt.getopt(sys.argv[1:], "bhi:m:qrvx:V",
1526 ["builddir", "help", "ignore",
1527 "maker", "quiet", "remove",
1528 "verbose", "exclude", "version"])
1529 maker = "make %s"
1530 builddir = '.'
1531 verbose = 0
1532 quiet = False
1533 remove = False
1534 ignores = []
1535 exclusions = []
1536 for (switch, val) in options:
1537 if switch in ('-h', '--help'):
1538 sys.stderr.write(__doc__)
1539 sys.exit(0)
1540 elif switch in ('-i', '--ignore'):
1541 ignores.append(val)
1542 elif switch in ('-m', '--maker'):
1543 maker = val
1544 elif switch in ('-b', '--builddir'):
1545 builddir = os.path.abspath(val)
1546 elif switch in ('-q', '--quiet'):
1547 quiet = True
1548 elif switch in ('-r', '--remove'):
1549 remove = True
1550 elif switch in ('-v', '--verbose'):
1551 verbose += 1
1552 elif switch in ('-V', '--version'):
1553 print("deheader", version)
1554 raise SystemExit(0)
1555 elif switch in ('-x', '--exclude'):
1556 exclusions.append(val)
1557 if not ignores:
1558 ignore = None
1559 else:
1560 ignore = re.compile("|".join(ignores))
1561 if not exclusions:
1562 exclusions = None
1563 else:
1564 exclusions = re.compile("|".join(exclusions))
1565 if not arguments:
1566 arguments = ["."]
1567
1568 summaries = []
1569 inclusion_map = InclusionMap(arguments, ignore, exclusions, verbose)
1570 for sourcefile in sorted(inclusion_map.depends_on.keys()):
1571 summaries.append(deheader(sourcefile, maker,
1572 inclusion_map.depends_on[sourcefile],
1573 inclusion_map.requires[sourcefile],
1574 remove, verbose))
1575 stats = Summary()
1576 for summary in summaries:
1577 stats = stats + summary
1578 if not quiet:
1579 print("deheader: saw %s" % stats)
1580 if stats.has_unneeded_includes():
1581 print("deheader: has unneeded includes %s" % " ".join(stats.unneeded))
1582 raise SystemExit(0)
1583
1584 # End