Update svn merge history.
[sdcc.git] / sdcc / src / SDCCutil.c
blob2c9e856d170cad981905de7381ea57b4b2b431d6
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
9 later version.
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 -------------------------------------------------------------------------*/
25 #include <math.h>
26 #include <string.h>
27 #include <ctype.h>
29 #ifdef _WIN32
30 #include <windows.h>
31 #undef TRUE
32 #undef FALSE
33 #endif
34 #include <sys/stat.h>
35 #include "dbuf.h"
36 #include "SDCCglobl.h"
37 #include "SDCCmacro.h"
38 #include "SDCCutil.h"
39 #include "newalloc.h"
40 #include "dbuf_string.h"
41 #ifndef _WIN32
42 #include "findme.h"
43 #endif
45 #include "version.h"
47 /** Given an array of name, value string pairs creates a new hash
48 containing all of the pairs.
50 hTab *
51 populateStringHash (const char **pin)
53 hTab *pret = NULL;
55 while (*pin)
57 shash_add (&pret, pin[0], pin[1]);
58 pin += 2;
61 return pret;
65 /** shell escape string
66 returns dynamically allocated string, which should be free-ed
68 char *
69 shell_escape (const char *str)
71 #ifdef _WIN32
72 /* see http://www.autohotkey.net/~deleyd/parameters/parameters.htm */
74 struct dbuf_s dbuf;
75 int backshl = 0;
76 const char *begin = str;
77 char backslbuf[16];
78 char *backslp;
80 dbuf_init (&dbuf, 128);
82 /* opening double quotes */
83 dbuf_append_char(&dbuf, '"');
84 while (*str)
86 if (NULL == begin)
87 begin = str;
89 if ('\\' == *str)
90 ++backshl;
91 else
93 if ('"' == *str)
95 /* append the remaining characters */
96 if (str > begin)
97 dbuf_append (&dbuf, begin, str - begin);
99 /* append additional backslash */
100 ++backshl;
102 /* special handling if last chars before double quote are backslashes */
103 backslp = backslbuf;
104 while (backshl--)
106 *backslp++ = '\\';
107 if (sizeof (backslbuf) == backslp - backslbuf)
109 dbuf_append (&dbuf, backslbuf, sizeof (backslbuf));
110 backslp = backslbuf;
113 if (backslp > backslbuf)
114 dbuf_append (&dbuf, backslbuf, backslp - backslbuf);
116 begin = str;
118 else if ('%' == *str)
120 /* disable env. variable expansion */
121 /* append the remaining characters */
122 if (begin && str > begin)
123 dbuf_append (&dbuf, begin, str - begin);
125 /* special handling if last chars before double quote are backslashes */
126 backslp = backslbuf;
127 while (backshl--)
129 *backslp++ = '\\';
130 if (sizeof (backslbuf) == backslp - backslbuf)
132 dbuf_append (&dbuf, backslbuf, sizeof (backslbuf));
133 backslp = backslbuf;
136 if (backslp > backslbuf)
137 dbuf_append (&dbuf, backslbuf, backslp - backslbuf);
139 /* closing doube quotes */
140 backslbuf[0] = '"';
141 backslbuf[1] = *str;
142 /* re opening double quotes */
143 backslbuf[2] = '"';
144 dbuf_append (&dbuf, backslbuf, 3);
145 begin = NULL;
147 backshl = 0;
149 ++str;
151 /* append the remaining characters */
152 if (begin && str > begin)
153 dbuf_append (&dbuf, begin, str - begin);
155 /* special handling if last chars before double quote are backslashes */
156 backslp = backslbuf;
157 while (backshl--)
159 *backslp++ = '\\';
160 if (sizeof (backslbuf) == backslp - backslbuf)
162 dbuf_append (&dbuf, backslbuf, sizeof (backslbuf));
163 backslp = backslbuf;
166 if (backslp > backslbuf)
167 dbuf_append (&dbuf, backslbuf, backslp - backslbuf);
169 /* closing doube quotes */
170 dbuf_append_char (&dbuf, '"');
172 return dbuf_detach_c_str (&dbuf);
173 #else
174 struct dbuf_s dbuf;
175 const char *s = str;
176 const char *begin = str;
178 dbuf_init (&dbuf, 128);
180 while (*s)
182 switch (*s)
184 case ' ': case '\t': case '\n': /* IFS white space */
185 case '\'': case '"': case '\\': /* quoting chars */
186 case '|': case '&': case ';': /* shell metacharacters */
187 case '(': case ')': case '<': case '>':
188 case '!': case '{': case '}': /* reserved words */
189 case '*': case '[': case '?': case ']': /* globbing chars */
190 case '^':
191 case '$': case '`': /* expansion chars */
192 case ',': /* brace expansion */
193 /* flush */
194 if (s > begin)
195 dbuf_append (&dbuf, begin, s - begin);
197 dbuf_append_char (&dbuf, '\\');
198 begin = s;
199 break;
201 case '~': /* tilde expansion */
202 if (s == str || s[-1] == '=' || s[-1] == ':')
204 /* flush */
205 if (s > begin)
206 dbuf_append (&dbuf, begin, s - begin);
208 dbuf_append_char (&dbuf, '\\');
209 begin = s;
211 break;
213 case '#': /* comment char */
215 /* flush */
216 if (s > begin)
217 dbuf_append (&dbuf, begin, s - begin);
219 dbuf_append_char (&dbuf, '\\');
220 begin = s;
222 /* FALLTHROUGH */
223 default:
224 break;
226 ++s;
228 /* flush */
229 if (s > begin)
230 dbuf_append (&dbuf, begin, s - begin);
232 return dbuf_detach_c_str (&dbuf);
233 #endif
237 /** Escape string for string constants.
238 Returns dynamically allocated string, which should be free-ed.
239 TODO: Maybe handle other non-printable characters.
241 char *
242 string_escape (const char *str)
244 struct dbuf_s dbuf;
246 dbuf_init (&dbuf, 128);
248 while (*str)
250 switch (*str)
252 case '\\': case '"':
253 dbuf_append_char (&dbuf, '\\');
254 dbuf_append_char (&dbuf, *str);
255 break;
257 case '\n':
258 dbuf_append_str (&dbuf, "\\n");
259 break;
261 default:
262 dbuf_append_char (&dbuf, *str);
263 break;
265 ++str;
268 return dbuf_detach_c_str (&dbuf);
272 /** Prints elements of the set to the file, each element on new line
274 void
275 fputStrSet (FILE * fp, set * list)
277 const char *s;
279 for (s = setFirstItem (list); s != NULL; s = setNextItem (list))
281 fputs (s, fp);
282 fputc ('\n', fp);
286 /** Prepend / append / process given strings to each item of string set.
287 The result is in a new string set.
289 set *
290 processStrSet (set * list, const char *pre, const char *post, char *(*func)(const char *))
292 set *new_list = NULL;
293 const char *item;
294 struct dbuf_s dbuf;
296 for (item = setFirstItem (list); item != NULL; item = setNextItem (list))
298 dbuf_init (&dbuf, PATH_MAX);
300 if (pre)
301 dbuf_append_str (&dbuf, pre);
303 if (func)
305 char *s = func (item);
307 dbuf_append_str (&dbuf, s);
308 Safe_free (s);
310 else
311 dbuf_append_str (&dbuf, item);
313 if (post)
314 dbuf_append_str (&dbuf, post);
316 addSet (&new_list, dbuf_detach_c_str (&dbuf));
319 return new_list;
322 /** Given a set returns a string containing all of the strings separated
323 by spaces. The returned string is on the heap.
325 const char *
326 joinStrSet (set * list)
328 const char *s;
329 struct dbuf_s dbuf;
331 dbuf_init (&dbuf, PATH_MAX);
333 for (s = setFirstItem (list); s != NULL; s = setNextItem (list))
335 dbuf_append_str (&dbuf, s);
336 dbuf_append_char (&dbuf, ' ');
339 return dbuf_detach_c_str (&dbuf);
342 /** Split the path string to the directory and file name (including extension) components.
343 The directory component doesn't contain trailing directory separator.
344 Returns true if the path contains the directory separator. */
346 dbuf_splitPath (const char *path, struct dbuf_s *dir, struct dbuf_s *file)
348 const char *p;
349 int ret;
350 const char *end = &path[strlen (path)];
352 for (p = end - 1; p >= path && !IS_DIR_SEPARATOR (*p); --p)
355 ret = p >= path;
357 if (NULL != dir)
359 int len = p - path;
361 if (0 < len)
362 dbuf_append (dir, path, len);
365 if (NULL != file)
367 int len;
369 ++p;
370 len = end - p;
372 if (0 < len)
373 dbuf_append (file, p, len);
376 return ret;
379 /** Split the path string to the file name (including directory) and file extension components.
380 File extension component contains the extension separator.
381 Returns true if the path contains the extension separator. */
383 dbuf_splitFile (const char *path, struct dbuf_s *file, struct dbuf_s *ext)
385 const char *p;
386 const char *end = &path[strlen (path)];
388 for (p = end - 1; p >= path && !IS_DIR_SEPARATOR (*p) && '.' != *p; --p)
391 if (p < path || '.' != *p)
393 dbuf_append_str (file, path);
395 return 0;
397 else
399 if (NULL != file)
401 int len = p - path;
403 if (0 < len)
404 dbuf_append (file, path, len);
407 if (NULL != ext)
409 int len = end - p;
411 if (0 < len)
412 dbuf_append (ext, p, len);
415 return 1;
419 /** Combine directory and the file name to a path string using the DIR_SEPARATOR_CHAR.
421 void
422 dbuf_makePath (struct dbuf_s *path, const char *dir, const char *file)
424 if (dir != NULL)
425 dbuf_append_str (path, dir);
427 dbuf_append_char (path, DIR_SEPARATOR_CHAR);
429 if (file != NULL)
430 dbuf_append_str (path, file);
433 /** Given a file with path information in the binary files directory,
434 returns the directory component. Used for discovery of bin
435 directory of SDCC installation. Returns NULL if the path is
436 impossible.
438 #ifdef _WIN32
439 const char *
440 getBinPath (const char *prel)
442 struct dbuf_s path;
443 const char *p;
445 dbuf_init (&path, 128);
446 dbuf_splitPath (prel, &path, NULL);
448 p = dbuf_c_str (&path);
449 if ('\0' != *p)
450 return p;
451 else
453 char module[PATH_MAX];
455 dbuf_destroy (&path);
457 /* not enough info in prel; do it with module name */
458 if (0 != GetModuleFileName (NULL, module, sizeof (module)))
460 dbuf_init (&path, 128);
462 dbuf_splitPath (module, &path, NULL);
463 return dbuf_detach_c_str (&path);
465 else
466 return NULL;
469 #else
470 const char *
471 getBinPath (const char *prel)
473 const char *ret_path;
475 if (NULL != (ret_path = findProgramPath (prel)))
477 struct dbuf_s path;
479 dbuf_init (&path, 128);
481 dbuf_splitPath (ret_path, &path, NULL);
482 free ((void *) ret_path);
483 return dbuf_detach_c_str (&path);
485 else
486 return NULL;
488 #endif
490 /** Returns true if the given path exists.
492 bool
493 pathExists (const char *ppath)
495 struct stat s;
497 return stat (ppath, &s) == 0;
500 static hTab *_mainValues;
502 void
503 setMainValue (const char *pname, const char *pvalue)
505 assert (pname);
507 shash_add (&_mainValues, pname, pvalue);
510 char *
511 buildMacros (const char *cmd)
513 return eval_macros (_mainValues, cmd);
516 char *
517 buildCmdLine (const char **cmds, const char *p1, const char *p2, const char *p3, set * list, set * list2)
519 int first = 1;
520 struct dbuf_s dbuf;
522 assert (cmds != NULL);
524 dbuf_init (&dbuf, 256);
526 while (*cmds)
528 const char *p, *from, *par;
529 int sep = 1;
531 from = *cmds;
532 cmds++;
534 /* See if it has a '$' anywhere - if not, just copy */
535 if ((p = strchr (from, '$')))
537 /* include first part of cmd */
538 if (p != from)
540 if (!first && sep)
541 dbuf_append_char (&dbuf, ' ');
542 dbuf_append (&dbuf, from, p - from);
543 sep = 0;
545 from = p + 2;
547 /* include parameter */
548 p++;
549 switch (*p)
551 case '1':
552 par = p1;
553 break;
555 case '2':
556 par = p2;
557 break;
559 case '3':
560 par = p3;
561 break;
563 case 'l':
565 const char *tmp;
566 par = NULL;
568 for (tmp = setFirstItem (list); tmp; tmp = setNextItem (list))
570 if (*tmp != '\0')
572 if (sep)
573 dbuf_append_char (&dbuf, ' '); /* separate it */
574 dbuf_append_str (&dbuf, tmp);
575 sep = 1;
579 break;
581 case 'L':
583 const char *tmp;
584 par = NULL;
586 for (tmp = setFirstItem (list2); tmp; tmp = setNextItem (list2))
588 if (*tmp != '\0')
590 if (sep)
591 dbuf_append_char (&dbuf, ' '); /* separate it */
592 dbuf_append_str (&dbuf, tmp);
593 sep = 1;
597 break;
599 default:
600 par = NULL;
601 assert (0);
604 if (par && *par != '\0')
606 if (!first && sep)
607 dbuf_append_char (&dbuf, ' '); /* separate it */
608 dbuf_append_str (&dbuf, par);
609 sep = 0;
613 /* include the rest of cmd, e.g. ".asm" from "$1.asm" */
614 if (*from != '\0')
616 if (!first && sep)
617 dbuf_append_char (&dbuf, ' '); /* separate it */
618 dbuf_append_str (&dbuf, from);
619 sep = 0;
622 first = 0;
625 return dbuf_detach_c_str (&dbuf);
628 char *
629 buildCmdLine2 (const char *pcmd, ...)
631 va_list ap;
632 char *poutcmd;
634 assert (pcmd);
635 assert (_mainValues);
637 va_start (ap, pcmd);
639 poutcmd = mvsprintf (_mainValues, pcmd, ap);
641 va_end (ap);
643 return poutcmd;
646 void
647 populateMainValues (const char **ppin)
649 _mainValues = populateStringHash (ppin);
652 /** Returns true if sz starts with the string given in key.
654 bool
655 startsWith (const char *sz, const char *key)
657 return !strncmp (sz, key, strlen (key));
660 /** Removes any newline characters from the string. Not strictly the
661 same as perl's chomp.
663 void
664 chomp (char *sz)
666 char *nl;
667 while ((nl = strrchr (sz, '\n')))
668 *nl = '\0';
671 hTab *
672 getRuntimeVariables (void)
674 return _mainValues;
677 /* strncpy() with guaranteed NULL termination. */
678 char *
679 strncpyz (char *dest, const char *src, size_t n)
681 assert (n > 0);
683 --n;
684 /* paranoia... */
685 if (strlen (src) > n)
687 fprintf (stderr, "strncpyz prevented buffer overrun!\n");
690 strncpy (dest, src, n);
691 dest[n] = 0;
692 return dest;
695 /* like strncat() with guaranteed NULL termination
696 * The passed size should be the size of the dest buffer, not the number of
697 * bytes to copy.
699 char *
700 strncatz (char *dest, const char *src, size_t n)
702 size_t maxToCopy;
703 size_t destLen = strlen (dest);
705 assert (n > 0);
706 assert (n > destLen);
708 maxToCopy = n - destLen - 1;
710 /* paranoia... */
711 if (strlen (src) + destLen >= n)
713 fprintf (stderr, "strncatz prevented buffer overrun!\n");
716 strncat (dest, src, maxToCopy);
717 dest[n - 1] = 0;
718 return dest;
721 /*-----------------------------------------------------------------*/
722 /* getBuildNumber - return build number */
723 /*-----------------------------------------------------------------*/
724 const char *
725 getBuildNumber (void)
727 return (SDCC_BUILD_NUMBER);
730 /*-----------------------------------------------------------------*/
731 /* getBuildEnvironment - return environment used to build SDCC */
732 /*-----------------------------------------------------------------*/
733 const char *
734 getBuildEnvironment (void)
736 #ifdef __CYGWIN__
737 return "CYGWIN";
738 #elif defined __MINGW64__
739 return "MINGW64";
740 #elif defined __MINGW32__
741 return "MINGW32";
742 #elif defined __DJGPP__
743 return "DJGPP";
744 #elif defined(_MSC_VER)
745 return "MSVC";
746 #elif defined(__BORLANDC__)
747 return "BORLANDC";
748 #elif defined(__APPLE__)
749 #if defined(__i386__)
750 return "Mac OS X i386";
751 #elif defined(__x86_64__)
752 return "Mac OS X x86_64";
753 #else
754 return "Mac OS X ppc";
755 #endif
756 #elif defined(__linux__)
757 return "Linux";
758 #elif defined(__NetBSD__)
759 return "NetBSD";
760 #elif defined(__FreeBSD__)
761 return "FreeBSD";
762 #elif defined(__OpenBSD__)
763 return "OpenBSD";
764 #elif defined(__sun)
765 #if defined(__i386)
766 return "Solaris i386";
767 #elif defined(__amd64)
768 return "Solaris amd64";
769 #else
770 return "Solaris SPARC";
771 #endif
772 #else
773 return "UNIX";
774 #endif
777 size_t
778 SDCCsnprintf (char *dst, size_t n, const char *fmt, ...)
780 va_list args;
781 int len;
783 va_start (args, fmt);
785 len = vsnprintf (dst, n, fmt, args);
787 va_end (args);
789 /* on some gnu systems, vsnprintf returns -1 if output is truncated.
790 * In the C99 spec, vsnprintf returns the number of characters that
791 * would have been written, were space available.
793 if ((len < 0) || (size_t) len >= n)
795 fprintf (stderr, "internal error: sprintf truncated.\n");
798 return len;
801 /** Pragma tokenizer
803 void
804 init_pragma_token (struct pragma_token_s *token)
806 dbuf_init (&token->dbuf, 16);
807 token->type = TOKEN_UNKNOWN;
810 char *
811 get_pragma_token (const char *s, struct pragma_token_s *token)
813 dbuf_set_length (&token->dbuf, 0);
815 /* skip leading spaces */
816 while ('\n' != *s && isspace (*s))
817 ++s;
819 if ('\0' == *s || '\n' == *s)
821 token->type = TOKEN_EOL;
823 else
825 char *end;
827 long val = strtol (s, &end, 0);
829 if (end != s && ('\0' == *end || isspace (*end)))
831 token->val.int_val = val;
832 token->type = TOKEN_INT;
833 dbuf_append (&token->dbuf, s, end - s);
834 s = end;
836 else
838 while ('\0' != *s && !isspace (*s))
840 dbuf_append_char (&token->dbuf, *s);
841 ++s;
844 token->type = TOKEN_STR;
848 return (char *) s;
851 const char *
852 get_pragma_string (struct pragma_token_s *token)
854 return dbuf_c_str (&token->dbuf);
857 void
858 free_pragma_token (struct pragma_token_s *token)
860 dbuf_destroy (&token->dbuf);
863 /*! /fn char hexEscape(char **src)
865 /param src Pointer to 'x' from start of hex character value
868 unsigned long int
869 hexEscape (const char **src)
871 char *s;
872 unsigned long value;
874 ++*src; /* Skip over the 'x' */
876 value = strtoul (*src, &s, 16);
878 if (s == *src)
880 /* no valid hex found */
881 werror (E_INVALID_HEX);
884 *src = s;
886 return value;
889 /*------------------------------------------------------------------*/
890 /* universalEscape - process an hex constant of exactly four digits */
891 /* return the hex value, throw an error warning for invalid hex */
892 /* adjust src to point at the last processed char */
893 /*------------------------------------------------------------------*/
895 unsigned long int
896 universalEscape (const char **str, unsigned int n)
898 unsigned int digits;
899 unsigned long value = 0;
900 const char *s = *str;
902 if (!options.std_c95)
904 werror (W_UNIVERSAL_C95);
907 ++*str; /* Skip over the 'u' or 'U' */
909 for (digits = 0; digits < n; ++digits)
911 if (**str >= '0' && **str <= '9')
913 value = (value << 4) + (**str - '0');
914 ++*str;
916 else if (tolower((unsigned char)(**str)) >= 'a' && (tolower((unsigned char)(**str)) <= 'f'))
918 value = (value << 4) + (tolower((unsigned char)(**str)) - 'a' + 10);
919 ++*str;
921 else
922 break;
924 if (digits != n || value < 0x00a0 && value != 0x0024 && value != 0x0040 && value != 0x0060 || value >= 0xd800 && 0xdfff >= value ||
925 value > 0x10ffff) // Additional diagnostic required in C23, but since it is just a warning, we enable it even for older standards.
927 werror (W_INVALID_UNIVERSAL, s);
930 return value;
933 /*------------------------------------------------------------------*/
934 /* octalEscape - process an octal constant of max three digits */
935 /* return the octal value, throw a warning for illegal octal */
936 /* adjust src to point at the last processed char */
937 /*------------------------------------------------------------------*/
939 unsigned long int
940 octalEscape (const char **str)
942 int digits;
943 unsigned value = 0;
945 for (digits = 0; digits < 3; ++digits)
947 if (**str >= '0' && **str <= '7')
949 value = value * 8 + (**str - '0');
950 ++*str;
952 else
954 break;
958 return value;
962 /fn const char *copyStr (const char *src, size_t *size)
964 Copies source string to a dynamically allocated buffer interpreting
965 escape sequences and special characters
967 /param src Buffer containing the source string with escape sequences
968 /param size Pointer to location where the resulting buffer length is written
969 /return Dynamically allocated resulting buffer
972 const char *
973 copyStr (const char *src, size_t *size)
975 const char *begin = NULL;
976 struct dbuf_s dbuf;
978 dbuf_init(&dbuf, 128);
980 while (*src)
982 if (*src == '\"')
984 if (begin)
986 /* copy what we have until now */
987 dbuf_append (&dbuf, begin, src - begin);
988 begin = NULL;
990 ++src;
992 else if (*src == '\\')
994 unsigned long int c;
995 bool universal = FALSE;
997 if (begin)
999 /* copy what we have until now */
1000 dbuf_append (&dbuf, begin, src - begin);
1001 begin = NULL;
1003 ++src;
1004 switch (*src)
1006 case 'n':
1007 c = '\n';
1008 break;
1010 case 't':
1011 c = '\t';
1012 break;
1014 case 'v':
1015 c = '\v';
1016 break;
1018 case 'b':
1019 c = '\b';
1020 break;
1022 case 'r':
1023 c = '\r';
1024 break;
1026 case 'f':
1027 c = '\f';
1028 break;
1030 case 'a':
1031 c = '\a';
1032 break;
1034 case '0':
1035 case '1':
1036 case '2':
1037 case '3':
1038 case '4':
1039 case '5':
1040 case '6':
1041 case '7':
1042 c = octalEscape (&src);
1043 --src;
1044 break;
1046 case 'x':
1047 c = hexEscape (&src);
1048 --src;
1049 break;
1051 case 'u':
1052 c = universalEscape (&src, 4);
1053 universal = TRUE;
1054 --src;
1055 break;
1057 case 'U':
1058 c = universalEscape (&src, 8);
1059 universal = TRUE;
1060 --src;
1061 break;
1063 case '\\':
1064 case '\?':
1065 case '\'':
1066 case '\"':
1067 default:
1068 c = *src;
1069 break;
1071 if (universal) // Encode one utf-32 character to utf-8
1073 char s[5] = "\0\0\0\0";
1074 if (c < 0x80)
1075 s[0] = (char)c;
1076 else if (c < 0x800)
1078 s[0] = (c >> 6) & 0x1f | 0xc0;
1079 s[1] = (c >> 0) & 0x3f | 0x80;
1081 else if (c < 0x10000)
1083 s[0] = (c >> 12) & 0x0f | 0xe0;
1084 s[1] = (c >> 6) & 0x3f | 0x80;
1085 s[2] = (c >> 0) & 0x3f | 0x80;
1087 else if (c < 0x110000)
1089 s[0] = (c >> 18) & 0x07 | 0xf0;
1090 s[1] = (c >> 12) & 0x3f | 0x80;
1091 s[2] = (c >> 6) & 0x3f | 0x80;
1092 s[3] = (c >> 0) & 0x3f | 0x80;
1094 else
1095 wassert (0);
1096 dbuf_append_str (&dbuf, s);
1098 else
1099 dbuf_append_char (&dbuf, (char)c);
1101 ++src;
1103 else
1105 if (!begin)
1106 begin = src;
1107 ++src;
1111 if (begin)
1113 /* copy what we have until now */
1114 dbuf_append (&dbuf, begin, src - begin);
1115 begin = NULL;
1118 if (size)
1120 /* include null terminator character
1121 appended by dbuf_detach_c_str() */
1122 *size = dbuf_get_length (&dbuf) + 1;
1125 return dbuf_detach_c_str (&dbuf);
1128 static char prefix[256] = "";
1129 static char suffix[256] = "";
1130 static char cmd[4096] = "";
1132 void getPrefixSuffix(const char *arg)
1134 const char *p;
1135 const char sdcc[] = "sdcc";
1137 if (!arg)
1138 return;
1140 p = arg + strlen (arg);
1141 while (p != arg && *(p - 1) != '\\' && *(p - 1) != '/')
1142 p--;
1143 arg = p;
1145 /* found no "sdcc" in command line argv[0] */
1146 if ((p = strstr (arg, sdcc)) == NULL)
1147 return;
1149 /* found more than one "sdcc" in command line argv[0] */
1150 if (strstr (p + strlen (sdcc), sdcc) != NULL)
1151 return;
1153 /* copy prefix and suffix */
1154 strncpy (prefix, arg, p - arg);
1155 strcpy (suffix, p + strlen (sdcc));
1158 char *setPrefixSuffix(const char *arg)
1160 const char *p;
1162 if (!arg)
1163 return NULL;
1164 else
1165 memset (cmd, 0x00, sizeof (cmd));
1167 /* find the core name of command line */
1168 for (p = arg; (*p) && isblank (*p); p++);
1169 arg = p;
1170 assert (strstr (arg, ".exe") == NULL);
1171 for (p = arg; (*p) && !isblank (*p); p++);
1173 /* compose new command line with prefix and suffix */
1174 strcpy (cmd, prefix);
1175 strncat (cmd, arg, p - arg);
1176 strcat (cmd, suffix);
1177 strcat (cmd, p);
1179 return cmd;
1182 char *formatInlineAsm (char *asmStr)
1184 char *p, *q;
1186 if (!asmStr)
1187 return NULL;
1188 else
1189 q = asmStr;
1191 for (;;)
1193 // omit leading space or tab
1194 while (*q == '\t' || *q == ' ')
1195 q++;
1196 // then record the head of current line
1197 p = q;
1198 // search for CL or reach the end
1199 while (*q != '\n' && *q != '\r' && *q != 0)
1200 q++;
1201 // omit more CL characters
1202 while (*q == '\n' || *q == '\r')
1203 q++;
1204 // replace the first with tab
1205 while (p != q)
1206 if (*p == '\t') // '\t' appears first then no need to do
1208 break;
1210 else if (*p == ' ') // find the first space then replace it with tab
1212 *p = '\t';
1213 break;
1215 else // go on to search
1217 p++;
1219 // check if end
1220 if (*q == 0)
1221 return asmStr;