Use 'ao-dbg' instead of 's51' to communicate with TeleMetrum
[fw/sdcc] / src / SDCCutil.c
index 3cd6a0c8b8c7b9c515444c6f23b1ad794bd33f92..c3880127f82741ec8c13b22862f905a8366f9eb4 100644 (file)
    what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
-#include "common.h"
+#include <math.h>
+#include <ctype.h>
+
+#ifdef _WIN32
+#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>
+#include "dbuf_string.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,190 +58,217 @@ 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 = Safe_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)
 {
-    buffer[0] = 0;  
-    
-    while (*pplist)
-    {
-       strncatz(buffer, *pplist, PATH_MAX);
-       strncatz(buffer, " ", PATH_MAX);
-       pplist++;
-    }
+  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_str(&dbuf, pre);
+    dbuf_append_str(&dbuf, item);
+    if (post != NULL)
+      dbuf_append_str(&dbuf, post);
+
+    /* null terminate the buffer */
+    dbuf_c_str(&dbuf);
+    addSet(&new_list, dbuf_detach(&dbuf));
+  }
 
-    return buffer;
+  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)
 {
-    buffer[0] = 0;  
-    
-    while (n--)
-    {
-       strncatz(buffer, *pplist, PATH_MAX);
-       strncatz(buffer, " ", PATH_MAX);
-       pplist++;
-    }
+  const char *s;
+  struct dbuf_s dbuf;
 
-    return buffer;
-}
+  dbuf_init(&dbuf, PATH_MAX);
 
-/** 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))
+  for (s = setFirstItem(list); s != NULL; s = setNextItem(list))
     {
-      return TRUE;
+      dbuf_append_str(&dbuf, s);
+      dbuf_append_char(&dbuf, ' ');
     }
-  /* 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
+
+  s = dbuf_c_str(&dbuf);
+  dbuf_detach(&dbuf);
+  return s;
 }
 
-static char
-pathCharTransform(char c)
+/** Split the path string to the directory and file name (including extension) components.
+    The directory component doesn't contain trailing directory separator.
+    Returns true if the path contains the directory separator. */
+int
+dbuf_splitPath(const char *path, struct dbuf_s *dir, struct dbuf_s *file)
 {
-#if NATIVE_WIN32
-  if (c == '/')
+  const char *p;
+  int ret;
+  const char *end = &path[strlen(path)];
+
+  for (p = end - 1; p >= path && !IS_DIR_SEPARATOR(*p); --p)
+    ;
+
+  ret = p >= path;
+
+  if (NULL != dir)
     {
-      return DIR_SEPARATOR_CHAR;
+      int len = p - path;
+
+      if (0 < len)
+        dbuf_append(dir, path, len);
     }
-  else
+
+  if (NULL != file)
     {
-      return c;
-    }
-#else
-  return c;
-#endif
-}
+      int len;
 
-/** 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;
+      ++p;
+      len = end - p;
 
-  while (*p)
-    {
-      *p = pathCharTransform(*p);
-      p++;
+      if (0 < len)
+        dbuf_append(file, p, len);
     }
-  *p = '\0';
 
-  return pin;
+  return ret;
 }
 
-/** Returns the characters in p2 past the last matching characters in
-    p1.  
-*/
-char *
-getPathDifference (char *pinto, const char *p1, const char *p2)
+/** Split the path string to the file name (including directory) and file extension components.
+    File extension component contains the extension separator.
+    Returns true if the path contains the extension separator. */
+int
+dbuf_splitFile(const char *path, struct dbuf_s *file, struct dbuf_s *ext)
 {
-  char *p = pinto;
+  const char *p;
+  const char *end = &path[strlen(path)];
+
+  for (p = end - 1; p >= path && !IS_DIR_SEPARATOR(*p) && '.' != *p; --p)
+    ;
 
-#if NATIVE_WIN32
-  /* win32 can have a path at the start. */
-  if (strchr(p2, ':'))
+  if (p < path || '.' != *p)
     {
-      p2 = strchr(p2, ':')+1;
-    }
-#endif  
+      dbuf_append_str(file, path);
 
-  while (*p1 != '\0' && *p2 != '\0')
+      return 0;
+    }
+  else
     {
-      if (pathCharsEquivalent(*p1, *p2) == FALSE)
+      if (NULL != file)
         {
-          break;
+          int len = p - path;
+
+          if (0 < len)
+            dbuf_append(file, path, len);
         }
-      p1++;
-      p2++;
-    }
-  while (*p2)
-    {
-      *p++ = *p2++;
-    }
-  *p = '\0';
 
-  return fixupPath(pinto);
+      if (NULL != ext)
+        {
+          int len = end - p;
+
+          if (0 < len)
+            dbuf_append(ext, p, len);
+        }
+
+      return 1;
+    }
 }
 
+/** Combine directory and the file name to a path string using the DIR_SEPARATOR_CHAR.
+ */
+void
+dbuf_makePath(struct dbuf_s *path,const char *dir, const char *file)
+{
+  if (dir != NULL)
+    dbuf_append_str(path, dir);
+  
+  dbuf_append_char(path, DIR_SEPARATOR_CHAR);
+
+  if (file != NULL)
+    dbuf_append_str(path, file);
+}
 
 /** 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.
 */
-char *
+#ifdef _WIN32
+const char *
 getBinPath(const char *prel)
 {
-  char *p;
-  size_t len;
-  static char path[PATH_MAX];
-    
-  if ((p = strrchr(prel, DIR_SEPARATOR_CHAR)) == NULL)
-#ifdef _WIN32
-    /* try *nix dir separator on WIN32 */
-    if ((p = strrchr(prel, UNIX_DIR_SEPARATOR_CHAR)) == NULL)
-#endif
-      return NULL;
+  struct dbuf_s path;
+  const char *p;
+
+  dbuf_init(&path, 128);
+  dbuf_splitPath(prel, &path, NULL);
+
+  p = dbuf_c_str(&path);
+  if ('\0' != *p)
+    return p;
+  else
+    {
+      char module[PATH_MAX];
 
-  len = min((sizeof path) - 1, p - prel);
-  strncpy(path, prel, len);
-  path[len] = '\0';
+      dbuf_destroy(&path);
 
-  return path;
+      /* not enough info in prel; do it with module name */
+      if (0 != GetModuleFileName(NULL, module, sizeof (module)))
+        {
+          dbuf_init(&path, 128);
+
+          dbuf_splitPath(module, &path, NULL);
+          dbuf_c_str(&path);
+          return dbuf_detach(&path);
+        }
+      else
+        return NULL;
+    }
 }
+#else
+const char *
+getBinPath(const char *prel)
+{
+  const char *ret_path;
+
+  if (NULL != (ret_path = findProgramPath(prel)))
+    {
+      struct dbuf_s path;
 
+      dbuf_init(&path, 128);
+
+      dbuf_splitPath(ret_path, &path, NULL);
+      free((void *)ret_path);
+      dbuf_c_str(&path);
+      return dbuf_detach(&path);
+    }
+  else
+    return NULL;
+}
+#endif
 
 /** Returns true if the given path exists.
  */
@@ -251,14 +291,22 @@ setMainValue (const char *pname, const char *pvalue)
 }
 
 void
-buildCmdLine2 (char *pbuffer, const char *pcmd, size_t len)
+buildCmdLine2 (char *pbuffer, size_t len, const char *pcmd, ...)
 {
+  va_list ap;
   char *poutcmd;
+
   assert(pbuffer && pcmd);
   assert(_mainValues);
 
-  poutcmd = msprintf(_mainValues, pcmd);
+  va_start(ap, pcmd);
+
+  poutcmd = mvsprintf(_mainValues, pcmd, ap);
+
+  va_end(ap);
+
   strncpyz(pbuffer, poutcmd, len);
+  Safe_free(poutcmd);
 }
 
 void
@@ -299,7 +347,7 @@ char *strncpyz(char *dest, const char *src, size_t n)
     assert(n > 0);
 
     --n;
-    // paranoia...
+    /* paranoia... */
     if (strlen(src) > n)
     {
        fprintf(stderr, "strncpyz prevented buffer overrun!\n");
@@ -324,10 +372,10 @@ char *strncatz(char *dest, const char *src, size_t n)
     
     maxToCopy = n - destLen - 1;
     
-    // paranoia...
+    /* paranoia... */
     if (strlen(src) + destLen >= n)
     {
-       fprintf(stderr, "strncatz prevented buffer overrun!\n");
+        fprintf(stderr, "strncatz prevented buffer overrun!\n");
     }
     
     strncat(dest, src, maxToCopy);
@@ -335,6 +383,47 @@ char *strncatz(char *dest, const char *src, size_t n)
     return dest;
 }
 
+/*-----------------------------------------------------------------*/
+/* getBuildNumber - return build number                            */
+/*-----------------------------------------------------------------*/
+const char *getBuildNumber(void)
+{
+  return (SDCC_BUILD_NUMBER);
+}
+
+/*-----------------------------------------------------------------*/
+/* getBuildDate - return build date                                */
+/*-----------------------------------------------------------------*/
+const char *getBuildDate(void)
+{
+  return (__DATE__);
+}
+
+/*-----------------------------------------------------------------*/
+/* getBuildEnvironment - return environment used to build SDCC     */
+/*-----------------------------------------------------------------*/
+const char *getBuildEnvironment(void)
+{
+#ifdef __CYGWIN__
+  return "CYGWIN";
+#elif defined __MINGW32__
+  return "MINGW32";
+#elif defined __DJGPP__
+  return "DJGPP";
+#elif defined(_MSC_VER)
+  return "MSVC";
+#elif defined(__BORLANDC__)
+  return "BORLANDC";
+#elif defined(__APPLE__)
+# if defined(__i386__)
+  return "Mac OS X i386";
+# else
+  return "Mac OS X ppc";
+#endif
+#else
+  return "UNIX";
+#endif
+}
 
 #if defined(HAVE_VSNPRINTF) || defined(HAVE_VSPRINTF)
 size_t SDCCsnprintf(char *dst, size_t n, const char *fmt, ...)
@@ -363,5 +452,223 @@ size_t SDCCsnprintf(char *dst, size_t n, const char *fmt, ...)
 
   return len;
 }
-
 #endif
+
+/** Pragma tokenizer
+ */
+void
+init_pragma_token(struct pragma_token_s *token)
+{
+  dbuf_init(&token->dbuf, 16);
+  token->type = TOKEN_UNKNOWN;
+}
+
+char *
+get_pragma_token(const char *s, struct pragma_token_s *token)
+{
+  dbuf_set_length(&token->dbuf, 0);
+
+  /* skip leading spaces */
+  while ('\n' != *s && isspace(*s))
+    ++s;
+
+  if ('\0' == *s || '\n' == *s)
+    {
+      token->type = TOKEN_EOL;
+    }
+  else
+    {
+      char *end;
+
+      long val = strtol(s, &end, 0);
+
+      if (end != s && ('\0' == *end || isspace(*end)))
+        {
+          token->val.int_val = val;
+          token->type = TOKEN_INT;
+          dbuf_append(&token->dbuf, s, end - s);
+          s = end;
+        }
+      else
+        {
+          while ('\0' != *s && !isspace(*s))
+            {
+              dbuf_append_char(&token->dbuf, *s);
+              ++s;
+            }
+
+          token->type = TOKEN_STR;
+        }
+    }
+
+  return (char *)s;
+}
+
+const char *
+get_pragma_string(struct pragma_token_s *token)
+{
+  return dbuf_c_str(&token->dbuf);
+}
+
+void
+free_pragma_token(struct pragma_token_s *token)
+{
+  dbuf_destroy(&token->dbuf);
+}
+
+/*! /fn char hexEscape(char **src)
+
+    /param src Pointer to 'x' from start of hex character value
+*/
+
+unsigned char
+hexEscape (const char **src)
+{
+  char *s ;
+  unsigned long value ;
+
+  (*src)++ ;    /* Skip over the 'x' */
+
+  value = strtol (*src, &s, 16);
+
+  if (s == *src)
+    {
+      // no valid hex found
+      werror(E_INVALID_HEX);
+    }
+  else
+    {
+      if (value > 255)
+        {
+          werror(W_ESC_SEQ_OOR_FOR_CHAR);
+        }
+    }
+  *src = s;
+
+  return (char) value;
+}
+
+/*------------------------------------------------------------------*/
+/* octalEscape - process an octal constant of max three digits      */
+/* return the octal value, throw a warning for illegal octal        */
+/* adjust src to point at the last proccesed char                   */
+/*------------------------------------------------------------------*/
+
+unsigned char
+octalEscape (const char **str)
+{
+  int digits;
+  unsigned value=0;
+
+  for (digits = 0; digits < 3; digits++)
+    {
+      if (**str >='0' && **str <= '7')
+        {
+          value = value*8 + (**str - '0');
+          (*str)++;
+        }
+      else
+        {
+          break;
+        }
+    }
+  if (digits)
+    {
+      if (value > 255 /* || (**str>='0' && **str<='7') */ )
+        {
+          werror (W_ESC_SEQ_OOR_FOR_CHAR);
+        }
+    }
+  return value;
+}
+
+/*!
+  /fn int copyStr (char *dest, char *src)
+
+  Copies a source string to a dest buffer interpreting escape sequences
+  and special characters
+
+  /param dest Buffer to receive the resultant string
+  /param src  Buffer containing the source string with escape sequecnes
+  /return Number of characters in output string
+
+*/
+
+int
+copyStr (char *dest, const char *src)
+{
+  char *OriginalDest = dest ;
+
+  while (*src)
+    {
+      if (*src == '\"')
+        src++;
+      else if (*src == '\\')
+        {
+          src++;
+          switch (*src)
+            {
+            case 'n':
+              *dest++ = '\n';
+              break;
+            case 't':
+              *dest++ = '\t';
+              break;
+            case 'v':
+              *dest++ = '\v';
+              break;
+            case 'b':
+              *dest++ = '\b';
+              break;
+            case 'r':
+              *dest++ = '\r';
+              break;
+            case 'f':
+              *dest++ = '\f';
+              break;
+            case 'a':
+              *dest++ = '\a';
+              break;
+
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+              *dest++ = octalEscape(&src);
+              src-- ;
+              break;
+
+            case 'x':
+              *dest++ = hexEscape(&src) ;
+              src-- ;
+              break ;
+
+            case '\\':
+              *dest++ = '\\';
+              break;
+            case '\?':
+              *dest++ = '\?';
+              break;
+            case '\'':
+              *dest++ = '\'';
+              break;
+            case '\"':
+              *dest++ = '\"';
+              break;
+            default:
+              *dest++ = *src;
+            }
+          src++;
+        }
+      else
+        *dest++ = *src++;
+    }
+
+  *dest++ = '\0';
+
+  return dest - OriginalDest ;
+}