more sfile work

This commit is contained in:
Søren Sandmann Pedersen
2004-11-21 00:08:14 +00:00
parent 3ac9b691d7
commit 9b76cbf1b4

319
sfile.c
View File

@ -79,8 +79,8 @@ struct Fragment
struct Action struct Action
{ {
TransitionType type; TransitionType type;
char *name;
char *name;
union union
{ {
struct struct
@ -114,6 +114,59 @@ struct Action
} u; } u;
}; };
static void
set_error (GError **err, gint code, const char *format, va_list args)
{
char *msg;
if (!err)
return;
msg = g_strdup_vprintf (format, args);
if (*err == NULL)
{
*err = g_error_new_literal (G_MARKUP_ERROR, code, msg);
}
else
{
/* Warning text from GLib */
g_warning ("GError set over the top of a previous GError or uninitialized memory.\n"
"This indicates a bug in someone's code. You must ensure an error is NULL before it's set.\n"
"The overwriting error message was: %s",
msg);
}
g_free (msg);
}
static void
set_unknown_element_error (GError **err, const char *format, ...)
{
va_list args;
va_start (args, format);
set_error (err, G_MARKUP_ERROR_UNKNOWN_ELEMENT, format, args);
va_end (args);
}
static void
set_unknown_attribute_error (GError **err, const char *format, ...)
{
va_list args;
va_start (args, format);
set_error (err, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, format, args);
va_end (args);
}
static void
set_invalid_content_error (GError **err, const char *format, ...)
{
va_list args;
va_start (args, format);
set_error (err, G_MARKUP_ERROR_INVALID_CONTENT, format, args);
va_end (args);
}
static State * static State *
state_new (void) state_new (void)
{ {
@ -123,93 +176,18 @@ state_new (void)
} }
static Transition * static Transition *
transition_new_begin_union (const char *name, State *from, State *to) transition_new (const char *element, TransitionType type, State *from, State *to)
{ {
return NULL; /* FIXME */ Transition *t = g_new (Transition, 1);
}
static Transition * t->element = element? g_strdup (element) : NULL;
transition_new_end_union (const char *name, State *from, State *to) t->type = type;
{ t->to = to;
return NULL; /* FIXME */
}
static Transition * if (from)
transition_new_begin_record (const char *name, State *from, State *to) g_queue_push_tail (from->transitions, t);
{
return NULL; /* FIXME */
}
static Transition * return t;
transition_new_end_record (const char *name, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_begin_pointer (const char *name, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_end_pointer (const char *name, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_begin_integer (const char *name, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_end_integer (const char *name, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_begin_string (const char *name, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_end_string (const char *name, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_begin_list (const char *name, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_end_list (const char *name, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_begin_value (const char *name, TransitionType type, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_end_value (const char *name, TransitionType type, State *from, State *to)
{
return NULL; /* FIXME */
}
static Transition *
transition_new_value (TransitionType type, State *from, State *to)
{
return NULL; /* FIXME */
} }
SFormat * SFormat *
@ -246,6 +224,7 @@ fragment_queue (va_list args)
return fragments; return fragments;
} }
#if 0
/* Consider adding unions at some point /* Consider adding unions at some point
* *
* To be useful they should probably be anonymous, so that * To be useful they should probably be anonymous, so that
@ -295,8 +274,8 @@ sformat_new_union (const char *name,
begin = state_new (); begin = state_new ();
end = state_new (); end = state_new ();
enter = transition_new_begin_union (name, NULL, begin); enter = transition_new (name, TRANSITION_BEGIN_UNION, NULL, begin);
exit = transition_new_end_union (name, end, NULL); exit = transition_new (name, TRANSITION_END_UNION, end, NULL);
for (list = fragments->head; list; list = list->next) for (list = fragments->head; list; list = list->next)
{ {
@ -322,6 +301,7 @@ sformat_new_union (const char *name,
return fragment; return fragment;
} }
#endif
gpointer gpointer
sformat_new_record (const char * name, sformat_new_record (const char * name,
@ -337,14 +317,14 @@ sformat_new_record (const char * name,
/* Build queue of fragments */ /* Build queue of fragments */
va_start (args, content1); va_start (args, content1);
fragments = fragment_queue (args); fragments = fragment_queue (args);
va_end (args); va_end (args);
/* chain fragments together */ /* chain fragments together */
begin = state_new (); begin = state_new ();
enter = transition_new_begin_record (name, NULL, begin); enter = transition_new (name, BEGIN_RECORD, NULL, begin);
state = begin; state = begin;
@ -365,7 +345,7 @@ sformat_new_record (const char * name,
/* Return resulting fragment */ /* Return resulting fragment */
fragment = g_new (Fragment, 1); fragment = g_new (Fragment, 1);
fragment->enter = enter; fragment->enter = enter;
fragment->exit = transition_new_end_record (name, state, NULL); fragment->exit = transition_new (name, END_RECORD, state, NULL);
return fragment; return fragment;
} }
@ -380,8 +360,8 @@ sformat_new_list (const char *name,
list_state = state_new (); list_state = state_new ();
enter = transition_new_begin_list (name, NULL, list_state); enter = transition_new (name, BEGIN_LIST, NULL, list_state);
exit = transition_new_end_list (name, list_state, NULL); exit = transition_new (name, END_LIST, list_state, NULL);
g_queue_push_tail (list_state->transitions, m->enter); g_queue_push_tail (list_state->transitions, m->enter);
m->exit->to = list_state; m->exit->to = list_state;
@ -392,7 +372,7 @@ sformat_new_list (const char *name,
return m; return m;
} }
gpointer static gpointer
sformat_new_value (const char *name, TransitionType type) sformat_new_value (const char *name, TransitionType type)
{ {
Fragment *m = g_new (Fragment, 1); Fragment *m = g_new (Fragment, 1);
@ -402,9 +382,9 @@ sformat_new_value (const char *name, TransitionType type)
before = state_new (); before = state_new ();
after = state_new (); after = state_new ();
m->enter = transition_new_begin_value (name, type, NULL, before); m->enter = transition_new (name, type, NULL, before);
m->exit = transition_new_end_value (name, type, after, NULL); m->exit = transition_new (name, type, after, NULL);
value = transition_new_value (type, before, after); value = transition_new (NULL, type, before, after);
return m; return m;
} }
@ -459,7 +439,8 @@ state_transition_check (const State *state, const char *element,
} }
} }
/* FIXME: generate appropriate error */ set_unknown_element_error (err, "<%s> or </%s> unexpected here", element, element);
return NULL; return NULL;
} }
@ -491,27 +472,20 @@ state_transition_text (const State *state, const char *text,
{ {
Transition *transition = list->data; Transition *transition = list->data;
if ((transition->type >= FIRST_BEGIN_TRANSITION && /* There will never be more than one allowed value transition for
transition->type <= LAST_BEGIN_TRANSITION) || * a given state
(transition->type >= FIRST_END_TRANSITION && */
transition->type <= LAST_END_TRANSITION)) if (transition->type == POINTER ||
transition->type == INTEGER ||
transition->type == STRING)
{ {
continue; *type = transition->type;
} return transition->to;
if (transition->type == POINTER)
{
}
else if (transition->type == INTEGER)
{
}
else if (transition->type == STRING)
{
} }
} }
set_invalid_content_error (err, "Unexpected text data unexpected (%s)", text);
return NULL;
} }
/* reading */ /* reading */
@ -520,7 +494,8 @@ typedef struct ParseNode ParseNode;
struct BuildContext struct BuildContext
{ {
State *state; const State *state;
Action *actions; Action *actions;
int n_actions; int n_actions;
}; };
@ -648,22 +623,39 @@ sfile_end_get (SFileInput *file,
GINT_TO_POINTER (action->u.end.id), object); GINT_TO_POINTER (action->u.end.id), object);
} }
static ParseNode * static int
parse_node_new (ParseNode *parent, get_id (const char **names, const char **values, GError **err)
const char *name)
{ {
ParseNode *node = g_new0 (ParseNode, 1); const char *id_string = NULL;
int id, i;
node->parent = parent;
node->name = g_strdup (name);
node->id = NULL;
node->children = g_ptr_array_new ();
node->text = g_string_new ("");
if (parent)
g_ptr_array_add (parent->children, node);
return node; for (i = 0; names[i] != NULL; ++i)
{
if (strcmp (names[i], "id") != 0)
{
set_unknown_attribute_error (err, "Unknown attribute: %s", names[i]);
return -1;
}
if (id_string)
{
set_invalid_content_error (err, "Attribute 'id' defined twice");
return -1;
}
id_string = values[i];
}
if (!id_string)
return 0;
if (!get_number (id_string, &id) || id < 1)
{
set_invalid_content_error (err, "Bad attribute value for attribute 'id' (must be >= 1)\n");
return -1;
}
return id;
} }
static void static void
@ -675,46 +667,18 @@ handle_begin_element (GMarkupParseContext *parse_context,
GError **err) GError **err)
{ {
BuildContext *build = user_data; BuildContext *build = user_data;
const char *id_string;
Action action; Action action;
int id; int id;
int i;
/* Check for id */ /* Check for id */
id_string = NULL; id = get_id (attribute_names, attribute_values, err);
for (i = 0; attribute_names[i] != NULL; ++i)
{
if (strcmp (attribute_names[i], "id") == 0)
{
if (id_string)
{
/* FIXME: error: id defined twice */
return;
}
else
{
id_string = attribute_values[i];
if (!get_number (id_string, &id) || id < 1)
{
/* FIXME: bad attribute value for attribute 'id' */
return;
}
}
}
else
{
/* FIXME: unknown attribute */
return;
}
}
/* */ if (id == -1)
return;
if (!state_transition_begin (build->state, element_name, &action.type, err)) build->state = state_transition_begin (build->state, element_name, &action.type, err);
{
/* FIXME: report error */ /* FIXME create action/add to list */
};
} }
static void static void
@ -724,6 +688,11 @@ handle_end_element (GMarkupParseContext *context,
GError **err) GError **err)
{ {
BuildContext *build = user_data; BuildContext *build = user_data;
Action action;
build->state = state_transition_end (build->state, element_name, &action.type, err);
/* FIXME create action/add to list */
} }
static void static void
@ -734,10 +703,20 @@ handle_text (GMarkupParseContext *context,
GError **err) GError **err)
{ {
BuildContext *build = user_data; BuildContext *build = user_data;
Action action;
build->state = state_transition_text (build->state, text, &action.type, err);
/* FIXME create acxtion/add to list */
}
static void
free_actions (Action *actions, int n_actions)
{
} }
static Action * static Action *
build_actions (const char *contents, int *n_actions, GError **err) build_actions (const char *contents, SFormat *format, int *n_actions, GError **err)
{ {
BuildContext build; BuildContext build;
GMarkupParseContext *parse_context; GMarkupParseContext *parse_context;
@ -750,11 +729,19 @@ build_actions (const char *contents, int *n_actions, GError **err)
NULL, /* error */ NULL, /* error */
}; };
build.state = sformat_get_start_state (format);
parse_context = g_markup_parse_context_new (&parser, 0, &build, NULL); parse_context = g_markup_parse_context_new (&parser, 0, &build, NULL);
if (!sformat_is_end_state (format, build.state))
{
set_invalid_content_error (err, "Unexpected end of file\n");
free_actions (build.actions, build.n_actions);
return NULL;
}
if (!g_markup_parse_context_parse (parse_context, contents, -1, err)) if (!g_markup_parse_context_parse (parse_context, contents, -1, err))
{ {
/* FIXME: free stuff */ free_actions (build.actions, build.n_actions);
return NULL; return NULL;
} }
@ -775,7 +762,7 @@ sfile_load (const char *filename,
input = g_new (SFileInput, 1); input = g_new (SFileInput, 1);
input->actions = build_actions (contents, &input->n_actions, err); input->actions = build_actions (contents, format, &input->n_actions, err);
if (!input->actions) if (!input->actions)
{ {