icode comments need space
[fw/sdcc] / src / SDCCutil.c
index 9d8f8f643851089ada349271140ccdd06d699e21..dd42706c221bce10e16725b0a5224b49f0c8623a 100644 (file)
@@ -55,7 +55,7 @@ addToList (const char **list, const char *str)
   /* This is the bad way to do things :) */
   while (*list)
     list++;
-  *list = strdup (str);
+  *list = Safe_strdup (str);
   if (!*list)
     {
       werror (E_OUT_OF_MEM, __FILE__, 0);
@@ -71,18 +71,16 @@ addToList (const char **list, const char *str)
 char *
 join(const char **pplist)
 {
-  char *pinto = buffer;
-  *pinto = '\0';
-
-  while (*pplist)
+    buffer[0] = 0;  
+    
+    while (*pplist)
     {
-      strcpy(pinto, *pplist);
-      pinto += strlen(*pplist);
-      *pinto++ = ' ';
-      pplist++;
+       strncatz(buffer, *pplist, PATH_MAX);
+       strncatz(buffer, " ", PATH_MAX);
+       pplist++;
     }
 
-  return buffer;
+    return buffer;
 }
 
 /** Given an array of string pointers, returns a string containing all
@@ -92,35 +90,124 @@ join(const char **pplist)
 char *
 joinn(char **pplist, int n)
 {
-  char *pinto = buffer;
-  *pinto = '\0';
+    buffer[0] = 0;  
+    
+    while (n--)
+    {
+       strncatz(buffer, *pplist, PATH_MAX);
+       strncatz(buffer, " ", PATH_MAX);
+       pplist++;
+    }
+
+    return buffer;
+}
+
+/** Returns TRUE if for the host the two path characters are
+    equivalent.
+*/
+static bool
+pathCharsEquivalent(char c1, char c2)
+{
+#if NATIVE_WIN32
+  /* win32 is case insensitive */
+  if (tolower(c1) == tolower(c2))
+    {
+      return TRUE;
+    }
+  /* And / is equivalent to \ */
+  else if (c1 == '/' && c2 == '\\')
+    {
+      return TRUE;
+    }
+  else if (c1 == '\\' && c2 == '/')
+    {
+      return TRUE;
+    }
+  else
+    {
+      return FALSE;
+    }
+#else
+  /* Assume a Unix host where they must match exactly. */
+  return c1 == c2;
+#endif
+}
+
+static bool
+pathEquivalent(const char *p1, const char *p2)
+{
+  while (*p1 != '\0' && *p2 != '\0')
+    {
+      if (pathCharsEquivalent (*p1, *p2) == FALSE)
+        {
+          break;
+        }
+      p1++;
+      p2++;
+    }
+
+  return *p1 == *p2;
+}
+
+static char
+pathCharTransform(char c)
+{
+#if NATIVE_WIN32
+  if (c == '/')
+    {
+      return DIR_SEPARATOR_CHAR;
+    }
+  else
+    {
+      return c;
+    }
+#else
+  return c;
+#endif
+}
+
+/** Fixes up a potentially mixed path to the proper representation for
+    the host.  Fixes up in place.
+*/
+static char *
+fixupPath(char *pin)
+{
+  char *p = pin;
 
-  while (n--)
+  while (*p)
     {
-      strcpy(pinto, *pplist);
-      pinto += strlen(*pplist);
-      *pinto++ = ' ';
-      pplist++;
+      *p = pathCharTransform(*p);
+      p++;
     }
-  *pinto = '\0';
+  *p = '\0';
 
-  return buffer;
+  return pin;
 }
 
 /** Returns the characters in p2 past the last matching characters in
     p1.  
 */
 char *
-getStringDifference (char *pinto, const char *p1, const char *p2)
+getPathDifference (char *pinto, const char *p1, const char *p2)
 {
   char *p = pinto;
 
+#if NATIVE_WIN32
+  /* win32 can have a path at the start. */
+  if (strchr(p2, ':'))
+    {
+      p2 = strchr(p2, ':')+1;
+    }
+#endif  
+
   while (*p1 != '\0' && *p2 != '\0')
     {
-      if (*p1++ != *p2++)
+      if (pathCharsEquivalent(*p1, *p2) == FALSE)
         {
           break;
         }
+      p1++;
+      p2++;
     }
   while (*p2)
     {
@@ -128,7 +215,7 @@ getStringDifference (char *pinto, const char *p1, const char *p2)
     }
   *p = '\0';
 
-  return pinto;
+  return fixupPath(pinto);
 }
 
 /** Given a file with path information in the binary files directory,
@@ -139,12 +226,12 @@ getStringDifference (char *pinto, const char *p1, const char *p2)
 char *
 getPrefixFromBinPath (const char *prel)
 {
-  strcpy(scratchFileName, prel);
+  strncpyz(scratchFileName, prel, PATH_MAX);
   /* Strip off the /sdcc at the end */
   *strrchr(scratchFileName, DIR_SEPARATOR_CHAR) = '\0';
   /* Compute what the difference between the prefix and the bin dir
      should be. */
-  getStringDifference (buffer, PREFIX, BINDIR);
+  getPathDifference (buffer, PREFIX, BINDIR);
 
   /* Verify that the path in has the expected suffix */
   if (strlen(buffer) > strlen(scratchFileName))
@@ -152,7 +239,8 @@ getPrefixFromBinPath (const char *prel)
       /* Not long enough */
       return NULL;
     }
-  if (strcmp(buffer, scratchFileName + strlen(scratchFileName) - strlen(buffer)) != 0)
+
+  if (pathEquivalent (buffer, scratchFileName + strlen(scratchFileName) - strlen(buffer)) == FALSE)
     {
       /* Doesn't match */
       return NULL;
@@ -160,7 +248,7 @@ getPrefixFromBinPath (const char *prel)
 
   scratchFileName[strlen(scratchFileName) - strlen(buffer)] = '\0';
 
-  return gc_strdup (scratchFileName);
+  return Safe_strdup (scratchFileName);
 }
 
 /** Returns true if the given path exists.
@@ -178,14 +266,21 @@ static hTab *_mainValues;
 void
 setMainValue (const char *pname, const char *pvalue)
 {
+  assert(pname);
+  assert(pvalue);
+
   shash_add (&_mainValues, pname, pvalue);
 }
 
 void
-buildCmdLine2 (char *pbuffer, const char *pcmd)
+buildCmdLine2 (char *pbuffer, const char *pcmd, size_t len)
 {
-  char *poutcmd = msprintf(_mainValues, pcmd);
-  strcpy(pbuffer, poutcmd);
+  char *poutcmd;
+  assert(pbuffer && pcmd);
+  assert(_mainValues);
+
+  poutcmd = msprintf(_mainValues, pcmd);
+  strncpyz(pbuffer, poutcmd, len);
 }
 
 void
@@ -194,15 +289,6 @@ populateMainValues (const char **ppin)
   _mainValues = populateStringHash(ppin);
 }
 
-char *
-gc_strdup (const char *s)
-{
-  char *ret;
-  ret = Safe_calloc (1, strlen (s) + 1);
-  strcpy (ret, s);
-  return ret;
-}
-
 /** Returns true if sz starts with the string given in key.
  */
 bool
@@ -222,3 +308,82 @@ chomp (char *sz)
     *nl = '\0';
 }
 
+hTab *
+getRuntimeVariables(void)
+{
+  return _mainValues;
+}
+
+
+/* strncpy() with guaranteed NULL termination. */
+char *strncpyz(char *dest, const char *src, size_t n)
+{
+    assert(n > 0);
+    
+    // paranoia...
+    if (strlen(src) >= n)
+    {
+       fprintf(stderr, "strncpyz prevented buffer overrun!\n");
+    }
+    
+    strncpy(dest, src, n);
+    dest[n - 1] = 0;
+    return dest;
+}
+
+/* like strncat() with guaranteed NULL termination
+ * The passed size should be the size of the dest buffer, not the number of 
+ * bytes to copy.
+ */
+char *strncatz(char *dest, const char *src, size_t n)
+{
+    size_t maxToCopy;
+    size_t destLen = strlen(dest);
+    
+    assert(n > 0);
+    assert(n > destLen);
+    
+    maxToCopy = n - destLen - 1;
+    
+    // paranoia...
+    if (strlen(src) + destLen >= n)
+    {
+       fprintf(stderr, "strncatz prevented buffer overrun!\n");
+    }
+    
+    strncat(dest, src, maxToCopy);
+    dest[n - 1] = 0;
+    return dest;
+}
+
+
+#if defined(HAVE_VSNPRINTF) || defined(have_VSPRINTF)
+size_t SDCCsnprintf(char *dst, size_t n, const char *fmt, ...)
+{
+    va_list args;
+    int  len;
+    
+    va_start(args, fmt);
+    
+# if defined(HAVE_VSNPRINTF)    
+    len = vsnprintf(dst, n, fmt, args);
+# else
+    vsprintf(dst, fmt, args);
+    len = strlen(dst) + 1;
+# endif    
+    
+    va_end(args);
+    
+    /* on some gnu systems, vsnprintf returns -1 if output is truncated.
+     * In the C99 spec, vsnprintf returns the number of characters that 
+     * would have been written, were space available.
+     */
+    if ((len < 0) || len >= n)
+    {
+       fprintf(stderr, "internal error: sprintf truncated.\n");
+    }
+    
+    return len;
+}
+
+#endif