Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/dsslib/stats/stats.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2002-2012 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 stats_usage[] =
23
"[+PLUGIN?\findex\f]"
24
"[+DESCRIPTION?The stats query lists the sum, average, unbiased standard"
25
" deviation, and minimum and maximum range values of the numeric"
26
" \afield\a operands. If no operands are specified then all numeric"
27
" fields are assumed. If \b-\b is specified then only records or"
28
" groups are counted. If any of \b--average\b, \b--count\b,"
29
" \b--deviation\b, \b--range\b or \b--sum\b are specified then only"
30
" those values are listed.]"
31
"[a:average?List the average.]"
32
"[c:count?List the record count.]"
33
"[d:deviation?List the unbiased standard deviation.]"
34
"[g:group?Group by values in \afield\a. More than one \b--group\b may be "
35
"specified; grouping is done by the tuple of all \afield\a "
36
"values.]:[field]"
37
"[l:label?Label the output with \alabel\a.]:[label]"
38
"[m:maxgroups?Maximum number of groupings. Values beyond \amax\a are"
39
" listed as \bOVERFLOW\b.]#[max:=100]"
40
"[p:print?Print summary data according to \aformat\a. The format fields"
41
" are:]:[format]{\ffields\f}"
42
"[r:range?List the minimum and maximum values.]"
43
"[s:sum?List the sum.]"
44
"\n"
45
"\n[ field ... ]\n"
46
"\n"
47
;
48
49
#include <dsslib.h>
50
#include <ast_float.h>
51
52
#define FW 15
53
54
#define STATS_AVERAGE 0x0001
55
#define STATS_COUNT 0x0002
56
#define STATS_DEVIATION 0x0004
57
#define STATS_FIELD 0x0008
58
#define STATS_GROUP 0x0010
59
#define STATS_MAX 0x0020
60
#define STATS_MIN 0x0040
61
#define STATS_SUM 0x0080
62
63
#define STATS_RANGE (STATS_MAX|STATS_MIN)
64
65
struct Bucket_s; typedef struct Bucket_s Bucket_t;
66
struct Field_s; typedef struct Field_s Field_t;
67
struct Group_s; typedef struct Group_s Group_t;
68
struct Print_s; typedef struct Print_s Print_t;
69
struct State_s; typedef struct State_s State_t;
70
struct Total_s; typedef struct Total_s Total_t;
71
72
struct Total_s
73
{
74
Cxnumber_t value;
75
Cxnumber_t square;
76
Cxnumber_t min;
77
Cxnumber_t max;
78
Cxunsigned_t count;
79
};
80
81
struct Bucket_s
82
{
83
Dtlink_t link;
84
Cxoperand_t* key;
85
Total_t total[1];
86
};
87
88
struct Group_s
89
{
90
Group_t* next;
91
Cxvariable_t* variable;
92
int string;
93
int width;
94
};
95
96
struct Field_s
97
{
98
Field_t* next;
99
Cxvariable_t* variable;
100
};
101
102
struct Print_s
103
{
104
Field_t* field;
105
Group_t* group;
106
const char* label;
107
Total_t* total;
108
Cxoperand_t* key;
109
};
110
111
struct State_s
112
{
113
Dtdisc_t bucketdisc;
114
Field_t* field;
115
char* format;
116
Cx_t* print;
117
Group_t* group;
118
char* label;
119
Cxoperand_t* key;
120
Dt_t* buckets;
121
Total_t* total;
122
Vmalloc_t* vm;
123
int fields;
124
int fw;
125
int groups;
126
int maxgroups;
127
int op;
128
};
129
130
static Cxvariable_t variables[] =
131
{
132
CXV("AVERAGE", "number", STATS_AVERAGE, "Average value.")
133
CXV("COUNT", "number", STATS_COUNT, "Number of values.")
134
CXV("DEVIATION","number", STATS_DEVIATION, "Unbiased standard deviation.")
135
CXV("FIELD", "string", STATS_FIELD, "Field name.")
136
CXV("GROUP", "string", STATS_GROUP, "Group (key) values.")
137
CXV("MAX", "number", STATS_MAX, "Maximum value.")
138
CXV("MIN", "number", STATS_MIN, "Minimum value.")
139
CXV("SUM", "number", STATS_SUM, "Sum of values.")
140
};
141
142
extern Dsslib_t dss_lib_stats;
143
144
static int
145
getop(Cx_t* cx, Cxinstruction_t* pc, Cxoperand_t* r, Cxoperand_t* a, Cxoperand_t* b, void* data, Cxdisc_t* disc)
146
{
147
register State_t* state = (State_t*)((Dssrecord_t*)data)->data;
148
Cxvariable_t* variable = pc->data.variable;
149
Group_t* group;
150
char* s;
151
char* v;
152
153
if (variable->data == (void*)&variables[0])
154
{
155
state->op |= variable->index;
156
if (variable->format.delimiter <= 0)
157
variable->format.delimiter = ':';
158
if (a && (s = a->value.string.data))
159
do
160
{
161
while (*s == ':')
162
s++;
163
for (v = s; *s && *s != ':'; s++);
164
if (strneq(v, "delimiter=", 10))
165
variable->format.delimiter = v[10];
166
else if (strneq(v, "nodelimiter", 11))
167
variable->format.delimiter = 0;
168
} while (*s);
169
}
170
else
171
{
172
group = state->group;
173
for (;;)
174
{
175
if (!group)
176
{
177
if (disc->errorf)
178
(*disc->errorf)(cx, disc, 2, "%s: unknown print variable", variable->name);
179
return -1;
180
}
181
if (group->variable == variable)
182
break;
183
group = group->next;
184
}
185
}
186
r->value.string.data = "";
187
r->value.string.size = 0;
188
return 0;
189
}
190
191
static int
192
getvalue(Cx_t* cx, Cxinstruction_t* pc, Cxoperand_t* r, Cxoperand_t* a, Cxoperand_t* b, void* data, Cxdisc_t* disc)
193
{
194
register Print_t* print = (Print_t*)((Dssrecord_t*)data)->data;
195
Cxvariable_t* variable = pc->data.variable;
196
char* s;
197
Group_t* group;
198
Cxoperand_t* key;
199
Cxoperand_t arg;
200
Cxnumber_t u;
201
int sep;
202
203
if (variable->data == (void*)&variables[0])
204
switch (variable->index)
205
{
206
case STATS_AVERAGE:
207
r->value.number = print->total->count ? print->total->value / (Cxinteger_t)print->total->count : 0;
208
break;
209
case STATS_COUNT:
210
r->value.number = (Cxinteger_t)print->total->count;
211
break;
212
case STATS_DEVIATION:
213
if (print->total->count)
214
{
215
u = print->total->value / (Cxinteger_t)print->total->count;
216
if ((u = print->total->square + u * (u - 2 * print->total->value)) < 0)
217
u = -u;
218
if (print->total->count > 1)
219
u /= (Cxinteger_t)(print->total->count - 1);
220
r->value.number = sqrt(u);
221
}
222
else
223
r->value.number = 0;
224
break;
225
case STATS_FIELD:
226
if (!print->field || !(r->value.string.data = (char*)print->field->variable->name))
227
r->value.string.data = "-";
228
r->value.string.size = strlen(r->value.string.data);
229
break;
230
case STATS_GROUP:
231
sfstrseek(cx->buf, SEEK_SET, 0);
232
if (key = print->key)
233
for (sep = 0, group = print->group; group; group = group->next, key++)
234
{
235
if (sep)
236
sfputc(cx->buf, sep);
237
else
238
sep = variable->format.delimiter;
239
if (group->string)
240
s = key->value.string.data;
241
else
242
{
243
arg = *key;
244
if (cxcast(cx, &arg, 0, cx->state->type_string, NiL, group->variable->format.details))
245
return -1;
246
s = arg.value.string.data;
247
}
248
sfprintf(cx->buf, "%s", s);
249
}
250
else if (print->label)
251
sfprintf(cx->buf, "%s", print->label);
252
r->value.string.size = sfstrtell(cx->buf);
253
r->value.string.data = sfstruse(cx->buf);
254
break;
255
case STATS_MAX:
256
r->value.number = print->total->max;
257
break;
258
case STATS_MIN:
259
r->value.number = print->total->min;
260
break;
261
case STATS_SUM:
262
r->value.number = print->total->value;
263
break;
264
}
265
else if (key = print->key)
266
{
267
for (group = print->group; group->variable != variable; group = group->next, key++);
268
r->value = key->value;
269
}
270
else
271
memset(&r->value, 0, sizeof(r->value));
272
return 0;
273
}
274
275
static int
276
bucketcmp(Dt_t* dt, void* a, void* b, Dtdisc_t* disc)
277
{
278
register State_t* state = (State_t*)disc;
279
register Cxoperand_t* ka = (Cxoperand_t*)a;
280
register Cxoperand_t* kb = (Cxoperand_t*)b;
281
register Group_t* group;
282
register int n;
283
284
for (group = state->group; group; group = group->next, ka++, kb++)
285
{
286
if (group->string)
287
{
288
n = ka->value.string.size < kb->value.string.size ? ka->value.string.size : kb->value.string.size;
289
if (n = memcmp(ka->value.string.data, kb->value.string.data, n))
290
return n;
291
if (ka->value.string.size < kb->value.string.size)
292
return -1;
293
if (ka->value.string.size > kb->value.string.size)
294
return 1;
295
}
296
else if (ka->value.number < kb->value.number)
297
return -1;
298
else if (ka->value.number > kb->value.number)
299
return 1;
300
}
301
return 0;
302
}
303
304
static int
305
stats_beg(Cx_t* cx, Cxexpr_t* expr, void* data, Cxdisc_t* disc)
306
{
307
char** argv = (char**)data;
308
int errors = error_info.errors;
309
int all;
310
int i;
311
char* s;
312
State_t* state;
313
Cxvariable_t* variable;
314
Field_t* field;
315
Field_t* lastfield;
316
Group_t* group;
317
Group_t* lastgroup;
318
Vmalloc_t* vm;
319
Dssrecord_t record;
320
Sfio_t* tmp;
321
322
if (!(vm = vmopen(Vmdcheap, Vmlast, 0)) || !(state = vmnewof(vm, 0, State_t, 1, 0)))
323
{
324
if (vm)
325
vmclose(vm);
326
if (disc->errorf)
327
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
328
return -1;
329
}
330
state->vm = vm;
331
state->maxgroups = 100;
332
if (!(state->print = cxopen(0, 0, disc)))
333
{
334
if (disc->errorf)
335
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
336
goto bad;
337
}
338
if (!cxscope(state->print, cx, 0, 0, disc))
339
{
340
cxclose(state->print);
341
goto bad;
342
}
343
for (i = 0; i < elementsof(variables); i++)
344
{
345
if (cxaddvariable(state->print, &variables[i], disc))
346
goto bad;
347
variables[i].data = &variables[0];
348
}
349
sfprintf(cx->buf, "%s%s", strchr(dss_lib_stats.description, '['), stats_usage);
350
s = sfstruse(cx->buf);
351
for (;;)
352
{
353
switch (optget(argv, s))
354
{
355
case 'a':
356
state->op |= STATS_AVERAGE;
357
continue;
358
case 'c':
359
state->op |= STATS_COUNT;
360
continue;
361
case 'd':
362
state->op |= STATS_DEVIATION;
363
continue;
364
case 'g':
365
if (!(variable = cxvariable(cx, opt_info.arg, NiL, disc)))
366
goto bad;
367
if (!(group = vmnewof(vm, 0, Group_t, 1, 0)))
368
{
369
if (disc->errorf)
370
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
371
goto bad;
372
}
373
group->variable = variable;
374
group->string = cxisstring(variable->type) || cxisbuffer(variable->type);
375
if (state->group)
376
lastgroup = lastgroup->next = group;
377
else
378
lastgroup = state->group = group;
379
state->groups++;
380
continue;
381
case 'l':
382
if (!(state->label = vmstrdup(vm, opt_info.arg)))
383
{
384
if (disc->errorf)
385
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
386
goto bad;
387
}
388
continue;
389
case 'm':
390
state->maxgroups = opt_info.num;
391
continue;
392
case 'p':
393
if (!(state->format = vmstrdup(vm, opt_info.arg)))
394
{
395
if (disc->errorf)
396
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
397
goto bad;
398
}
399
continue;
400
case 'r':
401
state->op |= STATS_RANGE;
402
continue;
403
case 's':
404
state->op |= STATS_SUM;
405
continue;
406
case '?':
407
if (disc->errorf)
408
{
409
(*disc->errorf)(cx, disc, ERROR_USAGE|4, "%s", opt_info.arg);
410
}
411
else
412
goto bad;
413
continue;
414
case ':':
415
if (disc->errorf)
416
(*disc->errorf)(cx, disc, 2, "%s", opt_info.arg);
417
else
418
goto bad;
419
continue;
420
}
421
break;
422
}
423
if (error_info.errors > errors)
424
goto bad;
425
argv += opt_info.index;
426
if (!state->op)
427
state->op = ~0;
428
if (all = !*argv)
429
variable = 0;
430
state->fw = 5;
431
do
432
{
433
if (all)
434
{
435
do
436
{
437
variable = (Cxvariable_t*)(variable ? dtnext(cx->fields, variable) : dtfirst(cx->fields));
438
} while (variable && (variable->data == (void*)&variables[0] || !cxisnumber(variable->type)));
439
if (!variable)
440
break;
441
}
442
else if (streq(*argv, "-"))
443
continue;
444
else if (!(variable = cxvariable(cx, *argv, NiL, disc)))
445
goto bad;
446
else if (!cxisnumber(variable->type))
447
{
448
if (disc->errorf)
449
(*disc->errorf)(cx, disc, 2, "%s: not a numeric field", variable->name);
450
goto bad;
451
}
452
if (!(field = vmnewof(vm, 0, Field_t, 1, 0)))
453
{
454
if (disc->errorf)
455
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
456
goto bad;
457
}
458
field->variable = variable;
459
if (state->field)
460
lastfield = lastfield->next = field;
461
else
462
lastfield = state->field = field;
463
state->fields++;
464
if (state->fw < (i = (int)strlen(variable->name)))
465
state->fw = i;
466
} while (all || *++argv);
467
if (!state->fields)
468
{
469
if (all)
470
{
471
if (disc->errorf)
472
(*disc->errorf)(cx, disc, 2, "no numeric fields");
473
goto bad;
474
}
475
state->fields = 1;
476
}
477
if (!(state->total = vmnewof(vm, 0, Total_t, state->fields, 0)))
478
{
479
if (disc->errorf)
480
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
481
goto bad;
482
}
483
if (state->group)
484
{
485
state->bucketdisc.comparf = bucketcmp;
486
state->bucketdisc.link = offsetof(Bucket_t, link);
487
state->bucketdisc.size = -1;
488
state->bucketdisc.key = offsetof(Bucket_t, key);
489
if (!(state->buckets = dtnew(vm, &state->bucketdisc, Dtoset)))
490
{
491
if (disc->errorf)
492
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
493
goto bad;
494
}
495
}
496
if (state->format)
497
{
498
if (!(tmp = sfstropen()))
499
{
500
if (disc->errorf)
501
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
502
goto bad;
503
}
504
state->print->getf = getop;
505
record.data = state;
506
i = dssprintf(DSS(cx), state->print, tmp, state->format, &record);
507
state->print->getf = getvalue;
508
sfclose(tmp);
509
if (i < 0)
510
goto bad;
511
}
512
expr->data = state;
513
return 0;
514
bad:
515
if (state->print)
516
cxscope(state->print, NiL, 0, 0, disc);
517
vmclose(vm);
518
return -1;
519
}
520
521
static int
522
stats_act(Cx_t* cx, Cxexpr_t* expr, void* data, Cxdisc_t* disc)
523
{
524
register State_t* state = (State_t*)expr->data;
525
register Cxoperand_t* key;
526
register Field_t* field;
527
register Group_t* group;
528
register Total_t* total;
529
Bucket_t* bucket;
530
Cxoperand_t val;
531
char* s;
532
int range;
533
int square;
534
535
total = state->total;
536
if (state->group)
537
{
538
if (!state->key && !(state->key = vmnewof(state->vm, 0, Cxoperand_t, state->groups, 0)))
539
{
540
if (disc->errorf)
541
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
542
return -1;
543
}
544
for (group = state->group, key = state->key; group; group = group->next, key++)
545
if (cxcast(cx, key, group->variable, group->variable->type, data, NiL))
546
return -1;
547
if (bucket = (Bucket_t*)dtmatch(state->buckets, state->key))
548
total = bucket->total;
549
else if (dtsize(state->buckets) < state->maxgroups)
550
{
551
if (!(bucket = vmnewof(state->vm, 0, Bucket_t, 1, (state->fields - 1) * sizeof(Total_t))))
552
{
553
if (disc->errorf)
554
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
555
return -1;
556
}
557
for (group = state->group, key = state->key; group; group = group->next, key++)
558
if (group->string)
559
{
560
s = key->value.string.data;
561
if (!(key->value.string.data = vmnewof(state->vm, 0, char, key->value.string.size, 1)))
562
{
563
if (disc->errorf)
564
(*disc->errorf)(cx, disc, ERROR_SYSTEM|2, "out of space");
565
return -1;
566
}
567
memcpy(key->value.string.data, s, key->value.string.size);
568
}
569
bucket->key = state->key;
570
state->key = 0;
571
dtinsert(state->buckets, bucket);
572
total = bucket->total;
573
}
574
}
575
if (!state->field)
576
total->count++;
577
else
578
{
579
range = !!(state->op & STATS_RANGE);
580
square = !!(state->op & STATS_DEVIATION);
581
for (field = state->field; field; field = field->next)
582
{
583
if (cxcast(cx, &val, field->variable, cx->state->type_number, data, NiL))
584
return -1;
585
total->count++;
586
total->value += val.value.number;
587
if (range)
588
{
589
if (total->min > val.value.number || total->count == 1)
590
total->min = val.value.number;
591
if (total->max < val.value.number || total->count == 1)
592
total->max = val.value.number;
593
}
594
if (square)
595
total->square += val.value.number * val.value.number;
596
total++;
597
}
598
}
599
return 0;
600
}
601
602
static void
603
number(Sfio_t* op, Cxnumber_t n, int fw)
604
{
605
if (n == 0 || ((n >= 0) ? n : -n) >= 1 && n >= FLTMAX_INTMAX_MIN && n <= FLTMAX_UINTMAX_MAX && n == (Cxinteger_t)n)
606
sfprintf(op, " %*I*u", fw, sizeof(Cxinteger_t), (Cxinteger_t)n);
607
else
608
{
609
if (n >= 0)
610
sfputc(op, ' ');
611
sfprintf(op, " %1.*I*e", fw - 7, sizeof(n), n);
612
}
613
}
614
615
static int
616
list(Cx_t* cx, register State_t* state, Sfio_t* op, const char* label, register Field_t* field, register Total_t* total, Cxoperand_t* key)
617
{
618
Dssrecord_t record;
619
Print_t pr;
620
Cxnumber_t u;
621
Cxoperand_t arg;
622
Group_t* group;
623
char* s;
624
625
do
626
{
627
if (state->format)
628
{
629
record.data = &pr;
630
pr.field = field;
631
pr.group = state->group;
632
pr.label = label;
633
pr.total = total;
634
pr.key = key;
635
if (dssprintf(DSS(cx), state->print, op, state->format, &record) < 0)
636
return -1;
637
}
638
else
639
{
640
if (field)
641
sfprintf(op, "%*s", state->fw, field->variable->name);
642
if (state->op & STATS_COUNT)
643
number(op, (Cxinteger_t)total->count, FW);
644
u = total->value / (Cxinteger_t)total->count;
645
if (state->op & STATS_SUM)
646
number(op, total->value, FW);
647
if (state->op & STATS_AVERAGE)
648
number(op, u, FW);
649
if (state->op & STATS_DEVIATION)
650
{
651
if ((u = total->square + u * (u - 2 * total->value)) < 0)
652
u = -u;
653
if (total->count > 1)
654
u /= (Cxinteger_t)(total->count - 1);
655
number(op, (Cxnumber_t)sqrt(u), FW);
656
}
657
if (state->op & STATS_RANGE)
658
{
659
number(op, total->min, FW);
660
number(op, total->max, FW);
661
}
662
if (label)
663
{
664
sfprintf(op, " %s", label);
665
label = 0;
666
}
667
else if (key)
668
{
669
for (group = state->group; group; group = group->next, key++)
670
{
671
sfputc(op, ' ');
672
if (group->string)
673
s = key->value.string.data;
674
else
675
{
676
arg = *key;
677
if (cxcast(cx, &arg, 0, cx->state->type_string, NiL, group->variable->format.details))
678
return -1;
679
s = arg.value.string.data;
680
}
681
sfprintf(op, "%*s", group->width, s);
682
}
683
key = 0;
684
}
685
sfprintf(op, "\n");
686
}
687
total++;
688
} while (field && (field = field->next));
689
return 0;
690
}
691
692
static int
693
stats_end(Cx_t* cx, Cxexpr_t* expr, void* data, Cxdisc_t* disc)
694
{
695
register State_t* state = (State_t*)expr->data;
696
register Bucket_t* bucket;
697
register Group_t* group;
698
699
if (state->label)
700
sfprintf(expr->op, "%s\n", state->label);
701
if (!state->format)
702
{
703
if (state->field)
704
sfprintf(expr->op, "%*s", state->fw, "FIELD");
705
if (state->op & STATS_COUNT)
706
sfprintf(expr->op, " %*s", FW, "COUNT");
707
if (state->op & STATS_SUM)
708
sfprintf(expr->op, " %*s", FW, "SUM");
709
if (state->op & STATS_AVERAGE)
710
sfprintf(expr->op, " %*s", FW, "AVERAGE");
711
if (state->op & STATS_DEVIATION)
712
sfprintf(expr->op, " %*s", FW, "DEVIATION");
713
if (state->op & STATS_RANGE)
714
sfprintf(expr->op, " %*s %*s", FW, "MIN", FW, "MAX");
715
if (state->buckets)
716
for (group = state->group; group; group = group->next)
717
{
718
group->width = group->variable->format.print ? group->variable->format.print : group->variable->type->format.print ? group->variable->type->format.print : FW;
719
sfprintf(expr->op, " %*s", group->width, group->variable->name);
720
}
721
sfprintf(expr->op, "\n");
722
}
723
if (state->buckets)
724
{
725
for (bucket = (Bucket_t*)dtfirst(state->buckets); bucket; bucket = (Bucket_t*)dtnext(state->buckets, bucket))
726
if (list(cx, state, expr->op, NiL, state->field, bucket->total, bucket->key))
727
goto bad;
728
if (state->total->count && list(cx, state, expr->op, "OVERFLOW", state->field, state->total, NiL))
729
goto bad;
730
}
731
else if (list(cx, state, expr->op, NiL, state->field, state->total, NiL))
732
goto bad;
733
vmclose(state->vm);
734
return 0;
735
bad:
736
vmclose(state->vm);
737
return -1;
738
}
739
740
static Cxquery_t queries[] =
741
{
742
{
743
"stats",
744
"collect numeric field value statistics",
745
CXH,
746
stats_beg,
747
0,
748
stats_act,
749
stats_end
750
},
751
{0}
752
};
753
754
Dsslib_t dss_lib_stats =
755
{
756
"stats",
757
"stats query"
758
"[-1lms5P?\n@(#)$Id: dss stats query (AT&T Research) 2011-09-11 $\n]"
759
USAGE_LICENSE,
760
CXH,
761
0,
762
0,
763
0,
764
0,
765
0,
766
0,
767
&queries[0]
768
};
769
770