mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
updates Various formatting fixes.
Sat Apr 22 15:08:01 2006 Soeren Sandmann <sandmann@redhat.com> * TODO: updates * profile.c, sfile.c, sformat.c: Various formatting fixes.
This commit is contained in:
committed by
Søren Sandmann Pedersen
parent
6c36cd060c
commit
e97dcc792a
@ -1,3 +1,8 @@
|
||||
Sat Apr 22 15:08:01 2006 Soeren Sandmann <sandmann@redhat.com>
|
||||
|
||||
* TODO: updates
|
||||
* profile.c, sfile.c, sformat.c: Various formatting fixes.
|
||||
|
||||
Wed Apr 5 11:26:30 2006 Søren Sandmann <sandmann@redhat.com>
|
||||
|
||||
* TODO: updates
|
||||
|
||||
15
TODO
15
TODO
@ -30,8 +30,6 @@ Before 1.2:
|
||||
* commandline version should check that the output file is writable
|
||||
before starting the profiling.
|
||||
|
||||
* screenshot window must be cleared when you press start.
|
||||
|
||||
* Maybe report idle time?
|
||||
|
||||
* Fix (deleted) problem. But more generally, whenever we can't display a
|
||||
@ -138,7 +136,8 @@ Before 1.2:
|
||||
int id; -> for begins that are pointed to
|
||||
}
|
||||
perhaps even with iterators. Should be compact and suitable for both
|
||||
input and output..
|
||||
input and output. As a first cut, perhaps just split out the
|
||||
Instruction code.
|
||||
|
||||
- make the api saner; add format/content structs
|
||||
|
||||
@ -312,11 +311,11 @@ Later:
|
||||
Profiling itself it appeared that most of the time was spent
|
||||
in the GMarkup parser
|
||||
- a newer version of sysprof with significantly more compact
|
||||
Instructions took about 5 seconds, but the profile looked
|
||||
about the same.
|
||||
Instructions structure took about 5 seconds, but the profile
|
||||
looked about the same.
|
||||
The difference between the two versions has to be in page faults/
|
||||
memory speed, but the profiles looked identically.
|
||||
Try and reproduce this result in a more controlled experiment.
|
||||
memory speed, but the profiles looked similar.
|
||||
Try and reproduce this in a more controlled experiment.
|
||||
|
||||
- See if it is possible to group the X server activity under the process that
|
||||
generated it.
|
||||
@ -495,6 +494,8 @@ Later:
|
||||
|
||||
DONE:
|
||||
|
||||
- screenshot window must be cleared when you press start.
|
||||
|
||||
- Formats should become first-class, stand-alone objects that offers
|
||||
help with parsing and nothing else.
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ typedef struct Node Node;
|
||||
|
||||
struct Profile
|
||||
{
|
||||
StackStash * stash;
|
||||
StackStash *stash;
|
||||
};
|
||||
|
||||
static SFormat *
|
||||
@ -470,7 +470,7 @@ profile_free (Profile *profile)
|
||||
}
|
||||
|
||||
void
|
||||
profile_descendant_free (ProfileDescendant *descendant)
|
||||
profile_descendant_free (ProfileDescendant *descendant)
|
||||
{
|
||||
if (!descendant)
|
||||
return;
|
||||
|
||||
207
sfile.c
207
sfile.c
@ -29,60 +29,6 @@
|
||||
#include "sfile.h"
|
||||
#include "sformat.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* reading */
|
||||
typedef struct BuildContext BuildContext;
|
||||
typedef struct Instruction Instruction;
|
||||
typedef enum
|
||||
@ -137,6 +83,63 @@ struct BuildContext
|
||||
GArray *instructions;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* reading */
|
||||
static gboolean
|
||||
is_all_blank (const char *text)
|
||||
{
|
||||
@ -212,8 +215,8 @@ sfile_get_pointer (SFileInput *file,
|
||||
|
||||
instruction = file->current_instruction++;
|
||||
g_return_if_fail (stype_is_pointer (instruction->type));
|
||||
|
||||
instruction->u.pointer.location = location;
|
||||
|
||||
instruction->u.pointer.location = location;
|
||||
|
||||
*location = (gpointer) 0xFedeAbe;
|
||||
|
||||
@ -227,9 +230,9 @@ sfile_get_pointer (SFileInput *file,
|
||||
}
|
||||
|
||||
void
|
||||
sfile_get_integer (SFileInput *file,
|
||||
const char *name,
|
||||
gint32 *integer)
|
||||
sfile_get_integer (SFileInput *file,
|
||||
const char *name,
|
||||
gint32 *integer)
|
||||
{
|
||||
Instruction *instruction;
|
||||
|
||||
@ -241,9 +244,9 @@ sfile_get_integer (SFileInput *file,
|
||||
}
|
||||
|
||||
void
|
||||
sfile_get_string (SFileInput *file,
|
||||
const char *name,
|
||||
char **string)
|
||||
sfile_get_string (SFileInput *file,
|
||||
const char *name,
|
||||
char **string)
|
||||
{
|
||||
Instruction *instruction;
|
||||
|
||||
@ -259,15 +262,11 @@ hook_up_pointers (SFileInput *file)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if 0
|
||||
g_print ("emfle\n");
|
||||
#endif
|
||||
for (i = 0; i < file->n_instructions; ++i)
|
||||
{
|
||||
Instruction *instruction = &(file->instructions[i]);
|
||||
|
||||
if (instruction->kind == VALUE &&
|
||||
stype_is_pointer (instruction->type))
|
||||
if (stype_is_pointer (instruction->type))
|
||||
{
|
||||
gpointer target_object;
|
||||
Instruction *target_instruction;
|
||||
@ -279,10 +278,6 @@ hook_up_pointers (SFileInput *file)
|
||||
else
|
||||
target_object = NULL;
|
||||
|
||||
#if 0
|
||||
g_print ("target object: %p\n", target_object);
|
||||
#endif
|
||||
|
||||
*(instruction->u.pointer.location) = target_object;
|
||||
}
|
||||
}
|
||||
@ -489,7 +484,7 @@ free_instructions (Instruction *instructions, int n_instructions)
|
||||
{
|
||||
Instruction *instruction = &(instructions[i]);
|
||||
|
||||
if (instruction->kind == VALUE && stype_is_string (instruction->type))
|
||||
if (stype_is_string (instruction->type))
|
||||
g_free (instruction->u.string.value);
|
||||
}
|
||||
|
||||
@ -536,7 +531,9 @@ process_instruction_pairs (Instruction *first)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
post_process_read_instructions (Instruction *instructions, int n_instructions, GError **err)
|
||||
post_process_read_instructions (Instruction *instructions,
|
||||
int n_instructions,
|
||||
GError **err)
|
||||
{
|
||||
gboolean retval = TRUE;
|
||||
GHashTable *instructions_by_id;
|
||||
@ -565,8 +562,7 @@ post_process_read_instructions (Instruction *instructions, int n_instructions, G
|
||||
{
|
||||
Instruction *instruction = &(instructions[i]);
|
||||
|
||||
if (instruction->kind == VALUE &&
|
||||
stype_is_pointer (instruction->type))
|
||||
if (stype_is_pointer (instruction->type))
|
||||
{
|
||||
int target_id = instruction->u.pointer.target_id;
|
||||
|
||||
@ -610,7 +606,10 @@ post_process_read_instructions (Instruction *instructions, int n_instructions, G
|
||||
}
|
||||
|
||||
static Instruction *
|
||||
build_instructions (const char *contents, SFormat *format, int *n_instructions, GError **err)
|
||||
build_instructions (const char *contents,
|
||||
SFormat *format,
|
||||
int *n_instructions,
|
||||
GError **err)
|
||||
{
|
||||
BuildContext build;
|
||||
GMarkupParseContext *parse_context;
|
||||
@ -791,9 +790,9 @@ sfile_check_value (SFileOutput *file,
|
||||
}
|
||||
|
||||
void
|
||||
sfile_add_string (SFileOutput *file,
|
||||
const char *name,
|
||||
const char *string)
|
||||
sfile_add_string (SFileOutput *file,
|
||||
const char *name,
|
||||
const char *string)
|
||||
{
|
||||
Instruction instruction;
|
||||
|
||||
@ -812,9 +811,9 @@ sfile_add_string (SFileOutput *file,
|
||||
}
|
||||
|
||||
void
|
||||
sfile_add_integer (SFileOutput *file,
|
||||
const char *name,
|
||||
int integer)
|
||||
sfile_add_integer (SFileOutput *file,
|
||||
const char *name,
|
||||
int integer)
|
||||
{
|
||||
Instruction instruction;
|
||||
|
||||
@ -831,9 +830,9 @@ sfile_add_integer (SFileOutput *file,
|
||||
}
|
||||
|
||||
void
|
||||
sfile_add_pointer (SFileOutput *file,
|
||||
const char *name,
|
||||
gpointer pointer)
|
||||
sfile_add_pointer (SFileOutput *file,
|
||||
const char *name,
|
||||
gpointer pointer)
|
||||
{
|
||||
Instruction instruction;
|
||||
|
||||
@ -898,7 +897,7 @@ post_process_write_instructions (SFileOutput *sfile)
|
||||
if (!target)
|
||||
{
|
||||
g_warning ("pointer has unknown target\n");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_assert (target->kind == END);
|
||||
@ -915,11 +914,14 @@ post_process_write_instructions (SFileOutput *sfile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
out:
|
||||
g_hash_table_destroy (instructions_by_object);
|
||||
}
|
||||
|
||||
static void
|
||||
add_indent (GString *output, int indent)
|
||||
add_indent (GString *output,
|
||||
int indent)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -928,13 +930,15 @@ add_indent (GString *output, int indent)
|
||||
}
|
||||
|
||||
static void
|
||||
add_integer (GString *output, int value)
|
||||
add_integer (GString *output,
|
||||
int value)
|
||||
{
|
||||
g_string_append_printf (output, "%d", value);
|
||||
}
|
||||
|
||||
static void
|
||||
add_string (GString *output, const char *str)
|
||||
add_string (GString *output,
|
||||
const char *str)
|
||||
{
|
||||
char *escaped = g_markup_escape_text (str, -1);
|
||||
g_string_append_c (output, '\"');
|
||||
@ -944,7 +948,10 @@ add_string (GString *output, const char *str)
|
||||
}
|
||||
|
||||
static void
|
||||
add_begin_tag (GString *output, int indent, const char *name, int id)
|
||||
add_begin_tag (GString *output,
|
||||
int indent,
|
||||
const char *name,
|
||||
int id)
|
||||
{
|
||||
add_indent (output, indent);
|
||||
|
||||
@ -955,7 +962,9 @@ add_begin_tag (GString *output, int indent, const char *name, int id)
|
||||
}
|
||||
|
||||
static void
|
||||
add_end_tag (GString *output, int indent, const char *name)
|
||||
add_end_tag (GString *output,
|
||||
int indent,
|
||||
const char *name)
|
||||
{
|
||||
add_indent (output, indent);
|
||||
g_string_append_printf (output, "</%s>", name);
|
||||
@ -968,10 +977,10 @@ add_nl (GString *output)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
file_replace (const gchar *filename,
|
||||
const gchar *contents,
|
||||
gssize length,
|
||||
GError **error);
|
||||
file_replace (const gchar *filename,
|
||||
const gchar *contents,
|
||||
gssize length,
|
||||
GError **error);
|
||||
|
||||
#if 0
|
||||
static void
|
||||
@ -1101,8 +1110,10 @@ sfile_output_save (SFileOutput *sfile,
|
||||
{
|
||||
add_string (output, instruction->u.string.value);
|
||||
}
|
||||
|
||||
add_end_tag (output, 0, get_name (instruction));
|
||||
add_nl (output);
|
||||
|
||||
add_nl (output);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1127,7 +1138,7 @@ sfile_output_save (SFileOutput *sfile,
|
||||
|
||||
|
||||
void
|
||||
sfile_input_free (SFileInput *file)
|
||||
sfile_input_free (SFileInput *file)
|
||||
{
|
||||
free_instructions (file->instructions, file->n_instructions);
|
||||
|
||||
|
||||
577
sformat.c
577
sformat.c
@ -62,6 +62,296 @@ struct SType
|
||||
|
||||
static void type_free (SType *type);
|
||||
|
||||
/*
|
||||
* Transition
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
BEGIN,
|
||||
VALUE,
|
||||
END
|
||||
} TransitionKind;
|
||||
|
||||
struct Transition
|
||||
{
|
||||
SType * type;
|
||||
TransitionKind kind;
|
||||
State * to;
|
||||
};
|
||||
|
||||
static Transition *transition_new (SFormat *format,
|
||||
TransitionKind kind,
|
||||
SType *type,
|
||||
State *from,
|
||||
State *to);
|
||||
static void transition_free (Transition *transition);
|
||||
static void transition_set_to_state (Transition *transition,
|
||||
State *to_state);
|
||||
|
||||
/*
|
||||
* State
|
||||
*/
|
||||
|
||||
struct State
|
||||
{
|
||||
GQueue *transitions;
|
||||
};
|
||||
|
||||
static State *state_new (SFormat *format);
|
||||
static void state_add_transition (State *state,
|
||||
Transition *transition);
|
||||
static void state_free (State *state);
|
||||
|
||||
/*
|
||||
* Format
|
||||
*/
|
||||
SFormat *
|
||||
sformat_new (void)
|
||||
{
|
||||
/* FIXME: should probably be refcounted, and an SContext
|
||||
* should have a ref on the format
|
||||
*/
|
||||
SFormat *format = g_new0 (SFormat, 1);
|
||||
|
||||
format->begin = NULL;
|
||||
format->end = NULL;
|
||||
|
||||
format->types = g_queue_new ();
|
||||
format->states = g_queue_new ();
|
||||
format->transitions = g_queue_new ();
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
void
|
||||
sformat_free (SFormat *format)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = format->types->head; list; list = list->next)
|
||||
{
|
||||
SType *type = list->data;
|
||||
|
||||
type_free (type);
|
||||
}
|
||||
g_queue_free (format->types);
|
||||
|
||||
for (list = format->states->head; list; list = list->next)
|
||||
{
|
||||
State *state = list->data;
|
||||
|
||||
state_free (state);
|
||||
}
|
||||
g_queue_free (format->states);
|
||||
|
||||
for (list = format->transitions->head; list; list = list->next)
|
||||
{
|
||||
Transition *transition = list->data;
|
||||
|
||||
transition_free (transition);
|
||||
}
|
||||
g_queue_free (format->transitions);
|
||||
|
||||
g_free (format);
|
||||
}
|
||||
|
||||
void
|
||||
sformat_set_type (SFormat *format,
|
||||
SType *type)
|
||||
{
|
||||
format->begin = state_new (format);
|
||||
format->end = state_new (format);
|
||||
|
||||
state_add_transition (format->begin, type->enter);
|
||||
transition_set_to_state (type->exit, format->end);
|
||||
}
|
||||
|
||||
/*
|
||||
* Type
|
||||
*/
|
||||
static SType *
|
||||
type_new (SFormat *format,
|
||||
TypeKind kind,
|
||||
const char *name)
|
||||
{
|
||||
SType *type = g_new0 (SType, 1);
|
||||
|
||||
type->kind = kind;
|
||||
type->name = name? g_strdup (name) : NULL;
|
||||
type->enter = NULL;
|
||||
type->exit = NULL;
|
||||
type->target = NULL;
|
||||
|
||||
g_queue_push_tail (format->types, type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static SType *
|
||||
type_new_from_forward (SFormat *format,
|
||||
TypeKind kind,
|
||||
const char *name,
|
||||
SForward *forward)
|
||||
{
|
||||
SType *type;
|
||||
|
||||
if (forward)
|
||||
{
|
||||
type = (SType *)forward;
|
||||
type->kind = kind;
|
||||
type->name = g_strdup (name);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = type_new (format, kind, name);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
static SType *
|
||||
type_new_value (SFormat *format, TypeKind kind, const char *name)
|
||||
{
|
||||
SType *type = type_new (format, kind, name);
|
||||
State *before, *after;
|
||||
Transition *value;
|
||||
|
||||
before = state_new (format);
|
||||
after = state_new (format);
|
||||
|
||||
type->enter = transition_new (format, BEGIN, type, NULL, before);
|
||||
type->exit = transition_new (format, END, type, after, NULL);
|
||||
value = transition_new (format, VALUE, type, before, after);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
type_free (SType *type)
|
||||
{
|
||||
g_free (type->name);
|
||||
g_free (type);
|
||||
}
|
||||
|
||||
SForward *
|
||||
sformat_declare_forward (SFormat *format)
|
||||
{
|
||||
SType *type = type_new (format, TYPE_FORWARD, NULL);
|
||||
|
||||
return (SForward *)type;
|
||||
}
|
||||
|
||||
|
||||
static GQueue *
|
||||
expand_varargs (SType *content1,
|
||||
va_list args)
|
||||
{
|
||||
GQueue *types = g_queue_new ();
|
||||
SType *type;
|
||||
|
||||
g_queue_push_tail (types, content1);
|
||||
|
||||
type = va_arg (args, SType *);
|
||||
while (type)
|
||||
{
|
||||
g_queue_push_tail (types, type);
|
||||
type = va_arg (args, SType *);
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
SType *
|
||||
sformat_make_record (SFormat *format,
|
||||
const char *name,
|
||||
SForward *forward,
|
||||
SType *content,
|
||||
...)
|
||||
{
|
||||
SType *type;
|
||||
va_list args;
|
||||
GQueue *types;
|
||||
GList *list;
|
||||
State *begin, *state;
|
||||
|
||||
/* Build queue of child types */
|
||||
va_start (args, content);
|
||||
types = expand_varargs (content, args);
|
||||
va_end (args);
|
||||
|
||||
/* chain types together */
|
||||
state = begin = state_new (format);
|
||||
|
||||
for (list = types->head; list != NULL; list = list->next)
|
||||
{
|
||||
SType *child_type = list->data;
|
||||
|
||||
state_add_transition (state, child_type->enter);
|
||||
|
||||
state = state_new (format);
|
||||
|
||||
transition_set_to_state (child_type->exit, state);
|
||||
}
|
||||
|
||||
g_queue_free (types);
|
||||
|
||||
/* create and return the new type */
|
||||
type = type_new_from_forward (format, TYPE_RECORD, name, forward);
|
||||
type->enter = transition_new (format, BEGIN, type, NULL, begin);
|
||||
type->exit = transition_new (format, END, type, state, NULL);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
SType *
|
||||
sformat_make_list (SFormat *format,
|
||||
const char *name,
|
||||
SForward *forward,
|
||||
SType *child_type)
|
||||
{
|
||||
SType *type;
|
||||
State *list_state;
|
||||
|
||||
type = type_new_from_forward (format, TYPE_LIST, name, forward);
|
||||
|
||||
list_state = state_new (format);
|
||||
|
||||
type->enter = transition_new (format, BEGIN, type, NULL, list_state);
|
||||
type->exit = transition_new (format, END, type, list_state, NULL);
|
||||
|
||||
state_add_transition (list_state, child_type->enter);
|
||||
transition_set_to_state (child_type->exit, list_state);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
SType *
|
||||
sformat_make_pointer (SFormat *format,
|
||||
const char *name,
|
||||
SForward *forward)
|
||||
{
|
||||
SType *type = type_new_value (format, TYPE_POINTER, name);
|
||||
type->target = (SType *)forward;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
SType *
|
||||
sformat_make_integer (SFormat *format,
|
||||
const char *name)
|
||||
{
|
||||
return type_new_value (format, TYPE_INTEGER, name);
|
||||
}
|
||||
|
||||
SType *
|
||||
sformat_make_string (SFormat *format,
|
||||
const char *name)
|
||||
{
|
||||
return type_new_value (format, TYPE_STRING, name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
gboolean
|
||||
stype_is_record (SType *type)
|
||||
@ -107,291 +397,6 @@ stype_get_name (SType *type)
|
||||
return type->name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transition
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
BEGIN,
|
||||
VALUE,
|
||||
END
|
||||
} TransitionKind;
|
||||
|
||||
struct Transition
|
||||
{
|
||||
SType * type;
|
||||
TransitionKind kind;
|
||||
State * to;
|
||||
};
|
||||
|
||||
static Transition *transition_new (SFormat *format,
|
||||
TransitionKind kind,
|
||||
SType *type,
|
||||
State *from,
|
||||
State *to);
|
||||
static void transition_free (Transition *transition);
|
||||
static void transition_set_to_state (Transition *transition,
|
||||
State *to_state);
|
||||
|
||||
/*
|
||||
* State
|
||||
*/
|
||||
|
||||
struct State
|
||||
{
|
||||
GQueue *transitions;
|
||||
};
|
||||
|
||||
static State *state_new (SFormat *format);
|
||||
static void state_add_transition (State *state,
|
||||
Transition *transition);
|
||||
static void state_free (State *state);
|
||||
|
||||
/*
|
||||
* Format
|
||||
*/
|
||||
SFormat *
|
||||
sformat_new (void)
|
||||
{
|
||||
/* FIXME: should probably be refcounted, and an SContext
|
||||
* should have a ref on the format
|
||||
*/
|
||||
SFormat *format = g_new0 (SFormat, 1);
|
||||
|
||||
format->begin = NULL;
|
||||
format->end = NULL;
|
||||
|
||||
format->types = g_queue_new ();
|
||||
format->states = g_queue_new ();
|
||||
format->transitions = g_queue_new ();
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
void
|
||||
sformat_free (SFormat *format)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = format->types->head; list; list = list->next)
|
||||
{
|
||||
SType *type = list->data;
|
||||
|
||||
type_free (type);
|
||||
}
|
||||
|
||||
for (list = format->states->head; list; list = list->next)
|
||||
{
|
||||
State *state = list->data;
|
||||
|
||||
state_free (state);
|
||||
}
|
||||
|
||||
for (list = format->transitions->head; list; list = list->next)
|
||||
{
|
||||
Transition *transition = list->data;
|
||||
|
||||
transition_free (transition);
|
||||
}
|
||||
|
||||
g_free (format);
|
||||
}
|
||||
|
||||
void
|
||||
sformat_set_type (SFormat *format,
|
||||
SType *type)
|
||||
{
|
||||
format->begin = state_new (format);
|
||||
format->end = state_new (format);
|
||||
|
||||
state_add_transition (format->begin, type->enter);
|
||||
transition_set_to_state (type->exit, format->end);
|
||||
|
||||
/* Fix up pointer types */
|
||||
}
|
||||
|
||||
/*
|
||||
* Type
|
||||
*/
|
||||
static SType *
|
||||
type_new (SFormat *format,
|
||||
TypeKind kind,
|
||||
const char *name)
|
||||
{
|
||||
SType *type = g_new0 (SType, 1);
|
||||
|
||||
type->kind = kind;
|
||||
type->name = name? g_strdup (name) : NULL;
|
||||
type->enter = NULL;
|
||||
type->exit = NULL;
|
||||
type->target = NULL;
|
||||
|
||||
g_queue_push_tail (format->types, type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
type_free (SType *type)
|
||||
{
|
||||
g_free (type->name);
|
||||
g_free (type);
|
||||
}
|
||||
|
||||
static GQueue *
|
||||
type_queue (SType *content1,
|
||||
va_list args)
|
||||
{
|
||||
GQueue *types = g_queue_new ();
|
||||
SType *type;
|
||||
|
||||
g_queue_push_tail (types, content1);
|
||||
|
||||
type = va_arg (args, SType *);
|
||||
while (type)
|
||||
{
|
||||
g_queue_push_tail (types, type);
|
||||
type = va_arg (args, SType *);
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
SForward *
|
||||
sformat_declare_forward (SFormat *format)
|
||||
{
|
||||
SType *type = type_new (format, TYPE_FORWARD, NULL);
|
||||
|
||||
return (SForward *)type;
|
||||
}
|
||||
|
||||
|
||||
SType *
|
||||
sformat_make_record (SFormat *format,
|
||||
const char *name,
|
||||
SForward *forward,
|
||||
SType *content,
|
||||
...)
|
||||
{
|
||||
SType *type;
|
||||
va_list args;
|
||||
GQueue *types;
|
||||
GList *list;
|
||||
State *begin, *state;
|
||||
|
||||
/* Build queue of child types */
|
||||
va_start (args, content);
|
||||
types = type_queue (content, args);
|
||||
va_end (args);
|
||||
|
||||
/* chain types together */
|
||||
state = begin = state_new (format);
|
||||
|
||||
for (list = types->head; list != NULL; list = list->next)
|
||||
{
|
||||
SType *child_type = list->data;
|
||||
|
||||
state_add_transition (state, child_type->enter);
|
||||
|
||||
state = state_new (format);
|
||||
|
||||
transition_set_to_state (child_type->exit, state);
|
||||
}
|
||||
|
||||
g_queue_free (types);
|
||||
|
||||
/* Return resulting fragment */
|
||||
if (forward)
|
||||
{
|
||||
type = (SType *)forward;
|
||||
type->kind = TYPE_RECORD;
|
||||
type->name = g_strdup (name);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = type_new (format, TYPE_RECORD, name);
|
||||
}
|
||||
|
||||
type->enter = transition_new (format, BEGIN, type, NULL, begin);
|
||||
type->exit = transition_new (format, END, type, state, NULL);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
SType *
|
||||
sformat_make_list (SFormat *format,
|
||||
const char *name,
|
||||
SForward *forward,
|
||||
SType *child_type)
|
||||
{
|
||||
SType *type;
|
||||
State *list_state;
|
||||
|
||||
if (forward)
|
||||
{
|
||||
type = (SType *)forward;
|
||||
type->kind = TYPE_LIST;
|
||||
type->name = g_strdup (name);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = type_new (format, TYPE_LIST, name);
|
||||
}
|
||||
|
||||
list_state = state_new (format);
|
||||
|
||||
type->enter = transition_new (format, BEGIN, type, NULL, list_state);
|
||||
type->exit = transition_new (format, END, type, list_state, NULL);
|
||||
|
||||
state_add_transition (list_state, child_type->enter);
|
||||
transition_set_to_state (child_type->exit, list_state);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static SType *
|
||||
type_new_value (SFormat *format, TypeKind kind, const char *name)
|
||||
{
|
||||
SType *type = type_new (format, kind, name);
|
||||
State *before, *after;
|
||||
Transition *value;
|
||||
|
||||
before = state_new (format);
|
||||
after = state_new (format);
|
||||
|
||||
type->enter = transition_new (format, BEGIN, type, NULL, before);
|
||||
type->exit = transition_new (format, END, type, after, NULL);
|
||||
value = transition_new (format, VALUE, type, before, after);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
SType *
|
||||
sformat_make_pointer (SFormat *format,
|
||||
const char *name,
|
||||
SForward *forward)
|
||||
{
|
||||
SType *type = type_new_value (format, TYPE_POINTER, name);
|
||||
type->target = (SType *)forward;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
SType *
|
||||
sformat_make_integer (SFormat *format,
|
||||
const char *name)
|
||||
{
|
||||
return type_new_value (format, TYPE_INTEGER, name);
|
||||
}
|
||||
|
||||
SType *
|
||||
sformat_make_string (SFormat *format,
|
||||
const char *name)
|
||||
{
|
||||
return type_new_value (format, TYPE_STRING, name);
|
||||
}
|
||||
|
||||
|
||||
/* Consider adding unions at some point
|
||||
*
|
||||
* To be useful they should probably be anonymous, so that
|
||||
@ -414,6 +419,8 @@ sformat_make_string (SFormat *format,
|
||||
* elements. That will make things a lot easier, and unions are
|
||||
* still pretty useful if you put big things like lists in them.
|
||||
*
|
||||
* Or maybe just give them a name ...
|
||||
*
|
||||
* We may also consider adding anonymous records. These will
|
||||
* not be able to have pointers associated with them though
|
||||
* (because there wouldn't be a natural place
|
||||
|
||||
Reference in New Issue
Block a user