summaryrefslogtreecommitdiff
path: root/jast.c
diff options
context:
space:
mode:
Diffstat (limited to 'jast.c')
-rw-r--r--jast.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/jast.c b/jast.c
new file mode 100644
index 0000000..99d4670
--- /dev/null
+++ b/jast.c
@@ -0,0 +1,267 @@
+/*
+ * Jast Another Symbol Table
+ * Copyright (c) 2012 Guillermo Ramos GutiƩrrez <0xwille@gmail.com>
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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 COPYRIGHT HOLDERS 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.
+ */
+
+
+#include <errno.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "doll.h"
+#include "jast.h"
+
+#define MIN(m,n) ((m) < (n) ? (m) : (n))
+#define MAX(m,n) ((m) > (n) ? (m) : (n))
+
+
+static struct doll *tables;
+static long uniq_count = 1;
+
+
+static char *__jast_alloc_string(char *s)
+{
+ int copylen = MIN(JAST_MAX_NAMELEN, strlen(s));
+ char *copy = malloc((copylen+1) * sizeof(char));
+ strncpy(copy, s, copylen);
+ copy[copylen] = '\0';
+ return copy;
+}
+
+
+struct jast *jast_creat(char *name)
+{
+ struct jast *new_tab = malloc(sizeof(struct jast));
+
+ if (name) {
+ new_tab->name = __jast_alloc_string(name);
+ } else {
+ int len = sizeof(char *)+12; // 12 == length of "[jast@0x]\0"
+ new_tab->name = malloc(len);
+ snprintf(new_tab->name, len, "[jast@%p]", (void *)new_tab);
+ }
+
+ new_tab->entries = doll_new();
+ new_tab->children = doll_new();
+
+ if (tables == NULL)
+ tables = doll_new();
+ doll_append(tables, new_tab);
+
+ return new_tab;
+}
+
+
+void jast_destroy(struct jast *tab)
+{
+ // TODO comprobar que tab existe
+ struct jast_entry *entry;
+ doll_foreach(entry, tab->entries) {
+ free(entry->name);
+ free(entry->uniq);
+ }
+
+ doll_remove(tables, tab);
+ doll_destroy(tab->entries);
+ doll_destroy(tab->children);
+ free(tab->name);
+ free(tab);
+}
+
+
+void jast_destroy_all(void)
+{
+ struct jast *tab;
+ doll_foreach(tab, tables)
+ jast_destroy(tab);
+}
+
+
+char *jast_uniq(char *begin)
+{
+ long varlen = strlen(begin) + ceill(log10(uniq_count)+1) + 1;
+ char *uniqname = malloc(varlen * sizeof(char));
+ snprintf(uniqname, varlen, "%s%ld", begin, uniq_count++);
+ return uniqname;
+}
+
+
+struct jast_entry *jast_new_entry(struct jast *tab, char *name)
+{
+ struct jast_entry *new;
+
+ if (name == NULL || (new = malloc(sizeof(struct jast_entry))) == NULL)
+ return NULL;
+
+ new->name = __jast_alloc_string(name);
+ new->uniq = jast_uniq("jast_var_");
+ new->tmp = 0;
+ new->type = JAST_UNDEF_T;
+ new->datatype = JAST_UNDEF_D;
+ new->datasize = 0;
+ new->attribs = NULL;
+
+ if (tab->entries == NULL)
+ tab->entries = doll_new();
+
+ doll_append(tab->entries, new);
+
+ return new;
+}
+
+
+struct jast_entry *jast_get_entry(struct jast *tab, char *name)
+{
+ struct jast_entry *entry;
+ doll_foreach(entry, tab->entries)
+ if (!strcmp(entry->name, name))
+ return entry;
+ return NULL;
+}
+
+// TODO usar get_entry
+enum jast_entry_t jast_entry_gettype(struct jast *tab, char *name)
+{
+ struct jast_entry *entry;
+ doll_foreach(entry, tab->entries)
+ if (!strcmp(entry->name, name))
+ return entry->type;
+ return JAST_ERR;
+}
+
+
+void jast_entry_settype(struct jast *tab, char *name, enum jast_entry_t type)
+{
+ struct jast_entry *entry;
+ doll_foreach(entry, tab->entries)
+ if (!strcmp(entry->name, name))
+ entry->type = type;
+// struct jast_entry *entry = doll_find(tab->entries, name);
+// if (entry)
+// entry->type = type;
+}
+
+
+enum jast_data_t jast_entry_getdatatype(struct jast *tab, char *name)
+{
+ struct jast_entry *entry;
+ doll_foreach(entry, tab->entries)
+ if (!strcmp(entry->name, name))
+ return entry->datatype;
+ return JAST_ERR;
+}
+
+void jast_entry_setdatatype(struct jast *tab, char *name, enum jast_data_t type)
+{
+ struct jast_entry *entry;
+ doll_foreach(entry, tab->entries)
+ if (!strcmp(entry->name, name))
+ entry->datatype = type;
+}
+
+
+inline void __jast_dump_n_spaces(int spaces, FILE *f)
+{
+ while (spaces--) putc(' ', f);
+}
+
+
+int jast_dump(struct jast *tab, char *filename)
+{
+ struct jast_entry *entry;
+ int i;
+ char *entry_type, *data_type;
+ FILE *f = fopen(filename, "w");
+ char *cols[] = {"name", "type", "data type", "uniq", "data size"};
+ int ncols = sizeof(cols)/sizeof(cols[0]);
+ unsigned collen[ncols];
+ unsigned colnamelen[ncols];
+ int totallen = (ncols*3)+1;
+
+ if (f == NULL || tab == NULL) // TODO quitar (puesto por warnings)
+ return -1;
+
+ for (i = 0; i < ncols; i++)
+ collen[i] = colnamelen[i] = strlen(cols[i]);
+
+ doll_foreach(entry, tab->entries) {
+ __jast_strentry(entry->type, entry_type);
+ __jast_strdata(entry->datatype, data_type);
+ collen[0] = MAX(collen[0], strlen(entry->name));
+ collen[1] = MAX(collen[1], strlen(entry_type));
+ collen[2] = MAX(collen[2], strlen(data_type));
+ collen[3] = MAX(collen[3], strlen(entry->uniq));
+ collen[4] = MAX(collen[4], log10(entry->datasize/10) + 2);
+ }
+
+ for (i = 0; i < ncols; i++)
+ totallen += collen[i];
+
+ char interline[totallen - 1];
+ memset(interline, '-', totallen-2);
+ interline[totallen-2] = '\0';
+
+ fprintf(f, "\n /==# %s (parent: %s)\n", tab->name,
+ tab->parent ? tab->parent->name : "none");
+ fprintf(f, "/%s\\\n|", interline);
+ for (i = 0; i < ncols; i++) {
+ __jast_dump_n_spaces(collen[i]-colnamelen[i]+1, f);
+ fprintf(f, "%s |", cols[i]);
+ }
+ fprintf(f, "\n|%s|\n", interline);
+ doll_foreach(entry, tab->entries) {
+ putc('|', f);
+ __jast_strentry(entry->type, entry_type);
+ __jast_strdata(entry->datatype, data_type);
+ __jast_dump_n_spaces(collen[0]-strlen(entry->name)+1, f);
+ fprintf(f, "%s |", entry->name);
+ __jast_dump_n_spaces(collen[1]-strlen(entry_type)+1, f);
+ fprintf(f, "%s |", entry_type);
+ __jast_dump_n_spaces(collen[2]-strlen(data_type)+1, f);
+ fprintf(f, "%s |", data_type);
+ __jast_dump_n_spaces(collen[3]-strlen(entry->uniq)+1, f);
+ fprintf(f, "%s |", entry->uniq);
+ __jast_dump_n_spaces(collen[4]-log10(entry->datasize/10+3), f);
+ fprintf(f, "%dB |\n", entry->datasize);
+ }
+ fprintf(f, "\\%s/\n\n", interline);
+
+ fclose(f);
+ return 0;
+}
+
+
+void jast_show_all(void)
+{
+ struct jast *t;
+ printf("\n-----------------------\n");
+ doll_foreach(t, tables)
+ printf("%s\n", t->name);
+ printf("-----------------------\n");
+}