IPPFIND_OP_LIST, /* List when true */
IPPFIND_OP_PRINT_NAME, /* Print URI when true */
IPPFIND_OP_PRINT_URI, /* Print name when true */
- IPPFIND_OP_QUIET, /* No output when true */
+ IPPFIND_OP_QUIET /* No output when true */
} ippfind_op_t;
typedef struct ippfind_expr_s /* Expression */
/* Expression tree */
*temp = NULL, /* New expression */
*parent = NULL, /* Parent expression */
- *current = NULL;/* Current expression */
+ *current = NULL,/* Current expression */
+ *parens[100]; /* Markers for parenthesis */
+ int num_parens = 0; /* Number of parenthesis */
ippfind_op_t logic = IPPFIND_OP_AND;
/* Logic for next expression */
int invert = 0; /* Invert expression? */
if (!strcmp(argv[i], "--and"))
{
- if (logic != IPPFIND_OP_AND && current && current->prev)
- {
- /*
- * OK, we have more than 1 rule in the current tree level.
- * Make a new group tree and move the previous rule to it...
- */
-
- if ((temp = new_expr(IPPFIND_OP_AND, 0, NULL, NULL, NULL)) == NULL)
- return (IPPFIND_EXIT_MEMORY);
-
- temp->child = current;
- temp->parent = current->parent;
- current->prev->next = temp;
- temp->prev = current->prev;
+ if (logic == IPPFIND_OP_OR)
+ {
+ _cupsLangPuts(stderr, _("ippfind: Cannot use --and after --or."));
+ show_usage();
+ }
- current->prev = NULL;
- current->parent = temp;
- parent = temp;
- }
- else if (parent)
- parent->op = IPPFIND_OP_AND;
+ if (!current)
+ {
+ _cupsLangPuts(stderr,
+ _("ippfind: Missing expression before \"--and\"."));
+ show_usage();
+ }
- logic = IPPFIND_OP_AND;
- temp = NULL;
+ temp = NULL;
}
else if (!strcmp(argv[i], "--domain"))
{
}
else if (!strcmp(argv[i], "--or"))
{
- if (logic != IPPFIND_OP_OR && current)
+ if (!current)
+ {
+ _cupsLangPuts(stderr,
+ _("ippfind: Missing expression before \"--or\"."));
+ show_usage();
+ }
+
+ logic = IPPFIND_OP_OR;
+
+ if (parent && parent->op == IPPFIND_OP_OR)
+ {
+ /*
+ * Already setup to do "foo --or bar --or baz"...
+ */
+
+ temp = NULL;
+ }
+ else if (!current->prev && parent)
+ {
+ /*
+ * Change parent node into an OR node...
+ */
+
+ parent->op = IPPFIND_OP_OR;
+ temp = NULL;
+ }
+ else if (!current->prev)
+ {
+ /*
+ * Need to group "current" in a new OR node...
+ */
+
+ if ((temp = new_expr(IPPFIND_OP_OR, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+
+ temp->parent = parent;
+ temp->child = current;
+ current->parent = temp;
+
+ if (parent)
+ parent->child = temp;
+ else
+ expressions = temp;
+
+ parent = temp;
+ temp = NULL;
+ }
+ else
{
/*
- * OK, we have two possibilities; either this is the top-level
- * rule or we have a bunch of AND rules at this level.
+ * Need to group previous expressions in an AND node, and then
+ * put that in an OR node...
*/
- if (!parent)
+ if ((temp = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+
+ while (current->prev)
{
- /*
- * This is the top-level rule; we have to group *all* of the AND
- * rules down a level, as AND has precedence over OR.
- */
+ current->parent = temp;
+ current = current->prev;
+ }
- if ((temp = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
- NULL)) == NULL)
- return (IPPFIND_EXIT_MEMORY);
+ current->parent = temp;
+ temp->child = current;
+ current = temp;
- while (current->prev)
- {
- current->parent = temp;
- current = current->prev;
- }
+ if ((temp = new_expr(IPPFIND_OP_OR, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
- current->parent = temp;
- temp->child = current;
+ temp->parent = parent;
+ current->parent = temp;
- expressions = current = temp;
- }
- else
- {
- /*
- * This isn't the top rule, so go up one level...
- */
+ if (parent)
+ parent->child = temp;
+ else
+ expressions = temp;
- current = parent;
- parent = current->parent;
- }
+ parent = temp;
+ temp = NULL;
}
-
- logic = IPPFIND_OP_OR;
- temp = NULL;
}
else if (!strcmp(argv[i], "--path"))
{
* Add new expression...
*/
+ if (logic == IPPFIND_OP_AND &&
+ current && current->prev &&
+ parent && parent->op != IPPFIND_OP_AND)
+ {
+ /*
+ * Need to re-group "current" in a new AND node...
+ */
+
+ ippfind_expr_t *tempand; /* Temporary AND node */
+
+ if ((tempand = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+
+ /*
+ * Replace "current" with new AND node at the end of this list...
+ */
+
+ current->prev->next = tempand;
+ tempand->prev = current->prev;
+ tempand->parent = parent;
+
+ /*
+ * Add "current to the new AND node...
+ */
+
+ tempand->child = current;
+ current->parent = tempand;
+ current->prev = NULL;
+ parent = tempand;
+ }
+
+ /*
+ * Add the new node at current level...
+ */
+
if (current)
{
temp->parent = parent;
temp->prev = current;
current = temp;
invert = 0;
+ logic = IPPFIND_OP_AND;
temp = NULL;
}
}
* Add new expression...
*/
+ if (logic == IPPFIND_OP_AND &&
+ current && current->prev &&
+ parent && parent->op != IPPFIND_OP_AND)
+ {
+ /*
+ * Need to re-group "current" in a new AND node...
+ */
+
+ ippfind_expr_t *tempand; /* Temporary AND node */
+
+ if ((tempand = new_expr(IPPFIND_OP_AND, 0, NULL, NULL,
+ NULL)) == NULL)
+ return (IPPFIND_EXIT_MEMORY);
+
+ /*
+ * Replace "current" with new AND node at the end of this list...
+ */
+
+ current->prev->next = tempand;
+ tempand->prev = current->prev;
+ tempand->parent = parent;
+
+ /*
+ * Add "current to the new AND node...
+ */
+
+ tempand->child = current;
+ current->parent = tempand;
+ current->prev = NULL;
+ parent = tempand;
+ }
+
+ /*
+ * Add the new node at current level...
+ */
+
if (current)
{
temp->parent = parent;
temp->prev = current;
current = temp;
invert = 0;
+ logic = IPPFIND_OP_AND;
temp = NULL;
}
}
}
else if (!strcmp(argv[i], "("))
{
+ if (num_parens >= 100)
+ {
+ _cupsLangPuts(stderr, _("ippfind: Too many parenthesis."));
+ show_usage();
+ }
+
if ((temp = new_expr(IPPFIND_OP_AND, invert, NULL, NULL, NULL)) == NULL)
return (IPPFIND_EXIT_MEMORY);
+ parens[num_parens++] = temp;
+
if (current)
{
temp->parent = current->parent;
current->next = temp;
+ temp->prev = current;
}
else
expressions = temp;
- temp->prev = current;
- parent = temp;
- current = NULL;
- invert = 0;
- logic = IPPFIND_OP_AND;
+ parent = temp;
+ current = NULL;
+ invert = 0;
+ logic = IPPFIND_OP_AND;
}
else if (!strcmp(argv[i], ")"))
{
- if (!parent)
+ if (num_parens <= 0)
{
_cupsLangPuts(stderr, _("ippfind: Missing open parenthesis."));
show_usage();
}
- current = parent;
+ current = parens[--num_parens];
parent = current->parent;
-
- if (!parent)
- logic = IPPFIND_OP_AND;
- else
- logic = parent->op;
+ invert = 0;
+ logic = IPPFIND_OP_AND;
}
else if (!strcmp(argv[i], "!"))
{
}
}
- if (parent)
+ if (num_parens > 0)
{
_cupsLangPuts(stderr, _("ippfind: Missing close parenthesis."));
show_usage();
}
- if (cupsArrayCount(searches) == 0)
- {
- /*
- * Add an implicit browse for IPP printers ("_ipp._tcp")...
- */
-
- cupsArrayAdd(searches, "_ipp._tcp");
- }
-
if (!have_output)
{
/*
if (current)
{
- temp->parent = parent;
+ while (current->parent)
+ current = current->parent;
+
current->next = temp;
+ temp->prev = current;
}
else
expressions = temp;
+ }
+
+ if (cupsArrayCount(searches) == 0)
+ {
+ /*
+ * Add an implicit browse for IPP printers ("_ipp._tcp")...
+ */
+
+ cupsArrayAdd(searches, "_ipp._tcp");
+ }
+
+ if (getenv("IPPFIND_DEBUG"))
+ {
+ int indent = 4; /* Indentation */
+ static const char * const ops[] =
+ {
+ "NONE",
+ "AND",
+ "OR",
+ "TRUE",
+ "FALSE",
+ "IS_LOCAL",
+ "IS_REMOTE",
+ "DOMAIN_REGEX",
+ "NAME_REGEX",
+ "HOST_REGEX",
+ "PORT_RANGE",
+ "PATH_REGEX",
+ "TXT_EXISTS",
+ "TXT_REGEX",
+ "URI_REGEX",
+ "EXEC",
+ "LIST",
+ "PRINT_NAME",
+ "PRINT_URI",
+ "QUIET"
+ };
+
+ puts("Expression tree:");
+ current = expressions;
+ while (current)
+ {
+ /*
+ * Print the current node...
+ */
+
+ printf("%*s%s%s\n", indent, "", current->invert ? "!" : "",
+ ops[current->op]);
+
+ /*
+ * Advance to the next node...
+ */
+
+ if (current->child)
+ {
+ current = current->child;
+ indent += 4;
+ }
+ else if (current->next)
+ current = current->next;
+ else if (current->parent)
+ {
+ current = current->parent->next;
+ indent -= 4;
+ }
+ else
+ current = NULL;
+ }
- temp->prev = current;
+ puts("\nSearch items:");
+ for (search = (const char *)cupsArrayFirst(searches);
+ search;
+ search = (const char *)cupsArrayNext(searches))
+ printf(" %s\n", search);
}
/*