aboutsummaryrefslogtreecommitdiff
path: root/src/txtacc.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-15 13:51:03 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-05-15 14:05:39 +0300
commita0826b4c7cd66c4862d9b61bb7e14d73fcba28f6 (patch)
tree71762fca263967e5803ce803b0a0aa94555e125d /src/txtacc.c
parentfd64fa62bc68d8c2e0d693033e874fcc1f023544 (diff)
downloadgrecs-a0826b4c7cd66c4862d9b61bb7e14d73fcba28f6.tar.gz
grecs-a0826b4c7cd66c4862d9b61bb7e14d73fcba28f6.tar.bz2
Provide a framework for multiple parsers. Implement meta1 parser.
* Makefile.am (EXTRA_DIST): Add build-aux/yyrename * am/grecs.m4: New options: parser-meta1 and all-parsers * src/.gitignore: Update. * src/Make.am [GRECS_COND_META1_PARSER]: Set GRECS_PARSER_META1 and GRECS_EXTRA_META1 (GRECS_SRC): Add new files. (EXTRA_DIST): Add GRECS_EXTRA_META1. (LEXCOMPILE,YACCCOMPILE): Redefine * src/grecs-gram.y: Don't include yygrecs.h (grecs_vasprintf,grecs_asprintf): Move to a separate file. (grecs_parse): Rename to grecs_grecs_parser. Actual grecs_parse is defined in parser.c (grecs_gram_trace): Move to parser.c * src/grecs-lex.l: Don't include yygrecs.h Use line_acc functions. * src/grecs.h (grecs_trace_flags): New extern. (GRECS_TRACE_GRAM, GRECS_TRACE_LEX): New flags. (grecs_lex_begin): Change signature. (grecs_grecs_parser,grecs_meta1_parser): New protos. (grecs_line_acc_create) (grecs_line_acc_free,grecs_line_acc_grow_char) (grecs_line_acc_grow_char_unescape) (grecs_line_acc_grow) (grecs_line_acc_grow_unescape_last): New protos. (GRECS_TXTACC_BUFSIZE): New const (grecs_txtacc_create,grecs_txtacc_free) (grecs_txtacc_grow,grecs_txtacc_finish) (grecs_txtacc_free_string): New protos. (grecs_value_match): New proto. * src/wordsplit.c (quote_transtab): Translate \" * src/yygrecs.h: Remove. * src/yytrans: New file. * build-aux/yyrename: New file. * src/asprintf.c: New file. * src/lineacc.c: New file. * src/meta1-gram.y: New file. * src/meta1-lex.l: New file. * src/parser.c: New file. * src/txtacc.c: New file. * doc/grecs_parse.3: Update. * doc/GRECS_SETUP.3: Update.
Diffstat (limited to 'src/txtacc.c')
-rw-r--r--src/txtacc.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/txtacc.c b/src/txtacc.c
new file mode 100644
index 0000000..ff13e42
--- /dev/null
+++ b/src/txtacc.c
@@ -0,0 +1,187 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2007, 2009-2011 Sergey Poznyakoff
+
+ Wydawca 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.
+
+ Wydawca 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 wydawca. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <string.h>
+#include "grecs.h"
+
+struct grecs_txtacc_entry
+{
+ char *buf; /* Text buffer */
+ size_t size; /* Buffer size */
+ size_t len; /* Actual number of bytes in buffer */
+};
+#define TXTACC_BUFSIZE 1024
+#define grecs_txtacc_entry_freesize(e) ((e)->size - (e)->len)
+
+struct grecs_txtacc
+{
+ struct grecs_list *cur; /* Current build list */
+ struct grecs_list *mem; /* List of already allocated elements */
+};
+
+static struct grecs_txtacc_entry *
+grecs_txtacc_alloc_entry(struct grecs_list *list, size_t size)
+{
+ struct grecs_txtacc_entry *p = grecs_malloc(sizeof (*p));
+ p->buf = grecs_malloc(size);
+ p->size = size;
+ p->len = 0;
+ grecs_list_append(list, p);
+ return p;
+}
+
+static struct grecs_txtacc_entry *
+grecs_txtacc_cur_entry(struct grecs_txtacc *acc)
+{
+ struct grecs_txtacc_entry *ent;
+
+ if (grecs_list_size(acc->cur) == 0)
+ return grecs_txtacc_alloc_entry(acc->cur,
+ GRECS_TXTACC_BUFSIZE);
+ ent = acc->cur->tail->data;
+ if (grecs_txtacc_entry_freesize(ent) == 0)
+ ent = grecs_txtacc_alloc_entry(acc->cur,
+ GRECS_TXTACC_BUFSIZE);
+ return ent;
+}
+
+static void
+grecs_txtacc_entry_append(struct grecs_txtacc_entry *ent,
+ const char *p, size_t size)
+{
+ memcpy(ent->buf + ent->len, p, size);
+ ent->len += size;
+}
+
+static void
+grecs_txtacc_entry_tailor(struct grecs_txtacc_entry *ent)
+{
+ if (ent->size > ent->len) {
+ char *p = realloc(ent->buf, ent->len);
+ if (!p)
+ return;
+ ent->buf = p;
+ ent->size = ent->len;
+ }
+}
+
+static void
+grecs_txtacc_entry_free(void *p)
+{
+ if (p) {
+ struct grecs_txtacc_entry *ent = p;
+ free(ent->buf);
+ free(ent);
+ }
+}
+
+struct grecs_txtacc *
+grecs_txtacc_create()
+{
+ struct grecs_txtacc *acc = grecs_malloc(sizeof (*acc));
+ acc->cur = grecs_list_create();
+ acc->cur->free_entry = grecs_txtacc_entry_free;
+ acc->mem = grecs_list_create();
+ acc->mem->free_entry = grecs_txtacc_entry_free;
+ return acc;
+}
+
+void
+grecs_txtacc_free(struct grecs_txtacc *acc)
+{
+ grecs_list_free (acc->cur);
+ grecs_list_free (acc->mem);
+ free (acc);
+}
+
+void
+grecs_txtacc_grow(struct grecs_txtacc *acc, const char *buf, size_t size)
+{
+ while (size) {
+ struct grecs_txtacc_entry *ent = grecs_txtacc_cur_entry(acc);
+ size_t rest = grecs_txtacc_entry_freesize(ent);
+ if (rest > size)
+ rest = size;
+ grecs_txtacc_entry_append(ent, buf, rest);
+ buf += rest;
+ size -= rest;
+ }
+}
+
+char *
+grecs_txtacc_finish(struct grecs_txtacc *acc, int steal)
+{
+ struct grecs_list_entry *ep;
+ struct grecs_txtacc_entry *txtent;
+ size_t size;
+ char *p;
+
+ switch (grecs_list_size(acc->cur)) {
+ case 0:
+ return NULL;
+
+ case 1:
+ txtent = acc->cur->head->data;
+ acc->cur->head->data = NULL;
+ grecs_txtacc_entry_tailor(txtent);
+ grecs_list_append(acc->mem, txtent);
+ break;
+
+ default:
+ size = 0;
+ for (ep = acc->cur->head; ep; ep = ep->next) {
+ txtent = ep->data;
+ size += txtent->len;
+ }
+
+ txtent = grecs_txtacc_alloc_entry(acc->mem, size);
+ for (ep = acc->cur->head; ep; ep = ep->next) {
+ struct grecs_txtacc_entry *tp = ep->data;
+ grecs_txtacc_entry_append(txtent, tp->buf, tp->len);
+ }
+ }
+
+ grecs_list_clear(acc->cur);
+ p = txtent->buf;
+ if (steal) {
+ grecs_list_remove_tail(acc->mem);
+ free(txtent);
+ }
+ return p;
+}
+
+void
+grecs_txtacc_free_string(struct grecs_txtacc *acc, char *str)
+{
+ struct grecs_list_entry *ep;
+ for (ep = acc->mem->head; ep; ep = ep->next) {
+ struct grecs_txtacc_entry *tp = ep->data;
+ if (tp->buf == str) {
+ grecs_list_remove_entry(acc->mem, ep);
+ grecs_free(tp->buf);
+ return;
+ }
+ }
+}
+
+void
+grecs_txtacc_clear(struct grecs_txtacc *acc)
+{
+ grecs_list_clear(acc->cur);
+}

Return to:

Send suggestions and report system problems to the System administrator.