mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-11 15:40:53 +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>
|
Wed Apr 5 11:26:30 2006 Søren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
* TODO: updates
|
* TODO: updates
|
||||||
|
|||||||
15
TODO
15
TODO
@ -30,8 +30,6 @@ Before 1.2:
|
|||||||
* commandline version should check that the output file is writable
|
* commandline version should check that the output file is writable
|
||||||
before starting the profiling.
|
before starting the profiling.
|
||||||
|
|
||||||
* screenshot window must be cleared when you press start.
|
|
||||||
|
|
||||||
* Maybe report idle time?
|
* Maybe report idle time?
|
||||||
|
|
||||||
* Fix (deleted) problem. But more generally, whenever we can't display a
|
* 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
|
int id; -> for begins that are pointed to
|
||||||
}
|
}
|
||||||
perhaps even with iterators. Should be compact and suitable for both
|
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
|
- make the api saner; add format/content structs
|
||||||
|
|
||||||
@ -312,11 +311,11 @@ Later:
|
|||||||
Profiling itself it appeared that most of the time was spent
|
Profiling itself it appeared that most of the time was spent
|
||||||
in the GMarkup parser
|
in the GMarkup parser
|
||||||
- a newer version of sysprof with significantly more compact
|
- a newer version of sysprof with significantly more compact
|
||||||
Instructions took about 5 seconds, but the profile looked
|
Instructions structure took about 5 seconds, but the profile
|
||||||
about the same.
|
looked about the same.
|
||||||
The difference between the two versions has to be in page faults/
|
The difference between the two versions has to be in page faults/
|
||||||
memory speed, but the profiles looked identically.
|
memory speed, but the profiles looked similar.
|
||||||
Try and reproduce this result in a more controlled experiment.
|
Try and reproduce this in a more controlled experiment.
|
||||||
|
|
||||||
- See if it is possible to group the X server activity under the process that
|
- See if it is possible to group the X server activity under the process that
|
||||||
generated it.
|
generated it.
|
||||||
@ -495,6 +494,8 @@ Later:
|
|||||||
|
|
||||||
DONE:
|
DONE:
|
||||||
|
|
||||||
|
- screenshot window must be cleared when you press start.
|
||||||
|
|
||||||
- Formats should become first-class, stand-alone objects that offers
|
- Formats should become first-class, stand-alone objects that offers
|
||||||
help with parsing and nothing else.
|
help with parsing and nothing else.
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ typedef struct Node Node;
|
|||||||
|
|
||||||
struct Profile
|
struct Profile
|
||||||
{
|
{
|
||||||
StackStash * stash;
|
StackStash *stash;
|
||||||
};
|
};
|
||||||
|
|
||||||
static SFormat *
|
static SFormat *
|
||||||
@ -470,7 +470,7 @@ profile_free (Profile *profile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
profile_descendant_free (ProfileDescendant *descendant)
|
profile_descendant_free (ProfileDescendant *descendant)
|
||||||
{
|
{
|
||||||
if (!descendant)
|
if (!descendant)
|
||||||
return;
|
return;
|
||||||
|
|||||||
207
sfile.c
207
sfile.c
@ -29,60 +29,6 @@
|
|||||||
#include "sfile.h"
|
#include "sfile.h"
|
||||||
#include "sformat.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 BuildContext BuildContext;
|
||||||
typedef struct Instruction Instruction;
|
typedef struct Instruction Instruction;
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -137,6 +83,63 @@ struct BuildContext
|
|||||||
GArray *instructions;
|
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
|
static gboolean
|
||||||
is_all_blank (const char *text)
|
is_all_blank (const char *text)
|
||||||
{
|
{
|
||||||
@ -212,8 +215,8 @@ sfile_get_pointer (SFileInput *file,
|
|||||||
|
|
||||||
instruction = file->current_instruction++;
|
instruction = file->current_instruction++;
|
||||||
g_return_if_fail (stype_is_pointer (instruction->type));
|
g_return_if_fail (stype_is_pointer (instruction->type));
|
||||||
|
|
||||||
instruction->u.pointer.location = location;
|
instruction->u.pointer.location = location;
|
||||||
|
|
||||||
*location = (gpointer) 0xFedeAbe;
|
*location = (gpointer) 0xFedeAbe;
|
||||||
|
|
||||||
@ -227,9 +230,9 @@ sfile_get_pointer (SFileInput *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sfile_get_integer (SFileInput *file,
|
sfile_get_integer (SFileInput *file,
|
||||||
const char *name,
|
const char *name,
|
||||||
gint32 *integer)
|
gint32 *integer)
|
||||||
{
|
{
|
||||||
Instruction *instruction;
|
Instruction *instruction;
|
||||||
|
|
||||||
@ -241,9 +244,9 @@ sfile_get_integer (SFileInput *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sfile_get_string (SFileInput *file,
|
sfile_get_string (SFileInput *file,
|
||||||
const char *name,
|
const char *name,
|
||||||
char **string)
|
char **string)
|
||||||
{
|
{
|
||||||
Instruction *instruction;
|
Instruction *instruction;
|
||||||
|
|
||||||
@ -259,15 +262,11 @@ hook_up_pointers (SFileInput *file)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#if 0
|
|
||||||
g_print ("emfle\n");
|
|
||||||
#endif
|
|
||||||
for (i = 0; i < file->n_instructions; ++i)
|
for (i = 0; i < file->n_instructions; ++i)
|
||||||
{
|
{
|
||||||
Instruction *instruction = &(file->instructions[i]);
|
Instruction *instruction = &(file->instructions[i]);
|
||||||
|
|
||||||
if (instruction->kind == VALUE &&
|
if (stype_is_pointer (instruction->type))
|
||||||
stype_is_pointer (instruction->type))
|
|
||||||
{
|
{
|
||||||
gpointer target_object;
|
gpointer target_object;
|
||||||
Instruction *target_instruction;
|
Instruction *target_instruction;
|
||||||
@ -279,10 +278,6 @@ hook_up_pointers (SFileInput *file)
|
|||||||
else
|
else
|
||||||
target_object = NULL;
|
target_object = NULL;
|
||||||
|
|
||||||
#if 0
|
|
||||||
g_print ("target object: %p\n", target_object);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*(instruction->u.pointer.location) = target_object;
|
*(instruction->u.pointer.location) = target_object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,7 +484,7 @@ free_instructions (Instruction *instructions, int n_instructions)
|
|||||||
{
|
{
|
||||||
Instruction *instruction = &(instructions[i]);
|
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);
|
g_free (instruction->u.string.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,7 +531,9 @@ process_instruction_pairs (Instruction *first)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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;
|
gboolean retval = TRUE;
|
||||||
GHashTable *instructions_by_id;
|
GHashTable *instructions_by_id;
|
||||||
@ -565,8 +562,7 @@ post_process_read_instructions (Instruction *instructions, int n_instructions, G
|
|||||||
{
|
{
|
||||||
Instruction *instruction = &(instructions[i]);
|
Instruction *instruction = &(instructions[i]);
|
||||||
|
|
||||||
if (instruction->kind == VALUE &&
|
if (stype_is_pointer (instruction->type))
|
||||||
stype_is_pointer (instruction->type))
|
|
||||||
{
|
{
|
||||||
int target_id = instruction->u.pointer.target_id;
|
int target_id = instruction->u.pointer.target_id;
|
||||||
|
|
||||||
@ -610,7 +606,10 @@ post_process_read_instructions (Instruction *instructions, int n_instructions, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Instruction *
|
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;
|
BuildContext build;
|
||||||
GMarkupParseContext *parse_context;
|
GMarkupParseContext *parse_context;
|
||||||
@ -791,9 +790,9 @@ sfile_check_value (SFileOutput *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sfile_add_string (SFileOutput *file,
|
sfile_add_string (SFileOutput *file,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *string)
|
const char *string)
|
||||||
{
|
{
|
||||||
Instruction instruction;
|
Instruction instruction;
|
||||||
|
|
||||||
@ -812,9 +811,9 @@ sfile_add_string (SFileOutput *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sfile_add_integer (SFileOutput *file,
|
sfile_add_integer (SFileOutput *file,
|
||||||
const char *name,
|
const char *name,
|
||||||
int integer)
|
int integer)
|
||||||
{
|
{
|
||||||
Instruction instruction;
|
Instruction instruction;
|
||||||
|
|
||||||
@ -831,9 +830,9 @@ sfile_add_integer (SFileOutput *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sfile_add_pointer (SFileOutput *file,
|
sfile_add_pointer (SFileOutput *file,
|
||||||
const char *name,
|
const char *name,
|
||||||
gpointer pointer)
|
gpointer pointer)
|
||||||
{
|
{
|
||||||
Instruction instruction;
|
Instruction instruction;
|
||||||
|
|
||||||
@ -898,7 +897,7 @@ post_process_write_instructions (SFileOutput *sfile)
|
|||||||
if (!target)
|
if (!target)
|
||||||
{
|
{
|
||||||
g_warning ("pointer has unknown target\n");
|
g_warning ("pointer has unknown target\n");
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert (target->kind == END);
|
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
|
static void
|
||||||
add_indent (GString *output, int indent)
|
add_indent (GString *output,
|
||||||
|
int indent)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -928,13 +930,15 @@ add_indent (GString *output, int indent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_integer (GString *output, int value)
|
add_integer (GString *output,
|
||||||
|
int value)
|
||||||
{
|
{
|
||||||
g_string_append_printf (output, "%d", value);
|
g_string_append_printf (output, "%d", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_string (GString *output, const char *str)
|
add_string (GString *output,
|
||||||
|
const char *str)
|
||||||
{
|
{
|
||||||
char *escaped = g_markup_escape_text (str, -1);
|
char *escaped = g_markup_escape_text (str, -1);
|
||||||
g_string_append_c (output, '\"');
|
g_string_append_c (output, '\"');
|
||||||
@ -944,7 +948,10 @@ add_string (GString *output, const char *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
add_indent (output, indent);
|
||||||
|
|
||||||
@ -955,7 +962,9 @@ add_begin_tag (GString *output, int indent, const char *name, int id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
add_indent (output, indent);
|
||||||
g_string_append_printf (output, "</%s>", name);
|
g_string_append_printf (output, "</%s>", name);
|
||||||
@ -968,10 +977,10 @@ add_nl (GString *output)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
file_replace (const gchar *filename,
|
file_replace (const gchar *filename,
|
||||||
const gchar *contents,
|
const gchar *contents,
|
||||||
gssize length,
|
gssize length,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void
|
static void
|
||||||
@ -1101,8 +1110,10 @@ sfile_output_save (SFileOutput *sfile,
|
|||||||
{
|
{
|
||||||
add_string (output, instruction->u.string.value);
|
add_string (output, instruction->u.string.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
add_end_tag (output, 0, get_name (instruction));
|
add_end_tag (output, 0, get_name (instruction));
|
||||||
add_nl (output);
|
|
||||||
|
add_nl (output);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1127,7 +1138,7 @@ sfile_output_save (SFileOutput *sfile,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sfile_input_free (SFileInput *file)
|
sfile_input_free (SFileInput *file)
|
||||||
{
|
{
|
||||||
free_instructions (file->instructions, file->n_instructions);
|
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);
|
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
|
gboolean
|
||||||
stype_is_record (SType *type)
|
stype_is_record (SType *type)
|
||||||
@ -107,291 +397,6 @@ stype_get_name (SType *type)
|
|||||||
return type->name;
|
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
|
/* 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
|
||||||
@ -414,6 +419,8 @@ sformat_make_string (SFormat *format,
|
|||||||
* elements. That will make things a lot easier, and unions are
|
* elements. That will make things a lot easier, and unions are
|
||||||
* still pretty useful if you put big things like lists in them.
|
* 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
|
* We may also consider adding anonymous records. These will
|
||||||
* not be able to have pointers associated with them though
|
* not be able to have pointers associated with them though
|
||||||
* (because there wouldn't be a natural place
|
* (because there wouldn't be a natural place
|
||||||
|
|||||||
Reference in New Issue
Block a user