Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/cs/vcs_src/vcs_search.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1990-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
/*
21
* search.c
22
* cmptime()
23
* search_tag
24
* gettagbyspec()
25
* lookup_tagtime()
26
* lookup_tag_t()
27
* pattern2time()
28
* gettagbytime()
29
* gettagbyname()
30
* rs_readlink()
31
*/
32
#include "vcs_rscs.h"
33
#include <ls.h>
34
#include <tm.h>
35
36
37
int cmptime(s1, s2)
38
const void* s1;
39
const void* s2;
40
{
41
#define TAGTIME(s) ((*((rdirent_t**)s))->tag->stat.st_mtime)
42
return (TAGTIME(s1) - TAGTIME(s2));
43
}
44
45
/*
46
* versions :: version
47
* | version ; versions
48
* | NULL
49
* version :: id
50
* | id distance
51
* id :: string | date_spec
52
* date_spec :: [ "(" ] date [ ")" ]
53
* distance :: [ "+" | "-" ] integer
54
* date :: month day [ time | year]
55
* time :: hh ":" mm [ ":" ss ]
56
*
57
*
58
*/
59
int search_tag(rf, ap, versions, domain, tpp, mode, dir)
60
Sfio_t* rf;
61
attr_t* ap;
62
char* versions;
63
int domain;
64
tag_t** tpp;
65
int mode;
66
rdirent_t** dir;
67
{
68
register rdirent_t* list;
69
int r;
70
tag_t* tp;
71
72
if ((list = rs_dir(rf, ap)) == NULL)
73
return (-1);
74
if (dir)
75
*dir = list;
76
if (!versions)
77
r = lookup_tag(list, rf, ap, versions, domain, &tp, 0);
78
else
79
r = gettagbyspec(list, versions, domain, &tp);
80
81
if (r)
82
return (r);
83
84
if (R_ISLINK(tp) && (mode & G_LINK))
85
{
86
if ((tp = gettagbyname(list, tp->version, G_LINK, 0)) == NULL)
87
return (-1);
88
}
89
*tpp = tp;
90
return (0);
91
}
92
93
94
95
int gettagbyspec(list, versions, domain, tpp)
96
register rdirent_t* list;
97
char* versions;
98
int domain;
99
tag_t** tpp;
100
{
101
char buf[2048];
102
register char* s;
103
char* elist[MAXDEPTH+1];
104
rdirent_t* tbl[MAXDEPTH+1];
105
register int i;
106
register rdirent_t* entry;
107
int sort = 0;
108
int total;
109
int num;
110
int flag;
111
int index;
112
int distance;
113
time_t to;
114
115
116
for (entry=list, i=0; entry; entry = entry->next, i++)
117
tbl[i] = entry;
118
total = i;
119
120
strcpy(buf, versions);
121
s = buf;
122
elist[num=chop(s, elist, MAXDEPTH, ';')] = NULL;
123
124
for (i = 0; i < num; i++)
125
{
126
distance = 0;
127
if ((s = strchr(elist[i], '-')) || (s = strchr(elist[i], '+')))
128
{
129
flag = (*s == '+') ? 0 : 1;
130
*s = '\0';
131
s++;
132
distance = (int)strtol(s, (char**)0, 0);
133
if (!sort)
134
{
135
qsort((char *)tbl, total, sizeof(rdirent_t *), cmptime);
136
sort++;
137
}
138
}
139
if ((index = lookup_tag_t(tbl, total, elist[i], domain, 0)) < 0)
140
{
141
if (pattern2time(elist[i], &to) < 0)
142
continue;
143
if (!sort)
144
{
145
qsort((char *)tbl, total, sizeof(rdirent_t *), cmptime);
146
sort++;
147
}
148
if ((index = lookup_tag_time(tbl, total, to, domain, 0)) < 0)
149
continue;
150
}
151
if (!distance)
152
{
153
*tpp = tbl[index]->tag;
154
return (0);
155
}
156
if (!flag)
157
index += distance;
158
else
159
index -= distance;
160
if (index >=0 && index < total)
161
{
162
*tpp = tbl[index]->tag;
163
return (0);
164
}
165
}
166
return (-1);
167
}
168
169
int lookup_tag_time(tbl, total, to, domain, first)
170
register rdirent_t** tbl;
171
int total;
172
time_t to;
173
int domain;
174
int first;
175
{
176
register int i;
177
int r;
178
179
r = -1;
180
181
for (i = 0; i < total; i++)
182
{
183
if (tbl[i]->tag->stat.st_mtime > to)
184
return (r);
185
if (domain && tbl[i]->tag->domain != domain)
186
continue;
187
if (first)
188
return (i);
189
r = i;
190
}
191
return (r);
192
}
193
194
195
196
/*
197
* mode = 0 any;
198
* mode = 1 domain must match
199
*/
200
201
int lookup_tag(entries, rf, ap, version, domain, tpp, mode)
202
rdirent_t* entries;
203
Sfio_t* rf;
204
attr_t* ap;
205
char* version;
206
int domain;
207
tag_t** tpp;
208
int mode;
209
{
210
register rdirent_t* list;
211
register rdirent_t* p;
212
register char* v;
213
rdirent_t* sp;
214
rdirent_t* ep;
215
time_t mtime;
216
int cnt = 0;
217
218
if (entries)
219
list = entries;
220
else if ((list = rs_dir(rf, ap)) == NULL)
221
return (-1);
222
223
if (version)
224
v = version;
225
else
226
v = "LATEST";
227
228
for (sp = NULL, ep = NULL, p = list; p; p = p->next)
229
{
230
if (strcmp(p->tag->version, v) == 0)
231
{
232
if (domain)
233
{
234
if (p->tag->domain == domain)
235
{
236
tpp = &(p->tag);
237
return (0);
238
}
239
}
240
else
241
{
242
cnt++;
243
if (!sp)
244
ep = sp = p;
245
else
246
ep = p;
247
}
248
}
249
}
250
if (mode)
251
return (-1);
252
253
switch (cnt)
254
{
255
case 0:
256
if (strcmp(v, "BASE") == 0)
257
{
258
/* return the base tag */
259
for (p =list; p; p = p->next)
260
{
261
if (ISBASE(p->tag))
262
{
263
tpp = &(p->tag);
264
return (0);
265
}
266
}
267
message((0, "can find the base"));
268
return (-1);
269
}
270
else if (strcmp(v, "LATEST") == 0)
271
{
272
/* return the latest one */
273
for (p = list, mtime = 0L; p; p = p->next)
274
{
275
if (p->tag->stat.st_mtime > mtime)
276
{
277
*tpp = p->tag;
278
mtime = p->tag->stat.st_mtime;
279
}
280
}
281
return (0);
282
}
283
else
284
return (-1);
285
case 1:
286
*tpp = sp->tag;
287
return (0);
288
default:
289
/*
290
* return the latest one
291
*/
292
for (p = sp, mtime = 0L; p != ep->next; p = p->next)
293
{
294
if (p->tag->stat.st_mtime > mtime)
295
{
296
*tpp = p->tag;
297
mtime = p->tag->stat.st_mtime;
298
}
299
}
300
return (0);
301
}
302
}
303
304
305
/*
306
* mode = 0 any;
307
* mode = 1 domain must match
308
*/
309
310
int lookup_tag_t(tbl, total, version, domain, mode)
311
register rdirent_t** tbl;
312
int total;
313
char* version;
314
int domain;
315
int mode;
316
{
317
register char* v;
318
register int i;
319
int cnt = 0;
320
int r;
321
322
323
if (version && *version)
324
v = version;
325
else
326
v = "LATEST";
327
328
for (i = 0; i < total; i++)
329
{
330
if (strcmp(tbl[i]->tag->version, v) == 0)
331
{
332
if (domain)
333
{
334
if (tbl[i]->tag->domain == domain)
335
return (i);
336
}
337
else
338
{
339
cnt++;
340
r = i;
341
}
342
}
343
}
344
345
if (mode)
346
return (-1);
347
348
if (cnt)
349
return (r);
350
351
if (strcmp(v, "BASE") == 0 || strcmp(v, "base") == 0)
352
{
353
for (i = 0; i < total; i++)
354
{
355
if (ISBASE(tbl[i]->tag))
356
return (i);
357
}
358
message((0, "can find the base"));
359
return (-1);
360
}
361
else if (strcmp(v, "LATEST") == 0 || strcmp(v, "LATEST") == 0)
362
return (total-1);
363
else
364
return (-1);
365
366
}
367
368
static char* MONTH[12]=
369
{
370
"Jan", "Feb", "Mar",
371
"Apr", "May", "Jun",
372
"Jul", "Aug", "Sep",
373
"Oct", "Nov", "Dec",
374
};
375
376
377
378
int pattern2time(pattern, to)
379
char* pattern;
380
time_t* to;
381
{
382
char buf[1024];
383
register char* s;
384
int dd, yy, hh, mm, ss;
385
char month[10];
386
char tbuf[128];
387
int flag = 0;
388
int mon;
389
390
391
message((5, "pattern2time ++ [%s]", pattern));
392
393
#define LINIT() (yy = 0, ss = 59, mm = 59, hh = 23)
394
395
LINIT();
396
397
if (*pattern == '(')
398
{
399
for (s=buf, pattern++; *pattern && *pattern != ')'; s++, pattern++)
400
{
401
*s = *pattern;
402
if (*s == '/')
403
flag++;
404
}
405
*s = '\0';
406
s = buf;
407
}
408
else
409
{
410
s = pattern;
411
if (strchr(s, '/'))
412
flag++;
413
}
414
if (flag)
415
{
416
if ((sfsscanf(s, "%d/%d/%d", &mon, &dd, &yy)) != 3)
417
return (-1);
418
if (mon <= 12)
419
strcpy(month, MONTH[--mon]);
420
else if (dd <= 12)
421
{
422
strcpy(month, MONTH[--dd]);
423
dd = mon;
424
}
425
else
426
return (-1);
427
}
428
else if (
429
(LINIT(), sfsscanf(s, "%s %d %d %d:%d:%d", month, &dd, &yy, &hh, &mm, &ss) != 6) &&
430
(LINIT(), sfsscanf(s, "%s %d %d:%d:%d", month, &dd, &hh, &mm, &ss) != 5) &&
431
(LINIT(), sfsscanf(s, "%s %d %d %d:%d", month, &dd, &yy, &hh, &mm) != 5) &&
432
(LINIT(), sfsscanf(s, "%s %d %d:%d", month, &dd, &hh, &mm) != 4) &&
433
(LINIT(), sfsscanf(s, "%s %d %d", month, &dd, &yy) != 3) &&
434
(LINIT(), sfsscanf(s, "%s %d", month, &dd) != 2))
435
{
436
message((5, "can't scan --"));
437
return (-1);
438
}
439
440
441
442
if (yy)
443
sfsprintf(tbuf, sizeof(tbuf), "%s %d %d %d:%d:%d", month, dd, yy, hh, mm, ss);
444
else
445
sfsprintf(tbuf, sizeof(tbuf), "%s %d %d:%d:%d", month, dd, hh, mm, ss);
446
447
message((3, "tbuf [from] %s", tbuf));
448
*to = tmdate(tbuf, (char **) 0, (time_t *) 0);
449
return (0);
450
}
451
452
tag_t* gettagbytime(list, mtime)
453
rdirent_t* list;
454
register time_t mtime;
455
{
456
register rdirent_t* ep;
457
458
for(ep =list; ep; ep =ep->next)
459
{
460
if (ep->tag->stat.st_mtime == mtime)
461
return (ep->tag);
462
}
463
return (NULL);
464
}
465
466
tag_t* gettagbyname(list, name, mode, level)
467
rdirent_t* list;
468
char* name;
469
int mode;
470
int level;
471
{
472
register rdirent_t* ep;
473
474
if (level > MAXLINKS)
475
return (NULL);
476
477
478
for (ep = list; ep; ep = ep->next)
479
{
480
if (strcmp(ep->tag->version, name) == 0)
481
{
482
if (R_ISLINK(ep->tag) && (mode & G_LINK))
483
{
484
return (gettagbyname(list, ep->link, mode, level +1));
485
}
486
return (ep->tag);
487
}
488
}
489
return (NULL);
490
}
491
492
493
char* rs_readlink(s)
494
char* s;
495
{
496
register char* t;
497
498
if ((t = strrchr(s, CHRLINK)) == NULL)
499
return (NULL);
500
501
*t = '\0';
502
return (++t);
503
}
504
505