Minor adjustments
[yaz-moved-to-github.git] / retrieval / d1_doespec.c
1 /*
2  * Copyright (c) 1995, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: d1_doespec.c,v $
7  * Revision 1.2  1995-11-01 13:54:45  quinn
8  * Minor adjustments
9  *
10  * Revision 1.1  1995/11/01  11:56:07  quinn
11  * Added Retrieval (data management) functions en masse.
12  *
13  *
14  */
15
16
17 #include <assert.h>
18 #include <log.h>
19 #include <proto.h>
20 #include <data1.h>
21
22 static int match_children(data1_node *n, Z_ETagUnit **t, int num);
23
24 static int match_children_wildpath(data1_node *n, Z_ETagUnit **t, int num)
25 {return 0;}
26
27 static int match_children_here(data1_node *n, Z_ETagUnit **t, int num)
28 {
29     int counter = 0, hits = 0;
30     data1_node *c;
31     Z_ETagUnit *tp = *t;
32     Z_Occurrences *occur;
33
34     for (c = n->child; c ; c = c->next)
35     {
36         data1_tag *tag = 0;
37
38         if (c->which != DATA1N_tag)
39             return 0;
40
41         if (tp->which == Z_ETagUnit_specificTag)
42         {
43             Z_SpecificTag *want = tp->u.specificTag;
44             occur = want->occurrences;
45             if (c->u.tag.element)
46                 tag = c->u.tag.element->tag;
47             if (*want->tagType != (tag ? tag->tagset->type : 3))
48                 continue;
49             if (want->tagValue->which == Z_StringOrNumeric_numeric)
50             {
51                 if (!tag || tag->which != DATA1T_numeric)
52                     continue;
53                 if (*want->tagValue->u.numeric != tag->value.numeric)
54                     continue;
55             }
56             else
57             {
58                 assert(want->tagValue->which == Z_StringOrNumeric_string);
59                 if (tag && tag->which != DATA1T_string)
60                     continue;
61                 if (data1_matchstr(want->tagValue->u.string,
62                     tag ? tag->value.string : c->u.tag.tag))
63                     continue;
64             }
65         }
66         else
67             occur = tp->u.wildThing;
68
69         /*
70          * Ok, so we have a matching tag. Are we within occurrences-range?
71          */
72         counter++;
73         if (occur && occur->which == Z_Occurrences_last)
74         {
75             logf(LOG_WARN, "Can't do occurrences=last (yet)");
76             return 0;
77         }
78         if (!occur || occur->which == Z_Occurrences_all ||
79             (occur->which == Z_Occurrences_values && counter >=
80             *occur->u.values->start))
81         {
82             if (match_children(c, t + 1, num - 1))
83             {
84                 c->u.tag.node_selected = 1;
85                 hits++;
86                 /*
87                  * have we looked at enough children?
88                  */
89                 if (!occur || (occur->which == Z_Occurrences_values &&
90                     counter - *occur->u.values->start >=
91                     *occur->u.values->howMany - 1))
92                     return hits;
93             }
94         }
95     }
96     return hits;
97 }
98
99 static void mark_children(data1_node *n)
100 {
101     data1_node *c;
102
103     for (c = n->child; c; c = c->next)
104     {
105         if (c->which != DATA1N_tag)
106             continue;
107         c->u.tag.node_selected = 1;
108         mark_children(c);
109     }
110 }
111
112 static int match_children(data1_node *n, Z_ETagUnit **t, int num)
113 {
114     if (!num)
115     {
116         mark_children(n); /* Here there shall be variants, like, dude */
117         return 1;
118     }
119     switch (t[0]->which)
120     {
121         case Z_ETagUnit_wildThing:
122         case Z_ETagUnit_specificTag: return match_children_here(n, t, num);
123         case Z_ETagUnit_wildPath: return match_children_wildpath(n, t, num);
124         default:
125             abort();
126     }
127 }
128
129 int data1_doespec1(data1_node *n, Z_Espec1 *e)
130 {
131     int i;
132
133     for (i = 0; i < e->num_elements; i++)
134         match_children(n,  e->elements[i]->u.simpleElement->path->tags,
135             e->elements[i]->u.simpleElement->path->num_tags);
136     return 0;
137 }