/* * YASM assembler line manager (for parse stage) * * Copyright (C) 2002 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. */ #define YASM_LIB_INTERNAL #include "util.h" /*@unused@*/ RCSID("$IdPath: yasm/libyasm/linemgr.c,v 1.33 2003/03/16 23:52:23 peter Exp $"); #include "coretype.h" #include "hamt.h" #include "errwarn.h" #include "linemgr.h" /* Source lines tracking */ typedef struct { struct line_index_mapping *vector; unsigned long size; unsigned long allocated; } line_index_mapping_head; typedef struct line_index_mapping { /* monotonically increasing line index */ unsigned long index; /* related info */ /* "original" source filename */ /*@null@*/ /*@dependent@*/ const char *filename; /* "original" source base line number */ unsigned long line; /* "original" source line number increment (for following lines) */ unsigned long line_inc; } line_index_mapping; typedef struct line_index_assoc_data_raw_head { /*@only@*/ void **vector; /*@null@*/ void (*delete_func) (/*@only@*/ void *); unsigned long size; } line_index_assoc_data_raw_head; typedef struct line_index_assoc_data { /*@only@*/ void *data; /*@null@*/ void (*delete_func) (/*@only@*/ void *); int type; } line_index_assoc_data; /* Shared storage for filenames */ static /*@only@*/ /*@null@*/ HAMT *filename_table; /* Virtual line number. Uniquely specifies every line read by the parser. */ static unsigned long line_index; static /*@only@*/ /*@null@*/ line_index_mapping_head *line_index_map; /* Associated data arrays for odd data types (those likely to have data * associated for every line). */ static line_index_assoc_data_raw_head *line_index_assoc_data_array; #define MAX_LINE_INDEX_ASSOC_DATA_ARRAY 8 static void filename_delete_one(/*@only@*/ void *d) { yasm_xfree(d); } static void yasm_std_linemgr_set(const char *filename, unsigned long line, unsigned long line_inc) { char *copy; int replace = 0; line_index_mapping *mapping; /* Create a new mapping in the map */ if (line_index_map->size >= line_index_map->allocated) { /* allocate another size bins when full for 2x space */ line_index_map->vector = yasm_xrealloc(line_index_map->vector, 2*line_index_map->allocated *sizeof(line_index_mapping)); line_index_map->allocated *= 2; } mapping = &line_index_map->vector[line_index_map->size]; line_index_map->size++; /* Fill it */ /* Copy the filename (via shared storage) */ copy = yasm__xstrdup(filename); /*@-aliasunique@*/ mapping->filename = HAMT_insert(filename_table, copy, copy, &replace, filename_delete_one); /*@=aliasunique@*/ mapping->index = line_index; mapping->line = line; mapping->line_inc = line_inc; } static void yasm_std_linemgr_initialize(void) { int i; filename_table = HAMT_new(yasm_internal_error_); line_index = 1; /* initialize mapping vector */ line_index_map = yasm_xmalloc(sizeof(line_index_mapping_head)); line_index_map->vector = yasm_xmalloc(8*sizeof(line_index_mapping)); line_index_map->size = 0; line_index_map->allocated = 8; /* initialize associated data arrays */ line_index_assoc_data_array = yasm_xmalloc(MAX_LINE_INDEX_ASSOC_DATA_ARRAY * sizeof(line_index_assoc_data_raw_head)); for (i=0; idelete_func && adrh->vector) { unsigned int j; for (j=0; jsize; j++) { if (adrh->vector[j]) adrh->delete_func(adrh->vector[j]); } yasm_xfree(adrh->vector); } } yasm_xfree(line_index_assoc_data_array); line_index_assoc_data_array = NULL; } if (line_index_map) { yasm_xfree(line_index_map->vector); yasm_xfree(line_index_map); line_index_map = NULL; } if (filename_table) { HAMT_delete(filename_table, filename_delete_one); filename_table = NULL; } } static unsigned long yasm_std_linemgr_get_current(void) { return line_index; } static void yasm_std_linemgr_add_assoc_data(int type, /*@only@*/ void *data, /*@null@*/ void (*delete_func) (void *)) { if ((type & 1) && type < MAX_LINE_INDEX_ASSOC_DATA_ARRAY*2) { line_index_assoc_data_raw_head *adrh = &line_index_assoc_data_array[type>>1]; if (adrh->size == 0) { unsigned int i; adrh->size = 4; adrh->vector = yasm_xmalloc(adrh->size*sizeof(void *)); adrh->delete_func = delete_func; for (i=0; isize; i++) adrh->vector[i] = NULL; } while (line_index > adrh->size) { unsigned int i; /* allocate another size bins when full for 2x space */ adrh->vector = yasm_xrealloc(adrh->vector, 2*adrh->size*sizeof(void *)); for(i=adrh->size; isize*2; i++) adrh->vector[i] = NULL; adrh->size *= 2; } adrh->vector[line_index-1] = data; if (adrh->delete_func != delete_func) yasm_internal_error(N_("multiple deletion functions specified")); } else { yasm_internal_error(N_("non-common data not supported yet")); delete_func(data); } } static unsigned long yasm_std_linemgr_goto_next(void) { return ++line_index; } static void yasm_std_linemgr_lookup(unsigned long lindex, const char **filename, unsigned long *line) { line_index_mapping *mapping; unsigned long vindex, step; assert(lindex <= line_index); /* Binary search through map to find highest line_index <= index */ assert(line_index_map != NULL); vindex = 0; /* start step as the greatest power of 2 <= size */ step = 1; while (step*2<=line_index_map->size) step*=2; while (step>0) { if (vindex+step < line_index_map->size && line_index_map->vector[vindex+step].index <= lindex) vindex += step; step /= 2; } mapping = &line_index_map->vector[vindex]; *filename = mapping->filename; *line = mapping->line+mapping->line_inc*(lindex-mapping->index); } static /*@dependent@*/ /*@null@*/ void * yasm_std_linemgr_lookup_data(unsigned long lindex, int type) { if ((type & 1) && type < MAX_LINE_INDEX_ASSOC_DATA_ARRAY*2) { line_index_assoc_data_raw_head *adrh = &line_index_assoc_data_array[type>>1]; if (lindex > adrh->size) return NULL; return adrh->vector[lindex-1]; } else return NULL; } yasm_linemgr yasm_std_linemgr = { yasm_std_linemgr_initialize, yasm_std_linemgr_cleanup, yasm_std_linemgr_get_current, yasm_std_linemgr_add_assoc_data, yasm_std_linemgr_goto_next, yasm_std_linemgr_set, yasm_std_linemgr_lookup, yasm_std_linemgr_lookup_data };