/*
** Splint - annotation-assisted static program checker
-** Copyright (C) 1994-2001 University of Virginia,
+** Copyright (C) 1994-2003 University of Virginia,
** Massachusetts Institute of Technology
**
** This program is free software; you can redistribute it and/or modify it
** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
** MA 02111-1307, USA.
**
-** For information on lclint: lclint-request@cs.virginia.edu
-** To report a bug: lclint-bug@cs.virginia.edu
+** For information on splint: info@splint.org
+** To report a bug: splint-bug@splint.org
** For more information: http://www.splint.org
*/
/*
* Herbert 06/12/2000:
* - added OS/2 specific includes before osd_getPid()
* - handle files like in WIN32 for OS/2 in osd_fileExists()
+ * Herbert 02/17/2002:
+ * - added OS/2 support to absolute file names
*/
/*@-allmacros*/
/* POSIX platforms should defined getpid in unistd.h */
# if defined (WIN32) || (defined(OS2) && defined(__IBMC__))
# include <process.h>
+# include <direct.h>
+# define getcwd _getcwd
# else
# include <unistd.h>
# endif
/*@end@*/
/*@=allmacros*/
-# include "lclintMacros.nf"
+# include "splintMacros.nf"
# include "basic.h"
# include "osd.h"
-# include "portab.h"
/* from stat.h */
/*@ignore@*/
fullPath = path;
llassert (cstring_isDefined (file));
+ /* 2002-01-01: make sure returnPath gets defined even when there are errors.
+ ** (fixed splint checking detected this)
+ */
+
+ *returnPath = cstring_undefined;
+
if (fullPath == NULL
||
# if defined(OS2) || defined(MSDOS) || defined(WIN32)
*fullPath == '\0' ||
(*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':'))
# else
- (*file == CONNECTCHAR)
+ (*file == CONNECTCHAR)
# endif
)
{
/* Path specified. Loop through directories in path looking for the */
/* first occurrence of the file. */
- while (nextdir (&fullPath, &dirPtr, &dirLen) &&
- rVal == OSD_FILENOTFOUND)
+ while (nextdir (&fullPath, &dirPtr, &dirLen)
+ && rVal == OSD_FILENOTFOUND)
{
if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
{
}
}
}
-
+
return rVal;
/*@noaccess cstring@*/
}
char aPath[MAXPATHLEN];
filestatus rVal = OSD_FILENOTFOUND; /* assume file not found. */
/*@access cstring@*/
-
+
+ *returnPath = cstring_undefined;
fullPath = osd_getEnvironmentVariable (path);
if (fullPath == NULL)
return (stat (cstring_toCharsSafe (filespec), &buf) == 0);
# else
# if defined (WIN32) || defined (OS2)
- FILE *test = fileTable_openFile (context_fileTable (), filespec, "r");
+ FILE *test = fileTable_openReadFile (context_fileTable (), filespec);
if (test != NULL)
{
# endif
}
+# if defined(__IBMC__) && defined(OS2)
+# define S_IFMT (unsigned short)0xFFFF
+# endif
+
+/*
+** Works form Win32 at least...
+*/
+
+# ifndef S_IXUSR
+/*@-macrounrecog@*/
+# define S_IXUSR _S_IEXEC
+/*@=macrounrecog@*/
+# endif
+
bool
osd_executableFileExists (/*@unused@*/ char *filespec)
{
# ifdef UNIX
- struct stat buf;
-# if defined(__IBMC__) && defined(OS2)
-# define S_IFMT (unsigned short)0xFFFF
-# endif
+ struct stat buf;
if (stat (filespec, &buf) == 0)
{
/* mask by file type */
{
/* as long as it is an executable file */
# if defined(__IBMC__) && defined(OS2)
- int com_or_exe_pos = strlen( filespec) - 4;
- return stricmp( &filespec[com_or_exe_pos], ".exe") == 0
- || stricmp( &filespec[com_or_exe_pos], ".com") == 0
- || stricmp( &filespec[com_or_exe_pos], ".bat") == 0
- || stricmp( &filespec[com_or_exe_pos], ".cmd") == 0;
+ int com_or_exe_pos = strlen( filespec) - 4;
+ return stricmp( &filespec[com_or_exe_pos], ".exe") == 0
+ || stricmp( &filespec[com_or_exe_pos], ".com") == 0
+ || stricmp( &filespec[com_or_exe_pos], ".bat") == 0
+ || stricmp( &filespec[com_or_exe_pos], ".cmd") == 0;
# else
return (((buf.st_mode & S_IXUSR)
-# if !defined(MSDOS) && !defined(OS2)
+# if defined (S_IXGRP) && defined (S_IXOTH)
| (buf.st_mode & S_IXGRP) |
(buf.st_mode & S_IXOTH)
# endif
# endif
}
}
-
# endif
return (FALSE);
if (**current_dir == '\0')
{
*len = 0;
+ *dir = NULL;
return FALSE;
}
# endif
}
-# ifndef NOLCL
-
-# ifdef WIN32
+# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
# endif
{
int res;
/* system ("printenv"); */
-# ifdef WIN32
+# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
(void) _flushall ();
# endif
res = system (cstring_toCharsSafe (cmd));
return res;
}
-# endif
# ifndef unlink
/* This should be defined by unistd.h */
/*@=redecl@*/
# endif
+static bool s_tempError = FALSE;
+
+void osd_setTempError (void)
+{
+ s_tempError = TRUE;
+}
+
int osd_unlink (cstring fname)
{
int res;
if (res != 0)
{
- llcontbug (message ("Cannot remove temporary file: %s (%s)",
- fname,
- cstring_fromChars (strerror (errno))));
+ if (!s_tempError)
+ {
+ llcontbug (message ("Cannot remove temporary file: %s (%s)",
+ fname,
+ cstring_fromChars (strerror (errno))));
+ }
}
return res;
bool osd_fileIsReadable (cstring f)
{
- FILE *fl = fileTable_openFile (context_fileTable (), f, "r");
+ FILE *fl = fileTable_openReadFile (context_fileTable (), f);
if (fl != NULL)
{
char *ret = NULL;
size_t size = PATH_MAX * sizeof (*ret);
+ DPRINTF (("Absolute for: %s", str));
+
+# if defined (WIN32) || defined (OS2) || defined (MSDOS)
+ if (strlen (str) > 1 && str[1] == ':')
+ {
+ /*
+ ** Its a drive letter
+ */
+
+ ret = dmalloc ((strlen (str) + 1) * sizeof (*ret));
+ strcpy (ret, str);
+ }
+ else
+# endif
if (osd_isConnectChar (str[0]))
{
ret = dmalloc ((strlen (str) + 1) * sizeof (*ret));
static void osd_setWorkingDirectory (void)
{
-# ifdef UNIX
+# if defined (UNIX) || defined (OS2)
char *buf = dmalloc (sizeof (*buf) * MAXPATHLEN);
char *cwd = getcwd (buf, MAXPATHLEN);
{
lldiagmsg (message ("Cannot get working directory: %s\n",
lldecodeerror (errno)));
+ osd_cwd = cstring_makeLiteral ("<missing directory>");
}
else
{
osd_setWorkingDirectory ();
}
+void osd_destroyMod (void)
+{
+ cstring_free (osd_cwd);
+ osd_cwd = cstring_undefined;
+}
+
cstring osd_absolutePath (cstring cwd, cstring filename)
{
-# ifdef UNIX
+# if defined (UNIX) || defined (OS2)
/* Setup the current working directory as needed. */
cstring cwd2 = cstring_isDefined (cwd) ? cwd : osd_cwd;
char *abs_buffer;
llassert (cstring_isDefined (cwd2));
llassert (cstring_isDefined (filename));
- abs_buffer = (char *) dmalloc (size_fromInt (cstring_length (cwd2) + cstring_length (filename) + 2));
+ abs_buffer = (char *) dmalloc (cstring_length (cwd2) + cstring_length (filename) + 2);
endp = abs_buffer;
/*
{
const char *src_p;
- if (filename[0] != '/')
+ if (!osd_isConnectChar (filename[0])
+# ifdef OS2
+ && !(isalpha (filename[0]) && filename[1] == ':')
+# endif
+ )
{
src_p = cwd2;
continue;
}
- *(endp-1) = '/'; /* overwrite null */
+ *(endp-1) = CONNECTCHAR; /* overwrite null */
}
src_p = filename;
{
break;
}
- else if (inp[0] == '/' && outp[-1] == '/')
+ else if (osd_isConnectChar (inp[0]) && osd_isConnectChar (outp[-1]))
{
inp++;
continue;
}
- else if (inp[0] == '.' && outp[-1] == '/')
+ else if (inp[0] == '.' && osd_isConnectChar (outp[-1]))
{
if (inp[1] == '\0')
{
break;
}
- else if (inp[1] == '/')
+ else if (osd_isConnectChar (inp[1]))
{
inp += 2;
continue;
}
else if ((inp[1] == '.')
- && (inp[2] == '\0' || inp[2] == '/'))
+ && (inp[2] == '\0' || osd_isConnectChar (inp[2])))
{
- inp += (inp[2] == '/') ? 3 : 2;
+ inp += (osd_isConnectChar (inp[2])) ? 3 : 2;
outp -= 2;
- while (outp >= abs_buffer && *outp != '/')
+ while (outp >= abs_buffer && !osd_isConnectChar (*outp))
{
outp--;
}
the last character of the returned string is *not* a slash. */
*outp = '\0';
- if (outp[-1] == '/')
+ if (osd_isConnectChar (outp[-1]))
*--outp = '\0';
/*@noaccess cstring@*/
return cstring_fromChars (abs_buffer);
# else
+ DPRINTF (("Here: %s", filename));
return cstring_copy (filename);
# endif
}
** is longer, then the full absolute filename is returned.
**
** KNOWN BUG: subpart of the original filename is actually a symbolic link.
+**
+** this is really horrible code...surely someone has written a less buggy version of this!
*/
cstring osd_outputPath (cstring filename)
{
-# ifdef UNIX
+# if defined (UNIX) || defined (OS2)
char *rel_buffer;
char *rel_buf_p;
cstring cwd_p = osd_cwd;
char *path_p;
int unmatched_slash_count = 0;
- size_t filename_len = size_fromInt (cstring_length (filename));
+ size_t filename_len = cstring_length (filename);
+ llassertretval (filename_len > 0, filename);
+
/*@access cstring@*/
path_p = filename;
- rel_buf_p = rel_buffer = (char *) dmalloc (filename_len);
+ rel_buffer = (char *) dmalloc (filename_len);
+ rel_buf_p = rel_buffer;
+ *rel_buf_p = '\0';
+
+ if (cwd_p == NULL)
+ {
+ /* Need to prevent recursive assertion failures */
+ return cstring_copy (filename);
+ }
llassert (cwd_p != NULL);
llassert (path_p != NULL);
path_p++;
}
- if ((*cwd_p == '\0') && (*path_p == '\0' || *path_p == '/')) /* whole pwd matched */
+ if ((*cwd_p == '\0') && (*path_p == '\0' || osd_isConnectChar (*path_p))) /* whole pwd matched */
{
if (*path_p == '\0') /* input *is* the current path! */
- return cstring_makeLiteral (".");
+ {
+ cstring_free (rel_buffer);
+ return cstring_makeLiteral (".");
+ }
else
{
- /*@i324 ! lclint didn't report an errors for: return ++path_p; */
- return cstring_fromCharsNew (++path_p);
+ cstring_free (rel_buffer);
+ return cstring_fromCharsNew (path_p + 1);
}
}
else
{
+
+ /* drl 2002-10/14 I had to put this code back*/
+ /* the case that needs it is when splint is given an absolute path name of a file outside of the current directory and the subdirectories below the current directory. e.g. cd /home/; splint /tmp/prog.c
+ */
+
+ /* evans 2002-02-05 This is horrible code, which I've removed. I couldn't find any
+ ** test cases that need it, so I hope I'm not breaking anything.
+ */
+ /*#if 0*/
+
if (*path_p != '\0')
{
--cwd_p;
--path_p;
- while (*cwd_p != '/') /* backup to last slash */
+
+ while (cwd_p >= osd_cwd && !osd_isConnectChar (*cwd_p)) /* backup to last slash */
{
--cwd_p;
--path_p;
path_p++;
unmatched_slash_count++;
}
-
+
/* Find out how many directory levels in cwd were *not* matched. */
while (*cwd_p != '\0')
{
- if (*cwd_p++ == '/')
+ if (osd_isConnectChar (*cwd_p++))
unmatched_slash_count++;
}
Reject it if longer than the input. */
if (unmatched_slash_count * 3 + strlen (path_p) >= filename_len)
{
+ cstring_free (rel_buffer);
+ /* fprintf (stderr, "Returning filename: %s [%p]\n", filename); */
return cstring_copy (filename);
}
-
- /*
- ** evans 2001-10-15
- ** I'm trusting the code on this one...don't see how this is guaranteed though.
- */
-
- assertSet (rel_buffer);
+ /*drl 10-14-2002 end previously removed code */
+ /*#endif*/
/* For each of them, put a `../' at the beginning of the short name. */
while (unmatched_slash_count-- > 0)
{
/* Give up if the result gets to be longer
than the absolute path name. */
- if (rel_buffer + filename_len <= rel_buf_p + 3)
+ char * temp_rel_buf_p;
+
+ /*drl This comment is necessary because for some reason Splint
+ does not realize that the pasts where rel_buf_p is released
+ do not reach here*/
+ /*@-usereleased@*/
+ temp_rel_buf_p = rel_buf_p;
+ /*@-usereleased@*/
+
+ if (rel_buffer + filename_len <= temp_rel_buf_p + 3)
{
sfree (rel_buffer);
return cstring_copy (filename);
*rel_buf_p++ = '.';
*rel_buf_p++ = '.';
- *rel_buf_p++ = '/';
+ *rel_buf_p++ = CONNECTCHAR;
}
/* Then tack on the unmatched part of the desired file's name. */
+
do
{
if (rel_buffer + filename_len <= rel_buf_p)
}
} /*@-usereleased@*/
while ((*rel_buf_p++ = *path_p++) != '\0') ;
- /*@=usereleased@*/ /*@i523! shouldn't need these */
+
+ /*@=usereleased@*/ /* Splint limitation: shouldn't need these */
--rel_buf_p;
- if (*(rel_buf_p-1) == '/')
+
+ if (osd_isConnectChar (*(rel_buf_p-1)))
*--rel_buf_p = '\0';
+ /* fprintf (stderr, "Returning buffer: %s [%p]\n", rel_buffer, rel_buffer); */
return rel_buffer;
}
/*@noaccess cstring@*/