1 /*-------------------------------------------------------------------------
2 SDCCutil.c - Small utility functions.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
33 #include "SDCCglobl.h"
34 #include "SDCCmacro.h"
37 #include "dbuf_string.h"
44 /** Given an array of name, value string pairs creates a new hash
45 containing all of the pairs.
48 populateStringHash(const char **pin)
54 shash_add (&pret, pin[0], pin[1]);
61 /** Prints elements of the set to the file, each element on new line
64 fputStrSet(FILE *fp, set *list)
68 for (s = setFirstItem(list); s != NULL; s = setNextItem(list)) {
74 /** Prepend / append given strings to each item of string set. The result is in a
78 appendStrSet(set *list, const char *pre, const char *post)
84 for (item = setFirstItem(list); item != NULL; item = setNextItem(list)) {
85 dbuf_init(&dbuf, PATH_MAX);
88 dbuf_append_str(&dbuf, pre);
89 dbuf_append_str(&dbuf, item);
91 dbuf_append_str(&dbuf, post);
93 /* null terminate the buffer */
95 addSet(&new_list, dbuf_detach(&dbuf));
101 /** Given a set returns a string containing all of the strings seperated
102 by spaces. The returned string is on the heap.
105 joinStrSet(set *list)
110 dbuf_init(&dbuf, PATH_MAX);
112 for (s = setFirstItem(list); s != NULL; s = setNextItem(list))
114 dbuf_append_str(&dbuf, s);
115 dbuf_append_char(&dbuf, ' ');
118 s = dbuf_c_str(&dbuf);
123 /** Split the path string to the directory and file name (including extension) components.
124 The directory component doesn't contain trailing directory separator.
125 Returns true if the path contains the directory separator. */
127 dbuf_splitPath(const char *path, struct dbuf_s *dir, struct dbuf_s *file)
131 const char *end = &path[strlen(path)];
133 for (p = end - 1; p >= path && !IS_DIR_SEPARATOR(*p); --p)
143 dbuf_append(dir, path, len);
154 dbuf_append(file, p, len);
160 /** Split the path string to the file name (including directory) and file extension components.
161 File extension component contains the extension separator.
162 Returns true if the path contains the extension separator. */
164 dbuf_splitFile(const char *path, struct dbuf_s *file, struct dbuf_s *ext)
167 const char *end = &path[strlen(path)];
169 for (p = end - 1; p >= path && !IS_DIR_SEPARATOR(*p) && '.' != *p; --p)
172 if (p < path || '.' != *p)
174 dbuf_append_str(file, path);
185 dbuf_append(file, path, len);
193 dbuf_append(ext, p, len);
200 /** Combine directory and the file name to a path string using the DIR_SEPARATOR_CHAR.
203 dbuf_makePath(struct dbuf_s *path,const char *dir, const char *file)
206 dbuf_append_str(path, dir);
208 dbuf_append_char(path, DIR_SEPARATOR_CHAR);
211 dbuf_append_str(path, file);
214 /** Given a file with path information in the binary files directory,
215 returns the directory component. Used for discovery of bin
216 directory of SDCC installation. Returns NULL if the path is
221 getBinPath(const char *prel)
226 dbuf_init(&path, 128);
227 dbuf_splitPath(prel, &path, NULL);
229 p = dbuf_c_str(&path);
234 char module[PATH_MAX];
238 /* not enough info in prel; do it with module name */
239 if (0 != GetModuleFileName(NULL, module, sizeof (module)))
241 dbuf_init(&path, 128);
243 dbuf_splitPath(module, &path, NULL);
245 return dbuf_detach(&path);
253 getBinPath(const char *prel)
255 const char *ret_path;
257 if (NULL != (ret_path = findProgramPath(prel)))
261 dbuf_init(&path, 128);
263 dbuf_splitPath(ret_path, &path, NULL);
264 free((void *)ret_path);
266 return dbuf_detach(&path);
273 /** Returns true if the given path exists.
276 pathExists (const char *ppath)
280 return stat (ppath, &s) == 0;
283 static hTab *_mainValues;
286 setMainValue (const char *pname, const char *pvalue)
290 shash_add (&_mainValues, pname, pvalue);
294 buildCmdLine2 (char *pbuffer, size_t len, const char *pcmd, ...)
299 assert(pbuffer && pcmd);
304 poutcmd = mvsprintf(_mainValues, pcmd, ap);
308 strncpyz(pbuffer, poutcmd, len);
313 populateMainValues (const char **ppin)
315 _mainValues = populateStringHash(ppin);
318 /** Returns true if sz starts with the string given in key.
321 startsWith (const char *sz, const char *key)
323 return !strncmp (sz, key, strlen (key));
326 /** Removes any newline characters from the string. Not strictly the
327 same as perl's chomp.
333 while ((nl = strrchr (sz, '\n')))
338 getRuntimeVariables(void)
344 /* strncpy() with guaranteed NULL termination. */
345 char *strncpyz(char *dest, const char *src, size_t n)
353 fprintf(stderr, "strncpyz prevented buffer overrun!\n");
356 strncpy(dest, src, n);
361 /* like strncat() with guaranteed NULL termination
362 * The passed size should be the size of the dest buffer, not the number of
365 char *strncatz(char *dest, const char *src, size_t n)
368 size_t destLen = strlen(dest);
373 maxToCopy = n - destLen - 1;
376 if (strlen(src) + destLen >= n)
378 fprintf(stderr, "strncatz prevented buffer overrun!\n");
381 strncat(dest, src, maxToCopy);
386 /*-----------------------------------------------------------------*/
387 /* getBuildNumber - return build number */
388 /*-----------------------------------------------------------------*/
389 const char *getBuildNumber(void)
391 return (SDCC_BUILD_NUMBER);
394 /*-----------------------------------------------------------------*/
395 /* getBuildDate - return build date */
396 /*-----------------------------------------------------------------*/
397 const char *getBuildDate(void)
402 /*-----------------------------------------------------------------*/
403 /* getBuildEnvironment - return environment used to build SDCC */
404 /*-----------------------------------------------------------------*/
405 const char *getBuildEnvironment(void)
409 #elif defined __MINGW32__
411 #elif defined __DJGPP__
413 #elif defined(_MSC_VER)
415 #elif defined(__BORLANDC__)
417 #elif defined(__APPLE__)
418 # if defined(__i386__)
419 return "Mac OS X i386";
421 return "Mac OS X ppc";
428 #if defined(HAVE_VSNPRINTF) || defined(HAVE_VSPRINTF)
429 size_t SDCCsnprintf(char *dst, size_t n, const char *fmt, ...)
436 # if defined(HAVE_VSNPRINTF)
437 len = vsnprintf(dst, n, fmt, args);
439 vsprintf(dst, fmt, args);
440 len = strlen(dst) + 1;
445 /* on some gnu systems, vsnprintf returns -1 if output is truncated.
446 * In the C99 spec, vsnprintf returns the number of characters that
447 * would have been written, were space available.
449 if ((len < 0) || (size_t) len >= n) {
450 fprintf(stderr, "internal error: sprintf truncated.\n");
460 init_pragma_token(struct pragma_token_s *token)
462 dbuf_init(&token->dbuf, 16);
463 token->type = TOKEN_UNKNOWN;
467 get_pragma_token(const char *s, struct pragma_token_s *token)
469 dbuf_set_length(&token->dbuf, 0);
471 /* skip leading spaces */
472 while ('\n' != *s && isspace(*s))
475 if ('\0' == *s || '\n' == *s)
477 token->type = TOKEN_EOL;
483 long val = strtol(s, &end, 0);
485 if (end != s && ('\0' == *end || isspace(*end)))
487 token->val.int_val = val;
488 token->type = TOKEN_INT;
489 dbuf_append(&token->dbuf, s, end - s);
494 while ('\0' != *s && !isspace(*s))
496 dbuf_append_char(&token->dbuf, *s);
500 token->type = TOKEN_STR;
508 get_pragma_string(struct pragma_token_s *token)
510 return dbuf_c_str(&token->dbuf);
514 free_pragma_token(struct pragma_token_s *token)
516 dbuf_destroy(&token->dbuf);
519 /*! /fn char hexEscape(char **src)
521 /param src Pointer to 'x' from start of hex character value
525 hexEscape (const char **src)
528 unsigned long value ;
530 (*src)++ ; /* Skip over the 'x' */
532 value = strtol (*src, &s, 16);
536 // no valid hex found
537 werror(E_INVALID_HEX);
543 werror(W_ESC_SEQ_OOR_FOR_CHAR);
551 /*------------------------------------------------------------------*/
552 /* octalEscape - process an octal constant of max three digits */
553 /* return the octal value, throw a warning for illegal octal */
554 /* adjust src to point at the last proccesed char */
555 /*------------------------------------------------------------------*/
558 octalEscape (const char **str)
563 for (digits = 0; digits < 3; digits++)
565 if (**str >='0' && **str <= '7')
567 value = value*8 + (**str - '0');
577 if (value > 255 /* || (**str>='0' && **str<='7') */ )
579 werror (W_ESC_SEQ_OOR_FOR_CHAR);
586 /fn int copyStr (char *dest, char *src)
588 Copies a source string to a dest buffer interpreting escape sequences
589 and special characters
591 /param dest Buffer to receive the resultant string
592 /param src Buffer containing the source string with escape sequecnes
593 /return Number of characters in output string
598 copyStr (char *dest, const char *src)
600 char *OriginalDest = dest ;
606 else if (*src == '\\')
641 *dest++ = octalEscape(&src);
646 *dest++ = hexEscape(&src) ;
673 return dest - OriginalDest ;