diff options
-rw-r--r-- | nasmlib.c | 63 | ||||
-rw-r--r-- | nasmlib.h | 4 | ||||
-rw-r--r-- | preproc.c | 48 | ||||
-rw-r--r-- | quote.c | 17 | ||||
-rw-r--r-- | stdscan.c | 29 |
5 files changed, 113 insertions, 48 deletions
@@ -149,31 +149,58 @@ char *nasm_strndup(char *s, size_t len) #ifndef nasm_stricmp int nasm_stricmp(const char *s1, const char *s2) { - while (*s1 && tolower(*s1) == tolower(*s2)) - s1++, s2++; - if (!*s1 && !*s2) - return 0; - else if (tolower(*s1) < tolower(*s2)) - return -1; - else - return 1; + unsigned char c1, c2; + int d; + + while (1) { + c1 = *s1++; + c2 = *s2++; + d = c1-c2; + + if (d) + return d; + if (!c1) + break; + } + return 0; } #endif #ifndef nasm_strnicmp -int nasm_strnicmp(const char *s1, const char *s2, int n) -{ - while (n > 0 && *s1 && tolower(*s1) == tolower(*s2)) - s1++, s2++, n--; - if ((!*s1 && !*s2) || n == 0) - return 0; - else if (tolower(*s1) < tolower(*s2)) - return -1; - else - return 1; +int nasm_strnicmp(const char *s1, const char *s2, size_t n) +{ + unsigned char c1, c2; + int d; + + while (n--) { + c1 = *s1++; + c2 = *s2++; + d = c1-c2; + + if (d) + return d; + if (!c1) + break; + } + return 0; } #endif +int nasm_memicmp(const char *s1, const char *s2, size_t n) +{ + unsigned char c1, c2; + int d; + + while (n--) { + c1 = tolower(*s1++); + c2 = tolower(*s2++); + d = c1-c2; + if (d) + return d; + } + return 0; +} + #ifndef nasm_strsep char *nasm_strsep(char **stringp, const char *delim) { @@ -122,9 +122,11 @@ int nasm_stricmp(const char *, const char *); #elif defined(HAVE_STRNICMP) #define nasm_strnicmp strnicmp #else -int nasm_strnicmp(const char *, const char *, int); +int nasm_strnicmp(const char *, const char *, size_t); #endif +int nasm_memicmp(const char *, const char *, size_t); + #if defined(HAVE_STRSEP) #define nasm_strsep strsep #else @@ -985,7 +985,8 @@ static void delete_Blocks(void) * back to the caller. It sets the type and text elements, and * also the mac and next elements to NULL. */ -static Token *new_Token(Token * next, enum pp_token_type type, char *text, int txtlen) +static Token *new_Token(Token * next, enum pp_token_type type, + char *text, int txtlen) { Token *t; int i; @@ -1006,8 +1007,8 @@ static Token *new_Token(Token * next, enum pp_token_type type, char *text, int t } else { if (txtlen == 0) txtlen = strlen(text); - t->text = nasm_malloc(1 + txtlen); - strncpy(t->text, text, txtlen); + t->text = nasm_malloc(txtlen+1); + memcpy(t->text, text, txtlen); t->text[txtlen] = '\0'; } return t; @@ -1144,16 +1145,12 @@ static int ppscan(void *private_data, struct tokenval *tokval) if (tline->type == TOK_STRING) { bool rn_warn; - char q, *r; - int l; + size_t l; - r = tline->text; - q = *r++; - l = strlen(r); + l = nasm_unquote(tline->text); + /* TOKEN_ERRNUM if improperly quoted... */ - if (l == 0 || r[l - 1] != q) - return tokval->t_type = TOKEN_ERRNUM; - tokval->t_integer = readstrnum(r, l - 1, &rn_warn); + tokval->t_integer = readstrnum(tline->text, l, &rn_warn); if (rn_warn) error(ERR_WARNING | ERR_PASS1, "character constant too long"); tokval->t_charptr = NULL; @@ -1205,6 +1202,16 @@ static int mstrcmp(const char *p, const char *q, bool casesense) } /* + * Compare a string to the name of an existing macro; this is a + * simple wrapper which calls either strcmp or nasm_stricmp + * depending on the value of the `casesense' parameter. + */ +static int mmemcmp(const char *p, const char *q, size_t l, bool casesense) +{ + return casesense ? memcmp(p, q, l) : nasm_memicmp(p, q, l); +} + +/* * Return the Context structure associated with a %$ token. Return * NULL, having _already_ reported an error condition, if the * context stack isn't deep enough for the supplied number of $ @@ -1511,13 +1518,20 @@ static bool if_condition(Token * tline, enum preproc_token ct) j = false; /* found mismatching tokens */ break; } - /* Unify surrounding quotes for strings */ - /* XXX: this doesn't work anymore */ + /* When comparing strings, need to unquote them first */ if (t->type == TOK_STRING) { - tt->text[0] = t->text[0]; - tt->text[strlen(tt->text) - 1] = t->text[0]; - } - if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) { + size_t l1 = nasm_unquote(t->text); + size_t l2 = nasm_unquote(tt->text); + + if (l1 != l2) { + j = false; + break; + } + if (mmemcmp(t->text, tt->text, l1, i == PPC_IFIDN)) { + j = false; + break; + } + } else if (mstrcmp(tt->text, t->text, i == PPC_IFIDN) != 0) { j = false; /* found mismatching tokens */ break; } @@ -340,6 +340,23 @@ size_t nasm_unquote(char *str) break; } } + switch (state) { + case st_start: + case st_backslash: + break; + case st_oct: + *q++ = nval; + break; + case st_hex: + *q++ = ndig ? nval : *escp; + break; + case st_ucs: + if (ndig) + q = emit_utf8(q, nval); + else + *q++ = *escp; + break; + } *q = '\0'; return q-str; } @@ -8,6 +8,7 @@ #include "nasm.h" #include "nasmlib.h" +#include "quote.h" #include "stdscan.h" #include "insns.h" @@ -166,26 +167,30 @@ int stdscan(void *private_data, struct tokenval *tv) r = stdscan_copy(r, stdscan_bufptr - r); tv->t_integer = readnum(r, &rn_error); stdscan_pop(); - if (rn_error) - return tv->t_type = TOKEN_ERRNUM; /* some malformation occurred */ + if (rn_error) { + /* some malformation occurred */ + return tv->t_type = TOKEN_ERRNUM; + } tv->t_charptr = NULL; return tv->t_type = TOKEN_NUM; } - } else if (*stdscan_bufptr == '\'' || *stdscan_bufptr == '"') { + } else if (*stdscan_bufptr == '\'' || *stdscan_bufptr == '"' || + *stdscan_bufptr == '`') { /* a char constant */ - char quote = *stdscan_bufptr++, *r; + char s; bool rn_warn; - r = tv->t_charptr = stdscan_bufptr; - while (*stdscan_bufptr && *stdscan_bufptr != quote) - stdscan_bufptr++; - tv->t_inttwo = stdscan_bufptr - r; /* store full version */ - if (!*stdscan_bufptr) + stdscan_bufptr = nasm_skip_string(tv->t_charptr = stdscan_bufptr); + s = *stdscan_bufptr; + tv->t_inttwo = nasm_unquote(tv->t_charptr); + if (!s) return tv->t_type = TOKEN_ERRNUM; /* unmatched quotes */ stdscan_bufptr++; /* skip over final quote */ - tv->t_integer = readstrnum(r, tv->t_inttwo, &rn_warn); - /* rn_warn is not checked on purpose; it might not be a valid number */ + tv->t_integer = readstrnum(tv->t_charptr, tv->t_inttwo, &rn_warn); + /* Issue: can't readily check rn_warn, because we might be in + a db family context... */ return tv->t_type = TOKEN_NUM; - } else if (*stdscan_bufptr == ';') { /* a comment has happened - stay */ + } else if (*stdscan_bufptr == ';') { + /* a comment has happened - stay */ return tv->t_type = 0; } else if (stdscan_bufptr[0] == '>' && stdscan_bufptr[1] == '>') { stdscan_bufptr += 2; |