Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/dsslib/merge/merge.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2003-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
static const char merge_usage[] =
23
"[+PLUGIN?\findex\f]"
24
"[+DESCRIPTION?The \bmerge\b query merges the input files based on"
25
" the ordering specified by \b--key\b and \b--reverse\b options."
26
" The files must already be ordered; there is no verification."
27
" Multiple \b--key\b and \b--reverse\b options may be specified.]"
28
"[k:key?\afield\a is a sort key in normal order.]:[field]"
29
"[r:reverse?\afield\a is a sort key in reverse order.]:[field]"
30
"\n"
31
"\n[ file ... ]\n"
32
"\n"
33
;
34
35
#include <dsslib.h>
36
37
struct File_s; typedef struct File_s File_t;
38
struct Key_s; typedef struct Key_s Key_t;
39
struct State_s; typedef struct State_s State_t;
40
41
struct File_s
42
{
43
Dtlink_t link;
44
Dssfile_t* file;
45
Dssrecord_t* record;
46
Cxoperand_t* data;
47
};
48
49
struct Key_s
50
{
51
Key_t* next;
52
Cxvariable_t* variable;
53
int sense;
54
};
55
56
struct State_s
57
{
58
Dtdisc_t orderdisc;
59
Dt_t* order;
60
Dss_t* dss;
61
Cx_t* cx;
62
size_t nkeys;
63
size_t nfiles;
64
Key_t* keys;
65
Cxcallout_f getf;
66
File_t files[1];
67
};
68
69
extern Dsslib_t dss_lib_merge;
70
71
static int
72
ordercmp(Dt_t* dict, void* a, void* b, Dtdisc_t* disc)
73
{
74
State_t* state = (State_t*)disc;
75
File_t* ap = (File_t*)a;
76
File_t* bp = (File_t*)b;
77
Key_t* kp;
78
size_t az;
79
size_t bz;
80
int k;
81
int r;
82
83
for (k = 0, kp = state->keys; k < state->nkeys; k++, kp = kp->next)
84
if (cxisstring(kp->variable->type) || cxisbuffer(kp->variable->type))
85
{
86
az = ap->data[k].value.buffer.size;
87
bz = bp->data[k].value.buffer.size;
88
if (r = memcmp(ap->data[k].value.buffer.data, bp->data[k].value.buffer.data, az < bz ? az : bz))
89
return (r < 0) ? -kp->sense : kp->sense;
90
if (az < bz)
91
return -kp->sense;
92
if (az > bz)
93
return kp->sense;
94
}
95
else if (ap->data[k].value.number < bp->data[k].value.number)
96
return -kp->sense;
97
else if (ap->data[k].value.number > bp->data[k].value.number)
98
return kp->sense;
99
if (ap < bp)
100
return -1;
101
if (ap > bp)
102
return 1;
103
return 0;
104
}
105
106
static void
107
enter(Dss_t* dss, register State_t* state, register File_t* file)
108
{
109
register int k;
110
register Key_t* kp;
111
Cxinstruction_t x;
112
113
if (file->record)
114
dtdelete(state->order, file);
115
if (file->record = dssfread(file->file))
116
{
117
for (k = 0, kp = state->keys; k < state->nkeys; k++, kp = kp->next)
118
{
119
x.data.variable = kp->variable;
120
if ((*state->getf)(state->cx, &x, file->data + k, NiL, NiL, file->record, state->cx->disc))
121
return;
122
}
123
dtinsert(state->order, file);
124
}
125
}
126
127
static int
128
merge_beg(Cx_t* cx, Cxexpr_t* expr, void* data, Cxdisc_t* disc)
129
{
130
register State_t* state;
131
register File_t* file;
132
char** argv = (char**)data;
133
char** files = expr->files;
134
Dss_t* dss = DSS(cx);
135
int errors = error_info.errors;
136
int i;
137
int k;
138
int n;
139
int r;
140
char* path;
141
char* u;
142
char** v;
143
Cxvariable_t* variable;
144
Cxoperand_t* operands;
145
Key_t* key;
146
Key_t* lastkey;
147
Key_t* keys;
148
Vmalloc_t* vm;
149
150
if (!(vm = vmopen(Vmdcheap, Vmbest, 0)))
151
{
152
if (disc->errorf)
153
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
154
return -1;
155
}
156
r = -1;
157
k = 0;
158
keys = 0;
159
sfprintf(cx->buf, "%s%s", strchr(dss_lib_merge.description, '['), merge_usage);
160
u = sfstruse(cx->buf);
161
for (;;)
162
{
163
switch (i = optget(argv, u))
164
{
165
case 'k':
166
case 'r':
167
if (!(variable = cxvariable(cx, opt_info.arg, NiL, disc)))
168
goto bad;
169
if (!(key = vmnewof(vm, 0, Key_t, 1, 0)))
170
{
171
if (disc->errorf)
172
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
173
goto bad;
174
}
175
key->variable = variable;
176
key->sense = (i == 'r') ? -1 : 1;
177
if (keys)
178
lastkey = lastkey->next = key;
179
else
180
lastkey = keys = key;
181
k++;
182
continue;
183
case '?':
184
if (disc->errorf)
185
(*disc->errorf)(NiL, disc, ERROR_USAGE|4, "%s", opt_info.arg);
186
else
187
return -1;
188
continue;
189
case ':':
190
if (disc->errorf)
191
(*disc->errorf)(NiL, disc, 2, "%s", opt_info.arg);
192
else
193
return -1;
194
continue;
195
}
196
break;
197
}
198
if (error_info.errors > errors)
199
goto bad;
200
argv += opt_info.index;
201
for (v = argv; *v; v++);
202
n = v - argv;
203
if (files)
204
{
205
for (v = files; *v; v++);
206
n += v - files;
207
}
208
if (!n)
209
n = 1;
210
if (!(state = vmnewof(vm, 0, State_t, 1, (n - 1) * sizeof(File_t))) || !(operands = vmnewof(vm, 0, Cxoperand_t, n * k, 0)))
211
{
212
if (cx->disc->errorf)
213
(*cx->disc->errorf)(NiL, cx->disc, ERROR_SYSTEM|2, "out of space");
214
goto bad;
215
}
216
state->cx = cx;
217
if (!(state->getf = cxcallout(cx, CX_GET, cx->state->type_void, cx->state->type_void, cx->disc)))
218
{
219
if (cx->disc->errorf)
220
(*cx->disc->errorf)(NiL, cx->disc, 2, "CX_GET callout required");
221
goto bad;
222
}
223
state->nfiles = n;
224
state->nkeys = k;
225
state->keys = keys;
226
for (n = 0; n < state->nfiles; n++)
227
{
228
state->files[n].data = operands;
229
operands += k;
230
}
231
state->orderdisc.comparf = ordercmp;
232
if (!(state->order = dtnew(vm, &state->orderdisc, Dtoset)))
233
{
234
if (cx->disc->errorf)
235
(*cx->disc->errorf)(NiL, cx->disc, ERROR_SYSTEM|2, "out of space");
236
goto bad;
237
}
238
n = 0;
239
if (path = *argv)
240
argv++;
241
else if (files)
242
{
243
argv = files;
244
files = 0;
245
if (path = *argv)
246
argv++;
247
}
248
for (;;)
249
{
250
if (!(state->files[n].file = dssfopen(dss, path, NiL, DSS_FILE_READ, NiL)))
251
goto drop;
252
enter(dss, state, &state->files[n]);
253
n++;
254
if (!(path = *argv++))
255
{
256
if (!files)
257
break;
258
argv = files;
259
files = 0;
260
if (!(path = *argv++))
261
break;
262
}
263
}
264
expr = expr->pass;
265
if (dssbeg(dss, expr))
266
goto drop;
267
while (file = (File_t*)dtfirst(state->order))
268
{
269
if (dsseval(dss, expr, file->record) < 0)
270
goto drop;
271
enter(dss, state, file);
272
}
273
if (error_info.errors == errors)
274
r = 0;
275
drop:
276
for (n = 0; n < state->nfiles; n++)
277
if (state->files[n].file)
278
dssfclose(state->files[n].file);
279
bad:
280
vmclose(vm);
281
return r;
282
}
283
284
static Cxquery_t queries[] =
285
{
286
{
287
"merge",
288
"merge input files",
289
CXH,
290
merge_beg,
291
0,
292
0,
293
0,
294
0,
295
0,
296
1
297
},
298
{0}
299
};
300
301
Dsslib_t dss_lib_merge =
302
{
303
"merge",
304
"merge query"
305
"[-1lms5P?\n@(#)$Id: dss merge query (AT&T Research) 2003-02-14 $\n]"
306
USAGE_LICENSE,
307
CXH,
308
0,
309
0,
310
0,
311
0,
312
0,
313
0,
314
&queries[0]
315
};
316
317