* (C) 2001 Ximian, Inc.
*/
+#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#include <ctype.h>
#include <assert.h>
#include <stdarg.h>
char *text;
int ivalue;
Tree *tree;
+ Rule *rule;
+ GList *rule_list;
}
%token <text> IDENT
%token <text> CODE
%token <text> STRING
%token START
+%token COST
%token TERM
+%token TERMPREFIX
%token <ivalue> INTEGER
%type <tree> tree
%type <text> optcost
+%type <text> optcfunc
%type <text> optcode
+%type <rule> rule
+%type <rule_list> rule_list
%%
decls : /* empty */
| START IDENT { start_nonterm ($2); } decls
| TERM tlist decls
- | IDENT ':' tree optcost optcode { create_rule ($1, $3, $5, $4); } decls
+ | TERMPREFIX plist decls
+ | rule_list optcost optcode optcfunc {
+ GList *tmp;
+ for (tmp = $1; tmp; tmp = tmp->next) {
+ rule_add (tmp->data, $3, $2, $4);
+ }
+ g_list_free ($1);
+ } decls
;
-optcode : /* empty */ { $$ = NULL }
+rule : IDENT ':' tree { $$ = make_rule ($1, $3); }
+ ;
+
+rule_list : rule { $$ = g_list_append (NULL, $1); }
+ | rule ',' rule_list { $$ = g_list_prepend ($3, $1); }
+ ;
+
+optcode : /* empty */ { $$ = NULL; }
| CODE
;
+plist : /* empty */
+ | plist IDENT { create_term_prefix ($2);}
+ ;
+
tlist : /* empty */
| tlist IDENT { create_term ($2, -1);}
| tlist IDENT '=' INTEGER { create_term ($2, $4); }
| IDENT '(' tree ',' tree ')' { $$ = create_tree ($1, $3, $5); }
;
-optcost : /* empty */ {$$ = "0"; }
+optcost : /* empty */ {$$ = NULL; }
| STRING
| INTEGER { $$ = g_strdup_printf ("%d", $1); }
;
+optcfunc : /*empty */ { $$ = NULL; }
+ | COST CODE { $$ = $2; }
+ ;
%%
-static char *
-strndup (const char *s, int n)
-{
- char *ns = malloc (n + 1);
- strncpy (ns, s, n);
- ns [n + 1] = '\0';
- return ns;
-}
-
static char input[2048];
static char *next = input;
exit (-1);
}
+static int state = 0;
+
+void
+reset_parser ()
+{
+ state = 0;
+}
+
+struct pplist {
+ struct pplist *next;
+ gboolean ignore;
+};
+
+static struct pplist *pp = NULL;
+
+static char*
+getvar (const char *input)
+{
+ char *var = g_strchug (g_strdup (input));
+ char *ptr;
+
+ for (ptr = var; *ptr && *ptr != '\n'; ++ptr) {
+ if (g_ascii_isspace (*ptr)) {
+ break;
+ }
+ }
+ *ptr = '\0';
+
+ return var;
+}
+
+static void
+push_if (char *input, gboolean flip)
+{
+ struct pplist *new_pp = g_new (struct pplist, 1);
+ char *var = getvar (input);
+
+ new_pp->ignore = (g_hash_table_lookup (definedvars, var) == NULL) ^ flip;
+ new_pp->next = pp;
+
+ new_pp->ignore |= (pp ? pp->ignore : 0);
+ pp = new_pp;
+ g_free (var);
+}
+
+static void
+flip_if ()
+{
+ if (!pp)
+ yyerror ("%%else without %%if");
+
+ pp->ignore = !pp->ignore | (pp->next ? pp->next->ignore : 0);
+}
+
+static void
+pop_if ()
+{
+ struct pplist *prev_pp = pp;
+
+ if (!pp)
+ yyerror ("%%endif without %%if");
+
+ pp = pp->next;
+ g_free (prev_pp);
+}
+
static char
nextchar ()
{
- static int state = 0;
int next_state ;
gboolean ll;
if (!fgets (input, sizeof (input), inputfd))
return 0;
- ll = (input [0] == '%' && input [1] == '%' && isspace (input [2]));
+ ll = (input [0] == '%' && input [1] == '%');
next_state = state;
+ if (state == 1) {
+ if (!ll && input [0] == '%') {
+ if (!strncmp (&input [1], "ifdef", 5)) {
+ push_if (&input [6], FALSE);
+ ll = TRUE;
+ continue;
+ }
+ else if (!strncmp (&input [1], "ifndef", 6)) {
+ push_if (&input [7], TRUE);
+ ll = TRUE;
+ continue;
+ }
+ else if (!strncmp (&input [1], "else", 4)) {
+ flip_if ();
+ ll = TRUE;
+ continue;
+ }
+ else if (!strncmp (&input [1], "endif", 5)) {
+ pop_if ();
+ ll = TRUE;
+ continue;
+ }
+ }
+ if (pp && pp->ignore) {
+ ll = TRUE;
+ continue;
+ }
+ }
+
switch (state) {
case 0:
if (ll) {
next_state = 1;
- } else
- fputs (input, stdout);
+ } else
+ fputs (input, outputfd);
break;
case 1:
- if (ll)
+ if (ll) {
next_state = 2;
+ *next = 0;
+ }
break;
default:
return 0;
void
yyparsetail (void)
{
- fputs (input, stdout);
+ fputs (input, outputfd);
while (fgets (input, sizeof (input), inputfd))
- fputs (input, stdout);
+ fputs (input, outputfd);
+ input [0] = '\0';
}
int
return START;
}
+ if (!strncmp (next, "termprefix", 10) && isspace (next[10])) {
+ next += 10;
+ return TERMPREFIX;
+ }
+
if (!strncmp (next, "term", 4) && isspace (next[4])) {
next += 4;
return TERM;
do {
num = 10*num + (c - '0');
- } while ((c = isdigit (*next++)));
+ } while (isdigit (c = (*next++)));
yylval.ivalue = num;
return INTEGER;
char *n = next;
int l;
- //if (!strncmp (next - 1, "cost", 4) && isspace (next[3])) {
- //next += 4;
- //return COST;
- //}
+ if (!strncmp (next - 1, "cost", 4) && isspace (next[3])) {
+ next += 4;
+ return COST;
+ }
- while (isalpha (*n) || isdigit (*n) || (*n == '_'))
+ while (isalpha (*n) || isdigit (*n) || *n == '_')
n++;
l = n - next + 1;
- yylval.text = strndup (next - 1, l);
- next += l - 1;
-
+ yylval.text = g_strndup (next - 1, l);
+ next = n;
return IDENT;
}
while ((c = *next++) != '"' && c)
buf [i++] = c;
- buf [--i] = '\0';
- yylval.text = strdup (buf);
+ buf [i] = '\0';
+ yylval.text = g_strdup (buf);
return STRING;
}
case '{': d++; break;
case '}': d--; break;
default:
+ break;
}
}
buf [--i] = '\0';
- yylval.text = strdup (buf);
+ yylval.text = g_strdup (buf);
return CODE;
}