X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCutil.c;h=b5ce4b302c5c097d0dee0d07ca17c27651f63a43;hb=3062f96ccb55d1d05caf9c8782f4961f87b341ce;hp=5a3be477c7fa7f8c50ed85d0266fa296025571e4;hpb=2f566bab0a5fe0bf025d6c892d6fc309966618f1;p=fw%2Fsdcc diff --git a/src/SDCCutil.c b/src/SDCCutil.c index 5a3be477..b5ce4b30 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,123 +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 = 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'; + 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 new_list; +} + +/** Given a set returns a string containing all of the strings seperated + by spaces. The returned string is on the heap. +*/ +const char * +joinStrSet(set *list) +{ + const char *s; + struct dbuf_s dbuf; + + dbuf_init(&dbuf, PATH_MAX); - while (*pplist) + for (s = setFirstItem(list); s != NULL; s = setNextItem(list)) { - strcpy(pinto, *pplist); - pinto += strlen(*pplist); - *pinto++ = ' '; - pplist++; + dbuf_append_str(&dbuf, s); + dbuf_append_char(&dbuf, ' '); } - return buffer; + s = dbuf_c_str(&dbuf); + dbuf_detach(&dbuf); + return s; } -/** 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. -*/ -char * -joinn(char **pplist, int n) +/** 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) { - char *pinto = buffer; - *pinto = '\0'; + 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) + { + int len = p - path; + + if (0 < len) + dbuf_append(dir, path, len); + } - while (n--) + if (NULL != file) { - strcpy(pinto, *pplist); - pinto += strlen(*pplist); - *pinto++ = ' '; - pplist++; + int len; + + ++p; + len = end - p; + + if (0 < len) + dbuf_append(file, p, len); } - *pinto = '\0'; - return buffer; + return ret; } -/** Returns the characters in p2 past the last matching characters in - p1. -*/ -char * -getStringDifference (char *pinto, const char *p1, const char *p2) +/** Split the path string to the file name (including directory) and file extension components. + The file name component doesn't contain trailing 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) + ; - while (*p1 != '\0' && *p2 != '\0') + if (p < path || '.' != *p) { - if (*p1++ != *p2++) - { - break; - } + dbuf_append_str(file, path); + + return 0; } - while (*p2) + else { - *p++ = *p2++; + if (NULL != file) + { + int len = p - path; + + if (0 < len) + dbuf_append(file, path, len); + } + + if (NULL != ext) + { + int len; + + ++p; + len = end - p; + + if (0 < len) + dbuf_append(ext, p, len); + } + + return 1; } - *p = '\0'; +} + +/** Combile 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); - return pinto; + if (file != NULL) + dbuf_append_str(path, file); } /** 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 + returns the directory component. Used for discovery of bin + directory of SDCC installation. Returns NULL if the path is impossible. */ -char * -getPrefixFromBinPath (const char *prel) +#ifdef _WIN32 +const char * +getBinPath(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. */ - getStringDifference (buffer, PREFIX, BINDIR); + struct dbuf_s path; + const char *p; - /* Verify that the path in has the expected suffix */ - if (strlen(buffer) > strlen(scratchFileName)) + dbuf_init(&path, 128); + dbuf_splitPath(prel, &path, NULL); + + p = dbuf_c_str(&path); + if ('\0' != *p) + return p; + else { - /* Not long enough */ - return NULL; + char module[PATH_MAX]; + + dbuf_destroy(&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); + return dbuf_c_str(&path); + } + else + return NULL; } - if (strcmp(buffer, scratchFileName + strlen(scratchFileName) - strlen(buffer)) != 0) +} +#else +const char * +getBinPath(const char *prel) +{ + struct dbuf_s path; + const char *ret_path; + + if (NULL != (ret_path = findProgramPath(prel))) { - /* Doesn't match */ - return NULL; - } + dbuf_splitPath(prel, path, NULL); - scratchFileName[strlen(scratchFileName) - strlen(buffer)] = '\0'; + free((void *)ret_path); - return gc_strdup (scratchFileName); + return dbuf_c_str(path); + } + else + return NULL; } +#endif /** Returns true if the given path exists. */ @@ -178,16 +285,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); - printf("In: \"%s\"\n", pcmd); - printf("Out: \"%s\"\n", poutcmd); - 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 @@ -196,15 +315,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 @@ -224,3 +334,151 @@ 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 + +/** 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); +}