X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=labels.c;h=98408b473262b4166971f1fddf7b95a27e6bb836;hb=HEAD;hp=d907b352caef07da6889b61d106d85326fe0b116;hpb=70055964fc24699c07c515dd9a603196ba06a654;p=platform%2Fupstream%2Fnasm.git diff --git a/labels.c b/labels.c index d907b35..98408b4 100644 --- a/labels.c +++ b/labels.c @@ -1,9 +1,38 @@ -/* labels.c label handling for the Netwide Assembler +/* ----------------------------------------------------------------------- * * - * The Netwide Assembler is copyright (C) 1996 Simon Tatham and - * Julian Hall. All rights reserved. The software is - * redistributable under the licence given in the file "Licence" - * distributed in the NASM archive. + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 COPYRIGHT HOLDERS AND + * 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 COPYRIGHT OWNER OR + * 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. + * + * ----------------------------------------------------------------------- */ + +/* + * labels.c label handling for the Netwide Assembler */ #include "compiler.h" @@ -25,46 +54,49 @@ * @@, so @@local is a TASM compatible local label. Note that we only * check for the first @ symbol, although TASM requires both. */ -#define islocal(l) \ - (tasm_compatible_mode ? \ - (((l)[0] == '.' || (l)[0] == '@') && (l)[1] != '.') : \ - ((l)[0] == '.' && (l)[1] != '.')) -#define islocalchar(c) \ - (tasm_compatible_mode ? \ - ((c) == '.' || (c) == '@') : \ - ((c) == '.')) - -#define LABEL_BLOCK 128 /* no. of labels/block */ -#define LBLK_SIZE (LABEL_BLOCK*sizeof(union label)) - -#define END_LIST -3 /* don't clash with NO_SEG! */ -#define END_BLOCK -2 -#define BOGUS_VALUE -4 - -#define PERMTS_SIZE 4096 /* size of text blocks */ -#if (PERMTS_SIZE > IDLEN_MAX) -#error "IPERMTS_SIZE must be less than or equal to IDLEN_MAX" +#define islocal(l) \ + (tasm_compatible_mode ? \ + (((l)[0] == '.' || (l)[0] == '@') && (l)[1] != '.') : \ + ((l)[0] == '.' && (l)[1] != '.')) +#define islocalchar(c) \ + (tasm_compatible_mode ? \ + ((c) == '.' || (c) == '@') : \ + ((c) == '.')) + +#define LABEL_BLOCK 128 /* no. of labels/block */ +#define LBLK_SIZE (LABEL_BLOCK * sizeof(union label)) + +#define END_LIST -3 /* don't clash with NO_SEG! */ +#define END_BLOCK -2 +#define BOGUS_VALUE -4 + +#define PERMTS_SIZE 16384 /* size of text blocks */ +#if (PERMTS_SIZE < IDLEN_MAX) + #error "IPERMTS_SIZE must be greater than or equal to IDLEN_MAX" #endif /* values for label.defn.is_global */ -#define DEFINED_BIT 1 -#define GLOBAL_BIT 2 -#define EXTERN_BIT 4 +#define DEFINED_BIT 1 +#define GLOBAL_BIT 2 +#define EXTERN_BIT 4 +#define COMMON_BIT 8 -#define NOT_DEFINED_YET 0 -#define TYPE_MASK 3 -#define LOCAL_SYMBOL (DEFINED_BIT) -#define GLOBAL_PLACEHOLDER (GLOBAL_BIT) -#define GLOBAL_SYMBOL (DEFINED_BIT|GLOBAL_BIT) +#define NOT_DEFINED_YET 0 +#define TYPE_MASK 3 +#define LOCAL_SYMBOL (DEFINED_BIT) +#define GLOBAL_PLACEHOLDER (GLOBAL_BIT) +#define GLOBAL_SYMBOL (DEFINED_BIT | GLOBAL_BIT) union label { /* actual label structures */ struct { - int32_t segment, offset; + int32_t segment; + int64_t offset; char *label, *special; int is_global, is_norm; } defn; struct { - int32_t movingon, dummy; + int32_t movingon; + int64_t dummy; union label *next; } admin; }; @@ -75,11 +107,11 @@ struct permts { /* permanent text storage */ char data[PERMTS_SIZE]; /* ... the data block itself */ }; -extern bool global_offset_changed; /* defined in nasm.c */ +extern int64_t global_offset_changed; /* defined in nasm.c */ -static struct hash_table *ltab; /* labels hash table */ -static union label *ldata; /* all label data blocks */ -static union label *lfree; /* labels free block */ +static struct hash_table ltab; /* labels hash table */ +static union label *ldata; /* all label data blocks */ +static union label *lfree; /* labels free block */ static struct permts *perm_head; /* start of perm. text storage */ static struct permts *perm_tail; /* end of perm. text storage */ @@ -108,45 +140,47 @@ static union label *find_label(char *label, int create) if (islocal(label)) { prev = prevlabel; - prevlen = strlen(prev); - len = strlen(label); - if (prevlen+len >= IDLEN_MAX) - return NULL; /* Error... */ - memcpy(label_str, prev, prevlen); - memcpy(label_str+prevlen, label, len+1); - label = label_str; + prevlen = strlen(prev); + len = strlen(label); + if (prevlen + len >= IDLEN_MAX) { + nasm_error(ERR_NONFATAL, "identifier length exceed %i bytes", + IDLEN_MAX); + return NULL; + } + memcpy(label_str, prev, prevlen); + memcpy(label_str+prevlen, label, len+1); + label = label_str; } else { prev = ""; - prevlen = 0; + prevlen = 0; } - lpp = (union label **) hash_find(ltab, label, &ip); + lpp = (union label **) hash_find(<ab, label, &ip); lptr = lpp ? *lpp : NULL; if (lptr || !create) - return lptr; + return lptr; /* Create a new label... */ if (lfree->admin.movingon == END_BLOCK) { - /* - * must allocate a new block - */ - lfree->admin.next = - (union label *)nasm_malloc(LBLK_SIZE); - lfree = lfree->admin.next; - init_block(lfree); + /* + * must allocate a new block + */ + lfree->admin.next = (union label *)nasm_malloc(LBLK_SIZE); + lfree = lfree->admin.next; + init_block(lfree); } - + lfree->admin.movingon = BOGUS_VALUE; lfree->defn.label = perm_copy(label); lfree->defn.special = NULL; lfree->defn.is_global = NOT_DEFINED_YET; - + hash_add(&ip, lfree->defn.label, lfree); return lfree++; } -bool lookup_label(char *label, int32_t *segment, int32_t *offset) +bool lookup_label(char *label, int32_t *segment, int64_t *offset) { union label *lptr; @@ -158,8 +192,9 @@ bool lookup_label(char *label, int32_t *segment, int32_t *offset) *segment = lptr->defn.segment; *offset = lptr->defn.offset; return true; - } else - return false; + } + + return false; } bool is_extern(char *label) @@ -173,9 +208,8 @@ bool is_extern(char *label) return (lptr && (lptr->defn.is_global & EXTERN_BIT)); } -void redefine_label(char *label, int32_t segment, int32_t offset, char *special, - bool is_norm, bool isextrn, struct ofmt *ofmt, - efunc error) +void redefine_label(char *label, int32_t segment, int64_t offset, char *special, + bool is_norm, bool isextrn) { union label *lptr; int exi; @@ -185,31 +219,32 @@ void redefine_label(char *label, int32_t segment, int32_t offset, char *special, * are even possible, nor whether they are checked somewhere else */ - (void)segment; /* Don't warn that this parameter is unused */ (void)special; /* Don't warn that this parameter is unused */ (void)is_norm; /* Don't warn that this parameter is unused */ (void)isextrn; /* Don't warn that this parameter is unused */ - (void)ofmt; /* Don't warn that this parameter is unused */ #ifdef DEBUG -#if DEBUG<3 +#if DEBUG < 3 if (!strncmp(label, "debugdump", 9)) #endif - error(ERR_DEBUG, "redefine_label (%s, %ld, %08lx, %s, %d, %d)", + nasm_error(ERR_DEBUG, "redefine_label (%s, %"PRIx32", %"PRIx64", %s, %d, %d)", label, segment, offset, special, is_norm, isextrn); #endif lptr = find_label(label, 1); if (!lptr) - error(ERR_PANIC, "can't find label `%s' on pass two", label); + nasm_error(ERR_PANIC, "can't find label `%s' on pass two", label); if (!islocal(label)) { if (!islocalchar(*label) && lptr->defn.is_norm) prevlabel = lptr->defn.label; } - global_offset_changed |= (lptr->defn.offset != offset); + if (lptr->defn.offset != offset) + global_offset_changed++; + lptr->defn.offset = offset; + lptr->defn.segment = segment; if (pass0 == 1) { exi = !!(lptr->defn.is_global & GLOBAL_BIT); @@ -226,28 +261,22 @@ void redefine_label(char *label, int32_t segment, int32_t offset, char *special, ofmt->symdef(xsymbol, segment, offset, exi, special ? special : lptr->defn.special); - ofmt->current_dfmt->debug_deflabel(xsymbol, segment, offset, - exi, - special ? special : lptr-> - defn.special); + ofmt->current_dfmt->debug_deflabel(xsymbol, segment, offset, exi, + special ? special : lptr->defn.special); /** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/ } else { - if ((lptr->defn.is_global & (GLOBAL_BIT | EXTERN_BIT)) != - EXTERN_BIT) { + if ((lptr->defn.is_global & (GLOBAL_BIT | EXTERN_BIT)) != EXTERN_BIT) { ofmt->symdef(lptr->defn.label, segment, offset, exi, special ? special : lptr->defn.special); - ofmt->current_dfmt->debug_deflabel(label, segment, offset, - exi, - special ? special : - lptr->defn.special); + ofmt->current_dfmt->debug_deflabel(label, segment, offset, exi, + special ? special : lptr->defn.special); } } - } - /* if (pass0 == 1) */ + } /* if (pass0 == 1) */ } -void define_label(char *label, int32_t segment, int32_t offset, char *special, - bool is_norm, bool isextrn, struct ofmt *ofmt, efunc error) +void define_label(char *label, int32_t segment, int64_t offset, char *special, + bool is_norm, bool isextrn) { union label *lptr; int exi; @@ -256,22 +285,25 @@ void define_label(char *label, int32_t segment, int32_t offset, char *special, #if DEBUG<3 if (!strncmp(label, "debugdump", 9)) #endif - error(ERR_DEBUG, "define_label (%s, %ld, %08lx, %s, %d, %d)", + nasm_error(ERR_DEBUG, "define_label (%s, %"PRIx32", %"PRIx64", %s, %d, %d)", label, segment, offset, special, is_norm, isextrn); #endif lptr = find_label(label, 1); + if (!lptr) + return; if (lptr->defn.is_global & DEFINED_BIT) { - error(ERR_NONFATAL, "symbol `%s' redefined", label); + nasm_error(ERR_NONFATAL, "symbol `%s' redefined", label); return; } lptr->defn.is_global |= DEFINED_BIT; if (isextrn) lptr->defn.is_global |= EXTERN_BIT; - if (!islocalchar(label[0]) && is_norm) /* not local, but not special either */ + if (!islocalchar(label[0]) && is_norm) { + /* not local, but not special either */ prevlabel = lptr->defn.label; - else if (islocal(label) && !*prevlabel) { - error(ERR_NONFATAL, "attempt to define a local label before any" + } else if (islocal(label) && !*prevlabel) { + nasm_error(ERR_NONFATAL, "attempt to define a local label before any" " non-local labels"); } @@ -279,7 +311,7 @@ void define_label(char *label, int32_t segment, int32_t offset, char *special, lptr->defn.offset = offset; lptr->defn.is_norm = (!islocalchar(label[0]) && is_norm); - if (pass0 == 1 || (!is_norm && !isextrn && (segment & 1))) { + if (pass0 == 1 || (!is_norm && !isextrn && (segment > 0) && (segment & 1))) { exi = !!(lptr->defn.is_global & GLOBAL_BIT); if (exi) { char *xsymbol; @@ -294,63 +326,66 @@ void define_label(char *label, int32_t segment, int32_t offset, char *special, ofmt->symdef(xsymbol, segment, offset, exi, special ? special : lptr->defn.special); - ofmt->current_dfmt->debug_deflabel(xsymbol, segment, offset, - exi, - special ? special : lptr-> - defn.special); + ofmt->current_dfmt->debug_deflabel(xsymbol, segment, offset, exi, + special ? special : lptr->defn.special); /** nasm_free(xsymbol); ! outobj.c stores the pointer; ouch!!! **/ } else { - if ((lptr->defn.is_global & (GLOBAL_BIT | EXTERN_BIT)) != - EXTERN_BIT) { + if ((lptr->defn.is_global & (GLOBAL_BIT | EXTERN_BIT)) != EXTERN_BIT) { ofmt->symdef(lptr->defn.label, segment, offset, exi, special ? special : lptr->defn.special); - ofmt->current_dfmt->debug_deflabel(label, segment, offset, - exi, - special ? special : - lptr->defn.special); + ofmt->current_dfmt->debug_deflabel(label, segment, offset, exi, + special ? special : lptr->defn.special); } } - } /* if (pass0 == 1) */ + } /* if (pass0 == 1) */ } -void define_common(char *label, int32_t segment, int32_t size, char *special, - struct ofmt *ofmt, efunc error) +void define_common(char *label, int32_t segment, int32_t size, char *special) { union label *lptr; lptr = find_label(label, 1); - if (lptr->defn.is_global & DEFINED_BIT) { - error(ERR_NONFATAL, "symbol `%s' redefined", label); + if (!lptr) return; + if ((lptr->defn.is_global & DEFINED_BIT) && + (passn == 1 || !(lptr->defn.is_global & COMMON_BIT))) { + nasm_error(ERR_NONFATAL, "symbol `%s' redefined", label); + return; } - lptr->defn.is_global |= DEFINED_BIT; + lptr->defn.is_global |= DEFINED_BIT|COMMON_BIT; - if (!islocalchar(label[0])) /* not local, but not special either */ + if (!islocalchar(label[0])) { prevlabel = lptr->defn.label; - else - error(ERR_NONFATAL, "attempt to define a local label as a " + } else { + nasm_error(ERR_NONFATAL, "attempt to define a local label as a " "common variable"); + return; + } lptr->defn.segment = segment; lptr->defn.offset = 0; + if (pass0 == 0) + return; + ofmt->symdef(lptr->defn.label, segment, size, 2, special ? special : lptr->defn.special); ofmt->current_dfmt->debug_deflabel(lptr->defn.label, segment, size, 2, - special ? special : lptr->defn. - special); + special ? special : lptr->defn.special); } -void declare_as_global(char *label, char *special, efunc error) +void declare_as_global(char *label, char *special) { union label *lptr; if (islocal(label)) { - error(ERR_NONFATAL, "attempt to declare local symbol `%s' as" + nasm_error(ERR_NONFATAL, "attempt to declare local symbol `%s' as" " global", label); return; } lptr = find_label(label, 1); + if (!lptr) + return; switch (lptr->defn.is_global & TYPE_MASK) { case NOT_DEFINED_YET: lptr->defn.is_global = GLOBAL_PLACEHOLDER; @@ -360,22 +395,24 @@ void declare_as_global(char *label, char *special, efunc error) case GLOBAL_SYMBOL: break; case LOCAL_SYMBOL: - if (!lptr->defn.is_global & EXTERN_BIT) - error(ERR_NONFATAL, "symbol `%s': GLOBAL directive must" - " appear before symbol definition", label); + if (!(lptr->defn.is_global & EXTERN_BIT)) { + nasm_error(ERR_WARNING, "symbol `%s': GLOBAL directive " + "after symbol definition is an experimental feature", label); + lptr->defn.is_global = GLOBAL_SYMBOL; + } break; } } int init_labels(void) { - ltab = hash_init(); + hash_init(<ab, HASH_LARGE); ldata = lfree = (union label *)nasm_malloc(LBLK_SIZE); init_block(lfree); - perm_head = - perm_tail = (struct permts *)nasm_malloc(sizeof(struct permts)); + perm_head = perm_tail = + (struct permts *)nasm_malloc(sizeof(struct permts)); perm_head->next = NULL; perm_head->size = PERMTS_SIZE; @@ -394,14 +431,14 @@ void cleanup_labels(void) initialized = false; - hash_free(ltab); + hash_free(<ab); lptr = lhold = ldata; while (lptr) { - lptr = &lptr[LABEL_BLOCK-1]; - lptr = lptr->admin.next; - nasm_free(lhold); - lhold = lptr; + lptr = &lptr[LABEL_BLOCK-1]; + lptr = lptr->admin.next; + nasm_free(lhold); + lhold = lptr; } while (perm_head) { @@ -426,6 +463,8 @@ static char *perm_copy(const char *string) char *p; int len = strlen(string)+1; + nasm_assert(len <= PERMTS_SIZE); + if (perm_tail->size - perm_tail->usage < len) { perm_tail->next = (struct permts *)nasm_malloc(sizeof(struct permts)); @@ -441,6 +480,11 @@ static char *perm_copy(const char *string) return p; } +char *local_scope(char *label) +{ + return islocal(label) ? prevlabel : ""; +} + /* * Notes regarding bug involving redefinition of external segments. *