archive->nrefs = 1;
archive->format = -1;
- archive->parser = pakfire_parser_create(pakfire);
+ archive->parser = pakfire_parser_create(pakfire, NULL);
archive->signatures = NULL;
}
#include <pakfire/types.h>
-PakfireParser pakfire_parser_create(Pakfire pakfire);
+PakfireParser pakfire_parser_create(Pakfire pakfire, PakfireParser parser);
+PakfireParser pakfire_parser_ref(PakfireParser parser);
PakfireParser pakfire_parser_unref(PakfireParser parser);
int pakfire_parser_set_declaration(PakfireParser parser,
const char* name, const char* value);
int pakfire_parser_append_declaration(PakfireParser parser,
const char* name, const char* value);
+
+char* pakfire_parser_expand(PakfireParser parser,
+ const char* namespace, const char* value);
char* pakfire_parser_get(PakfireParser parser, const char* name);
+PakfireParser pakfire_parser_merge(PakfireParser parser1, PakfireParser parser2);
+
int pakfire_parser_read(PakfireParser parser, FILE* f);
#ifdef PAKFIRE_PRIVATE
char* value;
};
+struct pakfire_parser_declarations {
+ struct pakfire_parser_declaration** declarations;
+ unsigned int next;
+ unsigned int num;
+};
+
+struct pakfire_parser_declarations** pakfire_parser_declarations(size_t max);
+struct pakfire_parser_declaration* pakfire_parser_make_declaration(
+ enum pakfire_parser_declaration_operator operator, const char* name, const char* value);
+
int pakfire_parser_parse_data(PakfireParser parser, const char* data, size_t len);
#endif /* PAKFIRE_PRIVATE */
# parser
pakfire_parser_create;
+ pakfire_parser_expand;
pakfire_parser_get;
pakfire_parser_parse_data;
pakfire_parser_read;
+ pakfire_parser_ref;
pakfire_parser_unref;
# problem
struct _PakfireParser {
Pakfire pakfire;
+ struct _PakfireParser* parent;
int nrefs;
struct pakfire_parser_declaration** declarations;
unsigned int num_declarations;
};
-PAKFIRE_EXPORT PakfireParser pakfire_parser_create(Pakfire pakfire) {
+#if 0
+struct pakfire_parser_declarations** pakfire_parser_declarations(size_t num) {
+ struct pakfire_parser_declarations* declarations =
+ pakfire_calloc(1, sizeof(*declarations));
+
+
+ pakfire_calloc(num, sizeof(*declarations));
+
+
+
+ return declarations;
+}
+
+void pakfire_parser_declarations_free(struct pakfire_parser_declarations** declarations) {
+ for (unsigned int i = 0; i < declarations->num; i++) {
+ if (declarations->declarations[i])
+ pakfire_free(declarations->declarations[i]);
+ }
+
+ pakfire_free(declarations);
+}
+
+struct pakfire_parser_declaration* pakfire_parser_make_declaration(
+ enum pakfire_parser_declaration_operator operator, const char* name, const char* value) {
+ struct pakfire_parser_declaration* d = pakfire_calloc(1, sizeof(*d));
+
+ if (d) {
+ d->name = pakfire_strdup(name);
+ d->value = pakfire_strdup(value);
+ d->operation = operator;
+ }
+
+ return d;
+}
+#endif
+
+PAKFIRE_EXPORT PakfireParser pakfire_parser_create(Pakfire pakfire, PakfireParser parent) {
PakfireParser parser = pakfire_calloc(1, sizeof(*parser));
if (parser) {
parser->pakfire = pakfire_ref(pakfire);
+ // Store a reference to the parent parser if we have one
+ if (parent)
+ parser->parent = pakfire_parser_ref(parent);
+
parser->num_declarations = NUM_DECLARATIONS;
// Allocate a decent number of declarations
return parser;
}
+PAKFIRE_EXPORT PakfireParser pakfire_parser_ref(PakfireParser parser) {
+ ++parser->nrefs;
+
+ return parser;
+}
+
Pakfire pakfire_parser_get_pakfire(PakfireParser parser) {
return pakfire_ref(parser->pakfire);
}
pakfire_parser_free_declarations(parser->declarations, parser->num_declarations);
+ pakfire_parser_unref(parser->parent);
pakfire_unref(parser->pakfire);
pakfire_free(parser);
}
return d;
}
+ // If nothing was found, we will try finding a match in the parent parser
+ if (parser->parent)
+ return pakfire_parser_get_declaration(parser->parent, name);
+
return NULL;
}
if (!declaration || !declaration->value)
return NULL;
+ // Get namespace of variable we are expanding
+ char* namespace = pakfire_strdup(declaration->name);
+ pakfire_parser_strip_namespace(namespace);
+
+ // Expand the value
+ char* buffer = pakfire_parser_expand(parser, namespace, declaration->value);
+
+ // Cleanup
+ pakfire_free(namespace);
+
+ return buffer;
+}
+
+PAKFIRE_EXPORT char* pakfire_parser_expand(PakfireParser parser,
+ const char* namespace, const char* value) {
+ // Return NULL when the value is NULL
+ if (!value)
+ return NULL;
+
// Compile the regular expression
regex_t preg;
int r = regcomp(&preg, VARIABLE_PATTERN, REG_EXTENDED);
return NULL;
}
- // Get namespace of variable we are expanding
- char* namespace = pakfire_strdup(declaration->name);
- pakfire_parser_strip_namespace(namespace);
-
// Create a working copy of the string we are expanding
- char* buffer = pakfire_strdup(declaration->value);
+ char* buffer = pakfire_strdup(value);
const size_t max_groups = 2;
regmatch_t groups[max_groups];
const char* value = NULL;
if (v && v->value) {
+ DEBUG(parser->pakfire, "Replacing %%{%s} with %s = '%s'\n",
+ variable, v->name, v->value);
+
value = v->value;
+ } else {
+ DEBUG(parser->pakfire, "Replacing %%{%s} with an empty string\n",
+ variable);
}
- DEBUG(parser->pakfire, "Replacing %%{%s} with %s = '%s'\n",
- variable, v->name, value);
-
// Reset offsets to the whole matched string
start = groups[0].rm_so; end = groups[0].rm_eo;
return pakfire_parser_expand_declaration(parser, d);
}
+PAKFIRE_EXPORT PakfireParser pakfire_parser_merge(PakfireParser parser1, PakfireParser parser2) {
+ DEBUG(parser1->pakfire, "Merging parsers %p and %p\n", parser1, parser2);
+
+ if (parser2) {
+ for (unsigned int i = 0; i < parser2->num_declarations; i++) {
+ struct pakfire_parser_declaration* d = parser2->declarations[i];
+
+ if (d)
+ pakfire_parser_set_declaration(parser1, d->name, d->value);
+ }
+ }
+
+ return parser1;
+}
+
PAKFIRE_EXPORT int pakfire_parser_read(PakfireParser parser, FILE* f) {
char* data;
size_t len;
char* current_block = NULL;
static char* pakfire_parser_make_canonical_name(const char* name);
+
+enum operator {
+ OP_EQUALS = 0,
+};
+
+static PakfireParser new_parser(PakfireParser parent);
+static PakfireParser make_if_stmt(PakfireParser parser, const enum operator op,
+ const char* val1, const char* val2, PakfireParser block);
+
%}
%token T_APPEND
%type <string> word;
%type <string> words;
+%type <parser> assignment;
+%type <parser> block_assignments;
+%type <parser> block_assignment;
+%type <parser> if_stmt;
+
%precedence T_WORD
%left T_APPEND
%left T_ASSIGN
%union {
+ PakfireParser parser;
char* string;
}
if_stmt : T_IF T_WORD T_EQUALS T_WORD T_EOL block_assignments end
{
- printf("IF STATEMENT NOT EVALUATED, YET: %s %s\n", $2, $4);
+ $$ = make_if_stmt(parser, OP_EQUALS, $2, $4, $6);
+ pakfire_parser_unref($6);
};
block_opening : variable T_EOL
block : block_opening block_assignments block_closing;
block_assignments : block_assignments block_assignment
+ {
+ $$ = pakfire_parser_merge($1, $2);
+ pakfire_parser_unref($2);
+ }
| block_assignment;
block_assignment : assignment
| if_stmt
- | empty;
+ | empty
+ {
+ $$ = new_parser(parser);
+ };
assignment : variable T_ASSIGN value T_EOL
{
if (!name)
ABORT;
- int r = pakfire_parser_set_declaration(parser, name, $3);
+ // Allocate a new parser
+ // XXX should not inherit from parser
+ $$ = new_parser(parser);
+
+ int r = pakfire_parser_set_declaration($$, name, $3);
pakfire_free(name);
- if (r < 0)
+ if (r < 0) {
+ pakfire_parser_unref($$);
ABORT;
+ }
}
| variable T_APPEND value T_EOL
{
if (!name)
ABORT;
- int r = pakfire_parser_append_declaration(parser, name, $3);
+ // Allocate a new parser
+ // XXX should not inherit from parser
+ $$ = new_parser(parser);
+
+ int r = pakfire_parser_append_declaration($$, name, $3);
pakfire_free(name);
- if (r < 0)
+ if (r < 0) {
+ pakfire_parser_unref($$);
ABORT;
+ }
}
| define text end
{
if (!name)
ABORT;
- int r = pakfire_parser_set_declaration(parser, name, $2);
+ // Allocate a new parser
+ // XXX should not inherit from parser
+ $$ = new_parser(parser);
+
+ int r = pakfire_parser_set_declaration($$, name, $2);
pakfire_free(name);
- if (r < 0)
+ if (r < 0) {
+ pakfire_parser_unref($$);
ABORT;
+ }
};
define : T_DEFINE variable T_EOL
pakfire_unref(pakfire);
}
+
+static PakfireParser new_parser(PakfireParser parent) {
+ Pakfire pakfire = pakfire_parser_get_pakfire(parent);
+
+ PakfireParser parser = pakfire_parser_create(pakfire, parent);
+ pakfire_unref(pakfire);
+
+ return parser;
+}
+
+static PakfireParser make_if_stmt(PakfireParser parser, const enum operator op,
+ const char* val1, const char* val2, PakfireParser block) {
+ Pakfire pakfire = pakfire_parser_get_pakfire(parser);
+
+ switch (op) {
+ case OP_EQUALS:
+ DEBUG(pakfire, "Evaluating if statement: %s == %s?\n", val1, val2);
+ break;
+ }
+
+ const char* namespace = current_block;
+
+ // Expand values
+ char* v1 = pakfire_parser_expand(parser, namespace, val1);
+ char* v2 = pakfire_parser_expand(parser, namespace, val2);
+
+ PakfireParser result = NULL;
+
+ switch (op) {
+ case OP_EQUALS:
+ DEBUG(pakfire, " '%s' == '%s'?\n", v1, v2);
+
+ if (strcmp(v1, v2) == 0)
+ result = block;
+
+ break;
+ }
+
+ pakfire_unref(pakfire);
+ pakfire_free(v1);
+ pakfire_free(v2);
+
+ if (result)
+ result = pakfire_parser_ref(result);
+
+ return result;
+}
FILE* f = fopen(path, "r");
assert_return(f, EXIT_FAILURE);
- PakfireParser parser = pakfire_parser_create(t->pakfire);
+ PakfireParser parser = pakfire_parser_create(t->pakfire, NULL);
int r = pakfire_parser_read(parser, f);
assert_return(r == 0, EXIT_FAILURE);