diff options
author | somov <[email protected]> | 2022-02-10 16:45:47 +0300 |
---|---|---|
committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:45:47 +0300 |
commit | a5950576e397b1909261050b8c7da16db58f10b1 (patch) | |
tree | 7ba7677f6a4c3e19e2cefab34d16df2c8963b4d4 /contrib/tools/yasm/libyasm/file.c | |
parent | 81eddc8c0b55990194e112b02d127b87d54164a9 (diff) |
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/yasm/libyasm/file.c')
-rw-r--r-- | contrib/tools/yasm/libyasm/file.c | 1342 |
1 files changed, 671 insertions, 671 deletions
diff --git a/contrib/tools/yasm/libyasm/file.c b/contrib/tools/yasm/libyasm/file.c index fc7dab6c17e..c4adde0a3a7 100644 --- a/contrib/tools/yasm/libyasm/file.c +++ b/contrib/tools/yasm/libyasm/file.c @@ -1,672 +1,672 @@ -/* - * File helper functions. - * - * Copyright (C) 2001-2007 Peter Johnson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include <util.h> - -/* Need either unistd.h or direct.h to prototype getcwd() and mkdir() */ -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef HAVE_DIRECT_H -#include <direct.h> -#endif - -#ifdef _WIN32 -#include <io.h> -#endif - -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#include <ctype.h> -#include <errno.h> - -#include "errwarn.h" -#include "file.h" - -#define BSIZE 8192 /* Fill block size */ - - -void -yasm_scanner_initialize(yasm_scanner *s) -{ - s->bot = NULL; - s->tok = NULL; - s->ptr = NULL; - s->cur = NULL; - s->lim = NULL; - s->top = NULL; - s->eof = NULL; -} - -void -yasm_scanner_delete(yasm_scanner *s) -{ - if (s->bot) { - yasm_xfree(s->bot); - s->bot = NULL; - } -} - -int -yasm_fill_helper(yasm_scanner *s, unsigned char **cursor, - size_t (*input_func) (void *d, unsigned char *buf, - size_t max), - void *input_func_data) -{ - size_t cnt; - int first = 0; - - if (s->eof) - return 0; - - cnt = s->tok - s->bot; - if (cnt > 0) { - memmove(s->bot, s->tok, (size_t)(s->lim - s->tok)); - s->tok = s->bot; - s->ptr -= cnt; - *cursor -= cnt; - s->lim -= cnt; - } - if (!s->bot) - first = 1; - if ((s->top - s->lim) < BSIZE) { - unsigned char *buf = yasm_xmalloc((size_t)(s->lim - s->bot) + BSIZE); - memcpy(buf, s->tok, (size_t)(s->lim - s->tok)); - s->tok = buf; - s->ptr = &buf[s->ptr - s->bot]; - *cursor = &buf[*cursor - s->bot]; - s->lim = &buf[s->lim - s->bot]; - s->top = &s->lim[BSIZE]; - if (s->bot) - yasm_xfree(s->bot); - s->bot = buf; - } - if ((cnt = input_func(input_func_data, s->lim, BSIZE)) == 0) { - s->eof = &s->lim[cnt]; - *s->eof++ = '\n'; - } - s->lim += cnt; - return first; -} - -void -yasm_unescape_cstring(unsigned char *str, size_t *len) -{ - unsigned char *s = str; - unsigned char *o = str; - unsigned char t[4]; - - while ((size_t)(s-str)<*len) { - if (*s == '\\' && (size_t)(&s[1]-str)<*len) { - s++; - switch (*s) { - case 'b': *o = '\b'; s++; break; - case 'f': *o = '\f'; s++; break; - case 'n': *o = '\n'; s++; break; - case 'r': *o = '\r'; s++; break; - case 't': *o = '\t'; s++; break; - case 'x': - /* hex escape; grab last two digits */ - s++; - while ((size_t)(&s[2]-str)<*len && isxdigit(s[0]) - && isxdigit(s[1]) && isxdigit(s[2])) - s++; - if ((size_t)(s-str)<*len && isxdigit(*s)) { - t[0] = *s++; - t[1] = '\0'; - t[2] = '\0'; - if ((size_t)(s-str)<*len && isxdigit(*s)) - t[1] = *s++; - *o = (unsigned char)strtoul((char *)t, NULL, 16); - } else - *o = '\0'; - break; - default: - if (isdigit(*s)) { - int warn = 0; - /* octal escape */ - if (*s > '7') - warn = 1; - *o = *s++ - '0'; - if ((size_t)(s-str)<*len && isdigit(*s)) { - if (*s > '7') - warn = 1; - *o <<= 3; - *o += *s++ - '0'; - if ((size_t)(s-str)<*len && isdigit(*s)) { - if (*s > '7') - warn = 1; - *o <<= 3; - *o += *s++ - '0'; - } - } - if (warn) - yasm_warn_set(YASM_WARN_GENERAL, - N_("octal value out of range")); - } else - *o = *s++; - break; - } - o++; - } else - *o++ = *s++; - } - *len = o-str; -} - -size_t -yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail) -{ - const char *s; - s = strrchr(path, '/'); - if (!s) { - /* No head */ - *tail = path; - return 0; - } - *tail = s+1; - /* Strip trailing ./ on path */ - while ((s-1)>=path && *(s-1) == '.' && *s == '/' - && !((s-2)>=path && *(s-2) == '.')) - s -= 2; - /* Strip trailing slashes on path (except leading) */ - while (s>path && *s == '/') - s--; - /* Return length of head */ - return s-path+1; -} - -size_t -yasm__splitpath_win(const char *path, /*@out@*/ const char **tail) -{ - const char *basepath = path; - const char *s; - - /* split off drive letter first, if any */ - if (isalpha(path[0]) && path[1] == ':') - basepath += 2; - - s = basepath; - while (*s != '\0') - s++; - while (s >= basepath && *s != '\\' && *s != '/') - s--; - if (s < basepath) { - *tail = basepath; - if (path == basepath) - return 0; /* No head */ - else - return 2; /* Drive letter is head */ - } - *tail = s+1; - /* Strip trailing .\ or ./ on path */ - while ((s-1)>=basepath && *(s-1) == '.' && (*s == '/' || *s == '\\') - && !((s-2)>=basepath && *(s-2) == '.')) - s -= 2; - /* Strip trailing slashes on path (except leading) */ - while (s>basepath && (*s == '/' || *s == '\\')) - s--; - /* Return length of head */ - return s-path+1; -} - -char * -yasm__getcwd(void) -{ - char *buf; - size_t size; - - size = 1024; - buf = yasm_xmalloc(size); - - if (getenv("YASM_TEST_SUITE")) { - strcpy(buf, "./"); - return buf; - } - - while (getcwd(buf, size-1) == NULL) { - if (errno != ERANGE) { - yasm__fatal(N_("could not determine current working directory")); - yasm_xfree(buf); - return NULL; - } - size *= 2; - buf = yasm_xrealloc(buf, size); - } - - /* append a '/' if not already present */ - size = strlen(buf); - if (buf[size-1] != '\\' && buf[size-1] != '/') { - buf[size] = '/'; - buf[size+1] = '\0'; - } - return buf; -} - -char * -yasm__abspath(const char *path) -{ - char *curdir, *abspath; - - curdir = yasm__getcwd(); - abspath = yasm__combpath(curdir, path); - yasm_xfree(curdir); - - return abspath; -} - -char * -yasm__combpath_unix(const char *from, const char *to) -{ - const char *tail; - size_t pathlen, i, j; - char *out; - - if (to[0] == '/') { - /* absolute "to" */ - out = yasm_xmalloc(strlen(to)+1); - /* Combine any double slashes when copying */ - for (j=0; *to; to++) { - if (*to == '/' && *(to+1) == '/') - continue; - out[j++] = *to; - } - out[j++] = '\0'; - return out; - } - - /* Get path component; note this strips trailing slash */ - pathlen = yasm__splitpath_unix(from, &tail); - - out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */ - - /* Combine any double slashes when copying */ - for (i=0, j=0; i<pathlen; i++) { - if (i<pathlen-1 && from[i] == '/' && from[i+1] == '/') - continue; - out[j++] = from[i]; - } - pathlen = j; - - /* Add trailing slash back in */ - if (pathlen > 0 && out[pathlen-1] != '/') - out[pathlen++] = '/'; - - /* Now scan from left to right through "to", stripping off "." and ".."; - * if we see "..", back up one directory in out unless last directory in - * out is also "..". - * - * Note this does NOT back through ..'s in the "from" path; this is just - * as well as that could skip symlinks (e.g. "foo/bar/.." might not be - * the same as "foo"). - */ - for (;;) { - if (to[0] == '.' && to[1] == '/') { - to += 2; /* current directory */ - while (*to == '/') - to++; /* strip off any additional slashes */ - } else if (pathlen == 0) - break; /* no more "from" path left, we're done */ - else if (to[0] == '.' && to[1] == '.' && to[2] == '/') { - if (pathlen >= 3 && out[pathlen-1] == '/' && out[pathlen-2] == '.' - && out[pathlen-3] == '.') { - /* can't ".." against a "..", so we're done. */ - break; - } - - to += 3; /* throw away "../" */ - while (*to == '/') - to++; /* strip off any additional slashes */ - - /* and back out last directory in "out" if not already at root */ - if (pathlen > 1) { - pathlen--; /* strip off trailing '/' */ - while (pathlen > 0 && out[pathlen-1] != '/') - pathlen--; - } - } else - break; - } - - /* Copy "to" to tail of output, and we're done */ - /* Combine any double slashes when copying */ - for (j=pathlen; *to; to++) { - if (*to == '/' && *(to+1) == '/') - continue; - out[j++] = *to; - } - out[j++] = '\0'; - - return out; -} - -char * -yasm__combpath_win(const char *from, const char *to) -{ - const char *tail; - size_t pathlen, i, j; - char *out; - - if ((isalpha(to[0]) && to[1] == ':') || (to[0] == '/' || to[0] == '\\')) { - /* absolute or drive letter "to" */ - out = yasm_xmalloc(strlen(to)+1); - /* Combine any double slashes when copying */ - for (j=0; *to; to++) { - if ((*to == '/' || *to == '\\') - && (*(to+1) == '/' || *(to+1) == '\\')) - continue; - if (*to == '/') - out[j++] = '\\'; - else - out[j++] = *to; - } - out[j++] = '\0'; - return out; - } - - /* Get path component; note this strips trailing slash */ - pathlen = yasm__splitpath_win(from, &tail); - - out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */ - - /* Combine any double slashes when copying */ - for (i=0, j=0; i<pathlen; i++) { - if (i<pathlen-1 && (from[i] == '/' || from[i] == '\\') - && (from[i+1] == '/' || from[i+1] == '\\')) - continue; - if (from[i] == '/') - out[j++] = '\\'; - else - out[j++] = from[i]; - } - pathlen = j; - - /* Add trailing slash back in, unless it's only a raw drive letter */ - if (pathlen > 0 && out[pathlen-1] != '\\' - && !(pathlen == 2 && isalpha(out[0]) && out[1] == ':')) - out[pathlen++] = '\\'; - - /* Now scan from left to right through "to", stripping off "." and ".."; - * if we see "..", back up one directory in out unless last directory in - * out is also "..". - * - * Note this does NOT back through ..'s in the "from" path; this is just - * as well as that could skip symlinks (e.g. "foo/bar/.." might not be - * the same as "foo"). - */ - for (;;) { - if (to[0] == '.' && (to[1] == '/' || to[1] == '\\')) { - to += 2; /* current directory */ - while (*to == '/' || *to == '\\') - to++; /* strip off any additional slashes */ - } else if (pathlen == 0 - || (pathlen == 2 && isalpha(out[0]) && out[1] == ':')) - break; /* no more "from" path left, we're done */ - else if (to[0] == '.' && to[1] == '.' - && (to[2] == '/' || to[2] == '\\')) { - if (pathlen >= 3 && out[pathlen-1] == '\\' - && out[pathlen-2] == '.' && out[pathlen-3] == '.') { - /* can't ".." against a "..", so we're done. */ - break; - } - - to += 3; /* throw away "../" (or "..\") */ - while (*to == '/' || *to == '\\') - to++; /* strip off any additional slashes */ - - /* and back out last directory in "out" if not already at root */ - if (pathlen > 1) { - pathlen--; /* strip off trailing '/' */ - while (pathlen > 0 && out[pathlen-1] != '\\') - pathlen--; - } - } else - break; - } - - /* Copy "to" to tail of output, and we're done */ - /* Combine any double slashes when copying */ - for (j=pathlen; *to; to++) { - if ((*to == '/' || *to == '\\') && (*(to+1) == '/' || *(to+1) == '\\')) - continue; - if (*to == '/') - out[j++] = '\\'; - else - out[j++] = *to; - } - out[j++] = '\0'; - - return out; -} - -size_t -yasm__createpath_common(const char *path, int win) -{ - const char *pp = path, *pe; - char *ts, *tp; - size_t len, lth; - - lth = len = strlen(path); - ts = tp = (char *) malloc(len + 1); - pe = pp + len; - while (pe > pp) { - if ((win && *pe == '\\') || *pe == '/') - break; - --pe; - --lth; - } - - while (pp <= pe) { - if (pp == pe || (win && *pp == '\\') || *pp == '/') { -#ifdef _WIN32 - struct _finddata_t fi; - intptr_t h; +/* + * File helper functions. + * + * Copyright (C) 2001-2007 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include <util.h> + +/* Need either unistd.h or direct.h to prototype getcwd() and mkdir() */ +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_DIRECT_H +#include <direct.h> +#endif + +#ifdef _WIN32 +#include <io.h> +#endif + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#include <ctype.h> +#include <errno.h> + +#include "errwarn.h" +#include "file.h" + +#define BSIZE 8192 /* Fill block size */ + + +void +yasm_scanner_initialize(yasm_scanner *s) +{ + s->bot = NULL; + s->tok = NULL; + s->ptr = NULL; + s->cur = NULL; + s->lim = NULL; + s->top = NULL; + s->eof = NULL; +} + +void +yasm_scanner_delete(yasm_scanner *s) +{ + if (s->bot) { + yasm_xfree(s->bot); + s->bot = NULL; + } +} + +int +yasm_fill_helper(yasm_scanner *s, unsigned char **cursor, + size_t (*input_func) (void *d, unsigned char *buf, + size_t max), + void *input_func_data) +{ + size_t cnt; + int first = 0; + + if (s->eof) + return 0; + + cnt = s->tok - s->bot; + if (cnt > 0) { + memmove(s->bot, s->tok, (size_t)(s->lim - s->tok)); + s->tok = s->bot; + s->ptr -= cnt; + *cursor -= cnt; + s->lim -= cnt; + } + if (!s->bot) + first = 1; + if ((s->top - s->lim) < BSIZE) { + unsigned char *buf = yasm_xmalloc((size_t)(s->lim - s->bot) + BSIZE); + memcpy(buf, s->tok, (size_t)(s->lim - s->tok)); + s->tok = buf; + s->ptr = &buf[s->ptr - s->bot]; + *cursor = &buf[*cursor - s->bot]; + s->lim = &buf[s->lim - s->bot]; + s->top = &s->lim[BSIZE]; + if (s->bot) + yasm_xfree(s->bot); + s->bot = buf; + } + if ((cnt = input_func(input_func_data, s->lim, BSIZE)) == 0) { + s->eof = &s->lim[cnt]; + *s->eof++ = '\n'; + } + s->lim += cnt; + return first; +} + +void +yasm_unescape_cstring(unsigned char *str, size_t *len) +{ + unsigned char *s = str; + unsigned char *o = str; + unsigned char t[4]; + + while ((size_t)(s-str)<*len) { + if (*s == '\\' && (size_t)(&s[1]-str)<*len) { + s++; + switch (*s) { + case 'b': *o = '\b'; s++; break; + case 'f': *o = '\f'; s++; break; + case 'n': *o = '\n'; s++; break; + case 'r': *o = '\r'; s++; break; + case 't': *o = '\t'; s++; break; + case 'x': + /* hex escape; grab last two digits */ + s++; + while ((size_t)(&s[2]-str)<*len && isxdigit(s[0]) + && isxdigit(s[1]) && isxdigit(s[2])) + s++; + if ((size_t)(s-str)<*len && isxdigit(*s)) { + t[0] = *s++; + t[1] = '\0'; + t[2] = '\0'; + if ((size_t)(s-str)<*len && isxdigit(*s)) + t[1] = *s++; + *o = (unsigned char)strtoul((char *)t, NULL, 16); + } else + *o = '\0'; + break; + default: + if (isdigit(*s)) { + int warn = 0; + /* octal escape */ + if (*s > '7') + warn = 1; + *o = *s++ - '0'; + if ((size_t)(s-str)<*len && isdigit(*s)) { + if (*s > '7') + warn = 1; + *o <<= 3; + *o += *s++ - '0'; + if ((size_t)(s-str)<*len && isdigit(*s)) { + if (*s > '7') + warn = 1; + *o <<= 3; + *o += *s++ - '0'; + } + } + if (warn) + yasm_warn_set(YASM_WARN_GENERAL, + N_("octal value out of range")); + } else + *o = *s++; + break; + } + o++; + } else + *o++ = *s++; + } + *len = o-str; +} + +size_t +yasm__splitpath_unix(const char *path, /*@out@*/ const char **tail) +{ + const char *s; + s = strrchr(path, '/'); + if (!s) { + /* No head */ + *tail = path; + return 0; + } + *tail = s+1; + /* Strip trailing ./ on path */ + while ((s-1)>=path && *(s-1) == '.' && *s == '/' + && !((s-2)>=path && *(s-2) == '.')) + s -= 2; + /* Strip trailing slashes on path (except leading) */ + while (s>path && *s == '/') + s--; + /* Return length of head */ + return s-path+1; +} + +size_t +yasm__splitpath_win(const char *path, /*@out@*/ const char **tail) +{ + const char *basepath = path; + const char *s; + + /* split off drive letter first, if any */ + if (isalpha(path[0]) && path[1] == ':') + basepath += 2; + + s = basepath; + while (*s != '\0') + s++; + while (s >= basepath && *s != '\\' && *s != '/') + s--; + if (s < basepath) { + *tail = basepath; + if (path == basepath) + return 0; /* No head */ + else + return 2; /* Drive letter is head */ + } + *tail = s+1; + /* Strip trailing .\ or ./ on path */ + while ((s-1)>=basepath && *(s-1) == '.' && (*s == '/' || *s == '\\') + && !((s-2)>=basepath && *(s-2) == '.')) + s -= 2; + /* Strip trailing slashes on path (except leading) */ + while (s>basepath && (*s == '/' || *s == '\\')) + s--; + /* Return length of head */ + return s-path+1; +} + +char * +yasm__getcwd(void) +{ + char *buf; + size_t size; + + size = 1024; + buf = yasm_xmalloc(size); + + if (getenv("YASM_TEST_SUITE")) { + strcpy(buf, "./"); + return buf; + } + + while (getcwd(buf, size-1) == NULL) { + if (errno != ERANGE) { + yasm__fatal(N_("could not determine current working directory")); + yasm_xfree(buf); + return NULL; + } + size *= 2; + buf = yasm_xrealloc(buf, size); + } + + /* append a '/' if not already present */ + size = strlen(buf); + if (buf[size-1] != '\\' && buf[size-1] != '/') { + buf[size] = '/'; + buf[size+1] = '\0'; + } + return buf; +} + +char * +yasm__abspath(const char *path) +{ + char *curdir, *abspath; + + curdir = yasm__getcwd(); + abspath = yasm__combpath(curdir, path); + yasm_xfree(curdir); + + return abspath; +} + +char * +yasm__combpath_unix(const char *from, const char *to) +{ + const char *tail; + size_t pathlen, i, j; + char *out; + + if (to[0] == '/') { + /* absolute "to" */ + out = yasm_xmalloc(strlen(to)+1); + /* Combine any double slashes when copying */ + for (j=0; *to; to++) { + if (*to == '/' && *(to+1) == '/') + continue; + out[j++] = *to; + } + out[j++] = '\0'; + return out; + } + + /* Get path component; note this strips trailing slash */ + pathlen = yasm__splitpath_unix(from, &tail); + + out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */ + + /* Combine any double slashes when copying */ + for (i=0, j=0; i<pathlen; i++) { + if (i<pathlen-1 && from[i] == '/' && from[i+1] == '/') + continue; + out[j++] = from[i]; + } + pathlen = j; + + /* Add trailing slash back in */ + if (pathlen > 0 && out[pathlen-1] != '/') + out[pathlen++] = '/'; + + /* Now scan from left to right through "to", stripping off "." and ".."; + * if we see "..", back up one directory in out unless last directory in + * out is also "..". + * + * Note this does NOT back through ..'s in the "from" path; this is just + * as well as that could skip symlinks (e.g. "foo/bar/.." might not be + * the same as "foo"). + */ + for (;;) { + if (to[0] == '.' && to[1] == '/') { + to += 2; /* current directory */ + while (*to == '/') + to++; /* strip off any additional slashes */ + } else if (pathlen == 0) + break; /* no more "from" path left, we're done */ + else if (to[0] == '.' && to[1] == '.' && to[2] == '/') { + if (pathlen >= 3 && out[pathlen-1] == '/' && out[pathlen-2] == '.' + && out[pathlen-3] == '.') { + /* can't ".." against a "..", so we're done. */ + break; + } + + to += 3; /* throw away "../" */ + while (*to == '/') + to++; /* strip off any additional slashes */ + + /* and back out last directory in "out" if not already at root */ + if (pathlen > 1) { + pathlen--; /* strip off trailing '/' */ + while (pathlen > 0 && out[pathlen-1] != '/') + pathlen--; + } + } else + break; + } + + /* Copy "to" to tail of output, and we're done */ + /* Combine any double slashes when copying */ + for (j=pathlen; *to; to++) { + if (*to == '/' && *(to+1) == '/') + continue; + out[j++] = *to; + } + out[j++] = '\0'; + + return out; +} + +char * +yasm__combpath_win(const char *from, const char *to) +{ + const char *tail; + size_t pathlen, i, j; + char *out; + + if ((isalpha(to[0]) && to[1] == ':') || (to[0] == '/' || to[0] == '\\')) { + /* absolute or drive letter "to" */ + out = yasm_xmalloc(strlen(to)+1); + /* Combine any double slashes when copying */ + for (j=0; *to; to++) { + if ((*to == '/' || *to == '\\') + && (*(to+1) == '/' || *(to+1) == '\\')) + continue; + if (*to == '/') + out[j++] = '\\'; + else + out[j++] = *to; + } + out[j++] = '\0'; + return out; + } + + /* Get path component; note this strips trailing slash */ + pathlen = yasm__splitpath_win(from, &tail); + + out = yasm_xmalloc(pathlen+strlen(to)+2); /* worst case maximum len */ + + /* Combine any double slashes when copying */ + for (i=0, j=0; i<pathlen; i++) { + if (i<pathlen-1 && (from[i] == '/' || from[i] == '\\') + && (from[i+1] == '/' || from[i+1] == '\\')) + continue; + if (from[i] == '/') + out[j++] = '\\'; + else + out[j++] = from[i]; + } + pathlen = j; + + /* Add trailing slash back in, unless it's only a raw drive letter */ + if (pathlen > 0 && out[pathlen-1] != '\\' + && !(pathlen == 2 && isalpha(out[0]) && out[1] == ':')) + out[pathlen++] = '\\'; + + /* Now scan from left to right through "to", stripping off "." and ".."; + * if we see "..", back up one directory in out unless last directory in + * out is also "..". + * + * Note this does NOT back through ..'s in the "from" path; this is just + * as well as that could skip symlinks (e.g. "foo/bar/.." might not be + * the same as "foo"). + */ + for (;;) { + if (to[0] == '.' && (to[1] == '/' || to[1] == '\\')) { + to += 2; /* current directory */ + while (*to == '/' || *to == '\\') + to++; /* strip off any additional slashes */ + } else if (pathlen == 0 + || (pathlen == 2 && isalpha(out[0]) && out[1] == ':')) + break; /* no more "from" path left, we're done */ + else if (to[0] == '.' && to[1] == '.' + && (to[2] == '/' || to[2] == '\\')) { + if (pathlen >= 3 && out[pathlen-1] == '\\' + && out[pathlen-2] == '.' && out[pathlen-3] == '.') { + /* can't ".." against a "..", so we're done. */ + break; + } + + to += 3; /* throw away "../" (or "..\") */ + while (*to == '/' || *to == '\\') + to++; /* strip off any additional slashes */ + + /* and back out last directory in "out" if not already at root */ + if (pathlen > 1) { + pathlen--; /* strip off trailing '/' */ + while (pathlen > 0 && out[pathlen-1] != '\\') + pathlen--; + } + } else + break; + } + + /* Copy "to" to tail of output, and we're done */ + /* Combine any double slashes when copying */ + for (j=pathlen; *to; to++) { + if ((*to == '/' || *to == '\\') && (*(to+1) == '/' || *(to+1) == '\\')) + continue; + if (*to == '/') + out[j++] = '\\'; + else + out[j++] = *to; + } + out[j++] = '\0'; + + return out; +} + +size_t +yasm__createpath_common(const char *path, int win) +{ + const char *pp = path, *pe; + char *ts, *tp; + size_t len, lth; + + lth = len = strlen(path); + ts = tp = (char *) malloc(len + 1); + pe = pp + len; + while (pe > pp) { + if ((win && *pe == '\\') || *pe == '/') + break; + --pe; + --lth; + } + + while (pp <= pe) { + if (pp == pe || (win && *pp == '\\') || *pp == '/') { +#ifdef _WIN32 + struct _finddata_t fi; + intptr_t h; +#elif defined(HAVE_SYS_STAT_H) + struct stat fi; +#endif + *tp = '\0'; + +#ifdef _WIN32 + h = _findfirst(ts, &fi); + if (h != -1) { + if (fi.attrib != _A_SUBDIR) { + _findclose(h); + break; + } + } else if (errno == ENOENT) { + if (_mkdir(ts) == -1) { + _findclose(h); + lth = -1; + break; + } + } + _findclose(h); #elif defined(HAVE_SYS_STAT_H) - struct stat fi; -#endif - *tp = '\0'; - -#ifdef _WIN32 - h = _findfirst(ts, &fi); - if (h != -1) { - if (fi.attrib != _A_SUBDIR) { - _findclose(h); - break; - } - } else if (errno == ENOENT) { - if (_mkdir(ts) == -1) { - _findclose(h); - lth = -1; - break; - } - } - _findclose(h); -#elif defined(HAVE_SYS_STAT_H) - if (stat(ts, &fi) != -1) { - if (!S_ISDIR(fi.st_mode)) - break; - } else if (errno == ENOENT) { - if (mkdir(ts, 0755) == -1) { - lth = 0; - break; - } - } -#else - break; -#endif - } - *tp++ = *pp++; - } - free(ts); - return lth; -} - -typedef struct incpath { - STAILQ_ENTRY(incpath) link; - /*@owned@*/ char *path; -} incpath; - -STAILQ_HEAD(incpath_head, incpath) incpaths = STAILQ_HEAD_INITIALIZER(incpaths); - -FILE * -yasm_fopen_include(const char *iname, const char *from, const char *mode, - char **oname) -{ - FILE *f; - char *combine; - incpath *np; - - /* Try directly relative to from first, then each of the include paths */ - if (from) { - combine = yasm__combpath(from, iname); - f = fopen(combine, mode); - if (f) { - if (oname) - *oname = combine; - else - yasm_xfree(combine); - return f; - } - yasm_xfree(combine); - } - - STAILQ_FOREACH(np, &incpaths, link) { - combine = yasm__combpath(np->path, iname); - f = fopen(combine, mode); - if (f) { - if (oname) - *oname = combine; - else - yasm_xfree(combine); - return f; - } - yasm_xfree(combine); - } - - if (oname) - *oname = NULL; - return NULL; -} - -void -yasm_delete_include_paths(void) -{ - incpath *n1, *n2; - - n1 = STAILQ_FIRST(&incpaths); - while (n1) { - n2 = STAILQ_NEXT(n1, link); - yasm_xfree(n1->path); - yasm_xfree(n1); - n1 = n2; - } - STAILQ_INIT(&incpaths); -} - -const char * -yasm_get_include_dir(void **iter) -{ - incpath *p = (incpath *)*iter; - - if (!p) - p = STAILQ_FIRST(&incpaths); - else - p = STAILQ_NEXT(p, link); - - *iter = p; - if (p) - return p->path; - else - return NULL; -} - -void -yasm_add_include_path(const char *path) -{ - incpath *np = yasm_xmalloc(sizeof(incpath)); - size_t len = strlen(path); - - np->path = yasm_xmalloc(len+2); - memcpy(np->path, path, len+1); - /* Add trailing slash if it is missing */ - if (path[len-1] != '\\' && path[len-1] != '/') { - np->path[len] = '/'; - np->path[len+1] = '\0'; - } - - STAILQ_INSERT_TAIL(&incpaths, np, link); -} - -size_t -yasm_fwrite_16_l(unsigned short val, FILE *f) -{ - if (fputc(val & 0xFF, f) == EOF) - return 0; - if (fputc((val >> 8) & 0xFF, f) == EOF) - return 0; - return 1; -} - -size_t -yasm_fwrite_32_l(unsigned long val, FILE *f) -{ - if (fputc((int)(val & 0xFF), f) == EOF) - return 0; - if (fputc((int)((val >> 8) & 0xFF), f) == EOF) - return 0; - if (fputc((int)((val >> 16) & 0xFF), f) == EOF) - return 0; - if (fputc((int)((val >> 24) & 0xFF), f) == EOF) - return 0; - return 1; -} - -size_t -yasm_fwrite_16_b(unsigned short val, FILE *f) -{ - if (fputc((val >> 8) & 0xFF, f) == EOF) - return 0; - if (fputc(val & 0xFF, f) == EOF) - return 0; - return 1; -} - -size_t -yasm_fwrite_32_b(unsigned long val, FILE *f) -{ - if (fputc((int)((val >> 24) & 0xFF), f) == EOF) - return 0; - if (fputc((int)((val >> 16) & 0xFF), f) == EOF) - return 0; - if (fputc((int)((val >> 8) & 0xFF), f) == EOF) - return 0; - if (fputc((int)(val & 0xFF), f) == EOF) - return 0; - return 1; -} + if (stat(ts, &fi) != -1) { + if (!S_ISDIR(fi.st_mode)) + break; + } else if (errno == ENOENT) { + if (mkdir(ts, 0755) == -1) { + lth = 0; + break; + } + } +#else + break; +#endif + } + *tp++ = *pp++; + } + free(ts); + return lth; +} + +typedef struct incpath { + STAILQ_ENTRY(incpath) link; + /*@owned@*/ char *path; +} incpath; + +STAILQ_HEAD(incpath_head, incpath) incpaths = STAILQ_HEAD_INITIALIZER(incpaths); + +FILE * +yasm_fopen_include(const char *iname, const char *from, const char *mode, + char **oname) +{ + FILE *f; + char *combine; + incpath *np; + + /* Try directly relative to from first, then each of the include paths */ + if (from) { + combine = yasm__combpath(from, iname); + f = fopen(combine, mode); + if (f) { + if (oname) + *oname = combine; + else + yasm_xfree(combine); + return f; + } + yasm_xfree(combine); + } + + STAILQ_FOREACH(np, &incpaths, link) { + combine = yasm__combpath(np->path, iname); + f = fopen(combine, mode); + if (f) { + if (oname) + *oname = combine; + else + yasm_xfree(combine); + return f; + } + yasm_xfree(combine); + } + + if (oname) + *oname = NULL; + return NULL; +} + +void +yasm_delete_include_paths(void) +{ + incpath *n1, *n2; + + n1 = STAILQ_FIRST(&incpaths); + while (n1) { + n2 = STAILQ_NEXT(n1, link); + yasm_xfree(n1->path); + yasm_xfree(n1); + n1 = n2; + } + STAILQ_INIT(&incpaths); +} + +const char * +yasm_get_include_dir(void **iter) +{ + incpath *p = (incpath *)*iter; + + if (!p) + p = STAILQ_FIRST(&incpaths); + else + p = STAILQ_NEXT(p, link); + + *iter = p; + if (p) + return p->path; + else + return NULL; +} + +void +yasm_add_include_path(const char *path) +{ + incpath *np = yasm_xmalloc(sizeof(incpath)); + size_t len = strlen(path); + + np->path = yasm_xmalloc(len+2); + memcpy(np->path, path, len+1); + /* Add trailing slash if it is missing */ + if (path[len-1] != '\\' && path[len-1] != '/') { + np->path[len] = '/'; + np->path[len+1] = '\0'; + } + + STAILQ_INSERT_TAIL(&incpaths, np, link); +} + +size_t +yasm_fwrite_16_l(unsigned short val, FILE *f) +{ + if (fputc(val & 0xFF, f) == EOF) + return 0; + if (fputc((val >> 8) & 0xFF, f) == EOF) + return 0; + return 1; +} + +size_t +yasm_fwrite_32_l(unsigned long val, FILE *f) +{ + if (fputc((int)(val & 0xFF), f) == EOF) + return 0; + if (fputc((int)((val >> 8) & 0xFF), f) == EOF) + return 0; + if (fputc((int)((val >> 16) & 0xFF), f) == EOF) + return 0; + if (fputc((int)((val >> 24) & 0xFF), f) == EOF) + return 0; + return 1; +} + +size_t +yasm_fwrite_16_b(unsigned short val, FILE *f) +{ + if (fputc((val >> 8) & 0xFF, f) == EOF) + return 0; + if (fputc(val & 0xFF, f) == EOF) + return 0; + return 1; +} + +size_t +yasm_fwrite_32_b(unsigned long val, FILE *f) +{ + if (fputc((int)((val >> 24) & 0xFF), f) == EOF) + return 0; + if (fputc((int)((val >> 16) & 0xFF), f) == EOF) + return 0; + if (fputc((int)((val >> 8) & 0xFF), f) == EOF) + return 0; + if (fputc((int)(val & 0xFF), f) == EOF) + return 0; + return 1; +} |