summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/Makefile24
-rw-r--r--compiler/cycle16
-rw-r--r--compiler/ex-ast.c301
-rw-r--r--compiler/ex-compiler.h260
-rw-r--r--compiler/ex-gather-symbols.c189
-rw-r--r--compiler/ex-main.c56
-rw-r--r--compiler/ex-parser.h57
-rw-r--r--compiler/ex-pass.c212
-rw-r--r--compiler/ex-phase.c52
-rw-r--r--compiler/ex-pretty.c256
-rw-r--r--compiler/ex-spec.lex216
-rw-r--r--compiler/ex-spec.y405
-rw-r--r--compiler/ex-util.c121
-rw-r--r--compiler/ex-weed.c231
-rw-r--r--compiler/scanner.c2142
-rw-r--r--ex-display.h50
-rw-r--r--ex-queue.c23
-rw-r--r--ex-queue.h15
-rw-r--r--exlcore.c96
-rw-r--r--exlcore.h35
-rw-r--r--exlib-notes356
-rw-r--r--exlib.h23
-rw-r--r--exlprivate.h4
-rw-r--r--render.spec138
-rw-r--r--xcore.spec151
25 files changed, 5429 insertions, 0 deletions
diff --git a/compiler/Makefile b/compiler/Makefile
new file mode 100644
index 0000000..9645dda
--- /dev/null
+++ b/compiler/Makefile
@@ -0,0 +1,24 @@
+binary = ex-spec-compiler
+sources = ex-parser.c ex-scanner.c ex-ast.c ex-util.c ex-main.c \
+ ex-pretty.c ex-weed.c ex-gather-symbols.c \
+ ex-pass.c
+headers = ex-parser.h ex-compiler.h
+
+CFLAGS = -Wall -W -ansi -pedantic -g
+
+$(binary): $(sources) $(headers)
+ gcc $(CFLAGS) $(sources) -o$(binary) -lfl
+
+YFLAGS = -d -v -t
+
+ex-parser.c ex-parser.h: ex-spec.y
+ $(YACC) $(YFLAGS) ex-spec.y && mv y.tab.h ex-parser.h && mv y.tab.c ex-parser.c
+
+ex-scanner.c: ex-spec.lex
+ $(LEX) ex-spec.lex && mv lex.yy.c ex-scanner.c
+
+CLEANFILES += $(BUILT_SOURCES) bison.stamp $(binary) *.o ex-parser.c ex-scanner.c y.output *~
+compiler: xspec.y xspec.lex
+
+clean:
+ rm -f $(CLEANFILES)
diff --git a/compiler/cycle b/compiler/cycle
new file mode 100644
index 0000000..ff71f88
--- /dev/null
+++ b/compiler/cycle
@@ -0,0 +1,16 @@
+er_der_nogen_cykler_som_involverer_denne_knude_eller_nogen_der_kan_naas?
+
+/* er n en del af en cykel? eller kan den naa en markeret knude?
+
+
+find_cycle (Node *n)
+{
+ mark n
+ for child:
+ if (child.mark)
+ return TRUE;
+ if (find_cycle (child))
+ return TRUE;
+ unmark n;
+ return FALSE;
+} \ No newline at end of file
diff --git a/compiler/ex-ast.c b/compiler/ex-ast.c
new file mode 100644
index 0000000..7d67410
--- /dev/null
+++ b/compiler/ex-ast.c
@@ -0,0 +1,301 @@
+#include "ex-compiler.h"
+
+ExSpec *
+ex_spec_new (ExUsesClause *clauses,
+ ExDefinition *definitions)
+{
+ ExSpec *spec = ex_new (ExSpec, 1);
+
+ spec->uses_clauses = clauses;
+ spec->definitions = definitions;
+
+ return spec;
+}
+
+ExUsesClause *
+ex_uses_clause_new (const char *name)
+{
+ ExUsesClause *clause = ex_new (ExUsesClause, 1);
+
+ clause->name = ex_strdup (name);
+
+ return clause;
+}
+
+ExDefinition *
+ex_definition_new_namespace (ExNamespace *namespace)
+{
+ ExDefinition *definition = ex_new (ExDefinition, 1);
+
+ definition->type = EX_DEFINITION_NAMESPACE;
+ definition->u.namespace = namespace;
+
+ return definition;
+}
+
+ExDefinition *
+ex_definition_new_extension (ExExtension *extension)
+{
+ ExDefinition *definition = ex_new (ExDefinition, 1);
+
+ definition->type = EX_DEFINITION_EXTENSION;
+ definition->u.extension = extension;
+
+ return definition;
+}
+
+ExDefinition *
+ex_definition_new_type_def (ExTypeDef *type_def)
+{
+ ExDefinition *definition = ex_new (ExDefinition, 1);
+
+ definition->type = EX_DEFINITION_TYPE_DEF;
+ definition->u.type_def = type_def;
+
+ return definition;
+}
+
+ExDefinition *
+ex_definition_new_request (ExRequest *request)
+{
+ ExDefinition *definition = ex_new (ExDefinition, 1);
+
+ definition->type = EX_DEFINITION_REQUEST;
+ definition->u.request = request;
+
+ return definition;
+}
+
+ExDefinition *
+ex_definition_new_event (ExEvent *event)
+{
+ ExDefinition *definition = ex_new (ExDefinition, 1);
+
+ definition->type = EX_DEFINITION_EVENT;
+ definition->u.event = event;
+
+ return definition;
+}
+
+ExDefinition *
+ex_definition_new_error (ExError *error)
+{
+ ExDefinition *definition = ex_new (ExDefinition, 1);
+
+ definition->type = EX_DEFINITION_ERROR;
+ definition->u.error = error;
+
+ return definition;
+}
+
+ExNamespace *
+ex_namespace_new (const char *name,
+ ExDefinition *definitions)
+{
+ ExNamespace *namespace = ex_new (ExNamespace, 1);
+
+#if 0
+ printf ("namespace: %s\n", name);
+#endif
+
+ namespace->name = ex_strdup (name);
+ namespace->definitions = definitions;
+
+ return namespace;
+}
+
+ExExtension *
+ex_extension_new (const char *name,
+ ExDefinition *definitions)
+{
+ ExExtension *extension = ex_new (ExExtension, 1);
+
+ extension->name = ex_strdup (name);
+ extension->definitions = definitions;
+
+ return extension;
+}
+
+ExTypeDef *
+ex_type_def_new (const char *name,
+ ExType *type)
+{
+ ExTypeDef *type_def = ex_new (ExTypeDef, 1);
+
+ type_def->name = ex_strdup (name);
+ type_def->type = type;
+
+ return type_def;
+}
+
+ExType *
+ex_type_new_enum (ExIdentifier *identifiers)
+{
+ ExType *type = ex_new (ExType, 1);
+
+ type->type = EX_TYPE_ENUM;
+ type->u._enum.identifiers = identifiers;
+
+ return type;
+}
+
+ExType *
+ex_type_new_struct (ExField *fields)
+{
+ ExType *type = ex_new (ExType, 1);
+
+#if 0
+ printf ("fields: %p\n", fields);
+#endif
+
+ type->type = EX_TYPE_STRUCT;
+ type->u._struct.fields = fields;
+
+ return type;
+}
+
+ExType *
+ex_type_bits_new (unsigned long mask,
+ ExIdentifier *identifiers)
+{
+ ExType *type = ex_new (ExType, 1);
+
+ type->type = EX_TYPE_BITS;
+ type->u.bits.mask = mask;
+ type->u.bits.fields = identifiers;
+
+ return type;
+}
+
+ExType *
+ex_type_derived_bits_new (const char *name,
+ unsigned long mask)
+{
+ ExType *type = ex_new (ExType, 1);
+
+ type->type = EX_TYPE_DERIVED_BITS;
+ type->u.derived_bits.derived_from_name = ex_strdup (name);
+ type->u.derived_bits.mask = mask;
+
+ return type;
+}
+
+ExType *
+ex_type_masked_list_new (ExField *fields)
+{
+ ExType *type = ex_new (ExType, 1);
+
+ type->type = EX_TYPE_MASKED_LIST;
+ type->u.masked_list.fields = fields;
+
+ return type;
+}
+
+ExType *
+ex_type_identifier_new (const char *name,
+ exboolean can_be_null)
+{
+ ExType *type = ex_new (ExType, 1);
+
+ type->type = EX_TYPE_IDENTIFIER;
+ type->u.identifier.name = ex_strdup (name);
+ type->u.identifier.can_be_null = can_be_null;
+
+ return type;
+}
+
+ExType *
+ex_type_union_new (ExField *fields)
+{
+ ExType *type = ex_new (ExType, 1);
+
+ type->type = EX_TYPE_UNION;
+ type->u._union.fields = fields;
+
+ return type;
+}
+
+ExType *
+ex_type_list_new (ExType *type)
+{
+ ExType *new_type = ex_new (ExType, 1);
+
+ new_type->type = EX_TYPE_LIST;
+ new_type->u._list.type = type;
+
+ return type;
+}
+
+ExType *
+ex_type_basic_new (ExTypeType type)
+{
+ ExType *new_type = ex_new (ExType, 1);
+
+ new_type->type = type;
+
+ return new_type;
+}
+
+ExIdentifier *
+ex_identifier_new (const char *name)
+{
+ ExIdentifier *id = ex_new (ExIdentifier, 1);
+
+ id->name = ex_strdup (name);
+
+ return id;
+}
+
+ExError *
+ex_error_new (const char *name)
+{
+ ExError *error = ex_new (ExError, 1);
+
+ error->name = ex_strdup (name);
+
+ return error;
+}
+
+ExField *
+ex_field_new (ExType *type,
+ const char *name,
+ exboolean is_created)
+{
+ ExField *field = ex_new (ExField, 1);
+
+ field->type = type;
+ field->name = ex_strdup (name);
+ field->is_created = is_created;
+
+ return field;
+}
+
+ExRequest *
+ex_request_new (const char *name,
+ int opcode,
+ ExField *parameters,
+ ExField *reply,
+ ExIdentifier *errors)
+{
+ ExRequest *request = ex_new (ExRequest, 1);
+
+ request->opcode = opcode;
+ request->name = ex_strdup (name);
+ request->parameters = parameters;
+ request->reply = reply;
+ request->errors = errors;
+
+ return request;
+}
+
+ExEvent *
+ex_event_new (const char *name,
+ ExField *fields)
+{
+ ExEvent *event = ex_new (ExEvent, 1);
+
+ event->name = ex_strdup (name);
+ event->fields = fields;
+
+ return event;
+}
diff --git a/compiler/ex-compiler.h b/compiler/ex-compiler.h
new file mode 100644
index 0000000..9328353
--- /dev/null
+++ b/compiler/ex-compiler.h
@@ -0,0 +1,260 @@
+#include <stdlib.h>
+#include <assert.h>
+
+typedef struct ExSpec ExSpec;
+typedef struct ExUsesClause ExUsesClause;
+typedef struct ExDefinition ExDefinition;
+typedef struct ExNamespace ExNamespace;
+typedef struct ExExtension ExExtension;
+typedef struct ExRequest ExRequest;
+typedef struct ExEvent ExEvent;
+typedef struct ExError ExError;
+typedef struct ExTypeDef ExTypeDef;
+typedef struct ExType ExType;
+typedef struct ExIdentifier ExIdentifier;
+typedef struct ExField ExField;
+typedef struct ExHashTable ExHashTable;
+
+/* types and utilities */
+
+#define EX_TRUE 1
+#define EX_FALSE 0
+
+typedef int exboolean;
+typedef void * expointer;
+typedef unsigned long exulong;
+
+char * ex_strdup (const char *str);
+void ex_parse_error (int line,
+ int pos,
+ const char *str);
+void ex_fatal_error (int line,
+ int pos,
+ const char *str);
+expointer ex_malloc (size_t n_bytes);
+
+#define ex_new(type,n) (type*)(ex_malloc(sizeof(type)*n))
+#define ex_assert(e) assert(e)
+
+/* Hash Table */
+ExHashTable *ex_hash_table_new (void);
+void ex_hash_table_insert (ExHashTable *table,
+ const char *str,
+ expointer data);
+expointer ex_hash_table_lookup (ExHashTable *table,
+ const char *str);
+
+
+/* AST nodes */
+struct ExSpec
+{
+ ExHashTable * symbols;
+ ExUsesClause * uses_clauses;
+ ExDefinition * definitions;
+};
+
+struct ExUsesClause
+{
+ char * name;
+ ExUsesClause * next;
+};
+
+typedef enum
+{
+ EX_DEFINITION_NAMESPACE,
+ EX_DEFINITION_EXTENSION,
+ EX_DEFINITION_REQUEST,
+ EX_DEFINITION_TYPE_DEF,
+ EX_DEFINITION_ERROR,
+ EX_DEFINITION_EVENT
+} ExDefinitionType;
+
+struct ExDefinition
+{
+ ExDefinitionType type;
+ union
+ {
+ ExNamespace *namespace;
+ ExExtension *extension;
+ ExRequest *request;
+ ExTypeDef *type_def;
+ ExError *error;
+ ExEvent *event;
+ } u;
+
+ ExDefinition *next;
+};
+
+struct ExField
+{
+ ExType * type;
+ char * name;
+ exboolean is_created;
+ ExField * next;
+};
+
+struct ExNamespace
+{
+ char *name;
+ ExDefinition *definitions;
+};
+
+struct ExExtension
+{
+ char *name;
+ ExDefinition *definitions;
+};
+
+struct ExIdentifier
+{
+ char *name;
+ ExIdentifier *next;
+};
+
+struct ExTypeDef
+{
+ char *name;
+ ExType *type;
+};
+
+struct ExRequest
+{
+ char *name;
+ int opcode;
+ ExField *parameters;
+ ExField *reply;
+ ExIdentifier *errors;
+};
+
+struct ExEvent
+{
+ char *name;
+ ExField *fields;
+};
+
+typedef enum
+{
+ EX_TYPE_CARD8,
+ EX_TYPE_CARD16,
+ EX_TYPE_CARD32,
+ EX_TYPE_CARD64,
+ EX_TYPE_INT8,
+ EX_TYPE_INT16,
+ EX_TYPE_INT32,
+ EX_TYPE_INT64,
+ EX_TYPE_BOOLEAN,
+
+ EX_TYPE_ENUM,
+ EX_TYPE_STRUCT,
+ EX_TYPE_BITS,
+ EX_TYPE_DERIVED_BITS,
+ EX_TYPE_MASKED_LIST,
+ EX_TYPE_IDENTIFIER,
+ EX_TYPE_UNION,
+ EX_TYPE_LIST,
+ EX_TYPE_XID
+} ExTypeType;
+
+struct ExType
+{
+ ExTypeType type;
+
+ union {
+ struct
+ {
+ ExIdentifier * identifiers;
+ } _enum;
+
+ struct
+ {
+ ExField * fields;
+ } _struct;
+
+ struct
+ {
+ exulong mask;
+ ExIdentifier * fields;
+ } bits;
+
+ struct
+ {
+ char * derived_from_name;
+ exulong mask;
+ } derived_bits;
+
+ struct
+ {
+ ExField * fields;
+ } masked_list;
+
+ struct
+ {
+ char * name;
+ exboolean can_be_null;
+ } identifier;
+
+ struct
+ {
+ ExField * fields;
+ } _union;
+
+ struct
+ {
+ ExType * type;
+ } _list;
+ } u;
+};
+
+struct ExError
+{
+ char *name;
+};
+
+/* constructors */
+
+ExSpec * ex_spec_new (ExUsesClause *clauses,
+ ExDefinition *definitions);
+ExUsesClause *ex_uses_clause_new (const char *name);
+ExDefinition *ex_definition_new_namespace (ExNamespace *namespace);
+ExDefinition *ex_definition_new_extension (ExExtension *extension);
+ExDefinition *ex_definition_new_type_def (ExTypeDef *type_def);
+ExDefinition *ex_definition_new_request (ExRequest *request);
+ExDefinition *ex_definition_new_event (ExEvent *event);
+ExDefinition *ex_definition_new_error (ExError *error);
+ExNamespace * ex_namespace_new (const char *name,
+ ExDefinition *definitions);
+ExExtension * ex_extension_new (const char *name,
+ ExDefinition *definitions);
+ExTypeDef * ex_type_def_new (const char *name,
+ ExType *type);
+ExType * ex_type_new_enum (ExIdentifier *identifiers);
+ExType * ex_type_new_struct (ExField *fields);
+ExType * ex_type_bits_new (unsigned long mask,
+ ExIdentifier *identifiers);
+ExType * ex_type_derived_bits_new (const char *name,
+ unsigned long mask);
+ExType * ex_type_masked_list_new (ExField *fields);
+ExType * ex_type_identifier_new (const char *name,
+ exboolean can_be_none);
+ExType * ex_type_union_new (ExField *fields);
+ExType * ex_type_list_new (ExType *type);
+ExType * ex_type_basic_new (ExTypeType type);
+ExIdentifier *ex_identifier_new (const char *name);
+ExError * ex_error_new (const char *name);
+ExField * ex_field_new (ExType *type,
+ const char *name,
+ exboolean is_created);
+ExRequest * ex_request_new (const char *name,
+ int opcode,
+ ExField *parameters,
+ ExField *reply,
+ ExIdentifier *errors);
+ExEvent * ex_event_new (const char *name,
+ ExField *fields);
+
+/* phases */
+void ex_init_scanner (void);
+ExSpec *ex_parse (const char *filename);
+void ex_dump (ExSpec *spec);
+void ex_weed (ExSpec *spec);
+void ex_gather_symbols (ExSpec *spec);
diff --git a/compiler/ex-gather-symbols.c b/compiler/ex-gather-symbols.c
new file mode 100644
index 0000000..dc326f2
--- /dev/null
+++ b/compiler/ex-gather-symbols.c
@@ -0,0 +1,189 @@
+#include "ex-compiler.h"
+
+static void gather_symbols_uses_clause (ExUsesClause *clause);
+static void gather_symbols_definition (ExDefinition *definition);
+static void gather_symbols_namespace (ExNamespace *namespace);
+static void gather_symbols_extension (ExExtension *extension);
+static void gather_symbols_request (ExRequest *request);
+static void gather_symbols_event (ExEvent *event);
+static void gather_symbols_type_def (ExTypeDef *type_def);
+static void gather_symbols_identifier (ExIdentifier *identifier);
+static void gather_symbols_type (ExType *type);
+static void gather_symbols_field (ExField *field);
+static void gather_symbols_error (ExError *error);
+
+void
+ex_gather_symbols (ExSpec *spec)
+{
+ if (!spec)
+ return;
+
+ gather_symbols_uses_clause (spec->uses_clauses);
+ gather_symbols_definition (spec->definitions);
+}
+
+static void
+gather_symbols_uses_clause (ExUsesClause *clause)
+{
+ if (!clause)
+ return;
+
+ gather_symbols_uses_clause (clause->next);
+}
+
+static void
+gather_symbols_definition (ExDefinition *definition)
+{
+ if (!definition)
+ return;
+
+ switch (definition->type)
+ {
+ case EX_DEFINITION_NAMESPACE:
+ gather_symbols_namespace (definition->u.namespace);
+ break;
+
+ case EX_DEFINITION_EXTENSION:
+ gather_symbols_extension (definition->u.extension);
+ break;
+
+ case EX_DEFINITION_REQUEST:
+ gather_symbols_request (definition->u.request);
+ break;
+
+ case EX_DEFINITION_TYPE_DEF:
+ gather_symbols_type_def (definition->u.type_def);
+ break;
+
+ case EX_DEFINITION_ERROR:
+ gather_symbols_error (definition->u.error);
+ break;
+
+ case EX_DEFINITION_EVENT:
+ gather_symbols_event (definition->u.event);
+ break;
+ }
+
+ gather_symbols_definition (definition->next);
+}
+
+static void
+gather_symbols_namespace (ExNamespace *namespace)
+{
+ if (!namespace)
+ return;
+
+ gather_symbols_definition (namespace->definitions);
+}
+
+static void
+gather_symbols_extension (ExExtension *extension)
+{
+ if (!extension)
+ return;
+
+ gather_symbols_definition (extension->definitions);
+}
+
+static void
+gather_symbols_request (ExRequest *request)
+{
+ if (!request)
+ return;
+
+ gather_symbols_field (request->parameters);
+ gather_symbols_field (request->reply);
+ gather_symbols_identifier (request->errors);
+}
+
+static void
+gather_symbols_type_def (ExTypeDef *type_def)
+{
+ if (!type_def)
+ return;
+
+ gather_symbols_type (type_def->type);
+}
+
+static void
+gather_symbols_error (ExError *error)
+{
+ if (!error)
+ return;
+}
+
+static void
+gather_symbols_event (ExEvent *event)
+{
+ if (!event)
+ return;
+
+ gather_symbols_field (event->fields);
+}
+
+static void
+gather_symbols_identifier (ExIdentifier *identifier)
+{
+ if (!identifier)
+ return;
+
+ gather_symbols_identifier (identifier->next);
+}
+
+static void
+gather_symbols_type (ExType *type)
+{
+ if (!type)
+ return;
+
+ switch (type->type)
+ {
+ case EX_TYPE_UNION:
+ gather_symbols_field (type->u._struct.fields);
+ break;
+
+ case EX_TYPE_LIST:
+ gather_symbols_type (type->u._list.type);
+ break;
+
+ case EX_TYPE_ENUM:
+ gather_symbols_identifier (type->u._enum.identifiers);
+ break;
+
+ case EX_TYPE_STRUCT:
+ gather_symbols_field (type->u._struct.fields);
+ break;
+
+ case EX_TYPE_BITS:
+ gather_symbols_identifier (type->u.bits.fields);
+ break;
+
+ case EX_TYPE_MASKED_LIST:
+ gather_symbols_field (type->u.masked_list.fields);
+ break;
+
+ case EX_TYPE_CARD8:
+ case EX_TYPE_CARD16:
+ case EX_TYPE_CARD32:
+ case EX_TYPE_CARD64:
+ case EX_TYPE_INT8:
+ case EX_TYPE_INT16:
+ case EX_TYPE_INT32:
+ case EX_TYPE_INT64:
+ case EX_TYPE_BOOLEAN:
+ case EX_TYPE_IDENTIFIER:
+ case EX_TYPE_XID:
+ case EX_TYPE_DERIVED_BITS:
+ break;
+ }
+}
+
+static void
+gather_symbols_field (ExField *field)
+{
+ if (!field)
+ return;
+
+ gather_symbols_type (field->type);
+ gather_symbols_field (field->next);
+}
diff --git a/compiler/ex-main.c b/compiler/ex-main.c
new file mode 100644
index 0000000..a0249ca
--- /dev/null
+++ b/compiler/ex-main.c
@@ -0,0 +1,56 @@
+#include "ex-compiler.h"
+#include <stdio.h>
+
+static void
+usage (void)
+{
+ printf ("you must give at least one command line argument\n");
+ printf ("FIXME: print something more informative here\n");
+ return;
+}
+
+static int debug = 0;
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ int n_specs;
+ ExSpec **specs;
+
+ if (argc < 2)
+ {
+ usage();
+ return -1;
+ }
+
+ n_specs = argc - 1;
+ specs = ex_new (ExSpec *, n_specs);
+
+ /* parse */
+ for (i = 1; i < argc; ++i)
+ {
+ specs[i] = ex_parse (argv[i]);
+ if (!specs[i])
+ {
+ printf ("Can't go on\n");
+ return -1;
+ }
+ }
+
+ /* dump */
+ if (debug)
+ {
+ for (i = 0; i < n_specs; ++i)
+ ex_dump (specs[i]);
+ }
+
+ for (i = 0; i < n_specs; ++i)
+ ex_weed (specs[i]);
+
+ /* gather symbols */
+ for (i = 0; i < n_specs; ++i)
+ ex_gather_symbols (specs[i]);
+
+ return 0;
+}
diff --git a/compiler/ex-parser.h b/compiler/ex-parser.h
new file mode 100644
index 0000000..b29b411
--- /dev/null
+++ b/compiler/ex-parser.h
@@ -0,0 +1,57 @@
+#ifndef YYERRCODE
+#define YYERRCODE 256
+#endif
+
+#define TOK_NAMESPACE 257
+#define TOK_EXTENSION 258
+#define TOK_TYPE 259
+#define TOK_BITS 260
+#define TOK_XID 261
+#define TOK_ENUM 262
+#define TOK_STRUCT 263
+#define TOK_LIST 264
+#define TOK_REQUEST 265
+#define TOK_EVENT 266
+#define TOK_ERROR 267
+#define TOK_MASKED_LIST 268
+#define TOK_ERRORS 269
+#define TOK_REPLY 270
+#define TOK_USES 271
+#define TOK_INT8 272
+#define TOK_INT16 273
+#define TOK_INT32 274
+#define TOK_INT64 275
+#define TOK_CARD8 276
+#define TOK_CARD16 277
+#define TOK_CARD32 278
+#define TOK_CARD64 279
+#define TOK_BOOLEAN 280
+#define TOK_COLON_COLON 281
+#define TOK_IDENTIFIER 282
+#define TOK_UNION 283
+#define TOK_INT_CONST 284
+#define TOK_STRING_CONST 285
+typedef union {
+ struct {
+ int first_line;
+ int last_line;
+ int first_char;
+ int last_char;
+
+ long int_const;
+ const char *string_const;
+ } token;
+ ExSpec *spec;
+ ExUsesClause *uses_clause;
+ ExDefinition *definition;
+ ExNamespace *namespace;
+ ExExtension *extension;
+ ExRequest *request;
+ ExEvent *event;
+ ExError *xerror;
+ ExTypeDef *type_def;
+ ExType *type;
+ ExIdentifier *identifier;
+ ExField *field;
+} YYSTYPE;
+extern YYSTYPE yylval;
diff --git a/compiler/ex-pass.c b/compiler/ex-pass.c
new file mode 100644
index 0000000..c8512cf
--- /dev/null
+++ b/compiler/ex-pass.c
@@ -0,0 +1,212 @@
+#include "ex-compiler.h"
+#include <stdio.h>
+
+static void pass_uses_clause (ExUsesClause *clause);
+static void pass_definition (ExDefinition *definition);
+static void pass_namespace (ExNamespace *namespace);
+static void pass_extension (ExExtension *extenstion);
+static void pass_request (ExRequest *request);
+static void pass_event (ExEvent *event);
+static void pass_type_def (ExTypeDef *type_def);
+static void pass_identifier (ExIdentifier *identifier);
+static void pass_type (ExType *type);
+static void pass_field (ExField *field);
+static void pass_error (ExError *error);
+
+void
+ex_pass (ExSpec *spec)
+{
+ if (!spec)
+ return;
+
+ pass_uses_clause (spec->uses_clauses);
+ pass_definition (spec->definitions);
+}
+
+static void
+pass_uses_clause (ExUsesClause *clause)
+{
+ if (!clause)
+ return;
+
+ pass_uses_clause (clause->next);
+}
+
+static void
+pass_definition (ExDefinition *definition)
+{
+ if (!definition)
+ return;
+
+ switch (definition->type)
+ {
+ case EX_DEFINITION_NAMESPACE:
+ pass_namespace (definition->u.namespace);
+ break;
+
+ case EX_DEFINITION_EXTENSION:
+ pass_extension (definition->u.extension);
+ break;
+
+ case EX_DEFINITION_REQUEST:
+ pass_request (definition->u.request);
+ break;
+
+ case EX_DEFINITION_TYPE_DEF:
+ pass_type_def (definition->u.type_def);
+ break;
+
+ case EX_DEFINITION_ERROR:
+ pass_error (definition->u.error);
+ break;
+
+ case EX_DEFINITION_EVENT:
+ pass_event (definition->u.event);
+ break;
+ }
+
+ pass_definition (definition->next);
+}
+
+static void
+pass_namespace (ExNamespace *namespace)
+{
+ if (!namespace)
+ return;
+
+ pass_definition (namespace->definitions);
+}
+
+static void
+pass_extension (ExExtension *extension)
+{
+ if (!extension)
+ return;
+
+ pass_definition (extension->definitions);
+}
+
+static void
+pass_request (ExRequest *request)
+{
+ if (!request)
+ return;
+
+ pass_field (request->parameters);
+ pass_field (request->reply);
+ pass_identifier (request->errors);
+}
+
+static void
+pass_type_def (ExTypeDef *type_def)
+{
+ if (!type_def)
+ return;
+
+ pass_type (type_def->type);
+}
+
+static void
+pass_error (ExError *error)
+{
+ if (!error)
+ return;
+}
+
+static void
+pass_event (ExEvent *event)
+{
+ if (!event)
+ return;
+
+ pass_field (event->fields);
+}
+
+static void
+pass_identifier (ExIdentifier *identifier)
+{
+ if (!identifier)
+ return;
+
+ pass_identifier (identifier->next);
+}
+
+static void
+pass_type (ExType *type)
+{
+ if (!type)
+ return;
+
+ switch (type->type)
+ {
+ case EX_TYPE_CARD8:
+ break;
+
+ case EX_TYPE_CARD16:
+ break;
+
+ case EX_TYPE_CARD32:
+ break;
+
+ case EX_TYPE_CARD64:
+ break;
+
+ case EX_TYPE_INT8:
+ break;
+
+ case EX_TYPE_INT16:
+ break;
+
+ case EX_TYPE_INT32:
+ break;
+
+ case EX_TYPE_INT64:
+ break;
+
+ case EX_TYPE_BOOLEAN:
+ break;
+
+ case EX_TYPE_ENUM:
+ pass_identifier (type->u._enum.identifiers);
+ break;
+
+ case EX_TYPE_STRUCT:
+ pass_field (type->u._struct.fields);
+ break;
+
+ case EX_TYPE_BITS:
+ pass_identifier (type->u.bits.fields);
+ break;
+
+ case EX_TYPE_DERIVED_BITS:
+ break;
+
+ case EX_TYPE_MASKED_LIST:
+ pass_field (type->u.masked_list.fields);
+ break;
+
+ case EX_TYPE_IDENTIFIER:
+ break;
+
+ case EX_TYPE_UNION:
+ pass_field (type->u._struct.fields);
+ break;
+
+ case EX_TYPE_LIST:
+ pass_type (type->u._list.type);
+ break;
+
+ case EX_TYPE_XID:
+ break;
+ }
+}
+
+static void
+pass_field (ExField *field)
+{
+ if (!field)
+ return;
+
+ pass_type (field->type);
+ pass_field (field->next);
+}
diff --git a/compiler/ex-phase.c b/compiler/ex-phase.c
new file mode 100644
index 0000000..4bb693c
--- /dev/null
+++ b/compiler/ex-phase.c
@@ -0,0 +1,52 @@
+#include "ex-compiler.h"
+
+static void phase_definition (ExDefinition *definition);
+static void phase_namespace (ExNamespace *namespace);
+static void phase_request (ExRequest *request);
+static void phase_event (ExEvent *event);
+static void phase_type_def (ExTypeDef *type_def);
+static void phase_identifier (ExIdentifier *identifier);
+static void phase_type (ExType *type);
+static void phase_field (ExField *field);
+static void phase_error (ExError *error);
+
+void
+ex_phase (ExSpec *spec)
+{
+ if (!spec)
+ return;
+
+ phase_definition (spec->definitions);
+}
+
+static void
+phase_definition (ExDefinition *definition)
+{
+ if (!definition)
+ return;
+
+ switch (definition->type)
+ {
+ case EX_DEFINITION_NAMESPACE:
+ dump_namespace (definition->u.namespace);
+ break;
+
+ case EX_DEFINITION_REQUEST:
+ dump_request (definition->u.request);
+ break;
+
+ case EX_DEFINITION_TYPE_DEF:
+ dump_type_def (definition->u.type_def);
+ break;
+
+ case EX_DEFINITION_ERROR:
+ dump_error (definition->u.error);
+ break;
+
+ case EX_DEFINITION_EVENT:
+ dump_event (definition->u.event);
+ break;
+ }
+
+ dump_definition (definition->next);
+}
diff --git a/compiler/ex-pretty.c b/compiler/ex-pretty.c
new file mode 100644
index 0000000..e7888c2
--- /dev/null
+++ b/compiler/ex-pretty.c
@@ -0,0 +1,256 @@
+#include "ex-compiler.h"
+#include <stdio.h>
+
+static void dump_uses_clause (ExUsesClause *clause);
+static void dump_definition (ExDefinition *definition);
+static void dump_namespace (ExNamespace *namespace);
+static void dump_extension (ExExtension *extension);
+static void dump_request (ExRequest *request);
+static void dump_event (ExEvent *event);
+static void dump_type_def (ExTypeDef *type_def);
+static void dump_identifier (ExIdentifier *identifier);
+static void dump_type (ExType *type);
+static void dump_field (ExField *field);
+static void dump_error (ExError *error);
+
+void
+ex_dump (ExSpec *spec)
+{
+ if (!spec)
+ return;
+
+ dump_uses_clause (spec->uses_clauses);
+ dump_definition (spec->definitions);
+}
+
+static void
+dump_uses_clause (ExUsesClause *clause)
+{
+ if (!clause)
+ return;
+
+ printf ("uses %s;\n", clause->name);
+ dump_uses_clause (clause->next);
+ printf ("\n");
+}
+
+static void
+dump_definition (ExDefinition *definition)
+{
+ if (!definition)
+ return;
+
+ switch (definition->type)
+ {
+ case EX_DEFINITION_NAMESPACE:
+ dump_namespace (definition->u.namespace);
+ break;
+
+ case EX_DEFINITION_EXTENSION:
+ dump_extension (definition->u.extension);
+ break;
+
+ case EX_DEFINITION_REQUEST:
+ dump_request (definition->u.request);
+ break;
+
+ case EX_DEFINITION_TYPE_DEF:
+ dump_type_def (definition->u.type_def);
+ break;
+
+ case EX_DEFINITION_ERROR:
+ dump_error (definition->u.error);
+ break;
+
+ case EX_DEFINITION_EVENT:
+ dump_event (definition->u.event);
+ break;
+ }
+
+ dump_definition (definition->next);
+}
+
+static void
+dump_namespace (ExNamespace *namespace)
+{
+ if (!namespace)
+ return;
+
+ printf ("namespace %s {\n", namespace->name);
+ dump_definition (namespace->definitions);
+ printf ("}\n");
+}
+
+static void
+dump_extension (ExExtension *extension)
+{
+ if (!extension)
+ return;
+
+ printf ("extension %s {\n", extension->name);
+ dump_definition (extension->definitions);
+ printf ("\n");
+}
+
+static void
+dump_request (ExRequest *request)
+{
+ if (!request)
+ return;
+
+ printf ("request %s = {\n", request->name);
+ dump_field (request->parameters);
+ printf ("reply:\n");
+ dump_field (request->reply);
+ printf ("errors:\n");
+ dump_identifier (request->errors);
+ printf ("}\n");
+}
+
+static void
+dump_type_def (ExTypeDef *type_def)
+{
+ if (!type_def)
+ return;
+
+ printf ("type %s = ", type_def->name);
+ dump_type (type_def->type);
+}
+
+static void
+dump_error (ExError *error)
+{
+ if (!error)
+ return;
+
+ printf ("error %s;\n", error->name);
+}
+
+static void
+dump_event (ExEvent *event)
+{
+ if (!event)
+ return;
+
+ printf ("event %s {\n", event->name);
+ dump_field (event->fields);
+ printf ("}\n");
+}
+
+static void
+dump_identifier (ExIdentifier *identifier)
+{
+ if (!identifier)
+ return;
+
+ printf ("%s,\n", identifier->name);
+ dump_identifier (identifier->next);
+}
+
+static void
+dump_type (ExType *type)
+{
+ if (!type)
+ return;
+
+ switch (type->type)
+ {
+ case EX_TYPE_CARD8:
+ printf ("card8\n");
+ break;
+
+ case EX_TYPE_CARD16:
+ printf ("card16\n");
+ break;
+
+ case EX_TYPE_CARD32:
+ printf ("card32\n");
+ break;
+
+ case EX_TYPE_CARD64:
+ printf ("card64\n");
+ break;
+
+ case EX_TYPE_INT8:
+ printf ("int8\n");
+ break;
+
+ case EX_TYPE_INT16:
+ printf ("int16\n");
+ break;
+
+ case EX_TYPE_INT32:
+ printf ("int32\n");
+ break;
+
+ case EX_TYPE_INT64:
+ printf ("int64\n");
+ break;
+
+ case EX_TYPE_BOOLEAN:
+ printf ("boolean\n");
+ break;
+
+ case EX_TYPE_ENUM:
+ printf ("enum {\n");
+ dump_identifier (type->u._enum.identifiers);
+ printf ("}");
+ break;
+
+ case EX_TYPE_STRUCT:
+ printf ("struct {\n");
+ dump_field (type->u._struct.fields);
+ printf ("}\n");
+ break;
+
+ case EX_TYPE_BITS:
+ printf ("bits {\n");
+ dump_identifier (type->u.bits.fields);
+ printf ("}\n");
+ break;
+
+ case EX_TYPE_DERIVED_BITS:
+ printf ("%s [%8lx];\n", type->u.derived_bits.derived_from_name,
+ type->u.derived_bits.mask);
+ break;
+
+ case EX_TYPE_MASKED_LIST:
+ printf ("masked_list {\n");
+ dump_field (type->u.masked_list.fields);
+ printf ("}\n");
+ break;
+
+ case EX_TYPE_IDENTIFIER:
+ printf ("%s%s\n",
+ type->u.identifier.name,
+ type->u.identifier.can_be_null? "?" : "");
+ break;
+
+ case EX_TYPE_UNION:
+ printf ("union {\n");
+ dump_field (type->u._struct.fields);
+ printf ("}\n");
+ break;
+
+ case EX_TYPE_LIST:
+ printf ("list [\n");
+ dump_type (type->u._list.type);
+ printf ("]\n");
+ break;
+
+ case EX_TYPE_XID:
+ printf ("xid\n");
+ break;
+ }
+}
+
+static void
+dump_field (ExField *field)
+{
+ if (!field)
+ return;
+
+ dump_type (field->type);
+ printf ("%s%s;\n", field->name, field->is_created? "*" : "");
+ dump_field (field->next);
+}
diff --git a/compiler/ex-spec.lex b/compiler/ex-spec.lex
new file mode 100644
index 0000000..c7dd03c
--- /dev/null
+++ b/compiler/ex-spec.lex
@@ -0,0 +1,216 @@
+/* Copyright (C) 2003 Søren Sandmann (sandmann@daimi.au.dk)
+ *
+ * Author: Søren Sandmann
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+%{
+#include <string.h>
+#include "ex-compiler.h"
+#include "ex-parser.h"
+
+ static int line;
+ static int pos;
+ static void set_position (void); /* update yylval.token */
+%}
+
+%option never-interactive nounput
+
+LETTER [A-Za-z_]
+DIGIT [0-9]
+HEX_DIGIT {DIGIT}|[A-Fa-f]
+OCTAL_DIGIT [0-7]
+BINARY_DIGIT [0-1]
+ID {LETTER}({LETTER}|{DIGIT})*
+WS [ \t\r\n]
+CCOMMENT "/*"([^*]|"*"[^/])*"*/"
+CPPCOMMENT \/\/[^\n]*\n
+EAT ({WS}|{CCOMMENT}|{CPPCOMMENT})+
+
+%%
+
+{EAT} {
+ set_position ();
+}
+"namespace" {
+ set_position ();
+ return TOK_NAMESPACE;
+}
+"extension" {
+ set_position ();
+ return TOK_EXTENSION;
+}
+"type" {
+ set_position ();
+ return TOK_TYPE;
+}
+"bits" {
+ set_position ();
+ return TOK_BITS;
+}
+"xid" {
+ set_position ();
+ return TOK_XID;
+}
+"enum" {
+ set_position ();
+ return TOK_ENUM;
+}
+"struct" {
+ set_position ();
+ return TOK_STRUCT;
+}
+"list" {
+ set_position ();
+ return TOK_LIST;
+}
+"request" {
+ set_position ();
+ return TOK_REQUEST;
+}
+"event" {
+ set_position ();
+ return TOK_EVENT;
+}
+"error" {
+ set_position ();
+ return TOK_ERROR;
+}
+"union" {
+ set_position ();
+ return TOK_UNION;
+}
+"masked_list" {
+ set_position ();
+ return TOK_MASKED_LIST;
+}
+"errors" {
+ set_position ();
+ return TOK_ERRORS;
+}
+"reply" {
+ set_position ();
+ return TOK_REPLY;
+}
+"uses" {
+ set_position ();
+ return TOK_USES;
+}
+"int8" {
+ set_position ();
+ return TOK_INT8;
+}
+"int16" {
+ set_position ();
+ return TOK_INT16;
+}
+"int32" {
+ set_position ();
+ return TOK_INT32;
+}
+"int64" {
+ set_position ();
+ return TOK_INT64;
+}
+"card8" {
+ set_position ();
+ return TOK_CARD8;
+}
+"card16" {
+ set_position ();
+ return TOK_CARD16;
+}
+"card32" {
+ set_position ();
+ return TOK_CARD32;
+}
+"card64" {
+ set_position ();
+ return TOK_CARD64;
+}
+"boolean" {
+ set_position ();
+ return TOK_BOOLEAN;
+}
+"::" {
+ set_position ();
+ return TOK_COLON_COLON;
+}
+0(x|X)([a-fA-F0-9][a-fA-F0-9]*) {
+ yylval.token.int_const = strtol (yytext, NULL, 16);
+ set_position ();
+ return TOK_INT_CONST;
+}
+[1-9][0-9]* {
+ yylval.token.int_const = strtol (yytext, NULL, 10);
+ set_position ();
+ return TOK_INT_CONST;
+}
+{ID} {
+ yylval.token.string_const = ex_strdup (yytext);
+ set_position ();
+ return TOK_IDENTIFIER;
+}
+\"([^\"]|\\\")*\" {
+ char *stripped;
+
+ stripped = ex_strdup (yytext + 1);
+ stripped [strlen (stripped) - 1] = '\0';
+
+ yylval.token.string_const = stripped;
+
+ set_position ();
+ return TOK_STRING_CONST;
+}
+. {
+ set_position ();
+ return *yytext;
+}
+
+%%
+
+static void
+set_position (void)
+{
+ const char *s;
+
+ yylval.token.first_line = line;
+ yylval.token.first_char = pos;
+
+ for (s = yytext; *s != '\0'; ++s)
+ {
+ if (*s == '\n')
+ {
+ line++;
+ pos = 1;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+
+ yylval.token.last_line = line;
+ yylval.token.last_char = pos;
+}
+
+void
+ex_init_scanner (void)
+{
+ line = 1;
+ pos = 1;
+}
diff --git a/compiler/ex-spec.y b/compiler/ex-spec.y
new file mode 100644
index 0000000..3ab43b4
--- /dev/null
+++ b/compiler/ex-spec.y
@@ -0,0 +1,405 @@
+%{
+/*
+ * Copyright (C) 2003 Soeren Sandmann (sandmann@daimi.au.dk)
+ *
+ * Author: Soeren Sandmann
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "ex-compiler.h"
+int yylex (void);
+static void yyerror ();
+
+static ExSpec *spec;
+
+#define YYDEBUG 1
+
+%}
+
+%token<token> TOK_NAMESPACE
+%token<token> TOK_EXTENSION
+%token<token> TOK_TYPE
+%token<token> TOK_BITS
+%token<token> TOK_XID
+%token<token> TOK_ENUM
+%token<token> TOK_STRUCT
+%token<token> TOK_LIST
+%token<token> TOK_REQUEST
+%token<token> TOK_EVENT
+%token<token> TOK_ERROR
+%token<token> TOK_MASKED_LIST
+%token<token> TOK_ERRORS
+%token<token> TOK_REPLY
+%token<token> TOK_USES
+%token<token> TOK_INT8
+%token<token> TOK_INT16
+%token<token> TOK_INT32
+%token<token> TOK_INT64
+%token<token> TOK_CARD8
+%token<token> TOK_CARD16
+%token<token> TOK_CARD32
+%token<token> TOK_CARD64
+%token<token> TOK_BOOLEAN
+%token<token> TOK_COLON_COLON
+%token<token> TOK_IDENTIFIER
+%token<token> TOK_UNION
+%token<token> TOK_INT_CONST
+%token<token> TOK_STRING_CONST
+
+%start spec
+
+%union {
+ struct {
+ int first_line;
+ int last_line;
+ int first_char;
+ int last_char;
+
+ long int_const;
+ const char *string_const;
+ } token;
+ ExSpec *spec;
+ ExUsesClause *uses_clause;
+ ExDefinition *definition;
+ ExNamespace *namespace;
+ ExExtension *extension;
+ ExRequest *request;
+ ExEvent *event;
+ ExError *xerror;
+ ExTypeDef *type_def;
+ ExType *type;
+ ExIdentifier *identifier;
+ ExField *field;
+}
+
+%type <spec> spec
+%type <uses_clause> uses_clauses ne_uses_clauses
+%type <definition> definitions ne_definitions definition
+%type <namespace> namespace;
+%type <extension> extension;
+%type <request> request
+%type <event> event
+%type <xerror> xerror
+%type <type_def> type_def
+%type <type> type
+%type <identifier> ne_identifiers identifiers errors_opt
+%type <field> fields ne_fields field fields reply_opt
+
+%%
+
+spec : uses_clauses definitions
+{
+ spec = ex_spec_new ($1, $2);
+};
+
+uses_clauses : /* empty */
+{
+ $$ = NULL;
+}
+ | ne_uses_clauses
+{
+ $$ = $1;
+};
+
+ne_uses_clauses : TOK_USES TOK_IDENTIFIER ';'
+{
+ $$ = ex_uses_clause_new ($2.string_const);
+}
+ | TOK_USES TOK_IDENTIFIER ';' ne_uses_clauses
+{
+ $$ = ex_uses_clause_new ($2.string_const);
+ $$->next = $4;
+};
+
+definitions : /* empty */
+{
+ $$ = NULL;
+}
+ | ne_definitions
+{
+ $$ = $1;
+};
+
+ne_definitions : definition semicolon_opt
+{
+ $$ = $1;
+}
+ | definition semicolon_opt ne_definitions
+{
+ $$ = $1;
+ $$->next = $3;
+};
+
+definition : namespace
+{
+ $$ = ex_definition_new_namespace ($1);
+}
+ | extension
+{
+ $$ = ex_definition_new_extension ($1);
+}
+ | type_def
+{
+ $$ = ex_definition_new_type_def ($1);
+}
+ | xerror
+{
+ $$ = ex_definition_new_error ($1);
+}
+ | request
+{
+ $$ = ex_definition_new_request ($1);
+}
+ | event
+{
+ $$ = ex_definition_new_event ($1);
+};
+
+namespace : TOK_NAMESPACE TOK_IDENTIFIER '{' definitions '}'
+{
+ $$ = ex_namespace_new ($2.string_const, $4);
+};
+
+extension : TOK_EXTENSION TOK_STRING_CONST '{' definitions '}'
+{
+ $$ = ex_extension_new ($2.string_const, $4);
+}
+
+type_def : TOK_TYPE TOK_IDENTIFIER '=' type
+{
+ $$ = ex_type_def_new ($2.string_const, $4);
+};
+
+type : TOK_ENUM '{' ne_identifiers '}'
+{
+ $$ = ex_type_new_enum ($3);
+}
+ | TOK_STRUCT '{' ne_fields '}'
+{
+ $$ = ex_type_new_struct ($3);
+}
+ | TOK_BITS '[' '~' TOK_INT_CONST ']' '{' ne_identifiers '}'
+{
+ $$ = ex_type_bits_new (~($4.int_const), $7);
+}
+ | TOK_BITS '[' TOK_INT_CONST ']' '{' ne_identifiers '}'
+{
+ $$ = ex_type_bits_new ($3.int_const, $6);
+}
+ | TOK_IDENTIFIER '[' '~' TOK_INT_CONST ']'
+{
+ $$ = ex_type_derived_bits_new ($1.string_const, ~($4.int_const));
+}
+ | TOK_IDENTIFIER '[' TOK_INT_CONST ']'
+{
+ $$ = ex_type_derived_bits_new ($1.string_const, $3.int_const);
+}
+ | TOK_MASKED_LIST '{' ne_fields '}'
+{
+ $$ = ex_type_masked_list_new ($3);
+}
+ | TOK_IDENTIFIER
+{
+ $$ = ex_type_identifier_new ($1.string_const, EX_FALSE);
+}
+ | TOK_IDENTIFIER '?'
+{
+ $$ = ex_type_identifier_new ($1.string_const, EX_TRUE);
+}
+ | TOK_UNION '{' ne_fields '}'
+{
+ $$ = ex_type_union_new ($3);
+}
+ | TOK_LIST '[' type ']'
+{
+ $$ = ex_type_list_new ($3);
+}
+ | TOK_XID
+{
+ $$ = ex_type_basic_new (EX_TYPE_XID);
+}
+ | TOK_CARD8
+{
+ $$ = ex_type_basic_new (EX_TYPE_CARD8);
+}
+ | TOK_CARD16
+{
+ $$ = ex_type_basic_new (EX_TYPE_CARD16);
+}
+ | TOK_CARD32
+{
+ $$ = ex_type_basic_new (EX_TYPE_CARD32);
+}
+ | TOK_CARD64
+{
+ $$ = ex_type_basic_new (EX_TYPE_CARD64);
+}
+ | TOK_INT8
+{
+ $$ = ex_type_basic_new (EX_TYPE_INT8);
+}
+ | TOK_INT16
+{
+ $$ = ex_type_basic_new (EX_TYPE_INT16);
+}
+ | TOK_INT32
+{
+ $$ = ex_type_basic_new (EX_TYPE_INT32);
+}
+ | TOK_INT64
+{
+ $$ = ex_type_basic_new (EX_TYPE_INT64);
+}
+ | TOK_BOOLEAN
+{
+ $$ = ex_type_basic_new (EX_TYPE_BOOLEAN);
+};
+
+identifiers : /* empty */
+{
+ $$ = NULL;
+}
+ | ne_identifiers
+{
+ $$ = $1;
+};
+
+ne_identifiers : TOK_IDENTIFIER comma_opt
+{
+ $$ = ex_identifier_new ($1.string_const);
+}
+ | TOK_IDENTIFIER ',' ne_identifiers
+{
+ $$ = ex_identifier_new ($1.string_const);
+ $$->next = $3;
+};
+
+fields : /* empty */
+{
+ $$ = NULL;
+}
+ | ne_fields
+{
+ $$ = $1;
+};
+
+ne_fields : field
+{
+ $$ = $1;
+}
+ | field ne_fields
+{
+ $$ = $1;
+
+ /* $1 is a list of fields, so append $2 to the end */
+ while ($1->next)
+ $1 = $1->next;
+ $1->next = $2;
+};
+
+field : type ne_identifiers ';'
+{
+ ExIdentifier *id;
+ ExField *result = NULL;
+ ExField **tail = &result;
+
+ /* create a separate field for each identifier */
+
+ for (id = $2; id != NULL; id = id->next)
+ {
+ *tail = ex_field_new ($1, id->name, EX_FALSE);
+
+ tail = &((*tail)->next);
+ }
+
+ $$ = result;
+}
+ | type TOK_IDENTIFIER '*' ';'
+{
+ $$ = ex_field_new ($1, $2.string_const, EX_TRUE);
+};
+
+xerror : TOK_ERROR TOK_IDENTIFIER ';'
+{
+ $$ = ex_error_new ($2.string_const);
+};
+
+comma_opt : /* empty */
+ | ','
+{
+};
+
+semicolon_opt : /* empty */
+ | ';'
+{
+};
+
+/* FIXME */
+request : TOK_REQUEST TOK_IDENTIFIER '[' TOK_INT_CONST ']' '{' fields reply_opt errors_opt semicolon_opt '}'
+{
+ $$ = ex_request_new ($2.string_const, $4.int_const, $7, $8, $9);
+};
+
+reply_opt : /* empty */
+{
+ $$ = NULL;
+}
+ | TOK_REPLY ':' fields
+{
+ $$ = $3;
+};
+
+errors_opt : /* empty */
+{
+ $$ = NULL;
+}
+ | TOK_ERRORS ':' identifiers
+{
+ $$ = $3;
+};
+
+event : TOK_EVENT TOK_IDENTIFIER '[' TOK_INT_CONST ']' '{' fields '}'
+{
+ $$ = ex_event_new ($2.string_const, $7);
+};
+
+%%
+
+static void
+yyerror ()
+{
+ extern char *yytext;
+ ex_parse_error (yylval.token.first_line,
+ yylval.token.first_char,
+ yytext);
+}
+
+ExSpec *
+ex_parse (const char *filename)
+{
+ int yyparse ();
+ extern FILE *yyin;
+#if 0
+ yydebug=1;
+#endif
+ yyin = fopen (filename, "r");
+ if (!yyin)
+ return NULL;
+ ex_init_scanner();
+ yyparse();
+ return spec;
+}
diff --git a/compiler/ex-util.c b/compiler/ex-util.c
new file mode 100644
index 0000000..34639a0
--- /dev/null
+++ b/compiler/ex-util.c
@@ -0,0 +1,121 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "ex-compiler.h"
+
+char *
+ex_strdup (const char *str)
+{
+ char *copy;
+
+ if (!str)
+ return NULL;
+
+ copy = calloc (strlen (str) + 1, sizeof (char));
+ strcpy (copy, str);
+
+ return copy;
+}
+
+void
+ex_parse_error (int line, int pos, const char *err)
+{
+ printf ("error: %d,%d: %s!\n", line, pos, err);
+ exit (1);
+}
+
+void
+ex_fatal_error (int line, int pos, const char *err)
+{
+ printf ("error: %d,%d: %s!\n", line, pos, err);
+ exit (1);
+}
+
+expointer
+ex_malloc (size_t n)
+{
+ return calloc (n, 1);
+}
+
+/* ExHashTable */
+typedef struct HashNode HashNode;
+
+enum {
+ HASH_SIZE = 367
+};
+
+struct HashNode
+{
+ char * key;
+ expointer value;
+ HashNode * next;
+};
+
+struct ExHashTable
+{
+ HashNode *nodes [HASH_SIZE];
+};
+
+ExHashTable *
+ex_hash_table_new (void)
+{
+ int i;
+ ExHashTable *hash_table;
+
+ hash_table = ex_new (ExHashTable, 1);
+ for (i = 0; i < HASH_SIZE; ++i)
+ hash_table->nodes[i] = NULL;
+
+ return hash_table;
+}
+
+static int
+hash_string (const char *key)
+{
+ int i;
+ int hash = 0;
+
+ for (i = 0; key[i] != 0; ++i)
+ hash = (hash << 5) + key[i];
+
+ return hash % HASH_SIZE;
+}
+
+void
+ex_hash_table_insert (ExHashTable *table,
+ const char *key,
+ expointer value)
+{
+ int hash;
+ HashNode *node;
+
+ hash = hash_string (key);
+
+ for (node = table->nodes[hash]; node != NULL; node = node->next)
+ {
+ if (strcmp (node->key, key) == 0)
+ {
+ node->value = value;
+ return;
+ }
+ }
+
+ node = ex_new (HashNode, 1);
+ node->next = table->nodes[hash];
+ table->nodes[hash] = node;
+}
+
+expointer
+ex_hash_table_lookup (ExHashTable *table, const char *key)
+{
+ HashNode *node;
+ int hash = hash_string (key);
+
+ for (node = table->nodes[hash]; node != NULL; node = node->next)
+ {
+ if (strcmp (node->key, key) == 0)
+ return node->value;
+ }
+
+ return NULL;
+}
diff --git a/compiler/ex-weed.c b/compiler/ex-weed.c
new file mode 100644
index 0000000..507129c
--- /dev/null
+++ b/compiler/ex-weed.c
@@ -0,0 +1,231 @@
+#include "ex-compiler.h"
+#include <stdio.h>
+
+static void weed_uses_clause (ExUsesClause *clause);
+static void weed_definition (ExDefinition *definition,
+ exboolean allow_extensions);
+static void weed_namespace (ExNamespace *namespace,
+ exboolean allow_extensions);
+static void weed_extension (ExExtension *extension,
+ exboolean allow_extensions);
+static void weed_request (ExRequest *request);
+static void weed_event (ExEvent *event);
+static void weed_type_def (ExTypeDef *type_def);
+static void weed_identifier (ExIdentifier *identifier);
+static void weed_type (ExType *type);
+static void weed_field (ExField *field,
+ exboolean allow_create);
+static void weed_error (ExError *error);
+
+void
+ex_weed (ExSpec *spec)
+{
+ if (!spec)
+ return;
+
+ weed_uses_clause (spec->uses_clauses);
+ weed_definition (spec->definitions, EX_TRUE);
+}
+
+static void
+weed_uses_clause (ExUsesClause *clause)
+{
+ if (!clause)
+ return;
+
+ weed_uses_clause (clause->next);
+}
+
+static void
+weed_definition (ExDefinition *definition,
+ exboolean allow_extensions)
+{
+ if (!definition)
+ return;
+
+ switch (definition->type)
+ {
+ case EX_DEFINITION_NAMESPACE:
+ weed_namespace (definition->u.namespace, allow_extensions);
+ break;
+
+ case EX_DEFINITION_EXTENSION:
+ if (!allow_extensions)
+ {
+ ex_fatal_error (-1, -1, "Nested extensions are not allowed");
+ return;
+ }
+ weed_extension (definition->u.extension, EX_FALSE);
+ break;
+
+ case EX_DEFINITION_REQUEST:
+ weed_request (definition->u.request);
+ break;
+
+ case EX_DEFINITION_TYPE_DEF:
+ weed_type_def (definition->u.type_def);
+ break;
+
+ case EX_DEFINITION_ERROR:
+ weed_error (definition->u.error);
+ break;
+
+ case EX_DEFINITION_EVENT:
+ weed_event (definition->u.event);
+ break;
+ }
+
+ weed_definition (definition->next, allow_extensions);
+}
+
+static void
+weed_namespace (ExNamespace *namespace,
+ exboolean allow_extensions)
+{
+ if (!namespace)
+ return;
+
+ weed_definition (namespace->definitions, allow_extensions);
+}
+
+static void
+weed_extension (ExExtension *extension,
+ exboolean allow_extensions)
+{
+ if (!extension)
+ return;
+
+ weed_definition (extension->definitions,
+ allow_extensions);
+}
+
+static void
+weed_request (ExRequest *request)
+{
+ if (!request)
+ return;
+
+ weed_field (request->parameters, EX_TRUE);
+ weed_field (request->reply, EX_FALSE);
+ weed_identifier (request->errors);
+}
+
+static void
+weed_type_def (ExTypeDef *type_def)
+{
+ if (!type_def)
+ return;
+
+ weed_type (type_def->type);
+}
+
+static void
+weed_error (ExError *error)
+{
+ if (!error)
+ return;
+}
+
+static void
+weed_event (ExEvent *event)
+{
+ if (!event)
+ return;
+
+ weed_field (event->fields, EX_FALSE);
+}
+
+static void
+weed_identifier (ExIdentifier *identifier)
+{
+ if (!identifier)
+ return;
+
+ weed_identifier (identifier->next);
+}
+
+static void
+weed_type (ExType *type)
+{
+ if (!type)
+ return;
+
+ switch (type->type)
+ {
+ case EX_TYPE_CARD8:
+ break;
+
+ case EX_TYPE_CARD16:
+ break;
+
+ case EX_TYPE_CARD32:
+ break;
+
+ case EX_TYPE_CARD64:
+ break;
+
+ case EX_TYPE_INT8:
+ break;
+
+ case EX_TYPE_INT16:
+ break;
+
+ case EX_TYPE_INT32:
+ break;
+
+ case EX_TYPE_INT64:
+ break;
+
+ case EX_TYPE_BOOLEAN:
+ break;
+
+ case EX_TYPE_ENUM:
+ weed_identifier (type->u._enum.identifiers);
+ break;
+
+ case EX_TYPE_STRUCT:
+ weed_field (type->u._struct.fields, EX_FALSE);
+ break;
+
+ case EX_TYPE_BITS:
+ weed_identifier (type->u.bits.fields);
+ break;
+
+ case EX_TYPE_DERIVED_BITS:
+ break;
+
+ case EX_TYPE_MASKED_LIST:
+ weed_field (type->u.masked_list.fields, EX_FALSE);
+ break;
+
+ case EX_TYPE_IDENTIFIER:
+ break;
+
+ case EX_TYPE_UNION:
+ weed_field (type->u._struct.fields, EX_FALSE);
+ break;
+
+ case EX_TYPE_LIST:
+ weed_type (type->u._list.type);
+ break;
+
+ case EX_TYPE_XID:
+ break;
+ }
+}
+
+static void
+weed_field (ExField *field,
+ exboolean allow_create)
+{
+ if (!field)
+ return;
+
+ if (!allow_create && field->is_created)
+ {
+ ex_fatal_error (-1, -1, "Created parameter is not allowed here");
+ }
+
+ weed_type (field->type);
+ weed_field (field->next, allow_create);
+}
diff --git a/compiler/scanner.c b/compiler/scanner.c
new file mode 100644
index 0000000..a8e2c70
--- /dev/null
+++ b/compiler/scanner.c
@@ -0,0 +1,2142 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+#include <unistd.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 61
+#define YY_END_OF_BUFFER 62
+static yyconst short int yy_accept[183] =
+ { 0,
+ 0, 0, 62, 60, 1, 1, 60, 60, 60, 60,
+ 60, 60, 60, 60, 56, 56, 60, 60, 60, 60,
+ 59, 60, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 59, 59, 59, 60, 1, 0, 53,
+ 0, 58, 0, 44, 51, 45, 42, 38, 40, 39,
+ 41, 35, 0, 0, 43, 0, 56, 34, 54, 36,
+ 52, 37, 55, 59, 46, 59, 59, 59, 59, 59,
+ 59, 59, 10, 59, 59, 59, 59, 59, 59, 17,
+ 18, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 47, 50, 58, 0, 0, 0, 57, 57, 48,
+
+ 49, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 59, 15, 59, 19, 59, 21, 59,
+ 59, 59, 59, 59, 59, 59, 33, 59, 59, 57,
+ 59, 59, 4, 5, 59, 7, 59, 59, 59, 12,
+ 59, 59, 59, 16, 20, 22, 59, 59, 59, 27,
+ 59, 32, 28, 59, 59, 3, 6, 59, 59, 59,
+ 29, 59, 14, 59, 23, 59, 30, 25, 59, 59,
+ 59, 11, 59, 26, 24, 31, 2, 59, 9, 13,
+ 8, 0
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 4, 5, 1, 1, 6, 7, 1, 1,
+ 1, 8, 9, 1, 10, 1, 11, 12, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 14, 1, 15,
+ 16, 17, 1, 1, 18, 18, 18, 18, 18, 18,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 20, 19, 19,
+ 1, 21, 1, 22, 19, 1, 23, 24, 25, 26,
+
+ 27, 28, 29, 30, 31, 19, 32, 33, 19, 34,
+ 35, 19, 19, 36, 37, 38, 39, 40, 41, 42,
+ 43, 19, 1, 44, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst int yy_meta[45] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 3, 1, 1, 1, 1, 3, 4, 4,
+ 1, 1, 3, 3, 3, 3, 3, 3, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 1
+ } ;
+
+static yyconst short int yy_base[189] =
+ { 0,
+ 0, 0, 223, 224, 43, 45, 206, 44, 205, 43,
+ 204, 42, 45, 52, 32, 54, 205, 54, 202, 55,
+ 0, 201, 40, 50, 51, 183, 56, 180, 54, 179,
+ 54, 186, 23, 54, 177, 181, 61, 92, 88, 224,
+ 87, 224, 92, 224, 224, 224, 224, 224, 224, 224,
+ 224, 224, 202, 206, 224, 196, 88, 224, 191, 224,
+ 224, 224, 190, 0, 224, 170, 177, 165, 69, 179,
+ 167, 172, 160, 161, 164, 162, 160, 158, 155, 0,
+ 154, 157, 149, 156, 150, 152, 155, 73, 59, 154,
+ 153, 224, 224, 105, 175, 171, 178, 224, 0, 224,
+
+ 224, 147, 156, 151, 150, 151, 139, 136, 150, 148,
+ 144, 133, 146, 145, 0, 132, 0, 137, 0, 132,
+ 125, 127, 124, 124, 125, 132, 0, 132, 124, 0,
+ 129, 123, 0, 0, 124, 0, 122, 113, 118, 0,
+ 123, 116, 110, 0, 0, 0, 111, 108, 120, 0,
+ 103, 0, 0, 98, 101, 0, 0, 89, 89, 94,
+ 0, 87, 0, 85, 0, 88, 80, 0, 82, 76,
+ 76, 0, 69, 0, 0, 0, 0, 84, 0, 0,
+ 0, 224, 126, 129, 133, 137, 140, 54
+ } ;
+
+static yyconst short int yy_def[189] =
+ { 0,
+ 182, 1, 182, 182, 182, 182, 182, 183, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 184, 182, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 182, 182, 182, 182,
+ 183, 182, 183, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 185, 186, 182, 187, 182, 182, 182, 182,
+ 182, 182, 182, 184, 182, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 182, 182, 183, 185, 185, 186, 182, 188, 182,
+
+ 182, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 188,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,
+ 184, 0, 182, 182, 182, 182, 182, 182
+ } ;
+
+static yyconst short int yy_nxt[269] =
+ { 0,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 21, 21,
+ 4, 22, 21, 23, 24, 25, 26, 27, 28, 21,
+ 29, 21, 30, 31, 21, 32, 33, 34, 21, 35,
+ 36, 21, 21, 37, 38, 38, 38, 38, 42, 45,
+ 48, 56, 86, 39, 50, 39, 130, 49, 46, 53,
+ 51, 52, 54, 87, 43, 57, 57, 55, 59, 60,
+ 62, 63, 69, 56, 66, 67, 92, 72, 75, 70,
+ 83, 80, 68, 88, 71, 73, 76, 81, 77, 89,
+ 78, 42, 84, 38, 38, 53, 94, 126, 54, 57,
+
+ 57, 127, 39, 124, 93, 105, 106, 43, 125, 42,
+ 181, 180, 43, 179, 178, 177, 176, 175, 174, 173,
+ 172, 171, 170, 169, 168, 43, 41, 41, 41, 41,
+ 64, 64, 64, 95, 95, 95, 95, 97, 97, 97,
+ 97, 99, 99, 167, 166, 165, 164, 163, 162, 161,
+ 160, 159, 158, 157, 156, 155, 154, 153, 152, 151,
+ 150, 149, 148, 147, 146, 145, 144, 143, 142, 141,
+ 140, 139, 138, 137, 136, 135, 134, 133, 132, 131,
+ 38, 38, 96, 129, 128, 123, 122, 121, 120, 119,
+ 118, 117, 116, 115, 114, 113, 112, 111, 110, 109,
+
+ 108, 107, 104, 103, 102, 101, 100, 98, 38, 96,
+ 91, 90, 85, 82, 79, 74, 65, 61, 58, 47,
+ 44, 40, 182, 3, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182
+ } ;
+
+static yyconst short int yy_chk[269] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 5, 5, 6, 6, 8, 10,
+ 12, 15, 33, 5, 13, 6, 188, 12, 10, 14,
+ 13, 13, 14, 33, 8, 16, 16, 14, 18, 18,
+ 20, 20, 24, 15, 23, 23, 37, 25, 27, 24,
+ 31, 29, 23, 34, 24, 25, 27, 29, 27, 34,
+ 27, 41, 31, 38, 38, 39, 43, 89, 39, 57,
+
+ 57, 89, 38, 88, 37, 69, 69, 41, 88, 94,
+ 178, 173, 43, 171, 170, 169, 167, 166, 164, 162,
+ 160, 159, 158, 155, 154, 94, 183, 183, 183, 183,
+ 184, 184, 184, 185, 185, 185, 185, 186, 186, 186,
+ 186, 187, 187, 151, 149, 148, 147, 143, 142, 141,
+ 139, 138, 137, 135, 132, 131, 129, 128, 126, 125,
+ 124, 123, 122, 121, 120, 118, 116, 114, 113, 112,
+ 111, 110, 109, 108, 107, 106, 105, 104, 103, 102,
+ 97, 96, 95, 91, 90, 87, 86, 85, 84, 83,
+ 82, 81, 79, 78, 77, 76, 75, 74, 73, 72,
+
+ 71, 70, 68, 67, 66, 63, 59, 56, 54, 53,
+ 36, 35, 32, 30, 28, 26, 22, 19, 17, 11,
+ 9, 7, 3, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 182, 182, 182, 182, 182, 182, 182, 182
+ } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "ninja.lex"
+#define INITIAL 0
+/* -*- Mode: C++; c-file-style: "bsd"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2001 Søren Sandmann (sandmann@daimi.au.dk)
+ *
+ * Author: Søren Sandmann
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#line 24 "ninja.lex"
+#include "ninja.hh"
+#include "parser.hh"
+
+ static int line = 1; // current line
+ static int pos = 1; // current position on line
+ static void set_position (); // updates yylval.token
+#define YY_NEVER_INTERACTIVE 1
+#define YY_NO_UNPUT 1
+#line 510 "lex.yy.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+ && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp = NULL, *yy_bp = NULL;
+ register int yy_act;
+
+#line 45 "ninja.lex"
+
+
+#line 664 "lex.yy.c"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 183 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 224 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+ yy_cp = yy_last_accepting_cpos;
+ yy_current_state = yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 47 "ninja.lex"
+{
+ set_position ();
+}
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 50 "ninja.lex"
+{
+ set_position ();
+ return T_BOOLEAN;
+}
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 54 "ninja.lex"
+{
+ set_position ();
+ return T_BREAK;
+}
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 58 "ninja.lex"
+{
+ set_position ();
+ return T_BYTE;
+}
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 62 "ninja.lex"
+{
+ set_position ();
+ return T_CASE;
+}
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 66 "ninja.lex"
+{
+ set_position ();
+ return T_CATCH;
+}
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 70 "ninja.lex"
+{
+ set_position ();
+ return T_CHAR;
+}
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 74 "ninja.lex"
+{
+ set_position ();
+ return T_CONTINUE;
+}
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 78 "ninja.lex"
+{
+ set_position ();
+ return T_DEFAULT;
+}
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 82 "ninja.lex"
+{
+ set_position ();
+ return T_DO;
+}
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 86 "ninja.lex"
+{
+ set_position ();
+ return T_DOUBLE;
+}
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 90 "ninja.lex"
+{
+ set_position ();
+ return T_ELSE;
+}
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 94 "ninja.lex"
+{
+ set_position ();
+ return T_FINALLY;
+}
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 98 "ninja.lex"
+{
+ set_position ();
+ return T_FLOAT;
+}
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 102 "ninja.lex"
+{
+ set_position ();
+ return T_FOR;
+}
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 106 "ninja.lex"
+{
+ set_position ();
+ return T_GOTO;
+}
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 110 "ninja.lex"
+{
+ set_position ();
+ return T_IF;
+}
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 114 "ninja.lex"
+{
+ set_position ();
+ return T_IN;
+}
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 118 "ninja.lex"
+{
+ set_position ();
+ return T_INT;
+}
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 122 "ninja.lex"
+{
+ set_position ();
+ return T_LONG;
+}
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 126 "ninja.lex"
+{
+ set_position ();
+ return T_NEW;
+}
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 130 "ninja.lex"
+{
+ set_position ();
+ return T_NULL;
+}
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 134 "ninja.lex"
+{
+ set_position ();
+ return T_SHORT;
+}
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 138 "ninja.lex"
+{
+ set_position ();
+ return T_SWITCH;
+}
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 142 "ninja.lex"
+{
+ set_position ();
+ return T_WHILE;
+}
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 146 "ninja.lex"
+{
+ set_position ();
+ return T_RETURN;
+}
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 150 "ninja.lex"
+{
+ set_position ();
+ return T_THIS;
+}
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 154 "ninja.lex"
+{
+ set_position ();
+ return T_VOID;
+}
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 158 "ninja.lex"
+{
+ set_position ();
+ return T_FALSE;
+}
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 162 "ninja.lex"
+{
+ set_position ();
+ return T_THROW;
+}
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 166 "ninja.lex"
+{
+ set_position ();
+ return T_THROWS;
+}
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 170 "ninja.lex"
+{
+ set_position ();
+ return T_TRUE;
+}
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 174 "ninja.lex"
+{
+ set_position ();
+ return T_TRY;
+}
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 178 "ninja.lex"
+{
+ set_position ();
+ return T_COLON_COLON;
+}
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 182 "ninja.lex"
+{
+ set_position ();
+ return T_ARROW;
+}
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 186 "ninja.lex"
+{
+ set_position ();
+ return T_LEQ;
+}
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 190 "ninja.lex"
+{
+ set_position ();
+ return T_GEQ;
+}
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 194 "ninja.lex"
+{
+ set_position ();
+ return T_PLUS_PLUS;
+}
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 198 "ninja.lex"
+{
+ set_position ();
+ return T_MINUS_MINUS;
+}
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 202 "ninja.lex"
+{
+ set_position ();
+ return T_PLUS_EQ;
+}
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 206 "ninja.lex"
+{
+ set_position ();
+ return T_MINUS_EQ;
+}
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 210 "ninja.lex"
+{
+ set_position ();
+ return T_MUL_EQ;
+}
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 214 "ninja.lex"
+{
+ set_position ();
+ return T_DIV_EQ;
+}
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 218 "ninja.lex"
+{
+ set_position ();
+ return T_MOD_EQ;
+}
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 222 "ninja.lex"
+{
+ set_position ();
+ return T_AND_EQ;
+}
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 226 "ninja.lex"
+{
+ set_position ();
+ return T_XOR_EQ;
+}
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 230 "ninja.lex"
+{
+ set_position ();
+ return T_OR_EQ;
+}
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 234 "ninja.lex"
+{
+ set_position ();
+ return T_SHL_EQ;
+}
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 238 "ninja.lex"
+{
+ set_position ();
+ return T_SHR_EQ;
+}
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 242 "ninja.lex"
+{
+ set_position ();
+ return T_OR_OR;
+}
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 246 "ninja.lex"
+{
+ set_position ();
+ return T_AND_AND;
+}
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 250 "ninja.lex"
+{
+ set_position ();
+ return T_EQ_EQ;
+}
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 254 "ninja.lex"
+{
+ set_position ();
+ return T_NOT_EQ;
+}
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 258 "ninja.lex"
+{
+ set_position ();
+ return T_SHL;
+}
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 262 "ninja.lex"
+{
+ set_position ();
+ return T_SHR;
+}
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 266 "ninja.lex"
+{
+ yylval.token.int_const = strtol (yytext, NULL, 0);
+ set_position ();
+ return T_INT_CONST;
+}
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 271 "ninja.lex"
+{
+ yylval.token.int_const = strtol (yytext, NULL, 0);
+ set_position ();
+ return T_INT_CONST;
+}
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 276 "ninja.lex"
+{
+ yylval.token.string_const = ninja_strdup (yytext + 1);
+ yylval.token.string_const [strlen (yylval.token.string_const) - 1] = '\0';
+
+ set_position ();
+ return T_STRING_CONST;
+}
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 283 "ninja.lex"
+{
+ yylval.token.string_const = ninja_strdup (yytext);
+ set_position ();
+ return T_IDENTIFIER;
+}
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 288 "ninja.lex"
+{
+ set_position ();
+ return *yytext;
+}
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 293 "ninja.lex"
+ECHO;
+ YY_BREAK
+#line 1237 "lex.yy.c"
+case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 183 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+ register char *yy_cp = yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yy_last_accepting_state = yy_current_state;
+ yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 183 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 182);
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+ {
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[
+ yy_current_buffer->yy_buf_size + 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+ }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ return EOF;
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+
+ return c;
+ }
+#endif /* YY_NO_INPUT */
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+ {
+ int len;
+ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( yy_str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+ {
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 293 "ninja.lex"
+
+
+static void
+set_position ()
+{
+ const char *s;
+
+ yylval.token.first_line = line;
+ yylval.token.first_char = pos;
+
+ for (s = yytext; *s != '\0'; ++s)
+ {
+ if (*s == '\n')
+ {
+ line++;
+ pos = 1;
+ }
+ else
+ pos++;
+ }
+
+ yylval.token.last_line = line;
+ yylval.token.last_char = pos;
+}
diff --git a/ex-display.h b/ex-display.h
new file mode 100644
index 0000000..f3e5cd1
--- /dev/null
+++ b/ex-display.h
@@ -0,0 +1,50 @@
+typedef struct ExDisplay ExDisplay;
+
+typedef enum
+{
+ EX_GARBAGE_FROM_SERVER, /* unparsable response */
+ EX_LOST_CONNECTION
+} ExFatalError;
+
+typedef void (* ExFatalErrorHandler) (ExDisplay *display,
+ ExFatalError error,
+ const char *detail);
+
+
+
+ExDisplay *ex_display_open (const char *display_name);
+void ex_display_close (ExDisplay *display);
+void ex_display_set_event_handler (ExDisplay *display,
+ ExEventHandler func);
+void ex_display_set_fatal_error_handler (ExDisplay *display,
+ ExFatalErrorHandler func);
+void ex_display_push_error_handler (ExDisplay *display,
+ ExErrorHandler func);
+void ex_display_pop_error_handler (ExDisplay *display);
+void ex_display_set_user_data (ExDisplay *display,
+ expointer data);
+expointer ex_display_get_user_data (ExDisplay *display);
+void ex_display_set_memory_vtable (ExDisplay *display,
+ ExMallocFunc malloc_,
+ ExMalloc0Func malloc0_,
+ ExReallocFunc realloc_
+ ExFreeFunc free_);
+
+/* main loop stuff */
+int ex_display_get_fd (ExDisplay *display);
+exboolean ex_display_iteration (ExDisplay *display,
+ exboolean may_block);
+exboolean ex_display_pending (ExDisplay *display);
+void ex_display_set_sync (ExDisplay *display,
+ exboolean sync);
+exboolean ex_display_get_sync (ExDisplay *display);
+exboolean ex_display_flush (ExDisplay *display,
+ exboolean may_block);
+void ex_display_sync (ExDisplay *display);
+
+
+
+/* internal */
+ExID ex_display_generate_xid (ExDisplay *display);
+void ex_display_release_xid (ExDisplay *display,
+ ExID id);
diff --git a/ex-queue.c b/ex-queue.c
new file mode 100644
index 0000000..b5ce752
--- /dev/null
+++ b/ex-queue.c
@@ -0,0 +1,23 @@
+#include "ex-queue.h"
+
+struct ExQueue
+{
+ int element_size;
+};
+
+ExQueue *
+ex_queue_new (int element_size)
+{
+
+}
+
+char * ex_queue_append (ExQueue *queue,
+ int n_elements);
+char * ex_queue_prepend (ExQueue *queue,
+ int n_elements);
+char * ex_queue_pop_head (ExQueue *queue,
+ int n_elements);
+char * ex_queue_pop_tail (ExQueue *queue,
+ int n_elements);
+void ex_queue_free (ExQueue *queue);
+int ex_queue_get_n_elements (ExQueue *queue);
diff --git a/ex-queue.h b/ex-queue.h
new file mode 100644
index 0000000..c6c8d03
--- /dev/null
+++ b/ex-queue.h
@@ -0,0 +1,15 @@
+typedef struct ExQueue ExQueue;
+
+ExQueue *ex_queue_new (int element_size);
+char * ex_queue_append (ExQueue *queue,
+ int n_elements);
+char * ex_queue_prepend (ExQueue *queue,
+ int n_elements);
+char * ex_queue_pop_head (ExQueue *queue,
+ int n_elements);
+char * ex_queue_pop_tail (ExQueue *queue,
+ int n_elements);
+void ex_queue_free (ExQueue *queue);
+int ex_queue_get_n_elements (ExQueue *queue);
+
+
diff --git a/exlcore.c b/exlcore.c
new file mode 100644
index 0000000..51eceaf
--- /dev/null
+++ b/exlcore.c
@@ -0,0 +1,96 @@
+#include "exlprivate.h"
+
+enum {
+ COPY_AREA = 8;
+};
+
+void
+exl_core_copy_area (ExlConnection *connection,
+ ExlCoreDrawable *src,
+ ExlCoreDrawable *dst,
+ ExlCoreGC *gc,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
+ int dst_x,
+ int dst_y)
+{
+ _exl_connection_write_request (
+ connection, COPY_AREA,
+ "XXXiiiiii", src, dst, gc, src_x, src_y, width, height, dst_x, dst_y);
+}
+
+ExlCoreWindow *
+exl_core_create_window (ExlConnection *connection,
+ ExlCoreWindow *parent,
+ ExlCoreWindowClass klass,
+ int depth,
+ ExlCoreVisual *visual,
+ int x,
+ int y,
+ int width,
+ int height,
+ int border_width,
+ ExlCoreWindowValueMask *mask,
+ ExlCoreWindowValues *values)
+{
+ ExlCoreWindow *window = _exl_connection_new_id (connection);
+
+ _exl_connection_write_request (
+ connection, CREATE_WINDOW,
+ "XXbXsssssiLi",
+ window, parent, depth, visual, x, y, width, height, border_width, bitmask);
+}
+
+typedef struct QueryTreeReply QueryTreeReply;
+struct QueryTreeReply
+{
+ ExlCoreQueryTreeReplyFunc reply_func
+ ExlCoreWindow * window;
+ ExlCoreWindow * parent;
+ int n_children;
+ ExlCoreWindow ** children;
+};
+
+static void
+exl_core_query_tree_reply (ExclConnection *connection,
+ const ExlError *err,
+ void *data)
+{
+ QueryTreeReply *reply = data;
+
+ reply->reply_func (
+ connection, err,
+ reply->window, reply->parent, reply->n_children, reply->children);
+
+ exl_free (reply);
+}
+
+void
+exl_core_query_tree (ExlConnection *connection,
+ ExlCoreWindow *window,
+ ExlCoreQueryTreeReplyFunc reply_func)
+{
+ QueryTreeReply *reply = exl_new (QueryTreeReply, 1);
+ int serial;
+
+ serial = _exl_connection_write_request (connection, QUERY_TREE, "X", window);
+ _exl_connection_add_reply_callback (
+ connection, reply,
+ "XXLX",
+ &(reply->root),
+ &(reply->parent),
+ &(reply->n_children),
+ &(reply->children));
+}
+
+
+void
+exl_core_intern_atom (ExlConnection *connection,
+ const char *name,
+ int only_if_exists)
+ ExlCore)
+{
+
+}
diff --git a/exlcore.h b/exlcore.h
new file mode 100644
index 0000000..44cf829
--- /dev/null
+++ b/exlcore.h
@@ -0,0 +1,35 @@
+typedef struct ExlCoreDrawable ExlCoreDrawable;
+typedef struct ExlCoreGC ExlCoreGC;
+
+typedef void (* ExlQueryTreeReplyFunc) (ExlConnection *connection,
+ ExlCoreWindow *window,
+ ExlCoreWindow *parent,
+ int n_children,
+ ExlCoreWindow **children);
+
+
+void exl_core_copy_area (ExlConnection *connection,
+ ExlCoreDrawable *src,
+ ExlCoreDrawable *dst,
+ ExlCoreGC *gc,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
+ int dst_x,
+ int dst_y);
+ExlCoreWindow *exl_core_create_window (ExlConnection *connection,
+ ExlCoreWindow *parent,
+ ExlCoreWindowClass klass,
+ int depth,
+ ExlCoreVisual *visual,
+ int x,
+ int y,
+ int width,
+ int height,
+ int border_width,
+ ExlCoreWindowValueMask *mask,
+ ExlCoreWindowValues *values);
+void exl_core_query_tree (ExlConnection *connection,
+ ExlCoreWindow *window,
+ ExlQueryTreeReplyFunc reply);
diff --git a/exlib-notes b/exlib-notes
new file mode 100644
index 0000000..2170292
--- /dev/null
+++ b/exlib-notes
@@ -0,0 +1,356 @@
+Notes on X library
+
+- maintain local stack of error handlers
+- maintain local queue of expected replies
+
+- init()
+ push_error_handler (default_error_handler)
+ [we will probably need a push_error_handler_unlocked()]
+
+- iterate (ex_boolean may_block):
+
+ LOCK();
+
+ if reply
+ {
+ look at expected replies
+ if there,
+ queue reply->func, display
+ remove it
+ queue decode()
+ else
+ complain
+ }
+ else if event
+ {
+ while next_expected_reply <= event.serial
+ queue complaint and remove reply
+
+ queue event();
+ }
+ else if error
+ {
+ while (next_expected_reply < error.serial)
+ queue complaint and remove reply
+
+ if (next expected reply matches == error.serial)
+ remove reply
+
+ pop_obsolete_handlers();
+
+ for (hnd = top; hnd; hnd = hnd->next)
+ {
+ if (error.serial >= item.begin_serial)
+ {
+ queue hnd.handler (error);
+ break;
+ }
+ }
+ }
+ else
+ {
+ queue_error ("garbage from server");
+ queue_close ("");
+ }
+
+ UNLOCK();
+
+ run queue(); /* note queue must be local / on stack */
+
+
+Error handling: /* what about wraparound? */
+
+ struct ErrorHandlerItem {
+ int begin_serial;
+ int end_serial;
+ ErrorHandler handler;
+ };
+
+ push()
+ {
+ pop_obsolete_handlers();
+ item = new Item
+ item.begin_serial = next_serial;
+ item.end_serial = MAX_INT;
+ item->next = current_handler;
+ }
+
+ pop()
+ {
+ if (!current_handler)
+ {
+ programmer_error ("pop without push");
+ return;
+ }
+ top_item.end_serial = next_serial;
+ }
+
+- flushing is application's response
+
+ /* if block is FALSE and this return FALSE, the application is
+ * expected to call select on the fd and call flush again
+ * when the fd selects writable
+ */
+
+ display_flush (display, boolean block)
+ {
+ write()
+ if (EAGAIN)
+ {
+ if (block)
+ select ();
+ write();
+ return TRUE;
+ else
+ return FALSE;
+ }
+ if (error)
+ {
+ queue_fatal_error();
+ return FALSE;
+ }
+ }
+
+
+- general stuff
+
+ ex_[display?]_set_lock(func, data)
+ ex_[display?]_set_unlock(func, data)
+
+ if func's are non-NULL, they'll be called around critical regions
+
+ ex_set_out_of_memory_func(); // can free stuff
+ // and return TRUE -> operation
+ // will be retried.
+ ex_set_malloc()
+ ex_set_free()
+
+- display methods
+
+ ex_display_set_event_func ()
+ ex_display_set_connection_closed_func(); // X server closed connection
+
+ ex_display_push_error_func ()
+ ex_display_pop_error_func ()
+
+
+
+protocol code:
+
+header:
+ typedef struct ExRenderPictureAttributes ExRenderPictureAttributes;
+
+ struct ExRenderPictureAttributes
+ {
+ int repeat;
+ ExRenderPicture * alpha_map;
+ int alpha_x_origin;
+ int alpha_y_origin;
+ int clip_x_origin;
+ int clip_y_origin;
+ ExCorePixmap * clip_mask;
+ int graphics_exposures;
+ };
+
+ typedef enum
+ {
+ EX_RENDER_PICTURE_REPEAT = 1 << 0,
+ EX_RENDER_PICTURE_ALPHA_MAP = 1 << 1,
+ EX_RENDER_PICTURE_ALPHA_Y_ORIGIN = 1 << 2,
+ EX_RENDER_PICTURE_ALPHA_X_ORIGIN = 1 << 3,
+ EX_RENDER_PICTURE_CLIP_X_ORIGIN = 1 << 4,
+ EX_RENDER_PICTURE_CLIP_Y_ORIGIN = 1 << 5,
+ EX_RENDER_PICTURE_CLIP_MASK = 1 << 6,
+ EX_RENDER_PICTURE_GRAPHICS_EXPOSURES = 1 << 7,
+ EX_RENDER_PICTURE_SUBWINDOW_MODE = 1 << 8,
+ EX_RENDER_PICTURE_POLY_EDGE = 1 << 9,
+ EX_RENDER_PICTURE_POLY_MODE = 1 << 10,
+ EX_RENDER_PICTURE_DITHER = 1 << 11,
+ EX_RENDER_PICTURE_COMPONENT_ALPHA = 1 << 12
+ } ExRenderPictureValueMask;
+
+.c:
+ static void
+ query_version_reply (ExDisplay *display,
+ ExRenderQueryVersionFunc func,
+ ex_pointer data)
+ {
+ int major, minor;
+
+ LOCK()
+
+ ex_display_read_reply (display, "uu", &major, &minor);
+
+ UNLOCK();
+
+ func (major, minor, data);
+ }
+
+ void
+ ex_render_query_version (ExDisplay *display,
+ int major,
+ int minor,
+ ExRenderQueryVersionFunc func,
+ ex_pointer data)
+ {
+ LOCK();
+
+ ex_display_send_request (display, "uu", major, minor);
+ ex_display_expect_reply (display, query_version_reply, func, data);
+
+ UNLOCK();
+ }
+
+ /* CreatePicture */
+
+ ExRenderPicture *
+ ex_render_create_picture (ExDisplay * display,
+ ExCoreDrawable * drawable,
+ ExRenderPictFormat * pict_format,
+ ExRenderPictureAttributes * attributes,
+ ExRenderPictureValueMask mask);
+
+ {
+ ExRenderPicture *picture;
+
+ LOCK();
+
+ picture = ex_display_new();
+
+ ex_display_send_request (display, "XXXB(bXssssXbbbb)",
+ drawable,
+ pict_format,
+ mask,
+ attributes->repeat,
+ attributes->alpha_map,
+ attributes->alpha_x_origin,
+ attributes->alpha_y_origin,
+ attributes->clip_x_origin,
+ attributes->clip_y_origin,
+ attributes->clip_mask,
+ attributes->graphics_exposures,
+ attributes->subwindow_mode,
+ attributes->poly_edge,
+ attributes->poly_mode,
+ attributes->dither);
+
+ UNLOCK();
+
+ return picture;
+ }
+
+ /* SetPictureClipRectangles */
+
+ void
+ ex_render_set_picture_rectangles (ExDisplay * display,
+ ExRenderPicture * picture,
+ int clip_x_origin,
+ int clip_y_origin,
+ int n_rectangles,
+ ExCoreRectangle * rectangles)
+ {
+ LOCK();
+ ex_display_send_request (display, "XssL(ssss)",
+ picture,
+ clip_x_origin,
+ clip_y_origin,
+ n_rectangles,
+ rectangles);
+ UNLOCK();
+ }
+
+
+
+- notes on format for generating protocl code
+
+ - "uses keyword" (extensions will generally use the types from core)
+
+ - some basic types (byte, short, card32, XID, possibly more)
+
+ - public and private types (public will be typedef'ed and appear in API,
+ private will be exploded) [not sure about this]
+
+ - type must have representations specified
+
+ - masked_list type (with defaults, component types must be public)
+
+ - list_of_blah type (blah must be public)
+
+ - enumerations (along with representation, if not specified, use
+ smallest possinle)
+
+ - namespaces (namespace ex { namespace render { ... } })
+
+ - errors, events, request
+
+ - lower case plus underscores, so all coding styles can be generated
+
+ - need some way to indicate that a given XID is created/destroyed
+
+ - union
+
+For RENDER:
+ namespace ex { namespace render {
+
+ /* errors */
+ error pict_format;
+ error picture;
+ error pict_op;
+ error glyph_set;
+ error glyph;
+
+ /* types */
+
+ type picture = XID;
+
+ type pict_type = enum { indexed, direct };
+
+ type pict_op = enum { clear, src, dst, over, over_reverse, in,
+ in_reverse, out, out_reverse, atop,
+ atop_reverse, xor, add, saturate };
+
+ type color = struct {
+ card16 red;
+ card16 green;
+ card16 blue;
+ card16 alpha;
+ };
+
+ ...
+
+ private type pict_depth = struct {
+ card8 depth
+ list[pict_visual] visuals
+ };
+ }}
+
+
+
+
+Highlevel notes:
+
+ - Target users are toolkit authors, Owen, TrollTech, Bill Spitzak, Carl Worth.
+ - smart people
+ - who understand X
+ - and intend to hide ExLib from the users
+
+ - In other words, the API docs are the protocol specs. The users will need that
+ anyway, and there is no point writing a watered down version of it
+
+ - Toolkits have their own main loop, ExLib should not try to provide its own
+ - Never send anything on our own, just queue up ontil toolkit flushes
+ - Hmm, trying to send when the buffer size reaches a threshold
+ may not be too bad, if we make sure not to block
+ - potential problem: app's could start using unbounded amounts
+ of memory when they lose connection. GTK+ fix by stopping
+ expose processing exposing when that happens. Perhaps simply
+ a mode "block/non-block"
+ - ExLib must never, ever block, not even for writes
+ The flush method should be
+ bool flush(bool blocking)
+ returning false if blocking is false and the operation would
+ block.
+ Rationale: an application that temprarily loses connection to
+ the X server should not have to block everything else.
+ - Just provide a file descriptor that can be selected on
+ - Provide round-trip free error handling.
diff --git a/exlib.h b/exlib.h
new file mode 100644
index 0000000..60b0ff4
--- /dev/null
+++ b/exlib.h
@@ -0,0 +1,23 @@
+typedef struct ExlConnection ExlConnection;
+typedef struct ExlEvent ExlEvent;
+
+typedef void (* ExlErrorFunction) (ExlConnection * connection,
+ ExlError * error);
+
+typedef void (* ExlEventFunction) (ExlConnection * connection,
+ ExlEvent * event);
+
+ExlConnection *exl_connection_new (const char *display);
+void exl_connection_close (ExlConnection *connection);
+void exl_connection_free (ExlConnection *connection);
+int exl_connection_get_fd (ExlConnection *connection);
+void exl_connection_set_event_function (ExlConnection *connection,
+ ExlEventFunction *event_function);
+void exl_connection_set_error_function (ExlConnection *connection,
+ ExlErrorFunction *error_function);
+void exl_connection_flush (ExlConnection *connection);
+void exl_connection_process_callbacks (ExlConnection *connection);
+
+#include <exl/exl-core.h>
+#include <exl/exl-render.h>
+#include <exl/exl-sync.h>
diff --git a/exlprivate.h b/exlprivate.h
new file mode 100644
index 0000000..21f437e
--- /dev/null
+++ b/exlprivate.h
@@ -0,0 +1,4 @@
+static void
+_exl_connection_write_request (ExlConnection *connection,
+ const char *format,
+ ...);
diff --git a/render.spec b/render.spec
new file mode 100644
index 0000000..a11378a
--- /dev/null
+++ b/render.spec
@@ -0,0 +1,138 @@
+uses core;
+
+namespace render [extension "RENDER"] {
+
+ /* errors */
+ error pict_format;
+ error picture;
+ error pict_op;
+ error glyph_set;
+ error glyph;
+
+ /* types */
+ type picture = xid;
+
+ type pict_type = enum {
+ indexed,
+ direct
+ };
+
+ type pict_op = enum {
+ clear, src, dst, over, over_reverse, in,
+ in_reverse, out, out_reverse, atop,
+ atop_reverse, xor, add, saturate
+ };
+
+ type color = struct
+ {
+ card16 red;
+ card16 green;
+ card16 blue;
+ card16 alpha;
+ };
+
+ type pict_depth = struct {
+ card8 depth;
+ list[pict_visual] visuals;
+ };
+
+ type subwindow_mode = enum {
+ clip_by_children,
+ include_inferiors
+ };
+
+ type glyph_set = xid;
+
+ type glyph = card32;
+
+ type glyph_info = struct {
+ card16 width;
+ card16 height;
+ int16 x;
+ int16 y;
+ int16 off_x;
+ int16 off_y;
+ };
+
+ type pict_glyph = struct {
+ glyph_info info;
+ int16 x, y;
+ };
+
+ type glyphable = union
+ {
+ glyphset glyphset;
+ fontable fontable;
+ };
+
+ type glyph_elt8 = struct
+ {
+ int16 dx, dy;
+ list[card8] glyphs;
+ };
+
+ type glyph_item8 = union
+ {
+ glyph_elt8 glyph_elt8;
+ glyphable glyphable;
+ };
+
+ type glyph_elt16 = struct
+ {
+ int16 dx, dy;
+ list[card16] glyphs;
+ };
+
+ type glyph_item16 = union
+ {
+ glyph_elt16 glyph_elt16;
+ glyphable glyphable;
+ };
+
+ type glyph_elt32 = struct
+ {
+ int16 dx, dy;
+ list[card32] glyphs;
+ };
+
+ type glyph_item32 = union {
+ glyph_elt32 glyph_elt32;
+ glyphable glyphable;
+ };
+
+ type picture_attributes = masked_list {
+ boolean repeat;
+ picture alpha_map;
+ int16 alpha_x_origin;
+ int16 alpha_y_origin;
+ int16 clip_x_origin;
+ int16 clip_y_origin;
+ picture clip_mask;
+ bool graphics_exposures;
+ subwindow_mode subwindow_mode; // ok, types != fields
+ poly_edge poly_edge;
+ poly_mode poly_mode;
+ atom dither;
+ boolean component_alpha;
+ };
+
+ /* requests */
+ request create_picture[1000] {
+ picture id *;
+ drawable drawable;
+ pict_format format;
+ picture_attributes attributes;
+
+ errors:
+ alloc, drawable, id_choice, match, picmap,
+ picture, pict_format, value
+ }
+
+ request query_pict_formats[23] {
+ reply:
+ pict_format fallback;
+ list[pict_form_info] formats;
+ list[pict_screen] screens;
+ }
+}
+}
diff --git a/xcore.spec b/xcore.spec
new file mode 100644
index 0000000..8be090d
--- /dev/null
+++ b/xcore.spec
@@ -0,0 +1,151 @@
+// Predefined types: BYTE, INT16, INT32, CARD8, CARD16, CARD32,
+// STRING8, ID
+
+namespace core {
+
+ error bad_request;
+
+ type event_mask = bits [~0xFE000000] {
+ key_press,
+ key_release,
+ button_press,
+ button_release,
+ enter_window,
+ leave_window,
+ pointer_motion,
+ pointer_motion_hint,
+ button1_motion,
+ button2_motion,
+ button3_motion,
+ button4_motion,
+ button5_motion,
+ button_motion,
+ keymap_state,
+ exposure,
+ visibility_change,
+ structure_notify,
+ resize_redirect,
+ structure_notify,
+ substructure_notify,
+ substructure_redirect,
+ focus_change,
+ property_change,
+ colormap_change,
+ owner_grab_button,
+ };
+
+ type pointer_event_mask = event_mask [~0xFFFF8003];
+ type device_event_mask = event_mask [~0xFFFFC0B0];
+
+ type bitmask = xid;
+ type window = xid;
+ type pixmap = xid;
+ type cursor = xid;
+ type font = xid;
+ type g_context = xid;
+ type colormap = xid;
+ type drawable = xid;
+ type fontable = xid;
+ type atom = xid;
+ type visual = xid;
+
+ type bit_gravity = enum {
+ forget, north_west, north, north_east, west,
+ center, east, south_west, south, south_east,
+ static,
+ };
+
+ type win_gravity = enum {
+ unmap, north_west, north, north_east, west,
+ center, east, south_west, south, south_east,
+ static
+ };
+
+ type key_but_mask = bits [~0xE000] {
+ shift, lock, control, mod1,
+ mod2, mod3, mod4, mod5,
+ button1, button2, button3, button4,
+ button5
+ }
+
+ type char_2b = struct {
+ card8 byte1;
+ card8 byte2;
+ };
+
+ type string16 = list[char_2b];
+
+ type point = struct {
+ int16 x, y;
+ };
+
+ type rectangle = struct {
+ int16 x, y;
+ card16 width, height;
+ };
+
+ type arc = struct {
+ int16 x, y;
+ card16 width, height;
+ int16 angle1, angle2;
+ };
+
+ type window_class = enum {
+ copy_from_parent,
+ input_output,
+ input_only,
+ };
+
+ /* more types needed ... */
+
+ /* events */
+ event key_press [1] {
+ window root;
+ window event_window;
+ window? child;
+ bool same_screen;
+ int16 root_x, root_y, event_x, event_y;
+ keycode keycode;
+ key_but_mask state;
+ timestamp time;
+ }
+
+ /* requests */
+ request create_window [1] {
+ card8 depth;
+ window wid *;
+ window parent;
+ int16 x, y;
+ card16 width, height;
+ card15 border_width;
+ window_class class;
+ visual visual;
+ }
+
+ request query_extension [100] {
+ string8 name;
+
+ reply:
+ boolean present;
+ card8 major_opcode;
+ card8 first_event;
+ card8 first_error;
+ };
+
+
+
+ /* events */
+
+ event key_release [1] {
+ window root;
+ window event_window;
+ window? child;
+ boolean same_screen;
+ int16 root_x, root_y, event_x, event_y;
+ keycode keycode;
+ key_but_mask state;
+ timestamp time;
+ }
+
+ error request_err;
+}