*** empty log message ***

This commit is contained in:
Søren Sandmann Pedersen
2004-11-24 18:39:35 +00:00
parent c5b66034c5
commit 81a527a31d
3 changed files with 234 additions and 186 deletions

415
sfile.c
View File

@ -9,7 +9,6 @@
typedef struct State State; typedef struct State State;
typedef struct Transition Transition; typedef struct Transition Transition;
typedef struct Fragment Fragment; typedef struct Fragment Fragment;
typedef struct Action Action;
struct SFormat struct SFormat
{ {
@ -60,44 +59,6 @@ struct Fragment
Transition *enter, *exit; Transition *enter, *exit;
}; };
struct Action
{
TransitionType type;
char *name;
union
{
struct
{
int n_items;
int id;
Action *end_action;
} begin;
struct
{
gpointer object;
} end;
struct
{
int target_id;
Action *target_action;
gpointer *location;
} pointer;
struct
{
int value;
} integer;
struct
{
char *value;
} string;
} u;
};
static void static void
set_error (GError **err, gint code, const char *format, va_list args) set_error (GError **err, gint code, const char *format, va_list args)
{ {
@ -476,13 +437,51 @@ state_transition_text (const State *state, TransitionType *type, GError **err)
/* reading */ /* reading */
typedef struct BuildContext BuildContext; typedef struct BuildContext BuildContext;
typedef struct ParseNode ParseNode; typedef struct ReadItem ReadItem;
struct ReadItem
{
TransitionType type;
char *name;
union
{
struct
{
int n_items;
int id;
ReadItem *end_item;
} begin;
struct
{
gpointer object;
} end;
struct
{
int target_id;
ReadItem *target_item;
gpointer *location;
} pointer;
struct
{
int value;
} integer;
struct
{
char *value;
} string;
} u;
};
struct BuildContext struct BuildContext
{ {
const State *state; const State *state;
GArray *actions; GArray *items;
}; };
static gboolean static gboolean
@ -507,32 +506,32 @@ get_number (const char *text, int *number)
struct SFileInput struct SFileInput
{ {
int n_actions; int n_items;
Action *actions; ReadItem *items;
Action *current_action; ReadItem *current_item;
GHashTable *actions_by_location; GHashTable *items_by_location;
GHashTable *objects_by_id; GHashTable *objects_by_id;
}; };
void void
sfile_begin_get_record (SFileInput *file, const char *name) sfile_begin_get_record (SFileInput *file, const char *name)
{ {
Action *action = file->current_action++; ReadItem *item = file->current_item++;
g_return_if_fail (action->type == BEGIN_RECORD && g_return_if_fail (item->type == BEGIN_RECORD &&
strcmp (action->name, name) == 0); strcmp (item->name, name) == 0);
} }
int int
sfile_begin_get_list (SFileInput *file, sfile_begin_get_list (SFileInput *file,
const char *name) const char *name)
{ {
Action *action = file->current_action++; ReadItem *item = file->current_item++;
g_return_val_if_fail (action->type == BEGIN_LIST && g_return_val_if_fail (item->type == BEGIN_LIST &&
strcmp (action->name, name) == 0, 0); strcmp (item->name, name) == 0, 0);
return action->u.begin.n_items; return item->u.begin.n_items;
} }
void void
@ -540,20 +539,20 @@ sfile_get_pointer (SFileInput *file,
const char *name, const char *name,
gpointer *location) gpointer *location)
{ {
Action *action = file->current_action++; ReadItem *item = file->current_item++;
g_return_if_fail (action->type == POINTER && g_return_if_fail (item->type == POINTER &&
strcmp (action->name, name) == 0); strcmp (item->name, name) == 0);
action->u.pointer.location = location; item->u.pointer.location = location;
*location = (gpointer) 0xFedeAbe; *location = (gpointer) 0xFedeAbe;
if (location) if (location)
{ {
if (g_hash_table_lookup (file->actions_by_location, location)) if (g_hash_table_lookup (file->items_by_location, location))
g_warning ("Reading into the same location twice\n"); g_warning ("Reading into the same location twice\n");
g_hash_table_insert (file->actions_by_location, location, action); g_hash_table_insert (file->items_by_location, location, item);
} }
} }
@ -562,12 +561,12 @@ sfile_get_integer (SFileInput *file,
const char *name, const char *name,
int *integer) int *integer)
{ {
Action *action = file->current_action++; ReadItem *item = file->current_item++;
g_return_if_fail (action->type == INTEGER && g_return_if_fail (item->type == INTEGER &&
strcmp (action->name, name) == 0); strcmp (item->name, name) == 0);
if (integer) if (integer)
*integer = action->u.integer.value; *integer = item->u.integer.value;
} }
void void
@ -575,12 +574,12 @@ sfile_get_string (SFileInput *file,
const char *name, const char *name,
char **string) char **string)
{ {
Action *action = file->current_action++; ReadItem *item = file->current_item++;
g_return_if_fail (action->type == STRING && g_return_if_fail (item->type == STRING &&
strcmp (action->name, name) == 0); strcmp (item->name, name) == 0);
if (string) if (string)
*string = g_strdup (action->u.string.value); *string = g_strdup (item->u.string.value);
} }
static void static void
@ -588,16 +587,16 @@ hook_up_pointers (SFileInput *file)
{ {
int i; int i;
for (i = 0; i < file->n_actions; ++i) for (i = 0; i < file->n_items; ++i)
{ {
Action *action = &(file->actions[i]); ReadItem *item = &(file->items[i]);
if (action->type == POINTER) if (item->type == POINTER)
{ {
gpointer target_object = gpointer target_object =
action->u.pointer.target_action->u.begin.end_action->u.end.object; item->u.pointer.target_item->u.begin.end_item->u.end.object;
*(action->u.pointer.location) = target_object; *(item->u.pointer.location) = target_object;
} }
} }
} }
@ -607,15 +606,15 @@ sfile_end_get (SFileInput *file,
const char *name, const char *name,
gpointer object) gpointer object)
{ {
Action *action = file->current_action++; ReadItem *item = file->current_item++;
g_return_if_fail ((action->type == END_LIST || g_return_if_fail ((item->type == END_LIST ||
action->type == END_RECORD) && item->type == END_RECORD) &&
strcmp (action->name, name) == 0); strcmp (item->name, name) == 0);
action->u.end.object = object; item->u.end.object = object;
if (file->current_action == file->actions + file->n_actions) if (file->current_item == file->items + file->n_items)
hook_up_pointers (file); hook_up_pointers (file);
} }
@ -663,17 +662,17 @@ handle_begin_element (GMarkupParseContext *parse_context,
GError **err) GError **err)
{ {
BuildContext *build = user_data; BuildContext *build = user_data;
Action action; ReadItem item;
action.u.begin.id = get_id (attribute_names, attribute_values, err); item.u.begin.id = get_id (attribute_names, attribute_values, err);
if (action.u.begin.id == -1) if (item.u.begin.id == -1)
return; return;
build->state = state_transition_begin (build->state, element_name, &action.type, err); build->state = state_transition_begin (build->state, element_name, &item.type, err);
action.name = g_strdup (element_name); item.name = g_strdup (element_name);
g_array_append_val (build->actions, action); g_array_append_val (build->items, item);
} }
static void static void
@ -683,13 +682,13 @@ handle_end_element (GMarkupParseContext *context,
GError **err) GError **err)
{ {
BuildContext *build = user_data; BuildContext *build = user_data;
Action action; ReadItem item;
build->state = state_transition_end (build->state, element_name, &action.type, err); build->state = state_transition_end (build->state, element_name, &item.type, err);
action.name = g_strdup (element_name); item.name = g_strdup (element_name);
g_array_append_val (build->actions, action); g_array_append_val (build->items, item);
} }
static gboolean static gboolean
@ -717,16 +716,16 @@ handle_text (GMarkupParseContext *context,
GError **err) GError **err)
{ {
BuildContext *build = user_data; BuildContext *build = user_data;
Action action; ReadItem item;
build->state = state_transition_text (build->state, &action.type, err); build->state = state_transition_text (build->state, &item.type, err);
action.name = NULL; item.name = NULL;
switch (action.type) switch (item.type)
{ {
case POINTER: case POINTER:
if (!get_number (text, &action.u.pointer.target_id)) if (!get_number (text, &item.u.pointer.target_id))
{ {
set_invalid_content_error (err, "Contents '%s' of pointer element is not a number", text); set_invalid_content_error (err, "Contents '%s' of pointer element is not a number", text);
return; return;
@ -734,7 +733,7 @@ handle_text (GMarkupParseContext *context,
break; break;
case INTEGER: case INTEGER:
if (!get_number (text, &action.u.integer.value)) if (!get_number (text, &item.u.integer.value))
{ {
set_invalid_content_error (err, "Contents '%s' of integer element not a number", text); set_invalid_content_error (err, "Contents '%s' of integer element not a number", text);
return; return;
@ -742,7 +741,7 @@ handle_text (GMarkupParseContext *context,
break; break;
case STRING: case STRING:
if (!decode_text (text, &action.u.string.value)) if (!decode_text (text, &item.u.string.value))
{ {
set_invalid_content_error (err, "Contents '%s' of text element is illformed", text); set_invalid_content_error (err, "Contents '%s' of text element is illformed", text);
return; return;
@ -754,117 +753,117 @@ handle_text (GMarkupParseContext *context,
break; break;
} }
g_array_append_val (build->actions, action); g_array_append_val (build->items, item);
} }
static void static void
free_actions (Action *actions, int n_actions) free_items (ReadItem *items, int n_items)
{ {
int i; int i;
for (i = 0; i < n_actions; ++i) for (i = 0; i < n_items; ++i)
{ {
Action *action = &(actions[i]); ReadItem *item = &(items[i]);
if (action->name) if (item->name)
g_free (action->name); g_free (item->name);
if (action->type == STRING) if (item->type == STRING)
g_free (action->u.string.value); g_free (item->u.string.value);
} }
g_free (actions); g_free (items);
} }
/* This functions counts the number of items in a list, and /* This functions counts the number of items in each list, and
* matches up pointers with the lists/records they point to. * matches up pointers with the lists/records they point to.
* FIMXE: think of a better name * FIMXE: think of a better name
*/ */
static Action * static ReadItem *
post_process_actions_recurse (Action *first, GHashTable *actions_by_id, GError **err) post_process_items_recurse (ReadItem *first, GHashTable *items_by_id, GError **err)
{ {
Action *action; ReadItem *item;
int n_items; int n_items;
g_assert (first->type >= FIRST_BEGIN_TRANSITION && g_assert (first->type >= FIRST_BEGIN_TRANSITION &&
first->type <= LAST_BEGIN_TRANSITION); first->type <= LAST_BEGIN_TRANSITION);
action = first + 1; item = first + 1;
n_items = 0; n_items = 0;
while (action->type < FIRST_END_TRANSITION || while (item->type < FIRST_END_TRANSITION ||
action->type > LAST_END_TRANSITION) item->type > LAST_END_TRANSITION)
{ {
if (action->type >= FIRST_BEGIN_TRANSITION && if (item->type >= FIRST_BEGIN_TRANSITION &&
action->type <= LAST_BEGIN_TRANSITION) item->type <= LAST_BEGIN_TRANSITION)
{ {
action = post_process_actions_recurse (action, actions_by_id, err); item = post_process_items_recurse (item, items_by_id, err);
if (!action) if (!item)
return NULL; return NULL;
} }
else else
{ {
if (action->type == POINTER) if (item->type == POINTER)
{ {
int target_id = action->u.pointer.target_id; int target_id = item->u.pointer.target_id;
Action *target = g_hash_table_lookup (actions_by_id, GINT_TO_POINTER (target_id)); ReadItem *target = g_hash_table_lookup (items_by_id, GINT_TO_POINTER (target_id));
if (!target) if (!target)
{ {
set_invalid_content_error (err, "Id %d doesn't reference any record or list\n", set_invalid_content_error (err, "Id %d doesn't reference any record or list\n",
action->u.pointer.target_id); item->u.pointer.target_id);
return NULL; return NULL;
} }
action->u.pointer.target_action = target; item->u.pointer.target_item = target;
} }
action++; item++;
} }
n_items++; n_items++;
} }
first->u.begin.n_items = n_items; first->u.begin.n_items = n_items;
first->u.begin.end_action = action; first->u.begin.end_item = item;
return action + 1; return item + 1;
} }
static gboolean static gboolean
post_process_actions (Action *actions, int n_actions, GError **err) post_process_items (ReadItem *items, int n_items, GError **err)
{ {
gboolean retval = TRUE; gboolean retval = TRUE;
GHashTable *actions_by_id; GHashTable *items_by_id;
int i; int i;
/* Build id->action map */ /* Build id->item map */
actions_by_id = g_hash_table_new (g_direct_hash, g_direct_equal); items_by_id = g_hash_table_new (g_direct_hash, g_direct_equal);
for (i = 0; i < n_actions; ++i) for (i = 0; i < n_items; ++i)
{ {
Action *action = &(actions[i]); ReadItem *item = &(items[i]);
if (action->type >= FIRST_BEGIN_TRANSITION && if (item->type >= FIRST_BEGIN_TRANSITION &&
action->type <= LAST_BEGIN_TRANSITION) item->type <= LAST_BEGIN_TRANSITION)
{ {
int id = action->u.begin.id; int id = item->u.begin.id;
if (id) if (id)
g_hash_table_insert (actions_by_id, GINT_TO_POINTER (id), action); g_hash_table_insert (items_by_id, GINT_TO_POINTER (id), item);
} }
} }
/* count list items, check pointers */ /* count list items, check pointers */
if (!post_process_actions_recurse (actions, actions_by_id, err)) if (!post_process_items_recurse (items, items_by_id, err))
retval = FALSE; retval = FALSE;
g_hash_table_destroy (actions_by_id); g_hash_table_destroy (items_by_id);
return retval; return retval;
} }
static Action * static ReadItem *
build_actions (const char *contents, SFormat *format, int *n_actions, GError **err) build_items (const char *contents, SFormat *format, int *n_items, GError **err)
{ {
BuildContext build; BuildContext build;
GMarkupParseContext *parse_context; GMarkupParseContext *parse_context;
@ -878,30 +877,31 @@ build_actions (const char *contents, SFormat *format, int *n_actions, GError **e
}; };
build.state = sformat_get_start_state (format); build.state = sformat_get_start_state (format);
build.items = g_array_new (TRUE, TRUE, sizeof (ReadItem));
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)) if (!sformat_is_end_state (format, build.state))
{ {
set_invalid_content_error (err, "Unexpected end of file\n"); set_invalid_content_error (err, "Unexpected end of file\n");
free_actions ((Action *)build.actions->data, build.actions->len); free_items ((ReadItem *)build.items->data, build.items->len);
return NULL; return NULL;
} }
if (!g_markup_parse_context_parse (parse_context, contents, -1, err)) if (!g_markup_parse_context_parse (parse_context, contents, -1, err))
{ {
free_actions ((Action *)build.actions->data, build.actions->len); free_items ((ReadItem *)build.items->data, build.items->len);
return NULL; return NULL;
} }
if (!post_process_actions ((Action *)build.actions->data, build.actions->len, err)) if (!post_process_items ((ReadItem *)build.items->data, build.items->len, err))
{ {
free_actions ((Action *)build.actions->data, build.actions->len); free_items ((ReadItem *)build.items->data, build.items->len);
return NULL; return NULL;
} }
*n_actions = build.actions->len; *n_items = build.items->len;
return (Action *)g_array_free (build.actions, FALSE); return (ReadItem *)g_array_free (build.items, FALSE);
} }
SFileInput * SFileInput *
@ -918,9 +918,9 @@ sfile_load (const char *filename,
input = g_new (SFileInput, 1); input = g_new (SFileInput, 1);
input->actions = build_actions (contents, format, &input->n_actions, err); input->items = build_items (contents, format, &input->n_items, err);
if (!input->actions) if (!input->items)
{ {
g_free (input); g_free (input);
g_free (contents); g_free (contents);
@ -933,10 +933,48 @@ sfile_load (const char *filename,
} }
/* Writing */ /* Writing */
typedef struct WriteItem WriteItem;
struct WriteItem
{
TransitionType type;
union
{
struct
{
char *name;
int id;
} begin;
struct
{
char *name;
} end;
struct
{
char *name;
gpointer object;
} pointer;
struct
{
char *name;
int value;
} integer;
struct
{
char *name;
char *value;
} string;
} u;
};
struct SFileOutput struct SFileOutput
{ {
SFormat *format; SFormat *format;
GArray *items;
const State *state; const State *state;
}; };
@ -947,6 +985,7 @@ sfile_output_mew (SFormat *format)
SFileOutput *output = g_new (SFileOutput, 1); SFileOutput *output = g_new (SFileOutput, 1);
output->format = format; output->format = format;
output->items = g_array_new (TRUE, TRUE, sizeof (WriteItem));
output->state = sformat_get_start_state (format); output->state = sformat_get_start_state (format);
return output; return output;
@ -956,28 +995,33 @@ void
sfile_begin_add_record (SFileOutput *file, sfile_begin_add_record (SFileOutput *file,
const char *name) const char *name)
{ {
Action action; WriteItem item;
TransitionType type;
file->state = state_transition_begin (file->state, name, &type, NULL); file->state = state_transition_begin (
file->state, name, &item.type, NULL);
g_return_if_fail (file->state && type == BEGIN_RECORD); g_return_if_fail (file->state && item.type == BEGIN_RECORD);
/* FIXME: add action */ item.u.begin.name = g_strdup (name);
g_array_append_val (file->items, item);
} }
void void
sfile_begin_add_list (SFileOutput *file, sfile_begin_add_list (SFileOutput *file,
const char *name) const char *name)
{ {
Action action; WriteItem item;
TransitionType type; TransitionType type;
file->state = state_transition_begin (file->state, name, &action.type, NULL); file->state = state_transition_begin (
file->state, name, &item.type, NULL);
g_return_if_fail (file->state && type == BEGIN_LIST); g_return_if_fail (file->state && type == BEGIN_LIST);
/* FIXME */ item.u.begin.name = g_strdup (name);
g_array_append_val (file->items, item);
} }
void void
@ -985,13 +1029,39 @@ sfile_end_add (SFileOutput *file,
const char *name, const char *name,
gpointer object) gpointer object)
{ {
WriteItem item;
file->state = state_transition_end (
file->state, name, &item.type, NULL);
g_return_if_fail (file->state &&
(item.type == END_RECORD || item.type == END_LIST));
item.u.end.name = g_strdup (name);
g_array_append_val (file->items, item);
}
static TransitionType
sfile_add_value (SFileOutput *file,
const char *name,
TransitionType begin,
TransitionType value,
TransitionType end)
{
TransitionType tmp_type;
TransitionType type; TransitionType type;
file->state = state_transition_end (file->state, name, &type, NULL);
g_return_if_fail (file->state && (type == END_RECORD || type == END_LIST));
/* FIXME */ file->state = state_transition_begin (file->state, name, &tmp_type, NULL);
g_return_if_fail (file->state && tmp_type == begin);
file->state = state_transition_text (file->state, &type, NULL);
g_return_if_fail (file->state && type == value);
file->state = state_transition_end (file->state, name, &tmp_type, NULL);
g_return_if_fail (file->state && tmp_type == end);
return type;
} }
void void
@ -999,22 +1069,7 @@ sfile_add_string (SFileOutput *file,
const char *name, const char *name,
const char *string) const char *string)
{ {
TransitionType type; sfile_add_value (file, name, BEGIN_STRING, STRING, END_STRING);
/* Strings must be utf-8 */
g_return_if_fail (g_utf8_validate (string, -1, NULL));
file->state = state_transition_begin (file->state, name, &type, NULL);
g_return_if_fail (file->state && type == BEGIN_STRING);
file->state = state_transition_text (file->state, &type, NULL);
g_return_if_fail (file->state && type == STRING);
file->state = state_transition_end (file->state, name, &type, NULL);
g_return_if_fail (file->state && type == END_STRING);
} }
void void
@ -1022,15 +1077,7 @@ sfile_add_integer (SFileOutput *file,
const char *name, const char *name,
int integer) int integer)
{ {
TransitionType type; sfile_add_value (file, name, BEGIN_INTEGER, INTEGER, END_INTEGER);
/* FIXME: check intermediate states */
file->state = state_transition_begin (file->state, name, &type, NULL);
file->state = state_transition_text (file->state, &type, NULL);
file->state = state_transition_end (file->state, name, &type, NULL);
} }
void void
@ -1038,7 +1085,7 @@ sfile_add_pointer (SFileOutput *file,
const char *name, const char *name,
gpointer pointer) gpointer pointer)
{ {
/* FIMXE */ sfile_add_value (file, name, BEGIN_POINTER, POINTER, END_POINTER);
} }
gboolean gboolean

View File

@ -47,7 +47,8 @@ void sfile_loader_free (SFileLoader *loader);
/* FIXME: see if we can't get rid of the names. It should be /* FIXME: see if we can't get rid of the names. It should be
= * possible to pass NULL to state_transition_check() and = * possible to pass NULL to state_transition_check() and
* have it interprete that as "whatever" * have it interprete that as "whatever". We would need
* a way to get the name back then, though.
*/ */
SFileOutput * sfile_output_mew (SFormat *format); SFileOutput * sfile_output_mew (SFormat *format);

View File

@ -304,7 +304,7 @@ on_timer(unsigned long dong)
{ {
struct task_struct *p; struct task_struct *p;
static const int cpu_profiler = 1; /* set to 0 to profile disk */ static const int cpu_profiler = 0; /* set to 0 to profile disk */
for_each_process (p) { for_each_process (p) {
if (p->state == (cpu_profiler? TASK_RUNNING : TASK_UNINTERRUPTIBLE)) { if (p->state == (cpu_profiler? TASK_RUNNING : TASK_UNINTERRUPTIBLE)) {