# include <fcntl.h>
# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
# include <io.h>
+/* SMF */
+# ifndef BCC32
# include <sys/utime.h> /* for __DATE__ and __TIME__ */
+# endif
+
# include <time.h>
# else
# ifndef VMS
# include <errno.h>
# include "splintMacros.nf"
-# include "llbasic.h"
+# include "basic.h"
# include "lcllib.h"
# include "cpplib.h"
# include "cpperror.h"
# include "cpphash.h"
# include "cppexp.h"
# include "version.h"
-# include "portab.h"
# include "osd.h"
/*
# define cppBuffer_get(BUFFER) \
((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur++ : EOF)
+/*@function static int cppBuffer_reachedEOF (sef cppBuffer *p_b) modifies nothing; @*/
+# define cppBuffer_reachedEOF(b) \
+ ((b)->cur < (b)->rlimit ? FALSE : TRUE)
+
/* Append string STR (of length N) to PFILE's output buffer. Make space. */
/*@function static void cppReader_puts (sef cppReader *p_file, char *p_str, sef size_t p_n)
modifies *p_file; @*/
/*@function static int cppReader_getC (cppReader *p_pfile) modifies *p_pfile; @*/
# define cppReader_getC(pfile) (cppBuffer_get (cppReader_getBufferSafe (pfile)))
+/*@function static int cppReader_reachedEOF (sef cppReader *p_pfile) modifies *p_pfile; @*/
+# define cppReader_reachedEOF(pfile) (cppBuffer_reachedEOF (cppReader_getBufferSafe (pfile)))
+
/*@function static int cppReader_peekC (cppReader *) modifies nothing;@*/
# define cppReader_peekC(pfile) (cpplib_bufPeek (cppReader_getBufferSafe (pfile)))
# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
+/* SMF */
+# ifndef BCC32
/*
** WIN32 (at least the VC++ include files) does not define mode_t.
*/
/*@-incondefs@*/ /*@-czechtypes@*/
typedef unsigned int mode_t;
/*@=incondefs@*/ /*@=czechtypes@*/
+# endif
# endif
opts->warn_comments = 0;
opts->warnings_are_errors = 0;
+ /* Added 2003-07-10: */
+ opts->traditional = FALSE;
+ opts->c89 = TRUE;
initialize_char_syntax (opts);
}
defn->predefined = NULL;
exp_p = defn->expansion = (char *) defn + sizeof (*defn);
+ *defn->expansion = '\0'; /* convince splint it is initialized */
defn->line = 0;
defn->rest_args = NULL;
llfatalbug (cstring_makeLiteral ("Maximum definition size exceeded."));
}
- return defn;
+ return defn; /* Spurious warning here */
}
/*
defn->pattern = NULL;
defn->nargs = nargs;
defn->predefined = NULL;
-
exp_p = defn->expansion = (char *) defn + sizeof (*defn);
defn->line = 0;
{
llfatalbug (cstring_makeLiteral ("Maximum definition size exceeded."));
}
-
- return defn;
+
+ /*@-compdef@*/ /* defn->expansion defined? */
+ return defn;
+ /*@=compdef@*/
}
/*
return FALSE;
}
-/* Return TRUE if two parts of two macro definitions are effectively different.
- One of the parts starts at BEG1 and has LEN1 chars;
- the other has LEN2 chars at BEG2.
- Any sequence of whitespace matches any other sequence of whitespace.
- FIRST means these parts are the first of a macro definition;
- so ignore leading whitespace entirely.
- LAST means these parts are the last of a macro definition;
- so ignore trailing whitespace entirely. */
- /*@i2@*/
+/*
+** Return TRUE if two parts of two macro definitions are effectively different.
+** One of the parts starts at BEG1 and has LEN1 chars;
+** the other has LEN2 chars at BEG2.
+** Any sequence of whitespace matches any other sequence of whitespace.
+** FIRST means these parts are the first of a macro definition;
+** so ignore leading whitespace entirely.
+** LAST means these parts are the last of a macro definition;
+** so ignore trailing whitespace entirely.
+*/
+
static bool
comp_def_part (bool first, char *beg1, int len1, char *beg2, int len2, bool last)
{
return (beg1 != end1) || (beg2 != end2);
}
-/* Process a #define command.
- BUF points to the contents of the #define command, as a contiguous string.
- LIMIT points to the first character past the end of the definition.
- KEYWORD is the keyword-table entry for #define,
- or NULL for a "predefined" macro. */
- /*@i2@*/
+/*
+** Process a #define command.
+** BUF points to the contents of the #define command, as a contiguous string.
+** LIMIT points to the first character past the end of the definition.
+** KEYWORD is the keyword-table entry for #define,
+** or NULL for a "predefined" macro.
+*/
+
static int
do_defineAux (cppReader *pfile, struct directive *keyword,
/*@exposed@*/ char *buf, char *limit, bool noExpand)
int hashcode;
macroDef mdef;
hashNode hp;
- /*@i2@*/
- DPRINTF (("Define aux: %d", noExpand));
- /*@i2@*/
+
mdef = create_definition (buf, limit, pfile, keyword == NULL, noExpand);
if (mdef.defn == 0)
goto nope;
- /*@i2@*/
+
hashcode = cpphash_hashCode (mdef.symnam, mdef.symlen, CPP_HASHSIZE);
- /*@i2@*/
- DPRINTF (("Macro: %s / %s",
- cstring_copyLength (mdef.symnam, mdef.symlen),
- bool_unparse (noExpand)));
- /*@i2@*/
+
if ((hp = cpphash_lookup (mdef.symnam, size_toInt (mdef.symlen), hashcode)) != NULL)
{
bool ok = FALSE;
else if (hp->type == T_CONST)
ok = !CPPOPTIONS (pfile)->done_initializing;
else {
- BADBRANCH;
+ ok = FALSE; /* Redefining anything else is bad. */
}
- /*@i2@*/
+
/* Print the warning if it's not ok. */
if (!ok)
{
}
cpp_setLocation (pfile);
- /*@i2@*/
+
if (hp->type == T_MACRO)
{
if (hp->value.defn->noExpand)
message ("Macro %q already defined",
cstring_copyLength (mdef.symnam,
mdef.symlen)));
- /*@i2@*/
}
}
*/
hashNode hn;
- /*@i2@*/
+
if (CPPOPTIONS (pfile)->debug_output && (keyword != NULL))
{
pass_thru_directive (buf, limit, pfile, keyword);
} /*@=branchstate@*/
return 0;
- /*@i2@*/
+
nope:
- /*@i2@*/
return 1;
}
DPRINTF (("Regular do define"));
return do_defineAux (pfile, keyword, buf, limit, FALSE);
}
- /*@i2@*/
-/* This structure represents one parsed argument in a macro call.
- `raw' points to the argument text as written (`raw_length' is its length).
- `expanded' points to the argument's macro-expansion
- (its length is `expand_length').
- `stringified_length' is the length the argument would have
- if stringified.
- `use_count' is the number of times this macro arg is substituted
- into the macro. If the actual use count exceeds 10,
- the value stored is 10. */
- /*@i2@*/
+
+/*
+** This structure represents one parsed argument in a macro call.
+** `raw' points to the argument text as written (`raw_length' is its length).
+** `expanded' points to the argument's macro-expansion
+** (its length is `expand_length').
+** `stringified_length' is the length the argument would have
+** if stringified.
+** `use_count' is the number of times this macro arg is substituted
+** into the macro. If the actual use count exceeds 10,
+** the value stored is 10.
+*/
+
/* raw and expanded are relative to ARG_BASE */
/*@notfunction@*/
#define ARG_BASE ((pfile)->token_buffer)
- /*@i2@*/
+
struct argdata {
/* Strings relative to pfile->token_buffer */
long raw;
int use_count;
};
-/* Allocate a new cppBuffer for PFILE, and push it on the input buffer stack.
- If BUFFER != NULL, then use the LENGTH characters in BUFFER
- as the new input buffer.
- Return the new buffer, or NULL on failure. */
- /*@i2@*/
+/*
+** Allocate a new cppBuffer for PFILE, and push it on the input buffer stack.
+** If BUFFER != NULL, then use the LENGTH characters in BUFFER
+** as the new input buffer.
+** Return the new buffer, or NULL on failure.
+*/
+
/*@null@*/ /*@exposed@*/ cppBuffer *
cppReader_pushBuffer (cppReader *pfile, char *buffer, size_t length)
{
return buf;
}
- /*@i2@*/
+
cppBuffer *
cppReader_popBuffer (cppReader *pfile)
{
return ++CPPBUFFER (pfile);
}
-/* Scan until CPPBUFFER (PFILE) is exhausted into PFILE->token_buffer.
- Pop the buffer when done. */
- /*@i2@*/
+/*
+** Scan until CPPBUFFER (PFILE) is exhausted into PFILE->token_buffer.
+** Pop the buffer when done.
+*/
+
void
cppReader_scanBuffer (cppReader *pfile)
{
}
}
}
- /*@i2@*/
/*
* Rescan a string (which may have escape marks) into pfile's buffer.
quote_string (pfile, string);
return;
}
+ case T_FUNC: /* added in ISO C99 */
+ {
+ /* We don't know the actual name of the function, but it doesn't matter */
+ char *string = "** function-name **";
+ cpplib_reserve (pfile, 3 + 4 * strlen (string));
+ quote_string (pfile, string);
+ return;
+ }
case T_INCLUDE_LEVEL:
true_indepth = 0;
cpplib_installBuiltin ("__DATE__", ctype_string, -1, T_DATE, 0, NULL, -1);
cpplib_installBuiltin ("__FILE__", ctype_string, -1, T_FILE, 0, NULL, -1);
cpplib_installBuiltin ("__BASE_FILE__", ctype_string, -1, T_BASE_FILE, 0, NULL, -1);
+ cpplib_installBuiltin ("__func__", ctype_string, -1, T_FUNC, 0, NULL, -1);
cpplib_installBuiltin ("__INCLUDE_LEVEL__", ctype_int, -1, T_INCLUDE_LEVEL, 0, NULL, -1);
cpplib_installBuiltin ("__VERSION__", ctype_string, -1, T_VERSION, 0, NULL, -1);
#ifndef NO_BUILTIN_SIZE_TYPE
cpplib_installBuiltin ("__REGISTER_PREFIX__", ctype_string, -1, T_REGISTER_PREFIX_TYPE, 0, NULL, -1);
cpplib_installBuiltin ("__TIME__", ctype_string, -1, T_TIME, 0, NULL, -1);
- /*
- ** No, don't define __STDC__
- **
-
if (!cppReader_isTraditional (pfile))
{
cpplib_installBuiltin ("__STDC__", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);
}
- **
- */
-
# ifdef WIN32
cpplib_installBuiltin ("_WIN32", ctype_int, -1, T_CONST, STDC_VALUE, NULL, -1);
# endif
/*drl 1/9/2001/ try to define the right symbol for the architecture
We use autoconf to determine the target cpu
*/
+# ifndef S_SPLINT_S
cpplib_installBuiltin ("__" TARGET_CPU, ctype_int, -1, T_CONST, 2, NULL, -1);
+# endif
/*drl 1/2/2002 set some flags based on uname
I'd like to be able to do this with autoconf macro instead...
}
else if (ap->raw_before || ap->raw_after || cppReader_isTraditional (pfile))
{
- /* Add 4 for two newline-space markers to prevent
- token concatenation. */
- assertSet (args); /*@i534 shouldn't need this */
+ /* Add 4 for two newline-space markers to prevent token concatenation. */
+ assertSet (args); /* Splint shouldn't need this */
xbuf_len += args[ap->argno].raw_length + 4;
}
else
/* We have an ordinary (expanded) occurrence of the arg.
So compute its expansion, if we have not already. */
- assertSet (args); /*@i534 shouldn't need this */
+ assertSet (args); /* shouldn't need this */
if (args[ap->argno].expand_length < 0)
{
if (f == IMPORT_FOUND)
{
- return 0; /* Already included this file */
+ return 0; /* Already included this file */
}
#ifdef EACCES
else if (f == IMPORT_NOT_FOUND && errno == EACCES)
&start_line, &start_column);
old_written = cpplib_getWritten (pfile);
string:
- DPRINTF (("Put char: %c", c));
+ DPRINTF (("Reading string: %c", c));
cppReader_putChar (pfile, c);
while (TRUE)
{
- int cc = cppReader_getC (pfile);
- DPRINTF (("cc: %c", c));
- if (cc == EOF)
+ /* evans-2003-06-07
+ ** Because of ISO8859-1 characters in string literals, we need a special test here.
+ */
+
+ if (cppReader_reachedEOF (pfile))
{
+
+ DPRINTF (("Matches EOF!"));
if (cppBuffer_isMacro (CPPBUFFER (pfile)))
{
/* try harder: this string crosses a macro expansion
CPPBUFFER (pfile) = next_buf;
continue;
}
+
if (!cppReader_isTraditional (pfile))
{
cpp_setLocation (pfile);
setLine (long_toInt (start_line));
setColumn (long_toInt (start_column));
-
+
if (pfile->multiline_string_line != long_toInt (start_line)
&& pfile->multiline_string_line != 0)
{
message ("Unterminated string or character constant"));
}
}
- /*@loopbreak@*/ break;
- }
- DPRINTF (("putting char: %c", cc));
- cppReader_putChar (pfile, cc);
- switch (cc)
+ /*@loopbreak@*/ break;
+ }
+ else
{
- case '\n':
- /* Traditionally, end of line ends a string constant with
- no error. So exit the loop and record the new line. */
- if (cppReader_isTraditional (pfile))
- goto while2end;
- if (c == '\'')
- {
- goto while2end;
- }
- if (cppReader_isPedantic (pfile)
- && pfile->multiline_string_line == 0)
- {
- cppReader_pedwarnWithLine
- (pfile, long_toInt (start_line),
- long_toInt (start_column),
- cstring_makeLiteral ("String constant runs past end of line"));
- }
- if (pfile->multiline_string_line == 0)
- {
- pfile->multiline_string_line = start_line;
- }
-
- /*@switchbreak@*/ break;
-
- case '\\':
- cc = cppReader_getC (pfile);
- if (cc == '\n')
- {
- /* Backslash newline is replaced by nothing at all. */
- cppReader_adjustWritten (pfile, -1);
- pfile->lineno++;
- }
- else
+ int cc = cppReader_getC (pfile);
+ DPRINTF (("cc: %c [%d] [%d]", cc, cc, EOF));
+ DPRINTF (("putting char: %c", cc));
+ cppReader_putChar (pfile, cc);
+ switch (cc)
{
- /* ANSI stupidly requires that in \\ the second \
- is *not* prevented from combining with a newline. */
- NEWLINE_FIX1(cc);
- if (cc != EOF)
- cppReader_putChar (pfile, cc);
+ case '\n':
+ /* Traditionally, end of line ends a string constant with
+ no error. So exit the loop and record the new line. */
+ if (cppReader_isTraditional (pfile))
+ goto while2end;
+ if (c == '\'')
+ {
+ goto while2end;
+ }
+ if (cppReader_isPedantic (pfile)
+ && pfile->multiline_string_line == 0)
+ {
+ cppReader_pedwarnWithLine
+ (pfile, long_toInt (start_line),
+ long_toInt (start_column),
+ cstring_makeLiteral ("String constant runs past end of line"));
+ }
+ if (pfile->multiline_string_line == 0)
+ {
+ pfile->multiline_string_line = start_line;
+ }
+
+ /*@switchbreak@*/ break;
+
+ case '\\':
+ cc = cppReader_getC (pfile);
+ if (cc == '\n')
+ {
+ /* Backslash newline is replaced by nothing at all. */
+ pfile->lineno++; /* 2003-11-03: AMiller suggested adding this, but
+ its not clear why it is needed. */
+ cppReader_adjustWritten (pfile, -1);
+ pfile->lineno++;
+ }
+ else
+ {
+ /* ANSI stupidly requires that in \\ the second \
+ is *not* prevented from combining with a newline. */
+ NEWLINE_FIX1(cc);
+ if (cc != EOF)
+ cppReader_putChar (pfile, cc);
+ }
+ /*@switchbreak@*/ break;
+
+ case '\"':
+ case '\'':
+ if (cc == c)
+ goto while2end;
+ /*@switchbreak@*/ break;
}
- /*@switchbreak@*/ break;
-
- case '\"':
- case '\'':
- if (cc == c)
- goto while2end;
- /*@switchbreak@*/ break;
}
}
while2end:
op2:
token = CPP_OTHER;
pfile->only_seen_white = 0;
- op2any:
+ op2any: /* jumped to for \ continuations */
cpplib_reserve(pfile, 3);
cppReader_putCharQ (pfile, c);
- cppReader_putCharQ (pfile, cppReader_getC (pfile));
+
+ /* evans 2003-08-24: This is a hack to fix line output for \
+ continuations. Someday I really should get a decent pre-processor!
+ */
+
+ if (c == '\\') {
+ (void) cppReader_getC (pfile); /* skip the newline to avoid extra lines */
+ } else {
+ cppReader_putCharQ (pfile, cppReader_getC (pfile));
+ }
+
cppReader_nullTerminateQ (pfile);
return token;
case '\\':
c2 = cppReader_peekC (pfile);
+ /* allow other stuff here if a flag is set? */
+ DPRINTF (("Got continuation!"));
if (c2 != '\n')
goto randomchar;
token = CPP_HSPACE;
bool system_header_p,
/*@dependent@*/ struct file_name_list *dirptr)
{
- mode_t st_mode;
+ mode_t st_mode; /* was __mode_t */
size_t st_size;
long i;
int length = 0;
if (fstat (fd, &sbuf) < 0) {
*mode_pointer = 0;
*size_pointer = 0;
+ /*@-compdestroy@*/ /* possibly spurious warnings here (or memory leak) */
return (-1);
+ /*@=compdestroy@*/
}
if (mode_pointer != NULL)
{
+ /*@-type@*/ /* confusion between __mode_t and mode_t types */
*mode_pointer = sbuf.st_mode;
+ /*@=type@*/
}
if (size_pointer != NULL)
*size_pointer = (size_t) sbuf.st_size;
}
+ /*@-compdestroy@*/ /* possibly spurious warnings here (or memory leak) */
return 0;
+ /*@=compdestroy@*/
}
/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
}
pmark->position = pbuf->cur - pbuf->buf;
- DPRINTF (("move mark: %s", pmark->position));
+ DPRINTF (("move mark: %d", pmark->position));
}
void cpplib_initializeReader (cppReader *pfile) /* Must be done after library is loaded. */
nlist->got_name_map = 0;
nlist->next = NULL;
- /*@i2523@*/ if (opts->first_system_include == NULL)
+ /* Spurious warning reported for opts->first_system_include */
+ /*@-usereleased@*/ if (opts->first_system_include == NULL)
{
opts->first_system_include = nlist;
}
-
+ /*@=usereleased@*/
+
cppReader_addIncludeChain (pfile, nlist);
}
}
cppReader_appendIncludeChain (pfile, opts->after_include,
opts->last_after_include);
- /*@i523@*/ if (opts->first_system_include == NULL)
+ /* Spurious warnings for opts->first_system_include */
+ /*@-usereleased@*/
+ if (opts->first_system_include == NULL)
{
opts->first_system_include = opts->after_include;
}
-
+ /*@=usereleased@*/
+
/* With -v, print the list of dirs to search. */
if (opts->verbose) {
struct file_name_list *p;
if (context_getFlag (FLG_SKIPSYSHEADERS))
{
- DPRINTF (("Skip include TRUE: %s", fname));
- return TRUE;
+ /*
+ ** 2003-04-18: Patch from Randal Parsons
+ */
+
+ /*
+ ** Don't skip include file unless the file actually exists.
+ ** It may be in a different directory.
+ */
+
+ int f = open (cstring_toCharsSafe (fname), O_RDONLY, 0666);
+
+ if (f >= 0)
+ {
+ check (close (f) == 0);
+ DPRINTF (("Skip include TRUE: %s", fname));
+ return TRUE;
+ }
+ else
+ {
+ /* Keep looking... */
+ }
}
}