]> andersk Git - splint.git/blob - src/help.c
Fixed problem with NULL being changed.
[splint.git] / src / help.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
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"
32 # include "llmain.h"
33 # include "version.h"
34
35 static void
36 describeVars (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 
81          ("systemdirs = %s (set by -systemdirs or environment variable %s)", 
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
88 static void
89 printAnnotations (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
211 static void
212 printComments (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   
263 static void
264 printFlags (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
274 static void
275 printMaintainer (void)
276 {
277   llmsg (message ("Maintainer: %s", cstring_makeLiteralTemp (SPLINT_MAINTAINER)));
278   llmsglit (LCL_COMPILE);
279 }
280
281 static void
282 printMail (void)
283 {
284   llmsglit ("Mailing Lists");
285   llmsglit ("-------------");
286   llmsglit ("");
287   llmsglit ("There are two mailing lists associated with Splint: ");
288   llmsglit ("");
289   llmsglit ("   splint-announce@cs.virginia.edu");
290   llmsglit ("");
291   llmsglit ("      Reserved for announcements of new releases and bug fixes.");
292   llmsglit ("");
293   llmsglit ("   splint-discuss@virginia.edu");
294   llmsglit ("");
295   llmsglit ("      Informal discussions on the use and development of Splint.");
296   llmsglit ("");
297   llmsglit ("To subscribe or view archives, visit http://www.splint.org/lists.html");
298 }
299
300 static void
301 printReferences (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
309 static void
310 describePrefixCodes (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
328 void 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
357 static bool
358 specialFlagsHelp (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
404 static void
405 printParseErrors (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
469 void 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         }
527       else if (flags_isModeName (cstring_fromChars (thisarg)))
528         {
529           llmsg (describeMode (cstring_fromChars (thisarg)));
530         }
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.087159 seconds and 5 git commands to generate.