]> andersk Git - splint.git/blame - src/help.c
Fixed problem with NULL being changed.
[splint.git] / src / help.c
CommitLineData
140c27a8 1/*
2** Splint - annotation-assisted static program checker
c59f5181 3** Copyright (C) 1994-2003 University of Virginia,
140c27a8 4** Massachusetts Institute of Technology
5**
6** This program is free software; you can redistribute it and/or modify it
7** under the terms of the GNU General Public License as published by the
8** Free Software Foundation; either version 2 of the License, or (at your
9** option) any later version.
10**
11** This program is distributed in the hope that it will be useful, but
12** WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14** General Public License for more details.
15**
16** The GNU General Public License is available from http://www.gnu.org/ or
17** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18** MA 02111-1307, USA.
19**
20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
22** For more information: http://www.splint.org
23*/
24/*
25** help.c
26*/
27
28# include "splintMacros.nf"
29# include "basic.h"
30# include "help.h"
31# include "osd.h"
4caf866b 32# include "llmain.h"
140c27a8 33# include "version.h"
34
35static void
36describeVars (void)
37{
38 cstring eval;
39 cstring def;
40
41 eval = context_getLarchPath ();
42 def = osd_getEnvironmentVariable (LARCH_PATH);
43
44 if (cstring_isDefined (def) ||
45 !cstring_equal (eval, cstring_fromChars (DEFAULT_LARCHPATH)))
46 {
47 llmsg (message ("LARCH_PATH = %s", eval));
48 }
49 else
50 {
51 llmsg (message ("LARCH_PATH = <not set> (default = %s)",
52 cstring_fromChars (DEFAULT_LARCHPATH)));
53 }
54
55 llmsglit (" --- path used to find larch initialization files and LSL traits");
56
57 eval = context_getLCLImportDir ();
58 def = osd_getEnvironmentVariable (cstring_makeLiteralTemp (LCLIMPORTDIR));
59
60 if (cstring_isDefined (def) ||
61 !cstring_equal (eval, cstring_fromChars (DEFAULT_LCLIMPORTDIR)))
62 {
63 llmsg (message ("%q = %s", cstring_makeLiteral (LCLIMPORTDIR), eval));
64 }
65 else
66 {
67 llmsg (message ("%s = <not set, default: %s>", cstring_makeLiteralTemp (LCLIMPORTDIR),
68 cstring_makeLiteralTemp (DEFAULT_LCLIMPORTDIR)));
69 }
70
71 llmsglit (" --- directory containing lcl standard library files "
72 "(import with < ... >)");;
73
74 llmsg (message
75 ("include path = %q (set by environment variable %s and -I flags)",
76 cppReader_getIncludePath (), INCLUDEPATH_VAR));
77
78 llmsglit (" --- path used to find #include'd files");
79
80 llmsg (message
b73d1009 81 ("systemdirs = %s (set by -systemdirs or environment variable %s)",
140c27a8 82 context_getString (FLG_SYSTEMDIRS),
83 INCLUDEPATH_VAR));
84
85 llmsglit (" --- if file is found on this path, it is treated as a system file for error reporting");
86}
87
88static void
89printAnnotations (void)
90{
91 llmsglit ("Annotations");
92 llmsglit ("-----------");
93 llmsglit ("");
94 llmsglit ("Annotations are semantic comments that document certain "
95 "assumptions about functions, variables, parameters, and types. ");
96 llmsglit ("");
97 llmsglit ("They may be used to indicate where the representation of a "
98 "user-defined type is hidden, to limit where a global variable may "
99 "be used or modified, to constrain what a function implementation "
100 "may do to its parameters, and to express checked assumptions about "
101 "variables, types, structure fields, function parameters, and "
102 "function results.");
103 llmsglit ("");
104 llmsglit ("Annotations are introduced by \"/*@\". The role of the @ may be "
105 "played by any printable character, selected using -commentchar <char>.");
106 llmsglit ("");
107 llmsglit ("Consult the User's Guide for descriptions of checking associated with each annotation.");
108 llmsglit ("");
109 llmsglit ("Globals: (in function declarations)");
110 llmsglit (" /*@globals <globitem>,+ @*/");
111 llmsglit (" globitem is an identifier, internalState or fileSystem");
112 llmsglit ("");
113 llmsglit ("Modifies: (in function declarations)");
114 llmsglit (" /*@modifies <moditem>,+ @*/");
115 llmsglit (" moditem is an lvalue");
116 llmsglit (" /*@modifies nothing @*/");
117 llmsglit (" /*@*/ (Abbreviation for no globals and modifies nothing.)");
118 llmsglit ("");
119 llmsglit ("Iterators:");
120 llmsglit (" /*@iter <identifier> (<parameter-type-list>) @*/ - declare an iterator");
121 llmsglit ("");
122 llmsglit ("Constants:");
123 llmsglit (" /*@constant <declaration> @*/ - declares a constant");
124 llmsglit ("");
125 llmsglit ("Alternate Types:");
126 llmsglit (" /*@alt <basic-type>,+ @*/");
127 llmsglit (" (e.g., int /*@alt char@*/ is a type matching either int or char)");
128 llmsglit ("");
129 llmsglit ("Declarator Annotations");
130 llmsglit ("");
131 llmsglit ("Type Definitions:");
132 llmsglit (" /*@abstract@*/ - representation is hidden from clients");
133 llmsglit (" /*@concrete@*/ - representation is visible to clients");
134 llmsglit (" /*@immutable@*/ - instances of the type cannot change value");
135 llmsglit (" /*@mutable@*/ - instances of the type can change value");
136 llmsglit (" /*@refcounted@*/ - reference counted type");
137 llmsglit ("");
138 llmsglit ("Global Variables:");
139 llmsglit (" /*@unchecked@*/ - weakest checking for global use");
140 llmsglit (" /*@checkmod@*/ - check modification by not use of global");
141 llmsglit (" /*@checked@*/ - check use and modification of global");
142 llmsglit (" /*@checkedstrict@*/ - check use of global strictly");
143 llmsglit ("");
144 llmsglit ("Memory Management:");
145 llmsglit (" /*@dependent@*/ - a reference to externally-owned storage");
146 llmsglit (" /*@keep@*/ - a parameter that is kept by the called function");
147 llmsglit (" /*@killref@*/ - a refcounted parameter, killed by the call");
148 llmsglit (" /*@only@*/ - an unshared reference");
149 llmsglit (" /*@owned@*/ - owner of storage that may be shared by /*@dependent@*/ references");
150 llmsglit (" /*@shared@*/ - shared reference that is never deallocated");
151 llmsglit (" /*@temp@*/ - temporary parameter");
152 llmsglit ("");
153 llmsglit ("Aliasing:");
154 llmsglit (" /*@unique@*/ - may not be aliased by any other visible reference");
155 llmsglit (" /*@returned@*/ - may be aliased by the return value");
156 llmsglit ("");
157 llmsglit ("Exposure:");
158 llmsglit (" /*@observer@*/ - reference that cannot be modified");
159 llmsglit (" /*@exposed@*/ - exposed reference to storage in another object");
160 llmsglit ("");
161 llmsglit ("Definition State:");
162 llmsglit (" /*@out@*/ - storage reachable from reference need not be defined");
163 llmsglit (" /*@in@*/ - all storage reachable from reference must be defined");
164 llmsglit (" /*@partial@*/ - partially defined, may have undefined fields");
165 llmsglit (" /*@reldef@*/ - relax definition checking");
166 llmsglit ("");
167 llmsglit ("Global State: (for globals lists, no /*@, since list is already in /*@\'s)");
168 llmsglit (" undef - variable is undefined before the call");
169 llmsglit (" killed - variable is undefined after the call");
170 llmsglit ("");
171 llmsglit ("Null State:");
172 llmsglit (" /*@null@*/ - possibly null pointer");
173 llmsglit (" /*@notnull@*/ - definitely non-null pointer");
174 llmsglit (" /*@relnull@*/ - relax null checking");
175 llmsglit ("");
176 llmsglit ("Null Predicates:");
177 llmsglit (" /*@nullwhentrue@*/ - if result is TRUE, first parameter is NULL");
178 llmsglit (" /*@falsewhennull@*/ - if result is TRUE, first parameter is not NULL");
179 llmsglit ("");
180 llmsglit ("Execution:");
181 llmsglit (" /*@noreturn@*/ - function never returns");
182 llmsglit (" /*@maynotreturn@*/ - function may or may not return");
183 llmsglit (" /*@noreturnwhentrue@*/ - function does not return if first parameter is TRUE");
184 llmsglit (" /*@noreturnwhenfalse@*/ - function does not return if first parameter if FALSE");
185 llmsglit (" /*@alwaysreturns@*/ - function always returns");
186 llmsglit ("");
187 llmsglit ("Side-Effects:");
188 llmsglit (" /*@sef@*/ - corresponding actual parameter has no side effects");
189 llmsglit ("");
190 llmsglit ("Declaration:");
191 llmsglit (" /*@unused@*/ - need not be used (no unused errors reported)");
192 llmsglit (" /*@external@*/ - defined externally (no undefined error reported)");
193 llmsglit ("");
194 llmsglit ("Case:");
195 llmsglit (" /*@fallthrough@*/ - fall-through case");
196 llmsglit ("");
197 llmsglit ("Break:");
198 llmsglit (" /*@innerbreak@*/ - break is breaking an inner loop or switch");
199 llmsglit (" /*@loopbreak@*/ - break is breaking a loop");
200 llmsglit (" /*@switchbreak@*/ - break is breaking a switch");
201 llmsglit (" /*@innercontinue@*/ - continue is continuing an inner loop");
202 llmsglit ("");
203 llmsglit ("Unreachable Code:");
204 llmsglit (" /*@notreached@*/ - statement may be unreachable.");
205 llmsglit ("");
206 llmsglit ("Special Functions:");
207 llmsglit (" /*@printflike@*/ - check variable arguments like printf");
208 llmsglit (" /*@scanflike@*/ - check variable arguments like scanf");
209}
210
211static void
212printComments (void)
213{
214 llmsglit ("Control Comments");
215 llmsglit ("----------------");
216 llmsglit ("");
217 llmsglit ("Setting Flags");
218 llmsglit ("");
219 llmsglit ("Most flags (all except those characterized as \"globally-settable only\") can be set locally using control comments. A control comment can set flags locally to override the command line settings. The original flag settings are restored before processing the next file.");
220 llmsglit ("");
221 llmsglit ("The syntax for setting flags in control comments is the same as that of the command line, except that flags may also be preceded by = to restore their setting to the original command-line value. For instance,");
222 llmsglit (" /*@+boolint -modifies =showfunc@*/");
223 llmsglit ("sets boolint on (this makes bool and int indistinguishable types), sets modifies off (this prevents reporting of modification errors), and sets showfunc to its original setting (this controls whether or not the name of a function is displayed before a message).");
224 llmsglit ("");
225 llmsglit ("Error Suppression");
226 llmsglit ("");
227 llmsglit ("Several comments are provided for suppressing messages. In general, it is usually better to use specific flags to suppress a particular error permanently, but the general error suppression flags may be more convenient for quickly suppressing messages for code that will be corrected or documented later.");
228 llmsglit ("");
229 llmsglit ("/*@ignore@*/ ... /*@end@*/");
230 llgenindentmsgnoloc
231 (cstring_makeLiteral
232 ("No errors will be reported in code regions between /*@ignore@*/ and /*@end@*/. These comments can be used to easily suppress an unlimited number of messages."));
233 llmsglit ("/*@i@*/");
234 llgenindentmsgnoloc
235 (cstring_makeLiteral
236 ("No errors will be reported from an /*@i@*/ comment to the end of the line."));
237 llmsglit ("/*@i<n>@*/");
238 llgenindentmsgnoloc
239 (cstring_makeLiteral
240 ("No errors will be reported from an /*@i<n>@*/ (e.g., /*@i3@*/) comment to the end of the line. If there are not exactly n errors suppressed from the comment point to the end of the line, Splint will report an error."));
241 llmsglit ("/*@t@*/, /*@t<n>@*/");
242 llgenindentmsgnoloc
243 (cstring_makeLiteral
244 ("Like i and i<n>, except controlled by +tmpcomments flag. These can be used to temporarily suppress certain errors. Then, -tmpcomments can be set to find them again."));
245 llmsglit ("");
246 llmsglit ("Type Access");
247 llmsglit ("");
248 llmsglit ("/*@access <type>@*/");
249 llmsglit (" Allows the following code to access the representation of <type>");
250 llmsglit ("/*@noaccess <type>@*/");
251 llmsglit (" Hides the representation of <type>");
252 llmsglit ("");
253 llmsglit ("Macro Expansion");
254 llmsglit ("");
255 llmsglit ("/*@notfunction@*/");
256 llgenindentmsgnoloc
257 (cstring_makeLiteral
258 ("Indicates that the next macro definition is not intended to be a "
259 "function, and should be expanded in line instead of checked as a "
260 "macro function definition."));
261}
262
263static void
264printFlags (void)
265{
266 llmsglit ("Flag Categories");
267 llmsglit ("---------------");
268 listAllCategories ();
269 llmsglit ("\nTo see the flags in a flag category, do\n splint -help flags <category>");
270 llmsglit ("To see a list of all flags in alphabetical order, do\n splint -help flags alpha");
271 llmsglit ("To see a full description of all flags, do\n splint -help flags full");
272}
273
274static void
275printMaintainer (void)
276{
277 llmsg (message ("Maintainer: %s", cstring_makeLiteralTemp (SPLINT_MAINTAINER)));
278 llmsglit (LCL_COMPILE);
279}
280
281static void
282printMail (void)
283{
284 llmsglit ("Mailing Lists");
285 llmsglit ("-------------");
286 llmsglit ("");
287 llmsglit ("There are two mailing lists associated with Splint: ");
288 llmsglit ("");
909cf5eb 289 llmsglit (" splint-announce@cs.virginia.edu");
140c27a8 290 llmsglit ("");
291 llmsglit (" Reserved for announcements of new releases and bug fixes.");
140c27a8 292 llmsglit ("");
909cf5eb 293 llmsglit (" splint-discuss@virginia.edu");
140c27a8 294 llmsglit ("");
295 llmsglit (" Informal discussions on the use and development of Splint.");
909cf5eb 296 llmsglit ("");
297 llmsglit ("To subscribe or view archives, visit http://www.splint.org/lists.html");
140c27a8 298}
299
300static void
301printReferences (void)
302{
303 llmsglit ("References");
304 llmsglit ("----------");
305 llmsglit ("");
306 llmsglit ("For more information, see the Splint web site: http://www.splint.org");
307}
308
309static void
310describePrefixCodes (void)
311{
312 llmsglit ("Prefix Codes");
313 llmsglit ("------------");
314 llmsglit ("");
315 llmsglit ("These characters have special meaning in name prefixes:");
316 llmsglit ("");
317 llmsg (message (" %h Any uppercase letter [A-Z]", PFX_UPPERCASE));
318 llmsg (message (" %h Any lowercase letter [a-z]", PFX_LOWERCASE));
319 llmsg (message (" %h Any character (valid in a C identifier)", PFX_ANY));
320 llmsg (message (" %h Any digit [0-9]", PFX_DIGIT));
321 llmsg (message (" %h Any non-uppercase letter [a-z0-9_]", PFX_NOTUPPER));
322 llmsg (message (" %h Any non-lowercase letter [A-Z0-9_]", PFX_NOTLOWER));
323 llmsg (message (" %h Any letter [A-Za-z]", PFX_ANYLETTER));
324 llmsg (message (" %h Any letter or digit [A-Za-z0-9]", PFX_ANYLETTERDIGIT));
325 llmsglit (" * Zero or more repetitions of the previous character class until the end of the name");
326}
327
328void help_showAvailableHelp (void)
329{
330 showHerald ();
331
332 llmsg (message ("Source files are .c, .h and %s files. If there is no suffix,",
333 LCL_EXTENSION));
334 llmsg (message (" Splint will look for <file>.c and <file>%s.", LCL_EXTENSION));
335 llmsglit ("");
336 llmsglit ("Use splint -help <topic or flag name> for more information");
337 llmsglit ("");
338 llmsglit ("Topics:");
339 llmsglit ("");
340 llmsglit (" annotations (describes source-code annotations)");
341 llmsglit (" comments (describes control comments)");
342 llmsglit (" flags (describes flag categories)");
343 llmsglit (" flags <category> (describes flags in category)");
344 llmsglit (" flags all (short description of all flags)");
345 llmsglit (" flags alpha (list all flags alphabetically)");
346 llmsglit (" flags full (full description of all flags)");
347 llmsglit (" mail (information on mailing lists)");
348 llmsglit (" modes (show mode settings)");
349 llmsglit (" parseerrors (help on handling parser errors)");
350 llmsglit (" prefixcodes (character codes in namespace prefixes)");
351 llmsglit (" references (sources for more information)");
352 llmsglit (" vars (environment variables)");
353 llmsglit (" version (information on compilation, maintainer)");
354 llmsglit ("");
355}
356
357static bool
358specialFlagsHelp (char *next)
359{
360 if ((next != NULL) && (*next != '-') && (*next != '+'))
361 {
362 if (mstring_equal (next, "alpha"))
363 {
364 printAlphaFlags ();
365 return TRUE;
366 }
367 else if (mstring_equal (next, "all"))
368 {
369 printAllFlags (TRUE, FALSE);
370 return TRUE;
371 }
372 else if (mstring_equal (next, "categories")
373 || mstring_equal (next, "cats"))
374 {
375 listAllCategories ();
376 return TRUE;
377 }
378 else if (mstring_equal (next, "full"))
379 {
380 printAllFlags (FALSE, TRUE);
381 return TRUE;
382 }
383 else if (mstring_equal (next, "manual"))
384 {
385 printFlagManual (FALSE);
386 return TRUE;
387 }
388 else if (mstring_equal (next, "webmanual"))
389 {
390 printFlagManual (TRUE);
391 return TRUE;
392 }
393 else
394 {
395 return FALSE;
396 }
397 }
398 else
399 {
400 return FALSE;
401 }
402}
403
404static void
405printParseErrors (void)
406{
407 llmsglit ("Parse Errors");
408 llmsglit ("------------");
409 llmsglit ("");
410 llmsglit ("Splint will sometimes encounter a parse error for code that "
411 "can be parsed with a local compiler. There are a few likely "
412 "causes for this and a number of techniques that can be used "
413 "to work around the problem.");
414 llmsglit ("");
415 llmsglit ("Compiler extensions --- compilers sometimes extend the C "
416 "language with compiler-specific keywords and syntax. While "
417 "it is not advisible to use these, oftentimes one has no choice "
418 "when the system header files use compiler extensions. ");
419 llmsglit ("");
420 llmsglit ("Splint supports some of the GNU (gcc) compiler extensions, "
421 "if the +gnuextensions flag is set. You may be able to workaround "
422 "other compiler extensions by using a pre-processor define. "
423 "Alternately, you can surround the unparseable code with");
424 llmsglit ("");
425 llmsglit (" # ifndef S_SPLINT_S");
426 llmsglit (" ...");
427 llmsglit (" # endif");
428 llmsglit ("");
429 /* evans 2000-12-21 fixed typo reported by Jeroen Ruigrok/Asmodai */
430 llmsglit ("Missing type definitions --- an undefined type name will usually "
431 "lead to a parse error. This often occurs when a standard header "
432 "file defines some type that is not part of the standard library. ");
433 llmsglit ("By default, Splint does not process the local files corresponding "
434 "to standard library headers, but uses a library specification "
435 "instead so dependencies on local system headers can be detected. "
436 "If another system header file that does not correspond to a "
437 "standard library header uses one of these superfluous types, "
438 "a parse error will result.");
439 llmsglit ("");
440 llmsglit ("If the parse error is inside a posix standard header file, the "
441 "first thing to try is +posixlib. This makes Splint use "
442 "the posix library specification instead of reading the posix "
443 "header files.");
444 llmsglit ("");
445 llmsglit ("Otherwise, you may need to either manually define the problematic "
446 "type (e.g., add -Dmlink_t=int to your .splintrc file) or force "
447 "splint to process the header file that defines it. This is done "
448 "by setting -skipisoheaders or -skipposixheaders before "
449 "the file that defines the type is #include'd.");
450 llmsglit ("(See splint -help "
451 "skipisoheaders and splint -help skipposixheaders for a list of "
452 "standard headers.) For example, if <sys/local.h> uses a type "
453 "defined by posix header <sys/types.h> but not defined by the "
454 "posix library, we might do: ");
455 llmsglit ("");
456 llmsglit (" /*@-skipposixheaders@*/");
457 llmsglit (" # include <sys/types.h>");
458 llmsglit (" /*@=skipposixheaders@*/");
459 llmsglit (" # include <sys/local.h>");
460 llmsglit ("");
461 llmsglit ("to force Splint to process <sys/types.h>.");
462 llmsglit ("");
463 llmsglit ("At last resort, +trytorecover can be used to make Splint attempt "
464 "to continue after a parse error. This is usually not successful "
465 "and the author does not consider assertion failures when +trytorecover "
466 "is used to be bugs.");
467}
468
469void help_processFlags (int argc, char **argv)
470{
471 int i;
472
473 showHerald ();
474
475 if (argc == 0)
476 {
477 help_showAvailableHelp ();
478 }
479
480 for (i = 0; i < argc; i++)
481 {
482 char *thisarg = argv[i];
483
484 if (*thisarg == '-' || *thisarg == '+')
485 {
486 thisarg++; /* skip '-' */
487 }
488 if (mstring_equal (thisarg, "modes"))
489 {
490 llmsg (describeModes ());
491 }
492 else if (mstring_equal (thisarg, "vars")
493 || mstring_equal (thisarg, "env"))
494 {
495 describeVars ();
496 }
497 else if (mstring_equal (thisarg, "annotations"))
498 {
499 printAnnotations ();
500 }
501 else if (mstring_equal (thisarg, "parseerrors"))
502 {
503 printParseErrors ();
504 }
505 else if (mstring_equal (thisarg, "comments"))
506 {
507 printComments ();
508 }
509 else if (mstring_equal (thisarg, "prefixcodes"))
510 {
511 describePrefixCodes ();
512 }
513 else if (mstring_equal (thisarg, "references")
514 || mstring_equal (thisarg, "refs"))
515 {
516 printReferences ();
517 }
518 else if (mstring_equal (thisarg, "mail"))
519 {
520 printMail ();
521 }
522 else if (mstring_equal (thisarg, "maintainer")
523 || mstring_equal (thisarg, "version"))
524 {
525 printMaintainer ();
526 }
210066f9 527 else if (flags_isModeName (cstring_fromChars (thisarg)))
5b99bfd6 528 {
210066f9 529 llmsg (describeMode (cstring_fromChars (thisarg)));
5b99bfd6 530 }
140c27a8 531 else if (mstring_equal (thisarg, "flags"))
532 {
533 if (i + 1 < argc)
534 {
535 char *next = argv[i + 1];
536
537 if (specialFlagsHelp (next))
538 {
539 i++;
540 }
541 else
542 {
543 flagkind k = identifyCategory (cstring_fromChars (next));
544
545 if (k != FK_NONE)
546 {
547 printCategory (k);
548 i++;
549 }
550 }
551 }
552 else
553 {
554 printFlags ();
555 }
556 }
557 else
558 {
559 cstring s = describeFlag (cstring_fromChars (thisarg));
560
561 if (cstring_isDefined (s))
562 {
563 llmsg (s);
564 }
565 }
566 }
567}
This page took 0.177265 seconds and 5 git commands to generate.