]> andersk Git - splint.git/blobdiff - src/osd.c
Surpressed spurious splintme error in osd.c
[splint.git] / src / osd.c
index 4c06580d30d0bc431bcd095936fea38c689bae2a..71b5de41f10f4f0978283258913a93d7b2e164eb 100644 (file)
--- a/src/osd.c
+++ b/src/osd.c
@@ -1,6 +1,6 @@
 /*
-** LCLint - annotation-assisted static program checker
-** Copyright (C) 1994-2000 University of Virginia,
+** Splint - annotation-assisted static program checker
+** Copyright (C) 1994-2003 University of Virginia,
 **         Massachusetts Institute of Technology
 **
 ** This program is free software; you can redistribute it and/or modify it
@@ -17,9 +17,9 @@
 ** 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 more information: http://lclint.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
 */
 /*
 ** osd.c
@@ -37,6 +37,8 @@
  * 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*/
 # include <sys/stat.h>
 /* Fix suggested by Lars Rasmussen */
 # include <errno.h>
+
+/* 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"
@@ -62,11 +74,13 @@ static bool osd_executableFileExists (char *);
 static bool nextdir (char **p_current_dir, /*@out@*/ char **p_dir, 
                     /*@out@*/ size_t *p_len);
 
-extern char *LSLRootName (char *filespec)
+extern cstring LSLRootName (cstring filespec)
 {
+  /*@access cstring@*/
   char *result, *startName, *tail;
   size_t nameLength;
 
+  llassert (cstring_isDefined (filespec));
   tail = strrchr (filespec, CONNECTCHAR);
   startName = (tail == NULL ? filespec : &tail[1]);
   tail = strrchr (startName, '.');
@@ -76,11 +90,13 @@ extern char *LSLRootName (char *filespec)
   strncpy (result, startName, nameLength);
   result[(int) nameLength] = '\0';
   return result;
+  /*@noaccess cstring@*/
 }
 
-extern /*@observer@*/ char *
-osd_getEnvironment (char *env, /*@returned@*/ char *def)
+extern /*@observer@*/ cstring
+osd_getEnvironment (cstring env, /*@returned@*/ cstring def)
 {
+  /*@access cstring@*/
   char *ret = osd_getEnvironmentVariable (env);
 
   if (ret == NULL)
@@ -91,6 +107,7 @@ osd_getEnvironment (char *env, /*@returned@*/ char *def)
     {
       return ret;
     }
+  /*@noaccess cstring@*/
 }
 
 
@@ -128,43 +145,53 @@ osd_getEnvironment (char *env, /*@returned@*/ char *def)
 **--
 */
 
-extern /*@null@*/ /*@observer@*/ char *
-  osd_getHomeDir ()
+extern /*@observer@*/ cstring osd_getHomeDir ()
 {
   /* Would something different be better for windows? */
-  return (osd_getEnvironmentVariable ("HOME"));
+  return (osd_getEnvironmentVariable (cstring_makeLiteralTemp ("HOME")));
 }
 
-filestatus osd_findOnLarchPath (char *file, char **returnPath)
+filestatus osd_findOnLarchPath (cstring file, cstring *returnPath)
 {
-  return (osd_getPath (cstring_toCharsSafe (context_getLarchPath ()), file, returnPath));
+  return (osd_getPath (context_getLarchPath (), file, returnPath));
 }
 
 extern filestatus
-osd_getPath (char *path, char *file, char **returnPath)
+osd_getPath (cstring path, cstring file, cstring *returnPath)
 {
   char *fullPath;
   char *dirPtr;
   size_t dirLen;
   char aPath[MAXPATHLEN];
   filestatus rVal = OSD_FILENOTFOUND;  /* assume file not found. */
-
+  
+  /*@access cstring@*/
+  
   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 (fullPath == NULL 
+      || 
 # if defined(OS2) || defined(MSDOS) || defined(WIN32)
-    /* under OS/2 and MSDOS the includePath may be empty, if so, search 
-     * the current directory. */
-    *fullPath == '\0' || 
-    (*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':')))
+      /* under OS/2 and MSDOS the includePath may be empty, if so, search 
+       * the current directory. */
+      *fullPath == '\0' || 
+      (*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':'))
 # else
-     (*file == CONNECTCHAR))
+    (*file == CONNECTCHAR)
 # endif
+      )
     {
-     /* No path specified. Look for it in the current directory.           */
-
+      /* No path specified. Look for it in the current directory.          */
+      
       strcpy (&aPath[0], file);
-
+      
       if (osd_fileExists (&aPath[0]))
        {
          rVal = OSD_FILEFOUND;
@@ -174,20 +201,20 @@ osd_getPath (char *path, char *file, char **returnPath)
     }
   else
     {
-     /* Path specified. Loop through directories in path looking for the */
-     /* first occurrence of the file.                              */
-
+      /* Path specified. Loop through directories in path looking for the */
+      /* first occurrence of the file.                             */
+      
       while (nextdir (&fullPath, &dirPtr, &dirLen) &&
             rVal == OSD_FILENOTFOUND)
        {
          if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
            {
-            /* Cat directory and filename, and see if file exists.  */
+             /* Cat directory and filename, and see if file exists.  */
              strncpy (&aPath[0], dirPtr, dirLen);
              strcpy (&aPath[0] + dirLen, "");  /* Null terminate aPath. */
              strcat (&aPath[0], CONNECTSTR);
              strcat (&aPath[0], file);
-
+             
              if (osd_fileExists (&aPath[0]))
                {
                  rVal = OSD_FILEFOUND;
@@ -203,25 +230,28 @@ osd_getPath (char *path, char *file, char **returnPath)
     }
 
   return rVal;
+  /*@noaccess cstring@*/
 }
 
 extern filestatus
-osd_getExePath (char *path, char *file, char **returnPath)
+osd_getExePath (cstring path, cstring file, cstring *returnPath)
 {
   char *fullPath;
   char *dirPtr;
   size_t dirLen;
   char aPath[MAXPATHLEN];
   filestatus rVal = OSD_FILENOTFOUND;  /* assume file not found. */
-  
-  fullPath = osd_getEnvironmentVariable (path);
+  /*@access cstring@*/ 
 
+  *returnPath = cstring_undefined;  
+  fullPath = osd_getEnvironmentVariable (path);
+  
   if (fullPath == NULL)
     {
-     /* No path specified. Look for it in the current directory. */
-
+      /* No path specified. Look for it in the current directory. */
+      llassert (cstring_isDefined (file));
       strcpy (&aPath[0], file);
-
+      
       if (osd_fileExists (&aPath[0]))
        {
          rVal = OSD_FILEFOUND;
@@ -239,7 +269,9 @@ osd_getExePath (char *path, char *file, char **returnPath)
       while (nextdir (&fullPath, &dirPtr, &dirLen) &&
             rVal == OSD_FILENOTFOUND)
        {
-         if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
+         llassert (cstring_isDefined (file));
+
+         if ((dirLen + cstring_length (file) + 2) <= MAXPATHLEN)
            {
              /* Cat directory and filename, and see if file exists.  */
              strncpy (&aPath[0], dirPtr, dirLen);
@@ -262,40 +294,53 @@ osd_getExePath (char *path, char *file, char **returnPath)
     }
 
   return rVal;
+  /*@noaccess cstring@*/
 }
 
 bool
-osd_fileExists (char *filespec)
+osd_fileExists (cstring filespec)
 {
 # ifdef UNIX
   struct stat buf;
-  return (stat (filespec, &buf) == 0);
+  return (stat (cstring_toCharsSafe (filespec), &buf) == 0);
 # else
 # if defined (WIN32) || defined (OS2)
-  FILE *test = fopen (filespec, "r");
+  FILE *test = fileTable_openReadFile (context_fileTable (), filespec);
+  
   if (test != NULL) 
-  {
-       (void) fclose (test);
-       return TRUE;
-  } 
+    {
+      (void) fileTable_closeFile (context_fileTable (),test);
+      return TRUE;
+    
   else
-  { 
-         return FALSE;
-  }
+    
+      return FALSE;
+    }
 # else 
   return FALSE;
 # endif
 # 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 */
@@ -304,14 +349,14 @@ osd_executableFileExists (/*@unused@*/ char *filespec)
        {
          /* 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
@@ -319,7 +364,6 @@ osd_executableFileExists (/*@unused@*/ char *filespec)
 # endif
        }
     }
-
 # endif
   return (FALSE);
 
@@ -373,13 +417,14 @@ nextdir (d_char *current_dir, d_char *dir, size_t *len)
   if (**current_dir == '\0')
     {
       *len = 0;
+      *dir = NULL;
       return FALSE;
     }
 
-  *dir = (**current_dir == SEPCHAR ? *current_dir + 1 : *current_dir);
+  *dir = (**current_dir == PATH_SEPARATOR ? *current_dir + 1 : *current_dir);
   
   /* Find next ':' or end of string */
-  for (tchar = *dir; *tchar != '\0' && *tchar != SEPCHAR; tchar++)
+  for (tchar = *dir; *tchar != '\0' && *tchar != PATH_SEPARATOR; tchar++)
     {
       ;
     }
@@ -389,25 +434,25 @@ nextdir (d_char *current_dir, d_char *dir, size_t *len)
   return TRUE;
 }
 
-/*@observer@*/ /*@null@*/ char *osd_getEnvironmentVariable (char *var)
+/*@observer@*/ /*@null@*/ cstring osd_getEnvironmentVariable (cstring var)
 {
-# ifdef UNIX
-       return getenv (var);
-# else
-# if defined(OS2) || defined(MSDOS)
-       return getenv (var);
-# else
-# if defined(WIN32)
-       return getenv (var);
+  /* evans - 2001-08-26 fixed OS instead of OS2 bug, reported by Alexander Mai */
+# if defined(UNIX) || defined(OS2) || defined(MSDOS) || defined(WIN32)
+  char *val = getenv (cstring_toCharsSafe (var));
+
+  if (val == NULL) 
+    {
+      return cstring_undefined;      
+    } 
+  else 
+    {
+      return cstring_makeLiteralTemp (val);
+    }
 # else
-       return NULL;
-# endif
-# endif
+  return cstring_undefined;
 # endif
 }
 
-# ifndef NOLCL
-
 # ifdef WIN32
 extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
 # endif
@@ -415,7 +460,7 @@ extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
 # ifndef system
 extern /*@external@*/ int system (const char *) /*@modifies fileSystem@*/ ;
 # endif
-int osd_system (const char *cmd)
+int osd_system (cstring cmd)
 {
   int res;
     /* system ("printenv"); */
@@ -423,39 +468,43 @@ int osd_system (const char *cmd)
   (void) _flushall (); 
 # endif
 
-  res = system (cmd);
+  res = system (cstring_toCharsSafe (cmd));
   return res;
 }
-# endif
 
 # ifndef unlink
+/* This should be defined by unistd.h */
 /*@-redecl@*/
 extern /*@external@*/ int unlink (const char *) /*@modifies fileSystem@*/ ;
 /*@=redecl@*/
 # endif
 
-int osd_unlink (const char *fname)
+static s_tempError = FALSE;
+
+void osd_setTempError (void)
+{
+  s_tempError = TRUE;
+}
+
+int osd_unlink (cstring fname)
 {
   int res;
 
-  res = unlink (fname);
+  res = unlink (cstring_toCharsSafe (fname));
 
   if (res != 0)
     {
-      llcontbug (message ("Cannot remove temporary file: %s (%s)",
-                         cstring_fromChars (fname),
-                         cstring_fromChars (strerror (errno))));
+      if (!s_tempError)
+       {
+         llcontbug (message ("Cannot remove temporary file: %s (%s)",
+                             fname,
+                             cstring_fromChars (strerror (errno))));
+       }
     }
   
   return res;
 }
 
-# if defined (WIN32) || (defined(OS2) && defined(__IBMC__))
-# include <process.h>
-# elif defined OS2
-# include <unistd.h>
-# endif
-
 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
 int
 # else
@@ -466,14 +515,16 @@ osd_getPid ()
 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
   int pid = _getpid ();
 # else
-   pid_t pid = getpid ();
+  pid_t pid = getpid ();
 # endif
 
   return (int) pid;
 }
   
-cstring osd_fixDefine (char *x)
+cstring osd_fixDefine (cstring x)
 {
+  /*@access cstring@*/
+  llassert (cstring_isDefined (x));
 # ifdef UNIX
   if (strchr (x, '\'') != NULL) {
     /*
@@ -507,16 +558,17 @@ cstring osd_fixDefine (char *x)
 
 # endif
 
-  return cstring_fromCharsNew (x);
+  return cstring_copy (x);
+  /*@noaccess cstring@*/
 }
 
-bool osd_fileIsReadable (char *f)
+bool osd_fileIsReadable (cstring f)
 {
-  FILE *fl = fopen (f, "r");
+  FILE *fl = fileTable_openReadFile (context_fileTable (), f);
 
-  if (fl != (FILE *) 0)
+  if (fl != NULL)
     {
-      check (fclose (fl) == 0);
+      check (fileTable_closeFile (context_fileTable (), fl));
       return (TRUE);
     }
   else
@@ -542,3 +594,601 @@ bool osd_isConnectChar (char c)
   return FALSE;
 }
 
+/*
+** Returns true if c2 starts with the same path as c1
+**
+** This is called by context_isSystemDir to determine if a
+** directory is on the system path.
+**
+** In unix, this is just a string comparison.  For Win32 and OS2, we need a more
+** complex comparison.
+*/
+
+bool osd_equalCanonicalPrefix (cstring dirpath, cstring prefixpath)
+{
+  llassert (cstring_isDefined (prefixpath));
+
+  if (cstring_isEmpty (dirpath)) 
+    {
+      return (cstring_isEmpty (prefixpath));
+    }
+
+# if defined (WIN32) || defined (OS2)
+
+  /*@access cstring@*/ /* Moved this from cstring - should abstract it... */
+
+  /*
+  ** If one has a drive specification, but the other doesn't, skip it.
+  */
+  
+  if (strchr (dirpath, ':') == NULL
+      && strchr (prefixpath, ':') != NULL)
+    {
+      prefixpath = strchr (prefixpath, ':') + 1;
+    }
+  else 
+    {
+      if (strchr (prefixpath, ':') == NULL
+         && strchr (dirpath, ':') != NULL)
+       {
+         dirpath = strchr (dirpath, ':') + 1;
+       }
+    }
+
+  {
+    int len = size_toInt (strlen (prefixpath));
+    int i = 0;
+    int slen = 0;
+
+    for (i = 0, slen = 0; i < len; i++, slen++)
+      {
+       /* Allow any number of connect characters in any combination:
+        * c:/usr//src\/foo == c:\\usr/src\/foo 
+        * After this we'll be at the last of such a sequence */
+
+       if (osd_isConnectChar (dirpath[slen]) && osd_isConnectChar (prefixpath[i]))
+         {
+           /* Skip one or more connect chars */
+
+           for (; osd_isConnectChar (dirpath[slen+1]); ++slen)
+             {
+               ; 
+             }
+           
+           for (; osd_isConnectChar (prefixpath[i+1]); ++i)
+             {
+               ;
+             }
+         }
+       /* Windows, MSDOS and OS/2 use case-insensitive path specs! */
+       else if (toupper (dirpath[slen]) != toupper (prefixpath[i]))
+         {
+           return FALSE;
+         }
+
+      }
+  }
+
+  /*@noaccess cstring@*/ 
+
+  return TRUE;
+# else
+  return (cstring_equalPrefix (dirpath, prefixpath));
+# endif
+}
+
+# if 0
+/*
+** This code provided by Herbert Martin Dietze, to canonicalize path names.
+*/
+
+char *osd_getcwd (/*@returned@*/ char *str, size_t size)
+{ 
+  return getcwd (str, size);
+}
+
+/*@null@*/ /*@observer@*/ char *
+osd_dirNext (char *str)
+{
+  char *p1 = strchr (str, '/');
+  char *p2 = strchr (str, '\\');
+
+  if (p1 == NULL)
+    {
+      if (p2 != NULL)
+       {
+         return p2 + 1;
+       }
+      else
+       {
+         return NULL;
+       }
+    }
+  else if (p2 == NULL)
+    {
+      return p1 + 1;
+    }
+  else /* both not null */
+    {
+      return (p1 < p2 ? p1 : p2) + 1;
+    }
+}
+
+static void 
+osd_dirShift (char *str, size_t num) /*@modifies str@*/
+{
+  int i;
+  
+  assert (num <= strlen (str));
+  
+  for (i = 0; str[i] != '\0'; i++)
+    {
+      str[i] = str[i + num];
+    }
+}
+
+bool
+osd_dirDotdot (char *str)
+{
+  return str[0] == '.' && str[1] == '.' && osd_isConnectChar (str[2]);
+}
+
+void
+osd_dirNormalize (char *str)
+{
+  char *pos1, *pos2;
+
+  for (; osd_isConnectChar (str[0]); str++)
+    {
+    }
+
+  for (; str != NULL && osd_dirDotdot (str); str = osd_dirNext (str))
+    {
+    }
+
+  for (pos1 = pos2 = str; 
+       pos1 != NULL; 
+       pos2 = pos1, pos1 = osd_dirNext (pos1))
+    {
+      /* remove redundant `./' entry */
+      while (pos1[0] == '.' && osd_isConnectChar (pos1[1]))
+        {
+          osd_dirShift (pos1, 2);
+        }
+
+      /* remove redundant `foo/../' entry */
+      if (osd_dirDotdot (pos1) && pos2 < pos1)
+        {
+          osd_dirShift (pos2, pos1 - pos2 + 1);
+          osd_dirNormalize (str);
+        }
+    }
+}
+
+/*@null@*/ char *
+osd_dirAbsolute (char *str)
+{
+  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));
+      strcpy (ret, str);
+    }
+  else
+    {
+      ret = dmalloc (size);
+      
+      ret = osd_getcwd (ret, size);
+      ret = realloc (ret, (strlen (str) + strlen (ret) + 2) * sizeof (*ret));
+
+      if (ret == NULL)
+        {
+          return NULL;
+        }
+
+      strcat (ret, CONNECTSTR);
+      strcat (ret, str);
+    }
+  
+  osd_dirNormalize (ret);
+  return ret;
+}
+
+# endif
+
+/*
+** absolute paths
+**
+** This code is adapted from:
+**
+** http://src.openresources.com/debian/src/devel/HTML/S/altgcc_2.7.2.2.orig%20altgcc-2.7.2.2.orig%20protoize.c.html#1297
+**
+**
+**  Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com).
+**   Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+**
+** This file is part of GNU CC.
+**
+** GNU CC is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2, or (at your option)
+** any later version.
+**
+** GNU CC is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+** 
+** You should have received a copy of the GNU General Public License
+** along with GNU CC; see the file COPYING.  If not, write to
+** the Free Software Foundation, 59 Temple Place - Suite 330,
+** Boston, MA 02111-1307, USA.  
+*/
+
+/* 
+** Return the absolutized filename for the given relative
+** filename.  Note that if that filename is already absolute, it may
+** still be returned in a modified form because this routine also
+** eliminates redundant slashes and single dots and eliminates double
+** dots to get a shortest possible filename from the given input
+** filename.  The absolutization of relative filenames is made by
+** assuming that the given filename is to be taken as relative to
+** the first argument (cwd) or to the current directory if cwd is
+** NULL.  
+*/
+
+/* A pointer to the current directory filename (used by abspath).  */
+static /*@only@*/ cstring osd_cwd = cstring_undefined;
+
+static void osd_setWorkingDirectory (void)
+{
+# if defined (UNIX) || defined (OS2)
+  char *buf = dmalloc (sizeof (*buf) * MAXPATHLEN);
+  char *cwd = getcwd (buf, MAXPATHLEN);
+
+  llassert (cstring_isUndefined (osd_cwd));
+
+  if (cwd == NULL)
+    {
+      lldiagmsg (message ("Cannot get working directory: %s\n",
+                         lldecodeerror (errno)));
+      osd_cwd = cstring_makeLiteral ("<missing directory>");
+    }
+  else
+    {
+      osd_cwd = cstring_fromCharsNew (cwd);
+    }
+
+  sfree (buf);
+# else
+  ; /* Don't know how to do this for non-POSIX platforms */
+# endif
+}
+
+void osd_initMod (void)
+{
+  osd_setWorkingDirectory ();
+}
+
+void osd_destroyMod (void)
+{
+  cstring_free (osd_cwd);
+  osd_cwd = cstring_undefined;
+}
+
+cstring osd_absolutePath (cstring cwd, cstring filename)
+{
+# if defined (UNIX) || defined (OS2)
+  /* Setup the current working directory as needed.  */
+  cstring cwd2 = cstring_isDefined (cwd) ? cwd : osd_cwd;
+  char *abs_buffer;
+  char *endp, *outp, *inp;
+
+  /*@access cstring@*/
+  llassert (cstring_isDefined (cwd2));
+  llassert (cstring_isDefined (filename));
+
+  abs_buffer = (char *) dmalloc (cstring_length (cwd2) + cstring_length (filename) + 2);
+  endp = abs_buffer;
+  
+  /*
+  ** Copy the  filename (possibly preceded by the current working
+  ** directory name) into the absolutization buffer.  
+  */
+  
+  {
+    const char *src_p;
+
+    if (!osd_isConnectChar (filename[0])
+# ifdef OS2
+       && !(isalpha (filename[0]) && filename[1] == ':')
+# endif
+       )
+      {
+        src_p = cwd2;
+
+        while ((*endp++ = *src_p++) != '\0') 
+         {
+           continue;
+         }
+
+        *(endp-1) = CONNECTCHAR;                        /* overwrite null */
+      }
+
+    src_p = filename;
+
+    while ((*endp++ = *src_p++) != '\0')
+      {
+       continue;
+      }
+  }
+  
+  /* Now make a copy of abs_buffer into abs_buffer, shortening the
+     filename (by taking out slashes and dots) as we go.  */
+  
+  outp = inp = abs_buffer;
+  *outp++ = *inp++;             /* copy first slash */
+#ifdef apollo
+  if (inp[0] == '/')
+    *outp++ = *inp++;           /* copy second slash */
+#endif
+  for (;;)
+    {
+      if (inp[0] == '\0')
+       {
+         break;
+       }
+      else if (osd_isConnectChar (inp[0]) && osd_isConnectChar (outp[-1]))
+       {
+         inp++;
+         continue;
+       }
+      else if (inp[0] == '.' && osd_isConnectChar (outp[-1]))
+       {
+         if (inp[1] == '\0')
+           {
+             break;
+           }
+         else if (osd_isConnectChar (inp[1]))
+           {
+             inp += 2;
+             continue;
+           }
+         else if ((inp[1] == '.') 
+                  && (inp[2] == '\0' || osd_isConnectChar (inp[2])))
+           {
+             inp += (osd_isConnectChar (inp[2])) ? 3 : 2;
+             outp -= 2;
+       
+             while (outp >= abs_buffer && !osd_isConnectChar (*outp))
+               {
+                 outp--;
+               }
+
+             if (outp < abs_buffer)
+               {
+                 /* Catch cases like /.. where we try to backup to a
+                     point above the absolute root of the logical file
+                     system.  */
+                 
+                 llfatalbug (message ("Invalid file name: %s", filename));
+               }
+
+             *++outp = '\0';
+             continue;
+           }
+         else
+           {
+             ;
+           }
+       }
+      else
+       {
+         ;
+       }
+
+      *outp++ = *inp++;
+    }
+  
+  /* On exit, make sure that there is a trailing null, and make sure that
+     the last character of the returned string is *not* a slash.  */
+  
+  *outp = '\0';
+  if (osd_isConnectChar (outp[-1]))
+    *--outp  = '\0';
+  
+  /*@noaccess cstring@*/
+  return cstring_fromChars (abs_buffer);
+# else
+  DPRINTF (("Here: %s", filename));
+  return cstring_copy (filename);
+# endif
+}
+
+/* 
+** Given a filename (and possibly a directory name from which the filename
+** is relative) return a string which is the shortest possible
+** equivalent for the corresponding full (absolutized) filename.  The
+** shortest possible equivalent may be constructed by converting the
+** absolutized filename to be a relative filename (i.e. relative to
+** the actual current working directory).  However if a relative filename
+** 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)
+{
+  /*@i2534 fix this junky code once and for all! */
+# 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 = cstring_length (filename);
+  
+  llassertretval (filename_len > 0, filename);
+
+  /*@access cstring@*/
+  path_p = filename;
+  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);
+
+  while ((*cwd_p != '\0') && (*cwd_p == *path_p))
+    {
+      cwd_p++;
+      path_p++;
+    }
+  
+  if ((*cwd_p == '\0') && (*path_p == '\0' || osd_isConnectChar (*path_p)))  /* whole pwd matched */
+    {
+      if (*path_p == '\0')             /* input *is* the current path! */
+       {
+         cstring_free (rel_buffer);
+         return cstring_makeLiteral (".");
+       }
+      else
+       {
+         /*@i324 ! splint didn't report an errors for: return ++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 >= osd_cwd && !osd_isConnectChar (*cwd_p)) /* backup to last slash */
+            {
+              --cwd_p;
+              --path_p;
+            }
+          cwd_p++;
+          path_p++;
+          unmatched_slash_count++;
+        }
+
+      /* Find out how many directory levels in cwd were *not* matched.  */
+      while (*cwd_p != '\0')
+       {
+         if (osd_isConnectChar (*cwd_p++))
+           unmatched_slash_count++;
+       }
+      
+      /* Now we know how long the "short name" will be.
+         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);
+       }
+
+      /*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.  */
+         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++ = CONNECTCHAR;
+        }
+      
+      /* Then tack on the unmatched part of the desired file's name.  */
+
+      do
+        {
+          if (rel_buffer + filename_len <= rel_buf_p)
+           {
+             cstring_free (rel_buffer);
+             return cstring_copy (filename);
+           }
+        } /*@-usereleased@*/
+      while ((*rel_buf_p++ = *path_p++) != '\0') ;
+
+      
+      /*@=usereleased@*/ /*@i523! shouldn't need these */
+      --rel_buf_p;
+
+      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@*/
+# else
+  return cstring_copy (filename);
+# endif
+}
+
+cstring osd_getCurrentDirectory ()
+{
+# if defined(MSDOS) || defined(OS2)
+  return cstring_makeLiteralTemp ("");
+# else
+  return cstring_makeLiteralTemp ("./");
+# endif
+}
+
+
+
This page took 0.099129 seconds and 4 git commands to generate.