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.
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);
- return buffer;
+ /* null terminate the buffer */
+ dbuf_c_str(&dbuf);
+ addSet(&new_list, 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)
{
- buffer[0] = 0;
-
- while (n--)
+ const char *s;
+ struct dbuf_s dbuf;
+
+ dbuf_init(&dbuf, PATH_MAX);
+
+ for (s = setFirstItem(list); s != NULL; s = setNextItem(list))
{
- strncatz(buffer, *pplist, PATH_MAX);
- strncatz(buffer, " ", PATH_MAX);
- pplist++;
+ dbuf_append_str(&dbuf, s);
+ dbuf_append_char(&dbuf, ' ');
}
- return buffer;
+ s = dbuf_c_str(&dbuf);
+ dbuf_detach(&dbuf);
+ return s;
}
-/** Returns TRUE if for the host the two path characters are
- equivalent.
-*/
-static bool
-pathCharsEquivalent(char c1, char c2)
+/** 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
- /* 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
+ 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 FALSE;
+ int len = p - path;
+
+ if (0 < len)
+ dbuf_append(dir, path, len);
}
-#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 (NULL != file)
{
- if (pathCharsEquivalent (*p1, *p2) == FALSE)
- {
- break;
- }
- p1++;
- p2++;
+ int len;
+
+ ++p;
+ len = end - p;
+
+ if (0 < len)
+ dbuf_append(file, p, len);
}
- return *p1 == *p2;
+ return ret;
}
-static char
-pathCharTransform(char c)
+/** 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)
{
-#if NATIVE_WIN32
- if (c == '/')
+ const char *p;
+ const char *end = &path[strlen(path)];
+
+ for (p = end - 1; p >= path && !IS_DIR_SEPARATOR(*p) && '.' != *p; --p)
+ ;
+
+ if (p < path || '.' != *p)
{
- return DIR_SEPARATOR_CHAR;
+ dbuf_append_str(file, path);
+
+ return 0;
}
else
{
- return c;
+ if (NULL != file)
+ {
+ int len = p - path;
+
+ if (0 < len)
+ dbuf_append(file, path, len);
+ }
+
+ if (NULL != ext)
+ {
+ int len = end - p;
+
+ if (0 < len)
+ dbuf_append(ext, p, len);
+ }
+
+ return 1;
}
-#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)
+/** 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)
{
- char *p = pin;
-
- while (*p)
- {
- *p = pathCharTransform(*p);
- p++;
- }
- *p = '\0';
+ if (dir != NULL)
+ dbuf_append_str(path, dir);
+
+ dbuf_append_char(path, DIR_SEPARATOR_CHAR);
- return pin;
+ if (file != NULL)
+ dbuf_append_str(path, file);
}
-/** Returns the characters in p2 past the last matching characters in
- p1.
+/** 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 *
-getPathDifference (char *pinto, const char *p1, const char *p2)
+#ifdef _WIN32
+const char *
+getBinPath(const char *prel)
{
- char *p = pinto;
+ struct dbuf_s path;
+ const char *p;
-#if NATIVE_WIN32
- /* win32 can have a path at the start. */
- if (strchr(p2, ':'))
- {
- p2 = strchr(p2, ':')+1;
- }
-#endif
+ dbuf_init(&path, 128);
+ dbuf_splitPath(prel, &path, NULL);
- while (*p1 != '\0' && *p2 != '\0')
+ p = dbuf_c_str(&path);
+ if ('\0' != *p)
+ return p;
+ else
{
- if (pathCharsEquivalent(*p1, *p2) == FALSE)
+ char module[PATH_MAX];
+
+ dbuf_destroy(&path);
+
+ /* not enough info in prel; do it with module name */
+ if (0 != GetModuleFileName(NULL, module, sizeof (module)))
{
- break;
+ dbuf_init(&path, 128);
+
+ dbuf_splitPath(module, &path, NULL);
+ dbuf_c_str(&path);
+ return dbuf_detach(&path);
}
- p1++;
- p2++;
- }
- while (*p2)
- {
- *p++ = *p2++;
+ else
+ return NULL;
}
- *p = '\0';
-
- return fixupPath(pinto);
}
-
-/** 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)
+#else
+const char *
+getBinPath(const char *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. */
- getPathDifference (buffer, PREFIX, BINDIR);
-
- /* Verify that the path in has the expected suffix */
- if (strlen(buffer) > strlen(scratchFileName))
- {
- /* Not long enough */
- return NULL;
- }
+ const char *ret_path;
- if (pathEquivalent (buffer, scratchFileName + strlen(scratchFileName) - strlen(buffer)) == FALSE)
+ if (NULL != (ret_path = findProgramPath(prel)))
{
- /* Doesn't match */
- return NULL;
- }
+ struct dbuf_s path;
- scratchFileName[strlen(scratchFileName) - strlen(buffer)] = '\0';
+ dbuf_init(&path, 128);
- return Safe_strdup (scratchFileName);
+ 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.
*/
setMainValue (const char *pname, const char *pvalue)
{
assert(pname);
- assert(pvalue);
shash_add (&_mainValues, pname, 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
char *strncpyz(char *dest, const char *src, size_t n)
{
assert(n > 0);
-
- // paranoia...
- if (strlen(src) >= n)
+
+ --n;
+ /* paranoia... */
+ if (strlen(src) > n)
{
fprintf(stderr, "strncpyz prevented buffer overrun!\n");
}
strncpy(dest, src, n);
- dest[n - 1] = 0;
+ dest[n] = 0;
return dest;
}
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);
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)
+#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);
+ 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)
+ 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
+
+/** 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)
{
- fprintf(stderr, "internal error: sprintf truncated.\n");
+ token->type = TOKEN_EOL;
}
-
- return len;
+ 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;
}
-#endif
+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 ;
+}