--- /dev/null
+# Makefile for Email gateway CCL
+# Europagate, 1995
+#
+# $Log: Makefile,v $
+# Revision 1.1 1995/02/13 12:35:20 adam
+# First version of CCL. Qualifiers aren't handled yet.
+#
+SHELL=/bin/sh
+INCLUDE=-I../include
+CFLAGS=-g -Wall -pedantic -ansi
+CC=gcc
+TPROG1=cclsh
+LIB=../lib/ccl.a
+PO=cclfind.o ccltoken.o cclerrms.o
+CPP=cc -E
+DEFS=$(INCLUDE)
+
+all: $(TPROG1)
+
+$(TPROG1): $(TPROG1).o $(LIB) ../lib/util.a
+ $(CC) $(CFLAGS) -o $(TPROG1) $(TPROG1).o $(LIB) ../lib/util.a
+
+$(LIB): $(PO)
+ rm -f $(LIB)
+ ar qc $(LIB) $(PO)
+ ranlib $(LIB)
+
+.c.o:
+ $(CC) -c $(DEFS) $(CFLAGS) $<
+
+clean:
+ rm -f *.log *.[oa] $(TPROG1) $(TPROG2) core mon.out gmon.out errlist *~
+
+depend: depend2
+
+depend1:
+ mv Makefile Makefile.tmp
+ sed '/^#Depend/q' <Makefile.tmp >Makefile
+ $(CPP) $(INCLUDE) -M *.c >>Makefile
+ -rm Makefile.tmp
+
+depend2:
+ $(CPP) $(INCLUDE) -M *.c >.depend
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
+
+#Depend --- DOT NOT DELETE THIS LINE
--- /dev/null
+/* CCL - public header file
+ * Europagate, 1995
+ *
+ * $Log: ccl.h,v $
+ * Revision 1.1 1995/02/13 12:35:20 adam
+ * First version of CCL. Qualifiers aren't handled yet.
+ *
+ */
+
+#define CCL_ERR_OK 0
+#define CCL_ERR_TERM_EXPECTED 1
+#define CCL_ERR_RP_EXPECTED 2
+#define CCL_ERR_SETNAME_EXPECTED 3
+#define CCL_ERR_OP_EXPECTED 4
+#define CCL_ERR_BAD_RP 5
+
+void ccl_find_str (const char *str, int *error, int *pos);
+
+char *ccl_err_msg (int ccl_errno);
--- /dev/null
+/*
+ * Europagate, 1995
+ *
+ * $Log: cclerrms.c,v $
+ * Revision 1.1 1995/02/13 12:35:20 adam
+ * First version of CCL. Qualifiers aren't handled yet.
+ *
+ */
+
+char *err_msg_array[] = {
+ "Ok",
+ "Search word expected",
+ ") expected",
+ "Set name expected",
+ "Operator expected",
+ "Unbalanced )"
+};
+
+const char *ccl_err_msg (int ccl_errno)
+{
+ return err_msg_array[ccl_errno];
+}
--- /dev/null
+/* CCL find (to rpn conversion)
+ * Europagate, 1995
+ *
+ * $Log: cclfind.c,v $
+ * Revision 1.1 1995/02/13 12:35:20 adam
+ * First version of CCL. Qualifiers aren't handled yet.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "cclp.h"
+
+static struct ccl_token *look_token;
+static int ccl_error;
+
+#define KIND (look_token->kind)
+#define ADVANCE look_token = look_token->next
+#define ADVX(x) x=(x)->next
+
+static void strxcat (char *n, const char *src, int len)
+{
+ while (*n)
+ n++;
+ while (--len >= 0)
+ *n++ = *src++;
+ *n = '\0';
+}
+
+static char *copy_token_name (struct ccl_token *tp)
+{
+ char *str = malloc (tp->len + 1);
+ memcpy (str, tp->name, tp->len);
+ str[tp->len] = '\0';
+ return str;
+}
+
+static struct ccl_rpn_node *mk_node (enum rpn_node_kind kind)
+{
+ struct ccl_rpn_node *p;
+ p = malloc (sizeof(*p));
+ assert (p);
+ p->kind = kind;
+ return p;
+}
+
+void ccl_rpn_delete (struct ccl_rpn_node *rpn)
+{
+ if (!rpn)
+ return;
+ switch (rpn->kind)
+ {
+ case AND:
+ case OR:
+ case NOT:
+ ccl_rpn_delete (rpn->u.p[0]);
+ ccl_rpn_delete (rpn->u.p[1]);
+ break;
+ case TERM:
+ free (rpn->u.t.term);
+ /* attr list */
+ break;
+ case SET:
+ free (rpn->u.setname);
+ break;
+ case PROX:
+ ccl_rpn_delete (rpn->u.p[0]);
+ ccl_rpn_delete (rpn->u.p[1]);
+ break;
+ }
+ free (rpn);
+}
+
+static struct ccl_rpn_node *find_spec (void);
+
+static struct ccl_rpn_node *search_term (void)
+{
+ struct ccl_rpn_node *p;
+ struct ccl_token *lookahead = look_token;
+ int len = 0;
+
+ if (KIND != CCL_TOK_TERM)
+ {
+ ccl_error = CCL_ERR_TERM_EXPECTED;
+ return NULL;
+ }
+ while (lookahead->kind == CCL_TOK_TERM)
+ {
+ len += 1+lookahead->len;
+ lookahead = lookahead->next;
+ }
+ p = mk_node (TERM);
+ p->u.t.term = malloc (len);
+ p->u.t.attr_list = NULL;
+ p->u.t.term[0] = '\0';
+ assert (p->u.t.term);
+ strxcat (p->u.t.term, look_token->name, look_token->len);
+ ADVANCE;
+ while (KIND == CCL_TOK_TERM)
+ {
+ strcat (p->u.t.term, " ");
+ strxcat (p->u.t.term, look_token->name, look_token->len);
+ ADVANCE;
+ }
+ return p;
+}
+
+static struct ccl_rpn_node *qualifiers (struct ccl_token *la)
+{
+ assert (0);
+ return NULL;
+}
+
+static struct ccl_rpn_node *search_terms (void)
+{
+ struct ccl_rpn_node *p1, *p2, *pn;
+ p1 = search_term ();
+ if (!p1)
+ return NULL;
+ while (1)
+ {
+ if (KIND == CCL_TOK_PROX)
+ {
+ ADVANCE;
+ p2 = search_term ();
+ if (!p2)
+ {
+ ccl_rpn_delete (p1);
+ return NULL;
+ }
+ pn = mk_node (PROX);
+ pn->u.p[0] = p1;
+ pn->u.p[1] = p2;
+ p1 = pn;
+ }
+ else if (KIND == CCL_TOK_TERM)
+ {
+ p2 = search_term ();
+ if (!p2)
+ {
+ ccl_rpn_delete (p1);
+ return NULL;
+ }
+ pn = mk_node (PROX);
+ pn->u.p[0] = p1;
+ pn->u.p[1] = p2;
+ p1 = pn;
+ }
+ else
+ break;
+ }
+ return p1;
+}
+
+static struct ccl_rpn_node *search_elements (void)
+{
+ struct ccl_rpn_node *p1;
+ struct ccl_token *lookahead;
+ if (KIND == CCL_TOK_LP)
+ {
+ ADVANCE;
+ p1 = find_spec ();
+ if (!p1)
+ return NULL;
+ if (KIND != CCL_TOK_RP)
+ {
+ ccl_error = CCL_ERR_RP_EXPECTED;
+ ccl_rpn_delete (p1);
+ return NULL;
+ }
+ ADVANCE;
+ return p1;
+ }
+ else if (KIND == CCL_TOK_SET)
+ {
+ ADVANCE;
+ if (KIND != CCL_TOK_TERM)
+ {
+ ccl_error = CCL_ERR_SETNAME_EXPECTED;
+ return NULL;
+ }
+ p1 = mk_node (SET);
+ p1->u.setname = copy_token_name (look_token);
+ ADVANCE;
+ return p1;
+ }
+ lookahead = look_token;
+
+ while (lookahead->kind==CCL_TOK_TERM || lookahead->kind==CCL_TOK_COMMA)
+ lookahead = lookahead->next;
+ if (lookahead->kind == CCL_TOK_REL || lookahead->kind == CCL_TOK_EQ)
+ return qualifiers (lookahead);
+ return search_terms ();
+}
+
+static struct ccl_rpn_node *find_spec (void)
+{
+ struct ccl_rpn_node *p1, *p2, *pn;
+ if (!(p1 = search_elements ()))
+ return NULL;
+ while (1)
+ {
+ switch (KIND)
+ {
+ case CCL_TOK_AND:
+ ADVANCE;
+ p2 = search_elements ();
+ if (!p2)
+ {
+ ccl_rpn_delete (p1);
+ return NULL;
+ }
+ pn = mk_node (AND);
+ pn->u.p[0] = p1;
+ pn->u.p[1] = p2;
+ p1 = pn;
+ continue;
+ case CCL_TOK_OR:
+ ADVANCE;
+ p2 = search_elements ();
+ if (!p2)
+ {
+ ccl_rpn_delete (p1);
+ return NULL;
+ }
+ pn = mk_node (OR);
+ pn->u.p[0] = p1;
+ pn->u.p[1] = p2;
+ p1 = pn;
+ continue;
+ case CCL_TOK_NOT:
+ ADVANCE;
+ p2 = search_elements ();
+ if (!p2)
+ {
+ ccl_rpn_delete (p1);
+ return NULL;
+ }
+ pn = mk_node (NOT);
+ pn->u.p[0] = p1;
+ pn->u.p[1] = p2;
+ p1 = pn;
+ continue;
+ }
+ break;
+ }
+ return p1;
+}
+
+struct ccl_rpn_node *ccl_find (struct ccl_token *list,
+ int *error, const char **pos)
+{
+ struct ccl_rpn_node *p;
+
+ look_token = list;
+ p = find_spec ();
+ if (p && KIND != CCL_TOK_EOL)
+ {
+ if (KIND == CCL_TOK_RP)
+ ccl_error = CCL_ERR_BAD_RP;
+ else
+ ccl_error = CCL_ERR_OP_EXPECTED;
+ ccl_rpn_delete (p);
+ p = NULL;
+ }
+ *pos = look_token->name;
+ if (p)
+ *error = CCL_ERR_OK;
+ else
+ *error = ccl_error;
+ return p;
+}
+
+static void pr_tree (struct ccl_rpn_node *rpn)
+{
+ switch (rpn->kind)
+ {
+ case TERM:
+ printf ("\"%s\"", rpn->u.t.term);
+ break;
+ case AND:
+ printf ("(");
+ pr_tree (rpn->u.p[0]);
+ printf (") and (");
+ pr_tree (rpn->u.p[1]);
+ printf (")");
+ break;
+ case OR:
+ printf ("(");
+ pr_tree (rpn->u.p[0]);
+ printf (") or (");
+ pr_tree (rpn->u.p[1]);
+ printf (")");
+ break;
+ case NOT:
+ printf ("(");
+ pr_tree (rpn->u.p[0]);
+ printf (") not (");
+ pr_tree (rpn->u.p[1]);
+ printf (")");
+ break;
+ case SET:
+ printf ("set=%s", rpn->u.setname);
+ break;
+ case PROX:
+ printf ("(");
+ pr_tree (rpn->u.p[0]);
+ printf (") prox (");
+ pr_tree (rpn->u.p[1]);
+ printf (")");
+ break;
+ default:
+ assert (0);
+ }
+}
+
+void ccl_find_str (const char *str, int *error, int *pos)
+{
+ struct ccl_token *list, *li;
+ struct ccl_rpn_node *rpn;
+ const char *char_pos;
+
+ list = ccl_tokenize (str);
+#if 0
+ for (li = list; li; li = li->next)
+ printf ("kind=%d, str='%.*s'\n", li->kind, li->len, li->name);
+#endif
+ rpn = ccl_find (list, error, &char_pos);
+ if (! *error)
+ {
+ pr_tree (rpn);
+ printf ("\n");
+ }
+ else
+ {
+ *pos = char_pos - str;
+ }
+}
--- /dev/null
+/* CCL - private header file
+ * Europagate, 1995
+ *
+ * $Log: cclp.h,v $
+ * Revision 1.1 1995/02/13 12:35:20 adam
+ * First version of CCL. Qualifiers aren't handled yet.
+ *
+ */
+
+#include "ccl.h"
+
+#define CCL_TOK_EOL 0
+#define CCL_TOK_TERM 1
+#define CCL_TOK_REL 2
+#define CCL_TOK_EQ 3
+#define CCL_TOK_PROX 4
+#define CCL_TOK_LP 5
+#define CCL_TOK_RP 6
+#define CCL_TOK_COMMA 7
+#define CCL_TOK_AND 8
+#define CCL_TOK_OR 7
+#define CCL_TOK_NOT 9
+#define CCL_TOK_MINUS 10
+#define CCL_TOK_SET 11
+
+struct ccl_token {
+ char kind;
+ char len;
+ const char *name;
+ struct ccl_token *next;
+ struct ccl_token *prev;
+};
+
+struct ccl_rpn_attr {
+ struct ccl_rpn_attr *next;
+ int name;
+ int value;
+};
+
+struct ccl_rpn_node {
+ enum rpn_node_kind { AND, OR, NOT, TERM, SET, PROX } kind;
+ union {
+ struct ccl_rpn_node *p[2];
+ struct {
+ char *term;
+ struct ccl_rpn_attr *attr_list;
+ } t;
+ char *setname;
+ } u;
+};
+
+struct ccl_token *ccl_tokenize (const char *command);
+void ccl_rpn_delete (struct ccl_rpn_node *rpn);
--- /dev/null
+/* CCL shell.
+ * Europagate 1995
+ *
+ * $Log: cclsh.c,v $
+ * Revision 1.1 1995/02/13 12:35:21 adam
+ * First version of CCL. Qualifiers aren't handled yet.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ccl.h"
+
+static int debug = 0;
+static char *prog;
+
+int main (int argc, char **argv)
+{
+ prog = *argv;
+ while (--argc > 0)
+ {
+ ++argv;
+ if (**++argv == '-')
+ {
+ switch (argv[0][1])
+ {
+ case 'd':
+ debug = 1;
+ break;
+ default:
+ fprintf (stderr, "%s: unknown option '%s'\n",
+ prog, *argv);
+ exit (1);
+ }
+ }
+ else
+ {
+ fprintf (stderr, "%s: no filenames, please\n", prog);
+ exit (1);
+ }
+ }
+ while (1)
+ {
+ char buf[80];
+ int error;
+ int pos;
+ printf ("CCLSH>"); fflush (stdout);
+ if (!fgets (buf, 79, stdin))
+ break;
+ ccl_find_str (buf, &error, &pos);
+ if (error)
+ {
+ printf ("%*s^ - ", 6+pos, " ");
+ printf ("%s\n", ccl_err_msg (error));
+
+ }
+ }
+ return 0;
+}
+
+
--- /dev/null
+/* CCL - lexical analysis
+ * Europagate, 1995
+ *
+ * $Log: ccltoken.c,v $
+ * Revision 1.1 1995/02/13 12:35:21 adam
+ * First version of CCL. Qualifiers aren't handled yet.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "cclp.h"
+
+static int strin (const char *s, const char *cset)
+{
+ while (*cset)
+ {
+ if (*cset++ == *s)
+ return 1;
+ }
+ return 0;
+}
+
+char *ccl_token_and = "and";
+char *ccl_token_or = "or";
+char *ccl_token_not = "not";
+char *ccl_token_set = "set";
+
+struct ccl_token *ccl_tokenize (const char *command)
+{
+ const char *cp = command;
+ struct ccl_token *first = NULL;
+ struct ccl_token *last = NULL;
+
+ while (1)
+ {
+ while (*cp && strin (cp, " \t\r\n"))
+ {
+ cp++;
+ continue;
+ }
+ if (!first)
+ {
+ first = last = malloc (sizeof (*first));
+ assert (first);
+ last->prev = NULL;
+ }
+ else
+ {
+ last->next = malloc (sizeof(*first));
+ assert (last->next);
+ last->next->prev = last;
+ last = last->next;
+ }
+ last->next = NULL;
+ last->name = cp;
+ last->len = 1;
+ switch (*cp++)
+ {
+ case '\0':
+ last->kind = CCL_TOK_EOL;
+ return first;
+ case '(':
+ last->kind = CCL_TOK_LP;
+ break;
+ case ')':
+ last->kind = CCL_TOK_RP;
+ break;
+ case ',':
+ last->kind = CCL_TOK_COMMA;
+ break;
+ case '%':
+ case '!':
+ last->kind = CCL_TOK_PROX;
+ while (*cp == '%' || *cp == '!')
+ {
+ ++ last->len;
+ cp++;
+ }
+ break;
+ case '>':
+ case '<':
+ case '=':
+ if (*cp == '=' || *cp == '<' || *cp == '>')
+ {
+ cp++;
+ last->kind = CCL_TOK_REL;
+ ++ last->len;
+ }
+ else if (cp[-1] == '=')
+ last->kind = CCL_TOK_EQ;
+ else
+ last->kind = CCL_TOK_REL;
+ break;
+ case '-':
+ last->kind = CCL_TOK_MINUS;
+ break;
+ case '\"':
+ last->kind = CCL_TOK_TERM;
+ last->name = cp;
+ last->len = 0;
+ while (*cp && *cp != '\"')
+ {
+ cp++;
+ ++ last->len;
+ }
+ if (*cp == '\"')
+ cp++;
+ break;
+ default:
+ while (*cp && !strin (cp, "(),%!><=- \t\n\r"))
+ {
+ cp++;
+ ++ last->len;
+ }
+ if (strlen (ccl_token_and)==last->len &&
+ !memcmp (ccl_token_and, last->name, last->len))
+ last->kind = CCL_TOK_AND;
+ else if (strlen (ccl_token_or)==last->len &&
+ !memcmp (ccl_token_or, last->name, last->len))
+ last->kind = CCL_TOK_OR;
+ else if (strlen (ccl_token_not)==last->len &&
+ !memcmp (ccl_token_not, last->name, last->len))
+ last->kind = CCL_TOK_NOT;
+ else if (strlen (ccl_token_set)==last->len &&
+ !memcmp (ccl_token_set, last->name, last->len))
+ last->kind = CCL_TOK_SET;
+ else
+ last->kind = CCL_TOK_TERM;
+ }
+ }
+ return first;
+}