X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCutil.c;h=c3880127f82741ec8c13b22862f905a8366f9eb4;hb=HEAD;hp=3cd6a0c8b8c7b9c515444c6f23b1ad794bd33f92;hpb=72cf40557bdf2e62a452a851d2ba115149b57ba3;p=fw%2Fsdcc diff --git a/src/SDCCutil.c b/src/SDCCutil.c index 3cd6a0c8..c3880127 100644 --- a/src/SDCCutil.c +++ b/src/SDCCutil.c @@ -22,11 +22,24 @@ what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ -#include "common.h" +#include +#include + +#ifdef _WIN32 +#include +#endif +#include +#include "dbuf.h" +#include "SDCCglobl.h" #include "SDCCmacro.h" #include "SDCCutil.h" #include "newalloc.h" -#include +#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 ; +}