diff --git a/Makefile b/Makefile index b9f53c0..0bab559 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ install: mspdebug mspdebug.man mspdebug: main.o fet.o rf2500.o dis.o uif.o ihex.o elf32.o stab.o util.o \ bsl.o sim.o symmap.o gdb.o btree.o device.o rtools.o sym.o devcmd.o \ - parse.o + parse.o vector.o $(CC) $(LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS) .c.o: diff --git a/sym.c b/sym.c index bd2c286..af8f380 100644 --- a/sym.c +++ b/sym.c @@ -27,6 +27,7 @@ #include "binfile.h" #include "util.h" #include "parse.h" +#include "vector.h" static int cmd_eval(char **arg) { @@ -174,59 +175,16 @@ struct rename_record { int start, end; }; -struct rename_record *renames; -static int renames_cap; -static int renames_len; - -static void renames_free(void) -{ - if (!renames) - return; - - free(renames); - renames = NULL; - renames_cap = 0; - renames_len = 0; -} - -static int renames_push(const char *old_name, - int start, int end) -{ - struct rename_record *r; - - if (renames_len + 1 > renames_cap) { - int new_cap = renames_cap * 2; - struct rename_record *new_array; - - if (!new_cap) - new_cap = 64; - - new_array = realloc(renames, new_cap * sizeof(renames[0])); - if (!new_array) { - perror("sym: can't allocate memory for renaming"); - return -1; - } - - renames = new_array; - renames_cap = new_cap; - } - - r = &renames[renames_len++]; - strncpy(r->old_name, old_name, sizeof(r->old_name)); - r->old_name[sizeof(r->old_name) - 1] = 0; - r->start = start; - r->end = end; - - return 0; -} +struct vector renames_vec; static int renames_do(const char *replace) { int i; int count = 0; - for (i = 0; i < renames_len; i++) { - struct rename_record *r = &renames[i]; + for (i = 0; i < renames_vec.size; i++) { + struct rename_record *r = + VECTOR_PTR(renames_vec, i, struct rename_record); char new_name[128]; int len = r->start; int value; @@ -269,8 +227,16 @@ static int find_renames(const char *name, u_int16_t value) regmatch_t pmatch; if (!regexec(&find_preg, name, 1, &pmatch, 0) && - pmatch.rm_so >= 0 && pmatch.rm_eo > pmatch.rm_so) - return renames_push(name, pmatch.rm_so, pmatch.rm_eo); + pmatch.rm_so >= 0 && pmatch.rm_eo > pmatch.rm_so) { + struct rename_record r; + + strncpy(r.old_name, name, sizeof(r.old_name)); + r.old_name[sizeof(r.old_name) - 1] = 0; + r.start = pmatch.rm_so; + r.end = pmatch.rm_eo; + + return vector_push(&renames_vec, &r, 1); + } return 0; } @@ -291,16 +257,18 @@ static int cmd_sym_rename(char **arg) return -1; } + vector_init(&renames_vec, sizeof(struct rename_record)); + if (stab_enum(find_renames) < 0) { fprintf(stderr, "sym: rename failed\n"); regfree(&find_preg); - renames_free(); + vector_destroy(&renames_vec); return -1; } regfree(&find_preg); ret = renames_do(replace); - renames_free(); + vector_destroy(&renames_vec); return ret; } diff --git a/vector.c b/vector.c new file mode 100644 index 0000000..9786d30 --- /dev/null +++ b/vector.c @@ -0,0 +1,91 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009, 2010 Daniel Beer + * + * 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 of the License, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include "vector.h" + +void vector_init(struct vector *v, int elemsize) +{ + memset(v, 0, sizeof(*v)); + v->elemsize = elemsize; +} + +void vector_destroy(struct vector *v) +{ + if (v->ptr) + free(v->ptr); + + memset(v, 0, sizeof(*v)); +} + +int vector_realloc(struct vector *v, int capacity) +{ + assert (capacity >= 0); + + if (capacity) { + void *new_ptr = realloc(v->ptr, capacity * v->elemsize); + + if (!new_ptr) + return -1; + + v->ptr = new_ptr; + } else { + v->ptr = NULL; + } + + v->capacity = capacity; + if (v->size > capacity) + v->size = capacity; + + return 0; +} + +int vector_push(struct vector *v, void *data, int count) +{ + int needed = v->size + count; + + assert (count >= 0); + + if (needed > v->capacity) { + int cap = needed; + + /* Find the smallest power of 2 which is greater than the + * necessary capacity. + */ + while (cap & (cap - 1)) + cap &= (cap - 1); + if (cap < needed) + cap <<= 1; + + /* Don't allocate fewer than 8 elements */ + if (cap < 8) + cap = 8; + + if (vector_realloc(v, cap) < 0) + return -1; + } + + memcpy((char *)v->ptr + v->size * v->elemsize, + data, + count * v->elemsize); + v->size += count; + + return 0; +} diff --git a/vector.h b/vector.h new file mode 100644 index 0000000..5114620 --- /dev/null +++ b/vector.h @@ -0,0 +1,62 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009, 2010 Daniel Beer + * + * 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 of the License, 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef VECTOR_H_ +#define VECTOR_H_ + +/* A vector is a flexible array type. It can be used to hold elements of + * any type. + * + * elemsize: size in bytes of each element + * capacity: maximum number of elements that ptr can hold + * size: number of elements currently held + */ +struct vector { + void *ptr; + int elemsize; + int capacity; + int size; +}; + +/* Create and destroy vectors */ +void vector_init(struct vector *v, int elemsize); +void vector_destroy(struct vector *v); + +/* Reallocate a vector to the given size. Returns 0 if successful, or -1 + * if memory could not be allocated. + */ +int vector_realloc(struct vector *v, int capacity); + +/* Append any number of elements to the end of a vector, reallocating if + * necessary. Returns 0 on success or -1 if memory could not be allocated. + */ +int vector_push(struct vector *v, void *data, int count); + +/* Dereference a vector, giving an expression for the element of type t at + * position i in vector v. Use as follows: + * + * struct vector v; + * + * VECTOR_AT(v, 3, int) = 57; + * *VECTOR_PTR(v, 3, int) = 57; + */ +#define VECTOR_AT(v, i, t) (*VECTOR_PTR(v, i, t)) +#define VECTOR_PTR(v, i, t) \ + ((t *)((char *)(v).ptr + (i) * (v).elemsize)) + +#endif