diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/SDCCutil.c | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'src/SDCCutil.c')
| -rw-r--r-- | src/SDCCutil.c | 1173 |
1 files changed, 1173 insertions, 0 deletions
diff --git a/src/SDCCutil.c b/src/SDCCutil.c new file mode 100644 index 0000000..59bd60c --- /dev/null +++ b/src/SDCCutil.c @@ -0,0 +1,1173 @@ +/*------------------------------------------------------------------------- + SDCCutil.c - Small utility functions. + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +#include <math.h> +#include <string.h> +#include <ctype.h> + +#ifdef _WIN32 +#include <windows.h> +#undef TRUE +#undef FALSE +#endif +#include <sys/stat.h> +#include "dbuf.h" +#include "SDCCglobl.h" +#include "SDCCmacro.h" +#include "SDCCutil.h" +#include "newalloc.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. +*/ +hTab * +populateStringHash (const char **pin) +{ + hTab *pret = NULL; + + while (*pin) + { + shash_add (&pret, pin[0], pin[1]); + pin += 2; + } + + return pret; +} + + +/** shell escape string + returns dynamically allocated string, which should be free-ed +*/ +char * +shell_escape (const char *str) +{ +#ifdef _WIN32 + /* see http://www.autohotkey.net/~deleyd/parameters/parameters.htm */ + + struct dbuf_s dbuf; + int backshl = 0; + const char *begin = str; + char backslbuf[16]; + char *backslp; + + dbuf_init (&dbuf, 128); + + /* opening double quotes */ + dbuf_append_char(&dbuf, '"'); + while (*str) + { + if (NULL == begin) + begin = str; + + if ('\\' == *str) + ++backshl; + else + { + if ('"' == *str) + { + /* append the remaining characters */ + if (str > begin) + dbuf_append (&dbuf, begin, str - begin); + + /* append additional beckslash */ + ++backshl; + + /* special handling if last chars before double quote are backslashes */ + backslp = backslbuf; + while (backshl--) + { + *backslp++ = '\\'; + if (sizeof (backslbuf) == backslp - backslbuf) + { + dbuf_append (&dbuf, backslbuf, sizeof (backslbuf)); + backslp = backslbuf; + } + } + if (backslp > backslbuf) + dbuf_append (&dbuf, backslbuf, backslp - backslbuf); + + begin = str; + } + else if ('%' == *str) + { + /* diseble env. variable expansion */ + /* append the remaining characters */ + if (begin && str > begin) + dbuf_append (&dbuf, begin, str - begin); + + /* special handling if last chars before double quote are backslashes */ + backslp = backslbuf; + while (backshl--) + { + *backslp++ = '\\'; + if (sizeof (backslbuf) == backslp - backslbuf) + { + dbuf_append (&dbuf, backslbuf, sizeof (backslbuf)); + backslp = backslbuf; + } + } + if (backslp > backslbuf) + dbuf_append (&dbuf, backslbuf, backslp - backslbuf); + + /* closing doube quotes */ + backslbuf[0] = '"'; + backslbuf[1] = *str; + /* re opening double quotes */ + backslbuf[2] = '"'; + dbuf_append (&dbuf, backslbuf, 3); + begin = NULL; + } + backshl = 0; + } + ++str; + } + /* append the remaining characters */ + if (begin && str > begin) + dbuf_append (&dbuf, begin, str - begin); + + /* special handling if last chars before double quote are backslashes */ + backslp = backslbuf; + while (backshl--) + { + *backslp++ = '\\'; + if (sizeof (backslbuf) == backslp - backslbuf) + { + dbuf_append (&dbuf, backslbuf, sizeof (backslbuf)); + backslp = backslbuf; + } + } + if (backslp > backslbuf) + dbuf_append (&dbuf, backslbuf, backslp - backslbuf); + + /* closing doube quotes */ + dbuf_append_char (&dbuf, '"'); + + return dbuf_detach_c_str (&dbuf); +#else + struct dbuf_s dbuf; + const char *s = str; + const char *begin = str; + + dbuf_init (&dbuf, 128); + + while (*s) + { + switch (*s) + { + case ' ': case '\t': case '\n': /* IFS white space */ + case '\'': case '"': case '\\': /* quoting chars */ + case '|': case '&': case ';': /* shell metacharacters */ + case '(': case ')': case '<': case '>': + case '!': case '{': case '}': /* reserved words */ + case '*': case '[': case '?': case ']': /* globbing chars */ + case '^': + case '$': case '`': /* expansion chars */ + case ',': /* brace expansion */ + /* flush */ + if (s > begin) + dbuf_append (&dbuf, begin, s - begin); + + dbuf_append_char (&dbuf, '\\'); + begin = s; + break; + + case '~': /* tilde expansion */ + if (s == str || s[-1] == '=' || s[-1] == ':') + { + /* flush */ + if (s > begin) + dbuf_append (&dbuf, begin, s - begin); + + dbuf_append_char (&dbuf, '\\'); + begin = s; + } + break; + + case '#': /* comment char */ + { + /* flush */ + if (s > begin) + dbuf_append (&dbuf, begin, s - begin); + + dbuf_append_char (&dbuf, '\\'); + begin = s; + } + /* FALLTHROUGH */ + default: + break; + } + ++s; + } + /* flush */ + if (s > begin) + dbuf_append (&dbuf, begin, s - begin); + + return dbuf_detach_c_str (&dbuf); +#endif +} + +/** Prints elements of the set to the file, each element on new line +*/ +void +fputStrSet (FILE * fp, set * list) +{ + const char *s; + + for (s = setFirstItem (list); s != NULL; s = setNextItem (list)) + { + fputs (s, fp); + fputc ('\n', fp); + } +} + +/** Prepend / append / process given strings to each item of string set. + The result is in a new string set. +*/ +set * +processStrSet (set * list, const char *pre, const char *post, char *(*func)(const char *)) +{ + 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) + dbuf_append_str (&dbuf, pre); + + if (func) + { + char *s = func (item); + + dbuf_append_str (&dbuf, s); + Safe_free (s); + } + else + dbuf_append_str (&dbuf, item); + + if (post) + dbuf_append_str (&dbuf, post); + + addSet (&new_list, dbuf_detach_c_str (&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); + + for (s = setFirstItem (list); s != NULL; s = setNextItem (list)) + { + dbuf_append_str (&dbuf, s); + dbuf_append_char (&dbuf, ' '); + } + + return dbuf_detach_c_str (&dbuf); +} + +/** 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) +{ + 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); + } + + if (NULL != file) + { + int len; + + ++p; + len = end - p; + + if (0 < len) + dbuf_append (file, p, len); + } + + return ret; +} + +/** 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) +{ + 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) + { + dbuf_append_str (file, path); + + return 0; + } + else + { + 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; + } +} + +/** 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. +*/ +#ifdef _WIN32 +const char * +getBinPath (const char *prel) +{ + 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]; + + 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_detach_c_str (&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); + return dbuf_detach_c_str (&path); + } + else + return NULL; +} +#endif + +/** Returns true if the given path exists. + */ +bool +pathExists (const char *ppath) +{ + struct stat s; + + return stat (ppath, &s) == 0; +} + +static hTab *_mainValues; + +void +setMainValue (const char *pname, const char *pvalue) +{ + assert (pname); + + shash_add (&_mainValues, pname, pvalue); +} + +char * +buildMacros (const char *cmd) +{ + return eval_macros (_mainValues, cmd); +} + +char * +buildCmdLine (const char **cmds, const char *p1, const char *p2, const char *p3, set * list) +{ + int first = 1; + struct dbuf_s dbuf; + + assert (cmds != NULL); + + dbuf_init (&dbuf, 256); + + while (*cmds) + { + const char *p, *from, *par; + int sep = 1; + + from = *cmds; + cmds++; + + /* See if it has a '$' anywhere - if not, just copy */ + if ((p = strchr (from, '$'))) + { + /* include first part of cmd */ + if (p != from) + { + if (!first && sep) + dbuf_append_char (&dbuf, ' '); + dbuf_append (&dbuf, from, p - from); + sep = 0; + } + from = p + 2; + + /* include parameter */ + p++; + switch (*p) + { + case '1': + par = p1; + break; + + case '2': + par = p2; + break; + + case '3': + par = p3; + break; + + case 'l': + { + const char *tmp; + par = NULL; + + if (list != NULL && (tmp = (const char *) setFirstItem (list)) != NULL) + { + do + { + if (*tmp != '\0') + { + if (sep) + dbuf_append_char (&dbuf, ' '); /* seperate it */ + dbuf_append_str (&dbuf, tmp); + tmp++; + sep = 1; + } + } + while ((tmp = (const char *) setNextItem (list)) != NULL); + } + } + break; + + default: + par = NULL; + assert (0); + } + + if (par && *par != '\0') + { + if (!first && sep) + dbuf_append_char (&dbuf, ' '); /* seperate it */ + dbuf_append_str (&dbuf, par); + sep = 0; + } + } + + /* include the rest of cmd, e.g. ".asm" from "$1.asm" */ + if (*from != '\0') + { + if (!first && sep) + dbuf_append_char (&dbuf, ' '); /* seperate it */ + dbuf_append_str (&dbuf, from); + sep = 0; + } + + first = 0; + } + + return dbuf_detach_c_str (&dbuf); +} + +char * +buildCmdLine2 (const char *pcmd, ...) +{ + va_list ap; + char *poutcmd; + + assert (pcmd); + assert (_mainValues); + + va_start (ap, pcmd); + + poutcmd = mvsprintf (_mainValues, pcmd, ap); + + va_end (ap); + + return poutcmd; +} + +void +populateMainValues (const char **ppin) +{ + _mainValues = populateStringHash (ppin); +} + +/** Returns true if sz starts with the string given in key. + */ +bool +startsWith (const char *sz, const char *key) +{ + return !strncmp (sz, key, strlen (key)); +} + +/** Removes any newline characters from the string. Not strictly the + same as perl's chomp. +*/ +void +chomp (char *sz) +{ + char *nl; + while ((nl = strrchr (sz, '\n'))) + *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); +} + +/*-----------------------------------------------------------------*/ +/* getBuildEnvironment - return environment used to build SDCC */ +/*-----------------------------------------------------------------*/ +const char * +getBuildEnvironment (void) +{ +#ifdef __CYGWIN__ + return "CYGWIN"; +#elif defined __MINGW64__ + return "MINGW64"; +#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"; +#elif defined(__x86_64__) + return "Mac OS X x86_64"; +#else + return "Mac OS X ppc"; +#endif +#elif defined(__linux__) + return "Linux"; +#elif defined(__NetBSD__) + return "NetBSD"; +#elif defined(__FreeBSD__) + return "FreeBSD"; +#elif defined(__OpenBSD__) + return "OpenBSD"; +#elif defined(__sun) +#if defined(__i386) + return "Solaris i386"; +#elif defined(__amd64) + return "Solaris amd64"; +#else + return "Solaris SPARC"; +#endif +#else + return "UNIX"; +#endif +} + +size_t +SDCCsnprintf (char *dst, size_t n, const char *fmt, ...) +{ + va_list args; + int len; + + va_start (args, fmt); + + len = vsnprintf (dst, n, fmt, args); + + 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; +} + +/** 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 long int +hexEscape (const char **src) +{ + char *s; + unsigned long value; + + ++*src; /* Skip over the 'x' */ + + value = strtoul (*src, &s, 16); + + if (s == *src) + { + /* no valid hex found */ + werror (E_INVALID_HEX); + } + + *src = s; + + return value; +} + +/*------------------------------------------------------------------*/ +/* universalEscape - process an hex constant of exactly four digits */ +/* return the hex value, throw a warning for illegal octal */ +/* adjust src to point at the last proccesed char */ +/*------------------------------------------------------------------*/ + +unsigned long int +universalEscape (const char **str, unsigned int n) +{ + unsigned int digits; + unsigned long value = 0; + const char *s = *str; + + if (!options.std_c95) + { + werror (W_UNIVERSAL_C95); + } + + ++*str; /* Skip over the 'u' or 'U' */ + + for (digits = 0; digits < n; ++digits) + { + if (**str >= '0' && **str <= '7') + { + value = (value << 4) + (**str - '0'); + ++*str; + } + else if ((**str | 0x20) >= 'a' && (**str | 0x20) <= 'f') + { + value = (value << 4) + (**str - 'a' + 10); + ++*str; + } + else + break; + } + if (digits != n || value < 0x00a0 && value != 0x0024 && value != 0x0040 && value != 0x0060 || value >= 0xd800 && 0xdfff >= value) + { + werror (E_INVALID_UNIVERSAL, s); + } + + return 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 long int +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; + } + } + + return value; +} + +/*! + /fn const char *copyStr (const char *src, size_t *size) + + Copies source string to a dynamically allocated buffer interpreting + escape sequences and special characters + + /param src Buffer containing the source string with escape sequecnes + /param size Pointer to loction where the resulting buffer length is written + /return Dynamically allocated resulting buffer +*/ + +const char * +copyStr (const char *src, size_t *size) +{ + const char *begin = NULL; + struct dbuf_s dbuf; + + dbuf_init(&dbuf, 128); + + while (*src) + { + if (*src == '\"') + { + if (begin) + { + /* copy what we have until now */ + dbuf_append (&dbuf, begin, src - begin); + begin = NULL; + } + ++src; + } + else if (*src == '\\') + { + unsigned long int c; + bool universal = FALSE; + + if (begin) + { + /* copy what we have until now */ + dbuf_append (&dbuf, begin, src - begin); + begin = NULL; + } + ++src; + switch (*src) + { + case 'n': + c = '\n'; + break; + + case 't': + c = '\t'; + break; + + case 'v': + c = '\v'; + break; + + case 'b': + c = '\b'; + break; + + case 'r': + c = '\r'; + break; + + case 'f': + c = '\f'; + break; + + case 'a': + c = '\a'; + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + c = octalEscape (&src); + --src; + break; + + case 'x': + c = hexEscape (&src); + --src; + break; + + case 'u': + c = universalEscape (&src, 4); + universal = TRUE; + --src; + break; + + case 'U': + c = universalEscape (&src, 8); + universal = TRUE; + --src; + break; + + case '\\': + case '\?': + case '\'': + case '\"': + default: + c = *src; + break; + } + if (universal) // Encode one utf-32 character to utf-8 + { + char s[5] = "\0\0\0\0"; + if (c < 0x80) + s[0] = (char)c; + else if (c < 0x800) + { + s[0] = (c >> 6) & 0x1f | 0xc0; + s[1] = (c >> 0) & 0x3f | 0x80; + } + else if (c < 0x10000) + { + s[0] = (c >> 12) & 0x0f | 0xe0; + s[1] = (c >> 6) & 0x3f | 0x80; + s[2] = (c >> 0) & 0x3f | 0x80; + } + else if (c < 0x110000) + { + s[0] = (c >> 18) & 0x07 | 0xf0; + s[1] = (c >> 12) & 0x3f | 0x80; + s[2] = (c >> 6) & 0x3f | 0x80; + s[3] = (c >> 0) & 0x3f | 0x80; + } + else + wassert (0); + dbuf_append_str (&dbuf, s); + } + else + dbuf_append_char (&dbuf, (char)c); + + ++src; + } + else + { + if (!begin) + begin = src; + ++src; + } + } + + if (begin) + { + /* copy what we have until now */ + dbuf_append (&dbuf, begin, src - begin); + begin = NULL; + } + + if (size) + { + /* include null terminator character + appended by dbuf_detach_c_str() */ + *size = dbuf_get_length (&dbuf) + 1; + } + + return dbuf_detach_c_str (&dbuf); +} + +static char prefix[256] = ""; +static char suffix[256] = ""; +static char cmd[4096] = ""; + +void getPrefixSuffix(const char *arg) +{ + const char *p; + const char sdcc[] = "sdcc"; + + if (!arg) + return; + + p = arg + strlen (arg); + while (p != arg && *(p - 1) != '\\' && *(p - 1) != '/') + p--; + arg = p; + + /* found no "sdcc" in command line argv[0] */ + if ((p = strstr (arg, sdcc)) == NULL) + return; + + /* found more than one "sdcc" in command line argv[0] */ + if (strstr (p + strlen (sdcc), sdcc) != NULL) + return; + + /* copy prefix and suffix */ + strncpy (prefix, arg, p - arg); + strcpy (suffix, p + strlen (sdcc)); +} + +char *setPrefixSuffix(const char *arg) +{ + const char *p; + + if (!arg) + return NULL; + else + memset (cmd, 0x00, sizeof (cmd)); + + /* find the core name of command line */ + for (p = arg; (*p) && isblank (*p); p++); + arg = p; + assert (strstr (arg, ".exe") == NULL); + for (p = arg; (*p) && !isblank (*p); p++); + + /* compose new command line with prefix and suffix */ + strcpy (cmd, prefix); + strncat (cmd, arg, p - arg); + strcat (cmd, suffix); + strcat (cmd, p); + + return cmd; +} + +char *formatInlineAsm (char *asmStr) +{ + char *p, *q; + + if (!asmStr) + return NULL; + else + q = asmStr; + + for (;;) + { + // omit leading space or tab + while (*q == '\t' || *q == ' ') + q++; + // then record the head of current line + p = q; + // search for CL or reach the end + while (*q != '\n' && *q != '\r' && *q != 0) + q++; + // omit more CL characters + while (*q == '\n' || *q == '\r') + q++; + // replace the first with tab + while (p != q) + if (*p == '\t') // '\t' appears first then no need to do + { + break; + } + else if (*p == ' ') // find the first space then replace it with tab + { + *p = '\t'; + break; + } + else // go on to search + { + p++; + } + // check if end + if (*q == 0) + return asmStr; + } +} |
