diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-11-08 01:20:37 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-11-08 01:20:37 +0100 |
commit | 7dbb2831b81ff0174054d30b1fc105b2113c272d (patch) | |
tree | fde5c878e2c9a89e6f41c8535034e1b16927c154 | |
parent | 1707fcabca80e2e664bef9c02ec5cc9d793ce37b (diff) | |
download | sciteco-7dbb2831b81ff0174054d30b1fc105b2113c272d.tar.gz |
added support for labels, including the goto label table
* uses BSD tree macros, might later be abstracted to a C++ table class
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | cmdline.cpp | 2 | ||||
-rw-r--r-- | goto.cpp | 193 | ||||
-rw-r--r-- | goto.h | 14 | ||||
-rw-r--r-- | parser.cpp | 14 | ||||
-rw-r--r-- | parser.h | 18 | ||||
-rw-r--r-- | sciteco.h | 5 | ||||
-rw-r--r-- | undo.h | 37 |
8 files changed, 272 insertions, 14 deletions
@@ -10,7 +10,8 @@ LDFLAGS:=$(GTK_LDFLAGS) $(SCI_LDFLAGS) all : sciteco -sciteco : main.o cmdline.o undo.o expressions.o parser.o +sciteco : main.o cmdline.o undo.o expressions.o \ + parser.o goto.o $(CXX) -o $@ $^ $(LDFLAGS) clean: diff --git a/cmdline.cpp b/cmdline.cpp index 2135f9a..e0159ec 100644 --- a/cmdline.cpp +++ b/cmdline.cpp @@ -4,6 +4,8 @@ #include <glib/gprintf.h> #include "sciteco.h" +#include "parser.h" +#include "undo.h" static gchar *macro_echo(const gchar *macro, const gchar *prefix = ""); diff --git a/goto.cpp b/goto.cpp new file mode 100644 index 0000000..f183ca1 --- /dev/null +++ b/goto.cpp @@ -0,0 +1,193 @@ +#include <bsd/sys/tree.h> + +#include <glib.h> +#include <glib/gprintf.h> + +#include "sciteco.h" +#include "parser.h" +#include "undo.h" +#include "goto.h" + +static gchar *skip_label = NULL; + +class GotoTable { + class UndoTokenSet : public UndoToken { + GotoTable *table; + + gchar *name; + gint pc; + + public: + UndoTokenSet(GotoTable *_table, gchar *_name, gint _pc = -1) + : table(_table), name(g_strdup(_name)), pc(_pc) {} + ~UndoTokenSet() + { + g_free(name); + } + + void + run(void) + { + table->set(name, pc); + g_free(name); + name = NULL; +#if 0 + table->dump(); +#endif + } + }; + + class Label { + public: + RB_ENTRY(Label) nodes; + + gchar *name; + gint pc; + + Label(gchar *_name, gint _pc = -1) + : name(g_strdup(_name)), pc(_pc) {} + ~Label() + { + g_free(name); + } + + static inline int + cmp(Label *l1, Label *l2) + { + return g_strcmp0(l1->name, l2->name); + } + }; + + RB_HEAD(Table, Label) head; + + RB_GENERATE(Table, Label, nodes, Label::cmp); + +public: + GotoTable() + { + RB_INIT(&head); + } + + ~GotoTable() + { + clear(); + } + + gint + remove(gchar *name) + { + gint existing_pc = -1; + + Label label(name); + Label *existing = RB_FIND(Table, &head, &label); + + if (existing) { + existing_pc = existing->pc; + RB_REMOVE(Table, &head, existing); + delete existing; + } + + return existing_pc; + } + + gint + find(gchar *name) + { + Label label(name); + Label *existing = RB_FIND(Table, &head, &label); + + return existing ? existing->pc : -1; + } + + gint + set(gchar *name, gint pc) + { + if (pc < 0) + return remove(name); + + Label *label = new Label(name, pc); + Label *existing; + gint existing_pc = -1; + + existing = RB_FIND(Table, &head, label); + if (existing) { + existing_pc = existing->pc; + g_free(existing->name); + existing->name = label->name; + existing->pc = label->pc; + + label->name = NULL; + delete label; + } else { + RB_INSERT(Table, &head, label); + } + +#if 0 + dump(); +#endif + return existing_pc; + } + + inline void + undo_set(gchar *name, gint pc = -1) + { + undo.push(new UndoTokenSet(this, name, pc)); + } + + void + clear(void) + { + Label *cur; + + while ((cur = RB_MIN(Table, &head))) { + RB_REMOVE(Table, &head, cur); + delete cur; + } + } + +#if 0 + void + dump(void) + { + Label *cur; + + RB_FOREACH(cur, Table, &head) + g_printf("table[\"%s\"] = %d\n", cur->name, cur->pc); + g_printf("---END---\n"); + } +#endif +}; + +static GotoTable table; + +State * +StateLabel::custom(gchar chr) +{ + gchar *new_str; + + if (chr == '!') { + table.undo_set(strings[0], table.set(strings[0], macro_pc)); + + if (!g_strcmp0(strings[0], skip_label)) { + undo.push_str(skip_label); + g_free(skip_label); + skip_label = NULL; + + undo.push_var<Mode>(mode); + mode = MODE_NORMAL; + } + + undo.push_str(strings[0]); + g_free(strings[0]); + strings[0] = NULL; + + return &states.start; + } + + undo.push_str(strings[0]); + new_str = g_strdup_printf("%s%c", strings[0] ? : "", chr); + g_free(strings[0]); + strings[0] = new_str; + + return this; +} @@ -0,0 +1,14 @@ +#ifndef __GOTO_H +#define __GOTO_H + +#include <glib.h> + +#include "sciteco.h" +#include "parser.h" + +class StateLabel : public State { +private: + State *custom(gchar chr); +}; + +#endif @@ -8,9 +8,7 @@ gint macro_pc = 0; -static struct { - StateStart start; -} states; +States states; static State *current_state = &states.start; @@ -19,10 +17,7 @@ static struct { bool at; } modifiers = {false, false}; -static enum Mode { - MODE_NORMAL = 0, - MODE_PARSE_ONLY -} mode = MODE_NORMAL; +enum Mode mode = MODE_NORMAL; /* FIXME: perhaps integrate into Mode */ static bool skip_else = false; @@ -34,6 +29,8 @@ static bool skip_else = false; static gint nest_level = 0; +gchar *strings[2] = {NULL, NULL}; + bool macro_execute(const gchar *macro) { @@ -113,6 +110,8 @@ StateStart::StateStart() : State() { transitions['\0'] = this; init(" \r\n\v"); + + transitions['!'] = &states.label; } void @@ -426,4 +425,3 @@ StateStart::custom(gchar chr) return this; } - @@ -50,4 +50,22 @@ private: State *custom(gchar chr); }; +#include "goto.h" + +extern gint macro_pc; + +extern struct States { + StateStart start; + StateLabel label; +} states; + +extern enum Mode { + MODE_NORMAL = 0, + MODE_PARSE_ONLY +} mode; + +extern gchar *strings[2]; + +bool macro_execute(const gchar *macro); + #endif @@ -8,10 +8,7 @@ #include <Scintilla.h> -#include "undo.h" - extern gchar *cmdline; -extern gint macro_pc; void message_display(GtkMessageType type, const gchar *fmt, ...) G_GNUC_PRINTF(2, 3); @@ -21,8 +18,6 @@ void cmdline_display(const gchar *cmdline); sptr_t editor_msg(unsigned int iMessage, uptr_t wParam = 0, sptr_t lParam = 0); -bool macro_execute(const gchar *macro); - #define IS_CTL(C) ((C) < ' ') #define CTL_ECHO(C) ((C) | 0x40) @@ -4,6 +4,7 @@ #include <bsd/sys/queue.h> #include <glib.h> +#include <glib/gprintf.h> #include <Scintilla.h> @@ -48,6 +49,31 @@ public: } }; +class UndoTokenString : public UndoToken { + gchar **ptr; + gchar *str; + +public: + UndoTokenString(gchar *&variable, gchar *_str) + : UndoToken(), ptr(&variable) + { + str = _str ? g_strdup(_str) : NULL; + } + + ~UndoTokenString() + { + g_free(str); + } + + void + run(void) + { + g_free(*ptr); + *ptr = str; + str = NULL; + } +}; + extern class UndoStack { SLIST_HEAD(undo_head, UndoToken) head; @@ -86,6 +112,17 @@ public: push_var<Type>(variable, variable); } + inline void + push_str(gchar *&variable, gchar *str) + { + push(new UndoTokenString(variable, str)); + } + inline void + push_str(gchar *&variable) + { + push_str(variable, variable); + } + void pop(gint pos); } undo; |