aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnulib.modules10
-rw-r--r--src/Makefile.am4
-rw-r--r--src/format.c13
-rw-r--r--src/grecs-gram.y335
-rw-r--r--src/grecs-lex.l107
-rw-r--r--src/grecs.h61
-rw-r--r--src/list.c20
-rw-r--r--src/mem.c80
-rw-r--r--src/preproc.c165
-rw-r--r--src/symtab.c406
-rw-r--r--src/text.c58
11 files changed, 971 insertions, 288 deletions
diff --git a/gnulib.modules b/gnulib.modules
deleted file mode 100644
index 83e66b2..0000000
--- a/gnulib.modules
+++ /dev/null
@@ -1,10 +0,0 @@
-# getdtablesize ??
-getline
-hash
-inttostr
-inttypes
-obstack
-strtoimax
-strtoumax
-vasprintf
-xalloc
diff --git a/src/Makefile.am b/src/Makefile.am
index 289373a..c97cee8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,7 +20,9 @@ libgrecs_a_SOURCES = \
grecs-gram.y\
grecs-lex.l\
list.c\
+ mem.c\
preproc.c\
+ symtab.c\
text.c\
grecs.h\
wordsplit.c\
@@ -28,7 +30,7 @@ libgrecs_a_SOURCES = \
EXTRA_DIST=grecs-gram.h $(PP_SETUP_FILE)
-INCLUDES = -I$(top_srcdir)/gnu -I../gnu -I$(srcdir)
+INCLUDES = -I$(srcdir)
AM_YFLAGS = -dtv
AM_LFLAGS = -dvp
# Use a modified ylwrap implementation that understands the --prefix option.
diff --git a/src/format.c b/src/format.c
index daa9b98..76121f8 100644
--- a/src/format.c
+++ b/src/format.c
@@ -23,15 +23,6 @@
#include <ctype.h>
#include <string.h>
-#if ENABLE_NLS
-# include "gettext.h"
-#else
-# define gettext(s) s
-#endif
-
-#define _(s) gettext (s)
-#define N_(s) s
-
const char *
grecs_data_type_string (enum grecs_data_type type)
{
@@ -50,9 +41,7 @@ grecs_data_type_string (enum grecs_data_type type)
case grecs_type_long:
case grecs_type_ulong:
case grecs_type_size:
-/* case grecs_type_off:*/
- case grecs_type_uintmax:
- case grecs_type_intmax:
+ /*FIXME case grecs_type_off:*/
return "number";
case grecs_type_time:
diff --git a/src/grecs-gram.y b/src/grecs-gram.y
index e36865d..ab757f8 100644
--- a/src/grecs-gram.y
+++ b/src/grecs-gram.y
@@ -30,16 +30,7 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
-
-#include <xalloc.h>
-#include <inttypes.h>
-
-#if ENABLE_NLS
-# include "gettext.h"
-# define _(msgid) gettext (msgid)
-#else
-# define _(msgid) msgid
-#endif
+#include <errno.h>
typedef union
{
@@ -255,15 +246,86 @@ simple_list_create (int dispose)
return lp;
}
-
+int
+grecs_vasprintf (char **pbuf, size_t *psize, const char *fmt, va_list ap)
+{
+ char *buf = *pbuf;
+ size_t buflen = *psize;
+ int rc = 0;
+
+ if (!buf)
+ {
+ if (buflen == 0)
+ buflen = 512; /* Initial allocation */
+
+ buf = calloc (1, buflen);
+ if (buf == NULL)
+ return ENOMEM;
+ }
+
+ for (;;)
+ {
+ ssize_t n = vsnprintf (buf, buflen, fmt, ap);
+ if (n < 0 || n >= buflen || !memchr (buf, '\0', n + 1))
+ {
+ char *newbuf;
+ size_t newlen = buflen * 2;
+ if (newlen < buflen)
+ {
+ rc = ENOMEM;
+ break;
+ }
+ newbuf = realloc (buf, newlen);
+ if (newbuf == NULL)
+ {
+ rc = ENOMEM;
+ break;
+ }
+ buflen = newlen;
+ buf = newbuf;
+ }
+ else
+ break;
+ }
+
+ if (rc)
+ {
+ if (!*pbuf)
+ {
+ /* We made first allocation, now free it */
+ free (buf);
+ buf = NULL;
+ buflen = 0;
+ }
+ }
+
+ *pbuf = buf;
+ *psize = buflen;
+ return rc;
+}
+
+int
+grecs_asprintf (char **pbuf, size_t *psize, const char *fmt, ...)
+{
+ int rc;
+ va_list ap;
+
+ va_start (ap, fmt);
+ rc = grecs_vasprintf (pbuf, psize, fmt, ap);
+ va_end (ap);
+ return rc;
+}
+
void
-grecs_warning(grecs_locus_t *locus, int errcode, const char *fmt, ...)
+grecs_warning (grecs_locus_t *locus, int errcode, const char *fmt, ...)
{
va_list ap;
char *buf = NULL;
+ size_t size = 0;
va_start (ap, fmt);
- vasprintf (&buf, fmt, ap);
+ if (grecs_vasprintf (&buf, &size, fmt, ap))
+ grecs_alloc_die ();
va_end (ap);
grecs_print_diag (locus, 0, errcode, buf);
free(buf);
@@ -274,9 +336,11 @@ grecs_error (grecs_locus_t *locus, int errcode, const char *fmt, ...)
{
va_list ap;
char *buf = NULL;
+ size_t size = 0;
va_start (ap, fmt);
- vasprintf (&buf, fmt, ap);
+ if (grecs_vasprintf (&buf, &size, fmt, ap))
+ grecs_alloc_die ();
va_end (ap);
grecs_print_diag (locus, 1, errcode, buf);
free (buf);
@@ -416,56 +480,6 @@ find_keyword (const char *ident)
}
static int
-string_to_signed (intmax_t *sval, const char *string,
- intmax_t minval, intmax_t maxval, grecs_locus_t *locus)
-{
- intmax_t t;
- char *p;
-
- t = strtoimax (string, &p, 0);
- if (*p)
- {
- grecs_error (locus, 0, _("cannot convert `%s' to number"),
- string);
- return 1;
- }
- else if (t < minval || t > maxval)
- {
- grecs_error (locus, 0,
- _("%s: value out of allowed range %"PRIiMAX"..%"PRIiMAX),
- string, minval, maxval);
- return 1;
- }
- *sval = t;
- return 0;
-}
-
-static int
-string_to_unsigned (uintmax_t *sval, const char *string, uintmax_t maxval,
- grecs_locus_t *locus)
-{
- uintmax_t t;
- char *p;
-
- t = strtoumax (string, &p, 0);
- if (*p)
- {
- grecs_error (locus, 0, _("cannot convert `%s' to number"),
- string);
- return 1;
- }
- else if (t > maxval)
- {
- grecs_error (locus, 0,
- _("%s: value out of allowed range 0..%"PRIuMAX),
- string, maxval);
- return 1;
- }
- *sval = t;
- return 0;
-}
-
-static int
string_to_bool (const char *string, int *pval, grecs_locus_t *locus)
{
if (strcmp (string, "yes") == 0
@@ -516,7 +530,7 @@ string_to_sockaddr (struct grecs_sockaddr *sp, const char *string,
s_un.sun_family = AF_UNIX;
strcpy (s_un.sun_path, string);
sp->len = sizeof (s_un);
- sp->sa = xmalloc (sp->len);
+ sp->sa = grecs_malloc (sp->len);
memcpy (sp->sa, &s_un, sp->len);
}
else
@@ -535,7 +549,7 @@ string_to_sockaddr (struct grecs_sockaddr *sp, const char *string,
sa.sin_addr.s_addr = INADDR_ANY;
else
{
- char *host = xmalloc (len + 1);
+ char *host = grecs_malloc (len + 1);
memcpy (host, string, len);
host[len] = 0;
@@ -583,19 +597,132 @@ string_to_sockaddr (struct grecs_sockaddr *sp, const char *string,
return 1;
}
sp->len = sizeof (sa);
- sp->sa = xmalloc (sp->len);
+ sp->sa = grecs_malloc (sp->len);
memcpy (sp->sa, &sa, sp->len);
}
return 0;
}
+
+/* The TYPE_* defines come from gnulib's intprops.h */
+
+/* True if the arithmetic type T is signed. */
+# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+
+/* The maximum and minimum values for the integer type T. These
+ macros have undefined behavior if T is signed and has padding bits. */
+# define TYPE_MINIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) 0 \
+ : TYPE_SIGNED_MAGNITUDE (t) \
+ ? ~ (t) 0 \
+ : ~ TYPE_MAXIMUM (t)))
+# define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ((((t) 1 << (sizeof (t) * CHAR_BIT - 2)) - 1) * 2 + 1)))
+# define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1)
+
+
+#define STRTONUM(s, type, base, res, limit, loc) \
+ { \
+ type sum = 0; \
+ \
+ for (; *s; s++) \
+ { \
+ type x; \
+ \
+ if ('0' <= *s && *s <= '9') \
+ x = sum * base + *s - '0'; \
+ else if (base == 16 && 'a' <= *s && *s <= 'f') \
+ x = sum * base + *s - 'a'; \
+ else if (base == 16 && 'A' <= *s && *s <= 'F') \
+ x = sum * base + *s - 'A'; \
+ else \
+ break; \
+ if (x <= sum) \
+ { \
+ grecs_error (loc, 0, _("numeric overflow")); \
+ return 1; \
+ } \
+ else if (limit && x > limit) \
+ { \
+ grecs_error (loc, 0, _("value out of allowed range")); \
+ return 1; \
+ } \
+ sum = x; \
+ } \
+ res = sum; \
+ }
+
+#define STRxTONUM(s, type, res, limit, loc) \
+ { \
+ int base; \
+ if (*s == '0') \
+ { \
+ s++; \
+ if (*s == 0) \
+ base = 10; \
+ else if (*s == 'x' || *s == 'X') \
+ { \
+ s++; \
+ base = 16; \
+ } \
+ else \
+ base = 8; \
+ } else \
+ base = 10; \
+ STRTONUM (s, type, base, res, limit, loc); \
+ }
+
+#define GETUNUM(str, type, res, loc) \
+ { \
+ type tmpres; \
+ const char *s = str; \
+ STRxTONUM (s, type, tmpres, 0, loc); \
+ if (*s) \
+ { \
+ grecs_error (loc, 0, _("not a number (stopped near `%s')"), \
+ s); \
+ return 1; \
+ } \
+ res = tmpres; \
+ }
+
+#define GETSNUM(str, type, res, loc) \
+ { \
+ unsigned type tmpres; \
+ const char *s = str; \
+ int sign; \
+ unsigned type limit; \
+ \
+ if (*s == '-') \
+ { \
+ sign = 1; \
+ s++; \
+ limit = TYPE_MINIMUM (type); \
+ limit = - limit; \
+ } \
+ else \
+ { \
+ sign = 0; \
+ limit = TYPE_MAXIMUM (type); \
+ } \
+ \
+ STRxTONUM (s, unsigned type, tmpres, limit, loc); \
+ if (*s) \
+ { \
+ grecs_error(loc, 0, _("not a number (stopped near `%s')"), s); \
+ return 1; \
+ } \
+ res = sign ? - tmpres : tmpres; \
+ }
+
+
int
grecs_string_convert (void *target, enum grecs_data_type type,
const char *string, grecs_locus_t *locus)
{
- uintmax_t uval;
- intmax_t sval;
-
switch (type)
{
case grecs_type_void:
@@ -606,71 +733,43 @@ grecs_string_convert (void *target, enum grecs_data_type type,
break;
case grecs_type_short:
- if (string_to_signed (&sval, string, SHRT_MIN, SHRT_MAX, locus) == 0)
- *(short*)target = sval;
- else
- return 1;
+ GETUNUM (string, short, *(short*)target, locus);
break;
case grecs_type_ushort:
- if (string_to_unsigned (&uval, string, USHRT_MAX, locus) == 0)
- *(unsigned short*)target = uval;
- else
- return 1;
+ GETUNUM (string, unsigned short, *(unsigned short*)target, locus);
break;
case grecs_type_bool:
return string_to_bool (string, (int*)target, locus);
case grecs_type_int:
- if (string_to_signed (&sval, string, INT_MIN, INT_MAX, locus) == 0)
- *(int*)target = sval;
- else
- return 1;
+ GETSNUM (string, int, *(int*)target, locus);
break;
case grecs_type_uint:
- if (string_to_unsigned (&uval, string, UINT_MAX, locus) == 0)
- *(unsigned int*)target = uval;
- else
- return 1;
+ GETUNUM (string, unsigned int, *(unsigned int*)target, locus);
break;
case grecs_type_long:
- if (string_to_signed (&sval, string, LONG_MIN, LONG_MAX, locus) == 0)
- *(long*)target = sval;
- else
- return 1;
+ GETSNUM (string, long, *(long*)target, locus);
break;
case grecs_type_ulong:
- if (string_to_unsigned (&uval, string, ULONG_MAX, locus) == 0)
- *(unsigned long*)target = uval;
- else
- return 1;
+ GETUNUM (string, unsigned long, *(unsigned long*)target, locus);
break;
case grecs_type_size:
- if (string_to_unsigned (&uval, string, SIZE_MAX, locus) == 0)
- *(size_t*)target = uval;
- else
- return 1;
+ GETUNUM (string, size_t, *(size_t*)target, locus);
break;
-
- case grecs_type_intmax:
- return string_to_signed ((intmax_t*)target, string,
- INTMAX_MIN, INTMAX_MAX, locus);
-
- case grecs_type_uintmax:
- return string_to_unsigned ((uintmax_t*)target, string, UINTMAX_MAX,
- locus);
-
+ /*FIXME
+ case grecs_type_off:
+ GETSNUM (string, off_t, *(off_t*)target, locus);
+ break;
+ */
case grecs_type_time:
/*FIXME: Use getdate */
- if (string_to_unsigned (&uval, string, (time_t)-1, locus) == 0)
- *(time_t*)target = uval;
- else
- return 1;
+ GETUNUM (string, time_t, *(time_t*)target, locus);
break;
case grecs_type_ipv4:
@@ -733,8 +832,7 @@ DECL_NUMCMP(short)
DECL_NUMCMP(int)
DECL_NUMCMP(long)
DECL_NUMCMP(size_t)
-DECL_NUMCMP(uintmax_t)
-DECL_NUMCMP(intmax_t)
+/*FIXME DECL_NUMCMP(off_t)*/
DECL_NUMCMP(time_t)
__DECL_NUMCMP(in_addr, struct in_addr)
__DECL_NUMCMP(grecs_sockaddr, struct grecs_sockaddr)
@@ -749,9 +847,10 @@ struct grecs_prop grecs_prop_tab[] = {
{ sizeof (long), NUMCMP (long) }, /* grecs_type_long */
{ sizeof (unsigned long), NUMCMP (long) }, /* grecs_type_ulong */
{ sizeof (size_t), NUMCMP (size_t) }, /* grecs_type_size */
- /* grecs_type_off,*/
- { sizeof (uintmax_t), NUMCMP (uintmax_t) }, /* grecs_type_uintmax */
- { sizeof (intmax_t), NUMCMP (intmax_t) }, /* grecs_type_intmax */
+#if 0
+ FIXME
+ { sizeof (off_t), NUMCMP (off_t) }, /* grecs_type_off */
+#endif
{ sizeof (time_t), NUMCMP (time_t) }, /* grecs_type_time */
{ sizeof (int), NUMCMP (int) }, /* grecs_type_bool */
{ sizeof (struct in_addr), NUMCMP (in_addr) }, /* grecs_type_ipv4 */
@@ -823,7 +922,7 @@ grecs_process_ident (struct grecs_keyword *kwp, grecs_value_t *value,
grecs_list_append (list, (void*) vp->v.string);
else
{
- void *ptr = xmalloc (size);
+ void *ptr = grecs_malloc (size);
if (grecs_string_convert (ptr, type, vp->v.string,
locus) == 0)
grecs_list_append (list, ptr);
@@ -864,7 +963,7 @@ grecs_process_ident (struct grecs_keyword *kwp, grecs_value_t *value,
grecs_list_append (list, value->v.string);
else
{
- ptr = xmalloc (size);
+ ptr = grecs_malloc (size);
if (grecs_string_convert (ptr, type, value->v.string, locus))
{
free (ptr);
diff --git a/src/grecs-lex.l b/src/grecs-lex.l
index 308ca8e..a16045a 100644
--- a/src/grecs-lex.l
+++ b/src/grecs-lex.l
@@ -29,19 +29,8 @@
#include <stdlib.h>
#include <errno.h>
-#define obstack_chunk_alloc malloc
-#define obstack_chunk_free free
-#include <obstack.h>
-#include <xalloc.h>
#include <wordsplit.h>
-#if ENABLE_NLS
-# include "gettext.h"
-# define _(msgid) gettext (msgid)
-#else
-# define _(msgid) msgid
-#endif
-
static char *multiline_delimiter;
static size_t multiline_delimiter_len;
static int multiline_unescape; /* Unescape here-document contents */
@@ -57,7 +46,9 @@ grecs_locus_t grecs_current_locus; /* Input file location */
Uff, running two preprocessors is confusing...
*/
static size_t xlines;
-static struct obstack stk;
+
+static struct grecs_list *line_acc;
+static struct grecs_list *string_list;
static void multiline_begin (char *);
static void multiline_add (char *);
@@ -179,12 +170,22 @@ yywrap ()
return 1;
}
+static void
+line_acc_free_entry (void *ptr)
+{
+ free (ptr);
+}
+
int
grecs_lex_begin (const char *name)
{
if (yy_flex_debug > 0)
yy_flex_debug = 0;
- obstack_init (&stk);
+
+ line_acc = grecs_list_create ();
+ line_acc->free_entry = line_acc_free_entry;
+ string_list = grecs_list_create ();
+
if (grecs_preprocessor)
{
int fd;
@@ -258,20 +259,44 @@ unquote_char (int c)
return -1;
}
+struct line_acc_entry
+{
+ size_t size;
+};
+#define line_acc_ptr(entry) (char*)(entry + 1)
+
+static void
+line_acc_add_string (const char *str, size_t len)
+{
+ struct line_acc_entry *ent = grecs_malloc (sizeof (*ent) + len + 1);
+ char *p = line_acc_ptr (ent);
+ memcpy (p, str, len);
+ p[len] = 0;
+ ent->size = len;
+ grecs_list_append (line_acc, ent);
+}
+
static void
-unescape_to_obstack (int c)
+line_acc_add_char (int c)
+{
+ char t = c;
+ line_acc_add_string (&t, 1);
+}
+
+static void
+list_acc_unescape_char (int c)
{
if (c != '\n')
{
int t = unquote_char (c);
if (t != -1)
- obstack_1grow (&stk, t);
+ line_acc_add_char (t);
else
{
grecs_warning(&grecs_current_locus, 0,
_("unknown escape sequence '\\%c'"),
c);
- obstack_1grow (&stk, c);
+ line_acc_add_char (c);
}
}
}
@@ -279,15 +304,15 @@ unescape_to_obstack (int c)
void
grecs_line_add (const char *text, size_t len)
{
- obstack_grow (&stk, text, len);
+ line_acc_add_string (text, len);
}
/* Same, but unescapes the last character from yytext */
static void
line_add_unescape_last (char *text, size_t len)
{
- obstack_grow (&stk, text, len - 2);
- unescape_to_obstack (text[len - 1]);
+ line_acc_add_string (text, len - 2);
+ list_acc_unescape_char (text[len - 1]);
}
static void
@@ -299,11 +324,11 @@ multiline_add (char *s)
{
if (*s == '\\')
{
- unescape_to_obstack (s[1]);
+ list_acc_unescape_char (s[1]);
++s;
}
else
- obstack_1grow (&stk, *s);
+ line_acc_add_char (*s);
}
}
else
@@ -365,7 +390,7 @@ multiline_begin (char *p)
/* Remove trailing newline */
multiline_delimiter_len--;
- multiline_delimiter = xmalloc (multiline_delimiter_len + 1);
+ multiline_delimiter = grecs_malloc (multiline_delimiter_len + 1);
memcpy (multiline_delimiter, p, multiline_delimiter_len);
multiline_delimiter[multiline_delimiter_len] = 0;
grecs_line_begin ();
@@ -374,20 +399,45 @@ multiline_begin (char *p)
char *
grecs_line_finish ()
{
- obstack_1grow (&stk, 0);
- return obstack_finish (&stk);
+ struct grecs_list_entry *ep;
+ size_t size = 0;
+ char *str, *p;
+
+ for (ep = line_acc->head; ep; ep = ep->next)
+ {
+ struct line_acc_entry *ent = ep->data;
+ size += ent->size;
+ }
+
+ str = grecs_malloc (size + 1);
+ grecs_list_append (string_list, str);
+ for (ep = line_acc->head, p = str; ep; ep = ep->next)
+ {
+ struct line_acc_entry *ent = ep->data;
+ char *str = line_acc_ptr (ent);
+ memcpy (p, str, ent->size);
+ p += ent->size;
+ }
+ *p = 0;
+ grecs_list_clear (line_acc);
+ return str;
}
static int
ident ()
{
char *p;
+ char *str;
+ size_t len;
for (p = yytext; *p && isspace (*p); p++)
;
- obstack_grow (&stk, p, strlen (p));
- obstack_1grow (&stk, 0);
- yylval.string = obstack_finish (&stk);
+
+ len = strlen (p);
+ str = grecs_malloc (len + 1);
+ strcpy (str, p);
+ grecs_list_append (string_list, str);
+ yylval.string = str;
return IDENT;
}
@@ -400,7 +450,8 @@ grecs_lex_trace (int n)
grecs_value_t *
grecs_value_dup (grecs_value_t *input)
{
- grecs_value_t *ptr = obstack_alloc (&stk, sizeof (*ptr));
+ grecs_value_t *ptr = grecs_malloc (sizeof (*ptr));
+ grecs_list_append (string_list, ptr);
*ptr = *input;
return ptr;
}
diff --git a/src/grecs.h b/src/grecs.h
index 42ef01e..077a01e 100644
--- a/src/grecs.h
+++ b/src/grecs.h
@@ -18,6 +18,21 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
+#include <stdarg.h>
+
+#if ENABLE_NLS
+# include "gettext.h"
+#else
+# ifndef gettext
+# define gettext(msgid) msgid
+# endif
+#endif
+#ifndef _
+# define _(msgid) gettext (msgid)
+#endif
+#ifndef N_
+# define N_(s) s
+#endif
typedef struct {
char *file;
@@ -37,8 +52,6 @@ enum grecs_data_type {
grecs_type_ulong,
grecs_type_size,
/* grecs_type_off,*/
- grecs_type_uintmax,
- grecs_type_intmax,
grecs_type_time,
grecs_type_bool,
grecs_type_ipv4,
@@ -112,6 +125,15 @@ struct grecs_sockaddr {
struct sockaddr *sa;
};
+extern void *(*grecs_malloc_fun)(size_t size);
+extern void *(*grecs_realloc_fun)(void *ptr, size_t size);
+extern void (*grecs_alloc_die_fun) (void);
+
+void *grecs_malloc(size_t size);
+void *grecs_realloc(void *ptr, size_t size);
+void grecs_alloc_die(void);
+char *grecs_strdup(const char *str);
+
grecs_value_t *grecs_value_dup(grecs_value_t *input);
extern void grecs_print_diag(grecs_locus_t *, int, int, const char*);
@@ -182,4 +204,39 @@ void *grecs_list_pop (struct grecs_list *lp);
void *grecs_list_locate (struct grecs_list *lp, void *data);
void *grecs_list_index (struct grecs_list *lp, size_t idx);
void *grecs_list_remove_tail (struct grecs_list *lp);
+void grecs_list_clear (struct grecs_list *lp);
+void grecs_list_free (struct grecs_list *lp);
+
+int grecs_vasprintf (char **pbuf, size_t *psize, const char *fmt, va_list ap);
+int grecs_asprintf (char **pbuf, size_t *psize, const char *fmt, ...);
+
+struct grecs_symtab;
+
+struct grecs_syment {
+ char *name;
+};
+
+typedef int (*grecs_symtab_enumerator_t)(void *sym, void *data);
+
+const char *grecs_symtab_strerror(int rc);
+
+void *grecs_symtab_lookup_or_install(struct grecs_symtab *st,
+ void *key, int *install);
+void grecs_symtab_clear(struct grecs_symtab *st);
+struct grecs_symtab *grecs_symtab_create(size_t elsize,
+ unsigned (*hash_fun)(void *, unsigned long),
+ int (*cmp_fun)(const void *, const void *),
+ int (*copy_fun)(void *, void *),
+ void *(*alloc_fun)(size_t),
+ void (*free_fun)(void *));
+struct grecs_symtab *grecs_symtab_create_default(size_t elsize);
+
+void grecs_symtab_free(struct grecs_symtab *pst);
+int grecs_symtab_remove(struct grecs_symtab *st, void *elt);
+int grecs_symtab_replace(struct grecs_symtab *st, void *ent, void **old_ent);
+int grecs_symtab_enumerate(struct grecs_symtab *st,
+ grecs_symtab_enumerator_t fun, void *data);
+
+size_t grecs_symtab_count_entries(struct grecs_symtab *st);
+
diff --git a/src/list.c b/src/list.c
index d2edf73..3bb0757 100644
--- a/src/list.c
+++ b/src/list.c
@@ -20,12 +20,14 @@
#include <grecs.h>
#include <grecs-gram.h>
#include <stdlib.h>
-#include <xalloc.h>
+#include <string.h>
struct grecs_list *
grecs_list_create ()
{
- return xcalloc (1, sizeof (struct grecs_list));
+ struct grecs_list *lp = grecs_malloc (sizeof (*lp));
+ memset (lp, 0, sizeof (*lp));
+ return lp;
}
size_t
@@ -37,7 +39,7 @@ grecs_list_size (struct grecs_list *lp)
void
grecs_list_append (struct grecs_list *lp, void *val)
{
- struct grecs_list_entry *ep = xmalloc (sizeof (*ep));
+ struct grecs_list_entry *ep = grecs_malloc (sizeof (*ep));
ep->data = val;
ep->next = NULL;
if (lp->tail)
@@ -51,7 +53,7 @@ grecs_list_append (struct grecs_list *lp, void *val)
void
grecs_list_push (struct grecs_list *lp, void *val)
{
- struct grecs_list_entry *ep = xmalloc (sizeof (*ep));
+ struct grecs_list_entry *ep = grecs_malloc (sizeof (*ep));
ep->data = val;
ep->next = lp->head;
lp->head = ep;
@@ -78,7 +80,7 @@ grecs_list_pop (struct grecs_list *lp)
}
void
-grecs_list_free (struct grecs_list *lp)
+grecs_list_clear (struct grecs_list *lp)
{
struct grecs_list_entry *ep = lp->head;
@@ -90,6 +92,14 @@ grecs_list_free (struct grecs_list *lp)
free (ep);
ep = next;
}
+ lp->head = lp->tail = NULL;
+ lp->count = 0;
+}
+
+void
+grecs_list_free (struct grecs_list *lp)
+{
+ grecs_list_clear (lp);
free (lp);
}
diff --git a/src/mem.c b/src/mem.c
new file mode 100644
index 0000000..c3c14ec
--- /dev/null
+++ b/src/mem.c
@@ -0,0 +1,80 @@
+/* grecs - Gray's Extensible Configuration System
+ Copyright (C) 2007, 2008, 2009, 2010, 2011 Sergey Poznyakoff
+
+ Grecs 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 3 of the License, or (at your
+ option) any later version.
+
+ Grecs 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 Grecs. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <grecs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+void *(*grecs_malloc_fun)(size_t size);
+void *(*grecs_realloc_fun)(void *ptr, size_t size);
+void (*grecs_alloc_die_fun) (void);
+
+static void *
+def_malloc_fun(size_t size)
+{
+ return malloc(size);
+}
+
+static void *
+def_realloc_fun(void *ptr, size_t size)
+{
+ return realloc(ptr, size);
+}
+
+void *
+grecs_malloc(size_t size)
+{
+ void *ptr;
+ if (!grecs_malloc_fun)
+ grecs_malloc_fun = def_malloc_fun;
+ ptr = grecs_malloc_fun(size);
+ if (!ptr)
+ grecs_alloc_die();
+ return ptr;
+}
+
+void *
+grecs_realloc(void *ptr, size_t size)
+{
+ void *newptr;
+
+ if (!grecs_realloc_fun)
+ grecs_realloc_fun = def_realloc_fun;
+ newptr = grecs_realloc_fun(ptr, size);
+ if (!newptr)
+ grecs_alloc_die();
+ return newptr;
+}
+
+char *
+grecs_strdup(const char *str)
+{
+ char *newstr = grecs_malloc(strlen(str) + 1);
+ return strcpy(newstr, str);
+}
+
+void
+grecs_alloc_die(void)
+{
+ if (grecs_alloc_die_fun)
+ grecs_alloc_die_fun();
+ grecs_error(NULL, ENOMEM, "fatal error");
+ exit(70); /* EX_SOFTWARE */
+}
diff --git a/src/preproc.c b/src/preproc.c
index 9cdea3c..a71c93f 100644
--- a/src/preproc.c
+++ b/src/preproc.c
@@ -29,18 +29,8 @@
#include <errno.h>
#include <signal.h>
-#include <xalloc.h>
-#include <hash.h>
-#include <inttostr.h>
#include <wordsplit.h>
-#if ENABLE_NLS
-# include "gettext.h"
-# define _(msgid) gettext (msgid)
-#else
-# define _(msgid) msgid
-#endif
-
int grecs_log_to_stderr = 1;
void (*grecs_log_setup_hook) () = NULL;
@@ -62,6 +52,8 @@ struct buffer_ctx
extern int yy_grecs_flex_debug;
static struct buffer_ctx *context_stack;
+static char *linebufbase = NULL;
+static size_t linebufsize = 0;
#define INFILE context_stack->infile
#define LOCUS context_stack->locus
@@ -76,6 +68,49 @@ static int push_source (const char *name, int once);
static int pop_source (void);
static int parse_include (const char *text, int once);
+static ssize_t
+pp_getline (char **pbuf, size_t *psize, FILE *fp)
+{
+ char *buf = *pbuf;
+ size_t size = *psize;
+ ssize_t off = 0;
+
+ do
+ {
+ size_t len;
+
+ if (off == size - 1)
+ {
+ if (!buf)
+ {
+ size = 1;
+ buf = grecs_malloc (size);
+ }
+ else
+ {
+ size_t nsize = 2 * size;
+ if (nsize < size)
+ grecs_alloc_die ();
+ buf = grecs_realloc (buf, nsize);
+ size = nsize;
+ }
+ }
+ if (!fgets (buf + off, size - off, fp))
+ {
+ if (off == 0)
+ off = -1;
+ break;
+ }
+ off += strlen (buf + off);
+ }
+ while (buf[off - 1] != '\n');
+
+ *pbuf = buf;
+ *psize = size;
+ return off;
+}
+
+
static void
putback (const char *str)
{
@@ -87,51 +122,34 @@ putback (const char *str)
if (len > putback_max)
{
putback_max = len;
- putback_buffer = xrealloc (putback_buffer, putback_max);
+ putback_buffer = grecs_realloc (putback_buffer, putback_max);
}
strcpy (putback_buffer, str);
putback_size = len - 1;
}
-/* Compute the size of the line
-
- #line NNN "FILENAME"
-*/
-static size_t
-pp_line_stmt_size ()
-{
- char lbuf[INT_BUFSIZE_BOUND(uintmax_t)];
- char xbuf[INT_BUFSIZE_BOUND(uintmax_t)];
- char *lp, *xp;
-
- lp = umaxtostr (LOCUS.line, lbuf);
- xp = umaxtostr (context_stack->xlines + 1, xbuf);
- if (context_stack->namelen == 0)
- context_stack->namelen = strlen (LOCUS.file);
- /* "#line " is 6 chars, two more spaces, two quotes and a linefeed
- make another 5, summa facit 11 */
- return 11 + strlen (lp) + strlen (xp) + context_stack->namelen;
-}
-
static void
pp_line_stmt ()
{
- char *p;
- size_t ls_size = pp_line_stmt_size ();
- size_t pb_size = putback_size + ls_size + 1;
+ size_t ls_size;
+ size_t pb_size;
+
+ if (grecs_asprintf (&linebufbase, &linebufsize, "#line %lu \"%s\" %lu\n",
+ (unsigned long) LOCUS.line,
+ LOCUS.file, (unsigned long) context_stack->xlines))
+ grecs_alloc_die ();
+
+ ls_size = strlen (linebufbase);
+ pb_size = putback_size + ls_size + 1;
if (pb_size > putback_max)
{
putback_max = pb_size;
- putback_buffer = xrealloc (putback_buffer, putback_max);
+ putback_buffer = grecs_realloc (putback_buffer, putback_max);
}
- p = putback_buffer + putback_size;
context_stack->xlines++;
- snprintf (p, putback_max - putback_size,
- "#line %lu \"%s\" %lu\n",
- (unsigned long) LOCUS.line,
- LOCUS.file, (unsigned long) context_stack->xlines);
+ strcpy (putback_buffer + putback_size, linebufbase);
putback_size += ls_size;
}
@@ -151,7 +169,7 @@ next_line ()
if (putback_size + 1 > bufsize)
{
bufsize = putback_size + 1;
- linebuf = xrealloc (linebuf, bufsize);
+ linebuf = grecs_realloc (linebuf, bufsize);
}
strcpy (linebuf, putback_buffer);
rc = putback_size;
@@ -160,7 +178,7 @@ next_line ()
else if (!context_stack)
return 0;
else
- rc = getline (&linebuf, &bufsize, INFILE);
+ rc = pp_getline (&linebuf, &bufsize, INFILE);
}
while (rc == -1 && pop_source () == 0);
return rc;
@@ -264,7 +282,7 @@ pp_list_find (struct grecs_list *list, struct file_data *dptr)
if (size > dptr->buflen)
{
dptr->buflen = size;
- dptr->buf = xrealloc (dptr->buf, dptr->buflen);
+ dptr->buf = grecs_realloc (dptr->buf, dptr->buflen);
}
strcpy (dptr->buf, dir);
strcat (dptr->buf, "/");
@@ -285,7 +303,7 @@ grecs_include_path_setup_v (char **dirs)
int i;
for (i = 0; dirs[i]; i++)
/* FIXME: Element never freed */
- grecs_list_append (std_include_path, xstrdup (dirs[i]));
+ grecs_list_append (std_include_path, grecs_strdup (dirs[i]));
}
}
@@ -306,7 +324,9 @@ grecs_include_path_setup (const char *dir, ...)
{
if (argc == 0)
argc = 16;
- argv = x2nrealloc (argv, &argc, sizeof (argv[0]));
+ else
+ argc += 16;
+ argv = grecs_realloc (argv, argc * sizeof (argv[0]));
}
argv[argi++] =