Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libjcl/uniq.c
1808 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
/*
23
* keep track of --list dups
24
*/
25
26
#include "jcllib.h"
27
28
typedef struct Uniq_s
29
{
30
Dtlink_t link;
31
char* name;
32
char* value;
33
size_t size;
34
unsigned long count;
35
unsigned long flags;
36
int recfm;
37
} Uniq_t;
38
39
typedef struct State_s
40
{
41
Dt_t* diff;
42
Dt_t* mark;
43
Dt_t* uniq;
44
Dtdisc_t diffdisc;
45
Dtdisc_t markdisc;
46
Dtdisc_t uniqdisc;
47
} State_t;
48
49
static State_t state;
50
51
/*
52
* return 1 if path is marked
53
* if dd!=0 then set dd->recfm and dd->lrecl if marked
54
*/
55
56
int
57
marked(const char* path, Jcldd_t* dd, Jcldisc_t* disc)
58
{
59
char* s;
60
char* e;
61
size_t n;
62
int f;
63
64
if (path && (s = strrchr(path, '%')) && s > (char*)path && *(s - 1) != '%')
65
{
66
f = 0;
67
for (;;)
68
{
69
switch (*++s)
70
{
71
case 0:
72
break;
73
case '0': case '1': case '2': case '3': case '4':
74
case '5': case '6': case '7': case '8': case '9':
75
if ((n = strtoul(s, &e, 10)) && (!*e || *e == '.' && !strchr(e, '/')))
76
{
77
if (dd)
78
{
79
dd->recfm = f;
80
dd->lrecl = n;
81
}
82
return 1;
83
}
84
break;
85
case 'A':
86
case 'a':
87
f |= JCL_RECFM_A;
88
continue;
89
case 'B':
90
case 'b':
91
f |= JCL_RECFM_B;
92
continue;
93
case 'D':
94
case 'd':
95
f |= JCL_RECFM_D;
96
continue;
97
case 'F':
98
case 'f':
99
f |= JCL_RECFM_F;
100
continue;
101
case 'M':
102
case 'm':
103
f |= JCL_RECFM_M;
104
continue;
105
case 'S':
106
case 's':
107
f |= JCL_RECFM_S;
108
continue;
109
case 'U':
110
case 'u':
111
f |= JCL_RECFM_U;
112
continue;
113
case 'V':
114
case 'v':
115
f |= JCL_RECFM_V;
116
continue;
117
default:
118
if (disc->errorf)
119
(*disc->errorf)(NiL, disc, 1, "%s: %c: unknown RECFM", path, *s);
120
continue;
121
}
122
break;
123
}
124
}
125
return 0;
126
}
127
128
/*
129
* if size>0 then name is marked with %size
130
* and the marked name is returned
131
* marked names are global
132
*
133
* if size==0 then marked name, if any, is returned
134
* otherwise 0 returned and name is not marked
135
* recfm is JCL_RECFM_F or JCL_RECFM_V
136
*/
137
138
char*
139
mark(const char* name, int recfm, size_t size, Jcldisc_t* disc)
140
{
141
register Uniq_t* u;
142
register char* s;
143
register size_t n;
144
int m;
145
146
if (marked(name, NiL, disc))
147
return (char*)name;
148
if (!state.mark)
149
{
150
if (!size)
151
return 0;
152
state.markdisc.link = offsetof(Uniq_t, link);
153
state.markdisc.key = offsetof(Uniq_t, name);
154
state.markdisc.size = -1;
155
if (!(state.mark = dtopen(&state.markdisc, Dtoset)))
156
{
157
nospace(NiL, disc);
158
return 0;
159
}
160
}
161
if (u = (Uniq_t*)dtmatch(state.mark, name))
162
{
163
if (disc->errorf)
164
{
165
if (size != u->size && size && u->size)
166
(*disc->errorf)(NiL, disc, 2, "%s: inconsistent size %I*u", u->value, sizeof(size), size);
167
if (recfm != u->recfm && recfm && u->recfm)
168
(*disc->errorf)(NiL, disc, 2, "%s: inconsistent recfm %s", u->value, (recfm & JCL_RECFM_V) ? "v" : "f");
169
}
170
return u->value;
171
}
172
if (!size)
173
return 0;
174
m = strlen(name);
175
n = 2 * (m + 1) + 8;
176
if (!(u = newof(NiL, Uniq_t, 1, n)))
177
{
178
nospace(NiL, disc);
179
return 0;
180
}
181
s = u->value = strcopy(u->name = (char*)(u + 1), name) + 1;
182
u->size = size;
183
m -= suflen(name);
184
sfsprintf(s, n, "%-.*s%%%s%I*u%s", m, name, (recfm & JCL_RECFM_V) ? "v" : "", sizeof(size), size, name + m);
185
message((-7, "mark %s => %s", name, u->value));
186
dtinsert(state.mark, u);
187
return s;
188
}
189
190
static int
191
uniqcmp(Dt_t* dt, register void* a, register void* b, Dtdisc_t* disc)
192
{
193
int n;
194
195
if (!(n = strcmp(((Uniq_t*)a)->name, ((Uniq_t*)b)->name)) && ((Uniq_t*)a)->value)
196
n = strcmp(((Uniq_t*)a)->value, ((Uniq_t*)b)->value);
197
return n;
198
}
199
200
/*
201
* add name [value] to the uniq dict
202
*/
203
204
void
205
uniq(const char* name, const char* value, unsigned long flags, Jcldisc_t* disc)
206
{
207
register Uniq_t* u;
208
register char* s;
209
register size_t n;
210
Uniq_t k;
211
212
if (!state.uniq)
213
{
214
state.uniqdisc.link = offsetof(Uniq_t, link);
215
state.uniqdisc.comparf = uniqcmp;
216
if (!(state.uniq = dtopen(&state.uniqdisc, Dtoset)))
217
{
218
nospace(NiL, disc);
219
return;
220
}
221
}
222
k.name = (char*)name;
223
k.value = (char*)value;
224
if (u = (Uniq_t*)dtsearch(state.uniq, &k))
225
u->count++;
226
else
227
{
228
n = strlen(name) + 1;
229
if (value)
230
n += strlen(value) + 1;
231
if (!(u = newof(NiL, Uniq_t, 1, n)))
232
{
233
nospace(NiL, disc);
234
return;
235
}
236
u->count = 1;
237
s = strcopy(u->name = (char*)(u + 1), name);
238
if (value)
239
strcpy(u->value = s, value);
240
dtinsert(state.uniq, u);
241
}
242
u->flags |= flags;
243
}
244
245
/*
246
* add name=value to the diff dict
247
* return 1 if value is different from previous
248
*/
249
250
int
251
diff(const char* name, const char* value, Jcldisc_t* disc)
252
{
253
register Uniq_t* u;
254
register size_t n;
255
256
if (!state.diff)
257
{
258
state.diffdisc.link = offsetof(Uniq_t, link);
259
state.diffdisc.key = offsetof(Uniq_t, name);
260
state.diffdisc.size = -1;
261
if (!(state.diff = dtopen(&state.diffdisc, Dtoset)))
262
{
263
nospace(NiL, disc);
264
return -1;
265
}
266
}
267
if (u = (Uniq_t*)dtmatch(state.diff, name))
268
{
269
u->count++;
270
if (streq(value, u->value))
271
return 0;
272
}
273
else
274
{
275
if (!(u = newof(NiL, Uniq_t, 1, strlen(name) + 1)))
276
{
277
nospace(NiL, disc);
278
return -1;
279
}
280
u->count = 1;
281
strcpy(u->name = (char*)(u + 1), name);
282
dtinsert(state.diff, u);
283
}
284
n = strlen(value);
285
if (n >= u->size)
286
{
287
u->size = roundof(n + 1, 16);
288
if (!(u->value = newof(u->value, char, u->size, 0)))
289
{
290
nospace(NiL, disc);
291
return -1;
292
}
293
}
294
strcpy(u->value, value);
295
return 1;
296
}
297
298
/*
299
* list uniq name [value] with optional count
300
*/
301
302
int
303
jclstats(Sfio_t* sp, unsigned long flags, Jcldisc_t* disc)
304
{
305
register Uniq_t* u;
306
register int c;
307
register unsigned long m;
308
309
if (state.uniq)
310
{
311
c = (flags & JCL_LISTCOUNTS) != 0;
312
m = flags & (JCL_LISTINPUTS|JCL_LISTOUTPUTS);
313
for (u = (Uniq_t*)dtfirst(state.uniq); u; u = (Uniq_t*)dtnext(state.uniq, u))
314
if (!m || (u->flags & m))
315
{
316
sfprintf(sp, "%s", u->name);
317
if (u->value)
318
sfprintf(sp, " %s", u->value);
319
if (c)
320
sfprintf(sp, " %lu", u->count);
321
sfputc(sp, '\n');
322
}
323
}
324
if (sfsync(sp))
325
{
326
if (disc->errorf)
327
(*disc->errorf)(NiL, disc, 2, "write error");
328
return -1;
329
}
330
return 0;
331
}
332
333