From d07d2452286997728f72fa4e8886b009d9e6eaa6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Mon, 7 Mar 2005 03:58:04 +0000 Subject: [PATCH] CSun Mar 6 22:56:21 2005 Soeren Sandmann * sfile.c: Generate id's for objects and pointers. --- ChangeLog | 4 ++ sfile.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------- sfile.h | 18 +++++ sysprof.c | 5 +- 4 files changed, 209 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9da881..e3a5e9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Sun Mar 6 22:56:21 2005 Soeren Sandmann + + * sfile.c: Generate id's for objects and pointers. + Sat Mar 5 01:09:33 2005 Soeren Sandmann * sfile.c: Bug fixes. Add actual generation. diff --git a/sfile.c b/sfile.c index f559ac3..760eeb9 100644 --- a/sfile.c +++ b/sfile.c @@ -473,7 +473,7 @@ struct Instruction { struct { - int n_instructions; + int n_elements; int id; Instruction *end_instruction; } begin; @@ -488,8 +488,8 @@ struct Instruction { int target_id; Instruction *target_instruction; + gpointer target_object; gpointer *location; - gpointer object; } pointer; struct @@ -573,7 +573,7 @@ sfile_begin_get_list (SFileInput *file, g_return_val_if_fail (strcmp (instruction->name, name) == 0, 0); g_return_val_if_fail (is_list_type (instruction->type), 0); - return instruction->u.begin.n_instructions; + return instruction->u.begin.n_elements; } void @@ -712,6 +712,7 @@ handle_begin_element (GMarkupParseContext *parse_context, build->state = state_transition_begin (build->state, element_name, &instruction.type, err); instruction.name = g_strdup (element_name); + instruction.kind = BEGIN; g_array_append_val (build->instructions, instruction); } @@ -728,6 +729,7 @@ handle_end_element (GMarkupParseContext *context, build->state = state_transition_end (build->state, element_name, &instruction.type, err); instruction.name = g_strdup (element_name); + instruction.kind = END; g_array_append_val (build->instructions, instruction); } @@ -762,7 +764,8 @@ handle_text (GMarkupParseContext *context, build->state = state_transition_text (build->state, &instruction.type, err); instruction.name = NULL; - + instruction.kind = VALUE; + switch (instruction.type) { case TYPE_POINTER: @@ -824,13 +827,13 @@ static Instruction * post_process_instructions_recurse (Instruction *first, GHashTable *instructions_by_id, GError **err) { Instruction *instruction; - int n_instructions; + int n_elements; g_assert (first->kind == BEGIN); instruction = first + 1; - n_instructions = 0; + n_elements = 0; while (instruction->kind != END) { if (instruction->kind == BEGIN) @@ -841,28 +844,52 @@ post_process_instructions_recurse (Instruction *first, GHashTable *instructions_ } else { - if (instruction->type == TYPE_POINTER) - { - int target_id = instruction->u.pointer.target_id; - Instruction *target = g_hash_table_lookup (instructions_by_id, GINT_TO_POINTER (target_id)); + instruction++; + } + + n_elements++; + } - if (!target) - { - set_invalid_content_error (err, "Id %d doesn't reference any record or list\n", - instruction->u.pointer.target_id); - return NULL; - } + first->u.begin.n_elements = n_elements; + first->u.begin.end_instruction = instruction; - instruction->u.pointer.target_instruction = target; - } - + instruction->u.end.begin_instruction = first; + + return instruction + 1; +} + +/* This functions makes end instructions point to the corresponding + * begin instructions, and counts the number of instructions + * contained in a begin/end pair + */ +static Instruction * +process_instruction_pairs (Instruction *first) +{ + Instruction *instruction; + int n_elements; + + g_assert (first->kind == BEGIN); + + instruction = first + 1; + + n_elements = 0; + while (instruction->kind != END) + { + if (instruction->kind == BEGIN) + { + instruction = process_instruction_pairs (instruction); + if (!instruction) + return NULL; + } + else + { instruction++; } - n_instructions++; + n_elements++; } - first->u.begin.n_instructions = n_instructions; + first->u.begin.n_elements = n_elements; first->u.begin.end_instruction = instruction; instruction->u.end.begin_instruction = first; @@ -877,6 +904,9 @@ post_process_read_instructions (Instruction *instructions, int n_instructions, G GHashTable *instructions_by_id; int i; + /* count list instructions, check pointers */ + process_instruction_pairs (instructions); + /* Build id->instruction map */ instructions_by_id = g_hash_table_new (g_direct_hash, g_direct_equal); for (i = 0; i < n_instructions; ++i) @@ -892,9 +922,27 @@ post_process_read_instructions (Instruction *instructions, int n_instructions, G } } - /* count list instructions, check pointers */ - if (!post_process_instructions_recurse (instructions, instructions_by_id, err)) - retval = FALSE; + /* Make pointer instructions point to the corresponding element */ + for (i = 0; i < n_instructions; ++i) + { + Instruction *instruction = &(instructions[i]); + + if (instruction->type == TYPE_POINTER) + { + int target_id = instruction->u.pointer.target_id; + + Instruction *target = g_hash_table_lookup (instructions_by_id, + GINT_TO_POINTER (target_id)); + + if (!target) + { + set_invalid_content_error (err, "Id %d doesn't reference any record or list\n", + instruction->u.pointer.target_id); + retval = FALSE; + break; + } + } + } g_hash_table_destroy (instructions_by_id); @@ -934,7 +982,8 @@ build_instructions (const char *contents, SFormat *format, int *n_instructions, return NULL; } - if (!post_process_read_instructions ((Instruction *)build.instructions->data, build.instructions->len, err)) + if (!post_process_read_instructions ((Instruction *)build.instructions->data, + build.instructions->len, err)) { free_instructions ((Instruction *)build.instructions->data, build.instructions->len); return NULL; @@ -977,10 +1026,10 @@ struct SFileOutput { SFormat *format; GArray *instructions; + GHashTable *objects; const State *state; }; - SFileOutput * sfile_output_new (SFormat *format) { @@ -989,6 +1038,7 @@ sfile_output_new (SFormat *format) output->format = format; output->instructions = g_array_new (TRUE, TRUE, sizeof (Instruction)); output->state = sformat_get_start_state (format); + output->objects = g_hash_table_new (g_direct_hash, g_direct_equal); return output; } @@ -1036,16 +1086,29 @@ sfile_end_add (SFileOutput *file, { Instruction instruction; + if (object && g_hash_table_lookup (file->objects, object)) + { + g_warning ("Adding the same object (%p) twice", object); + return; + } + file->state = state_transition_end ( file->state, name, &instruction.type, NULL); - g_return_if_fail (file->state); + if (!file->state) + { + g_warning ("invalid call of sfile_end_add()"); + return; + } instruction.kind = END; instruction.name = g_strdup (name); instruction.u.end.object = object; g_array_append_val (file->instructions, instruction); + + if (object) + g_hash_table_insert (file->objects, object, object); } static void @@ -1113,12 +1176,81 @@ sfile_add_pointer (SFileOutput *file, instruction.kind = VALUE; instruction.type = TYPE_POINTER; instruction.name = g_strdup (name); - instruction.u.pointer.object = pointer; + instruction.u.pointer.target_object = pointer; g_array_append_val (file->instructions, instruction); } static void +post_process_write_instructions (SFileOutput *sfile) +{ + int i; + Instruction *instructions = (Instruction *)sfile->instructions->data; + int n_instructions = sfile->instructions->len; + int id; + GHashTable *instructions_by_object; + + process_instruction_pairs (instructions); + + /* Set all id's to -1 and create map from objects to instructions */ + + instructions_by_object = g_hash_table_new (g_direct_hash, g_direct_equal); + + for (i = 0; i < n_instructions; ++i) + { + Instruction *instruction = &(instructions[i]); + + if (instruction->kind == BEGIN) + { + instruction->u.begin.id = -1; + } + else if (instruction->kind == END && instruction->u.end.object) + { + g_hash_table_insert (instructions_by_object, + instruction->u.end.object, instruction); + } + } + + /* Assign an id to all pointed-to instructions */ + id = 1; + for (i = 0; i < n_instructions; ++i) + { + Instruction *instruction = &(instructions[i]); + + if (instruction->type == TYPE_POINTER) + { + if (instruction->u.pointer.target_object) + { + Instruction *target; + + target = + g_hash_table_lookup (instructions_by_object, + instruction->u.pointer.target_object); + + if (!target) + { + g_warning ("pointer has unknown target\n"); + return; + } + + g_assert (target->kind == END); + + if (target->u.end.begin_instruction->u.begin.id == -1) + target->u.end.begin_instruction->u.begin.id = id++; + + instruction->u.pointer.target_id = + target->u.end.begin_instruction->u.begin.id; + } + else + { + instruction->u.pointer.target_id = 0; + } + } + } + +} + +static void add_indent (GString *output, int indent) { int i; @@ -1140,10 +1272,14 @@ add_string (GString *output, const char *str) } static void -add_begin_tag (GString *output, int indent, const char *name) +add_begin_tag (GString *output, int indent, const char *name, int id) { add_indent (output, indent); - g_string_append_printf (output, "<%s>", name); + + if (id != -1) + g_string_append_printf (output, "<%s id=\"%d\">", name, id); + else + g_string_append_printf (output, "<%s>", name); } static void @@ -1168,11 +1304,14 @@ sfile_output_save (SFileOutput *sfile, Instruction *instructions; GString *output; int indent; + gboolean retval; g_return_val_if_fail (sfile != NULL, FALSE); instructions = (Instruction *)sfile->instructions->data; + post_process_write_instructions (sfile); + indent = 0; output = g_string_new (""); for (i = 0; i < sfile->instructions->len; ++i) @@ -1182,7 +1321,8 @@ sfile_output_save (SFileOutput *sfile, switch (instruction->kind) { case BEGIN: - add_begin_tag (output, indent, instruction->name); + add_begin_tag (output, indent, instruction->name, + instruction->u.begin.id); add_nl (output); indent += 4; break; @@ -1194,7 +1334,7 @@ sfile_output_save (SFileOutput *sfile, break; case VALUE: - add_begin_tag (output, indent, instruction->name); + add_begin_tag (output, indent, instruction->name, -1); switch (instruction->type) { case TYPE_INTEGER: @@ -1215,12 +1355,20 @@ sfile_output_save (SFileOutput *sfile, } } - /* FIXME: write to disk */ + /* FIXME: don't dump this to stdout */ g_print (output->str); - - g_string_free (output, TRUE); - return TRUE; /* FIXME */ +#if 0 + /* FIXME, cut-and-paste the g_file_write() implementation + * as long as it isn't in glib + */ + retval = g_file_write (filename, output->str, - 1, err); +#endif + retval = TRUE; + + g_string_free (output, TRUE); + + return retval; } diff --git a/sfile.h b/sfile.h index 88a3ca0..6a6e936 100644 --- a/sfile.h +++ b/sfile.h @@ -3,6 +3,24 @@ typedef struct SFileInput SFileInput; typedef struct SFileOutput SFileOutput; typedef guint SType; + +/* A possibly better API/naming scheme + * + * Serializer *serializer_new (SerializerFormat *format); + * + * SerializerReadContext *serializer_begin_read (serializer *serialize, + * const char *filename, + * GError *err); + * serializer_get_blah (SerializerReadContext *); + * void serialzier_end_read (...); + * + * SerializerWritecontext *...; + * serializer_begin_write (context); + * serializer_write_int (); + * serializer_end_write (..., GError **err); + * + */ + /* - Describing Types - */ SFormat *sformat_new (gpointer f); gpointer sformat_new_record (const char *name, diff --git a/sysprof.c b/sysprof.c index b45a4e0..d387cad 100644 --- a/sysprof.c +++ b/sysprof.c @@ -465,13 +465,14 @@ on_reset_clicked (gpointer widget, gpointer data) static void on_save_as_clicked (gpointer widget, gpointer data) { + GError *err = NULL; Application *app = data; ensure_profile (app); /* FIXME */ - if (!profile_save (app->profile, "name.profile", NULL)) - sorry (NULL, "Couldn't save\n"); + if (!profile_save (app->profile, "name.profile", &err)) + sorry (NULL, "Couldn't save: %s\n", err->message); #if 0 sorry (NULL, "Saving profiles is not yet implemented."); -- 2.7.4