* as/hc08/lkaomf51.c (OutputName),
[fw/sdcc] / src / SDCCutil.c
index edbe8e6e7fc15869fbb306e66262c81d0e5c7e7f..da0223f6f6b67c36715ac3f119ed2a4fefffd4d0 100644 (file)
    what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
-#include "common.h"
+#include <math.h>
+
+#ifdef _WIN32
+#include <ctype.h>
+#include <windows.h>
+#endif
+#include <sys/stat.h>
+#include "dbuf.h"
+#include "SDCCglobl.h"
 #include "SDCCmacro.h"
 #include "SDCCutil.h"
 #include "newalloc.h"
-#include <sys/stat.h>
+#ifndef _WIN32
+#include "findme.h"
+#endif
+
+#include "version.h"
 
 /** Given an array of name, value string pairs creates a new hash
     containing all of the pairs.
@@ -45,216 +57,124 @@ populateStringHash(const char **pin)
   return pret;
 }
 
-/** Given an array of string pointers and another string, adds the
-    string to the end of the list.  The end of the list is assumed to
-    be the first NULL pointer.
+/** Prints elements of the set to the file, each element on new line
 */
 void
-addToList (const char **list, const char *str)
+fputStrSet(FILE *fp, set *list)
 {
-  /* This is the bad way to do things :) */
-  while (*list)
-    list++;
-  *list = strdup (str);
-  if (!*list)
-    {
-      werror (E_OUT_OF_MEM, __FILE__, 0);
-      exit (1);
-    }
-  *(++list) = NULL;
+  const char *s;
+
+  for (s = setFirstItem(list); s != NULL; s = setNextItem(list)) {
+    fputs(s, fp);
+    fputc('\n', fp);
+  }
 }
 
-/** Given an array of string pointers returns a string containing all
-    of the strings seperated by spaces.  The returned string is on the
-    heap.  The join stops when a NULL pointer is hit.
+/** Prepend / append given strings to each item of string set. The result is in a
+    new string set.
 */
-char *
-join(const char **pplist)
+set *
+appendStrSet(set *list, const char *pre, const char *post)
 {
-  char *pinto = buffer;
-  *pinto = '\0';
-
-  while (*pplist)
-    {
-      strcpy(pinto, *pplist);
-      pinto += strlen(*pplist);
-      *pinto++ = ' ';
-      pplist++;
-    }
-
-  return buffer;
+  set *new_list = NULL;
+  const char *item;
+  struct dbuf_s dbuf;
+
+  for (item = setFirstItem(list); item != NULL; item = setNextItem(list)) {
+    dbuf_init(&dbuf, PATH_MAX);
+    if (pre != NULL)
+      dbuf_append(&dbuf, pre, strlen(pre));
+    dbuf_append(&dbuf, item, strlen(item));
+    if (post != NULL)
+      dbuf_append(&dbuf, post, strlen(post));
+    addSet(&new_list, (void *)dbuf_c_str(&dbuf));
+    dbuf_detach(&dbuf);
+  }
+
+  return new_list;
 }
 
-/** Given an array of string pointers, returns a string containing all
-    of the strings seperated by spaces.  The returned string is on the
-    heap.  n is the number of strings in the list.
+/** Given a set returns a string containing all of the strings seperated
+    by spaces. The returned string is on the heap.
 */
-char *
-joinn(char **pplist, int n)
+const char *
+joinStrSet(set *list)
 {
-  char *pinto = buffer;
-  *pinto = '\0';
+  const char *s;
+  struct dbuf_s dbuf;
 
-  while (n--)
+  dbuf_init(&dbuf, PATH_MAX);
+
+  for (s = setFirstItem(list); s != NULL; s = setNextItem(list))
     {
-      strcpy(pinto, *pplist);
-      pinto += strlen(*pplist);
-      *pinto++ = ' ';
-      pplist++;
+      dbuf_append(&dbuf, s, strlen(s));
+      dbuf_append(&dbuf, " ", 1);
     }
-  *pinto = '\0';
 
-  return buffer;
+  s = dbuf_c_str(&dbuf);
+  dbuf_detach(&dbuf);
+  return s;
 }
 
-/** Returns TRUE if for the host the two path characters are
-    equivalent.
+/** Given a file with path information in the binary files directory,
+    returns the directory component. Used for discovery of bin
+    directory of SDCC installation. Returns NULL if the path is
+    impossible.
 */
-static bool
-pathCharsEquivalent(char c1, char c2)
+#ifdef _WIN32
+char *
+getBinPath(const char *prel)
 {
-#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;
-    }
+  char *p;
+  size_t len;
+  static char path[PATH_MAX];
+    
+  /* try DOS and *nix dir separator on WIN32 */
+  if (NULL != (p = strrchr(prel, DIR_SEPARATOR_CHAR)) ||
+    NULL != (p = strrchr(prel, UNIX_DIR_SEPARATOR_CHAR))) {
+    len = min((sizeof path) - 1, p - prel);
+    strncpy(path, prel, len);
+    path[len] = '\0';
+    return path;
+  }
+  /* not enough info in prel; do it with module name */
+  else if (0 != GetModuleFileName(NULL, path, sizeof path) &&
+    NULL != (p = strrchr(path, DIR_SEPARATOR_CHAR))) {
+    *p = '\0';
+    return path;
+  }
   else
-    {
-      return FALSE;
-    }
-#else
-  /* Assume a Unix host where they must match exactly. */
-  return c1 == c2;
-#endif
+    return NULL;
 }
-
-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 (*p)
-    {
-      *p = pathCharTransform(*p);
-      p++;
-    }
-  *p = '\0';
-
-  return pin;
-}
-
-/** Returns the characters in p2 past the last matching characters in
-    p1.  
-*/
 char *
-getPathDifference (char *pinto, const char *p1, const char *p2)
+getBinPath(const char *prel)
 {
-  char *p = pinto;
-
-#if NATIVE_WIN32
-  /* win32 can have a path at the start. */
-  if (strchr(p2, ':'))
-    {
-      p2 = strchr(p2, ':')+1;
-    }
-#endif  
+  static char path[PATH_MAX];
+  const char *ret_path;
 
-  while (*p1 != '\0' && *p2 != '\0')
-    {
-      if (pathCharsEquivalent(*p1, *p2) == FALSE)
-        {
-          break;
-        }
-      p1++;
-      p2++;
-    }
-  while (*p2)
-    {
-      *p++ = *p2++;
-    }
-  *p = '\0';
+  if (NULL != (ret_path = findProgramPath(prel))) {
+    char *p;
+    size_t len;
 
-  return fixupPath(pinto);
-}
+    if (NULL != (p = strrchr(ret_path, DIR_SEPARATOR_CHAR)) &&
+      PATH_MAX > (len = p - ret_path)) {
+      memcpy(path, ret_path, len);
+      path[len] = '\0';
+      free((void *)ret_path);
 
-/** Given a file with path information in the binary files directory,
-    returns what PREFIX must be to get this path.  Used for discovery
-    of where SDCC is installed.  Returns NULL if the path is
-    impossible.
-*/
-char *
-getPrefixFromBinPath (const char *prel)
-{
-  strcpy(scratchFileName, prel);
-  /* 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. */
-  getPathDifference (buffer, PREFIX, BINDIR);
-
-  /* Verify that the path in has the expected suffix */
-  if (strlen(buffer) > strlen(scratchFileName))
-    {
-      /* Not long enough */
-      return NULL;
+      return path;
     }
+    else {
+      free((void *)ret_path);
 
-  if (pathEquivalent (buffer, scratchFileName + strlen(scratchFileName) - strlen(buffer)) == FALSE)
-    {
-      /* Doesn't match */
       return NULL;
     }
-
-  scratchFileName[strlen(scratchFileName) - strlen(buffer)] = '\0';
-
-  return gc_strdup (scratchFileName);
+  }
+  else
+    return NULL;
 }
+#endif
 
 /** Returns true if the given path exists.
  */
@@ -271,14 +191,28 @@ static hTab *_mainValues;
 void
 setMainValue (const char *pname, const char *pvalue)
 {
+  assert(pname);
+
   shash_add (&_mainValues, pname, pvalue);
 }
 
 void
-buildCmdLine2 (char *pbuffer, const char *pcmd)
+buildCmdLine2 (char *pbuffer, size_t len, const char *pcmd, ...)
 {
-  char *poutcmd = msprintf(_mainValues, pcmd);
-  strcpy(pbuffer, poutcmd);
+  va_list ap;
+  char *poutcmd;
+
+  assert(pbuffer && pcmd);
+  assert(_mainValues);
+
+  va_start(ap, pcmd);
+
+  poutcmd = mvsprintf(_mainValues, pcmd, ap);
+
+  va_end(ap);
+
+  strncpyz(pbuffer, poutcmd, len);
+  Safe_free(poutcmd);
 }
 
 void
@@ -287,15 +221,6 @@ populateMainValues (const char **ppin)
   _mainValues = populateStringHash(ppin);
 }
 
-char *
-gc_strdup (const char *s)
-{
-  char *ret;
-  ret = Safe_alloc ( strlen (s) + 1);
-  strcpy (ret, s);
-  return ret;
-}
-
 /** Returns true if sz starts with the string given in key.
  */
 bool
@@ -315,3 +240,90 @@ 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);
+
+    --n;
+    /* paranoia... */
+    if (strlen(src) > n)
+    {
+       fprintf(stderr, "strncpyz prevented buffer overrun!\n");
+    }
+    
+    strncpy(dest, src, n);
+    dest[n] = 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;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* getBuildNumber - return build number                            */
+/*-----------------------------------------------------------------*/
+const char *getBuildNumber(void)
+{
+  return (SDCC_BUILD_NUMBER);
+}
+
+#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) || (size_t) len >= n) {
+    fprintf(stderr, "internal error: sprintf truncated.\n");
+  }
+
+  return len;
+}
+
+#endif