Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libmam/mam.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1989-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
* Glenn Fowler
23
* AT&T Bell Laboratories
24
*
25
* make abstract machine library
26
*/
27
28
static const char id[] = "\n@(#)$Id: libmam (AT&T Research) 1995-10-11 $\0\n";
29
30
static const char lib[] = "libmam:mam";
31
32
#include <mamlib.h>
33
#include <ctype.h>
34
#include <error.h>
35
#include <tok.h>
36
37
/*
38
* free a rule
39
*/
40
41
static int
42
freerule(register struct rule* r)
43
{
44
register struct list* p;
45
register struct list* x;
46
47
x = r->prereqs;
48
while (p = x)
49
{
50
x = p->next;
51
free(p);
52
}
53
free(r);
54
return(0);
55
}
56
57
/*
58
* get a process context
59
*/
60
61
static struct proc*
62
getproc(struct mam* mp, long pid)
63
{
64
register struct proc* pp;
65
66
for (pp = mp->procs; pp; pp = pp->next)
67
if (pp->pid == pid) return(pp);
68
if (!(pp = newof(0, struct proc, 1, 0)) ||
69
!(pp->bp = pp->fp = newof(0, struct frame, 1, 0)) ||
70
!(pp->rules = hashalloc(0, HASH_set, HASH_ALLOCATE, HASH_free, freerule, HASH_name, "mam-rules", 0)) ||
71
!(pp->vars = hashalloc(0, HASH_set, HASH_ALLOCATE, HASH_free, free, HASH_name, "mam-variables", 0)))
72
{
73
errorf(mp, mp, 2, "out of space");
74
return(0);
75
}
76
pp->next = mp->procs;
77
mp->procs = pp;
78
pp->pid = pid;
79
pp->fp->rule = pp->root = mamrule(pp, "");
80
return(pp);
81
}
82
83
/*
84
* allocate a mam scope
85
*/
86
87
struct mam*
88
mamalloc(void)
89
{
90
register struct mam* mp;
91
92
if (!(mp = newof(0, struct mam, 1, 0))) return(0);
93
mp->id = lib;
94
if (!(mp->main = getproc(mp, 0)))
95
{
96
mamfree(mp);
97
return(0);
98
}
99
return(mp);
100
}
101
102
/*
103
* free a mam scope
104
*/
105
106
void
107
mamfree(register struct mam* mp)
108
{
109
if (mp)
110
{
111
register struct proc* pp;
112
113
while (pp = mp->procs)
114
{
115
mp->procs = pp->next;
116
if (pp->rules) hashfree(pp->rules);
117
if (pp->vars) hashfree(pp->vars);
118
if (pp->pwd) free(pp->pwd);
119
if (pp->view) free(pp->view);
120
if (pp->root) freerule(pp->root);
121
free(pp);
122
}
123
free(mp);
124
}
125
}
126
127
/*
128
* check for rule alias
129
* this covers for an nmake mam output bug
130
*/
131
132
static struct rule*
133
alias(struct proc* pp, const char* name)
134
{
135
char buf[PATH_MAX];
136
137
if (*name != '/' || *pp->fp->rule->name == '/' || !pp->pwd) return(0);
138
sfsprintf(buf, sizeof(buf), "%s/%s", pp->pwd, pp->fp->rule->name);
139
pathcanon(buf, sizeof(buf), 0);
140
if (!streq(buf, name)) return(0);
141
putrule(pp, name, pp->fp->rule);
142
return(pp->fp->rule);
143
}
144
145
/*
146
* set r attributes from s
147
* prereq list pointer returned
148
*/
149
150
static struct list**
151
attributes(struct proc* pp, struct rule* r, char* s)
152
{
153
char* arg;
154
struct list** p = 0;
155
156
while (tokscan(s, &s, " %s ", &arg) == 1)
157
{
158
if (streq(arg, "archive"))
159
r->attributes |= A_archive;
160
else if (streq(arg, "dontcare"))
161
r->attributes |= A_dontcare;
162
else if (streq(arg, "implicit"))
163
p = &pp->fp->rule->implicit;
164
else if (streq(arg, "metarule"))
165
r->attributes |= A_metarule;
166
else if (streq(arg, "virtual"))
167
r->attributes |= A_virtual;
168
}
169
return(p);
170
}
171
172
/*
173
* scan a mam input stream
174
*/
175
176
int
177
mamscan(register struct mam* mp, const char* file)
178
{
179
register struct proc* pp;
180
struct rule* r;
181
struct block* a;
182
char* s;
183
char* op;
184
char* arg;
185
char* val;
186
unsigned long t;
187
int n;
188
Sfio_t* input;
189
char* ofile;
190
int oline;
191
#if __sparc__ /* strcpy() and strcmp() bug() when '\0' is last byte in last page */
192
char buf[8096];
193
#endif
194
195
if (!file) input = sfstdin;
196
else if (!(input = sfopen(NiL, file, "r")))
197
{
198
errorf(mp, mp, 2, "%s: cannot read", file);
199
return(-1);
200
}
201
#if __sparc__
202
sfsetbuf(input, buf, sizeof(buf));
203
#endif
204
ofile = error_info.file;
205
error_info.file = (char*)file;
206
oline = error_info.line;
207
error_info.line = 0;
208
while (s = sfgetr(input, '\n', 1))
209
{
210
error_info.line++;
211
if (tokscan(s, &s, " %s ", &op) != 1) continue;
212
if (isdigit(*op))
213
{
214
if (!(pp = getproc(mp, strtol(op, NiL, 10)))) return(-1);
215
if (tokscan(s, &s, " %s ", &op) != 1) continue;
216
}
217
else pp = mp->main;
218
if (!pp->bp)
219
{
220
errorf(mp, mp, 1, "%s: process %d is finished", op, pp->pid);
221
continue;
222
}
223
if (streq(op, "note"))
224
{
225
/* comment */;
226
}
227
else if (streq(op, "setv"))
228
{
229
tokscan(s, &val, " %s ", &arg);
230
while (isspace(*val)) val++;
231
mamvar(pp, arg, strdup(val));
232
}
233
else if ((n = streq(op, "make")) || streq(op, "prev"))
234
{
235
tokscan(s, &s, " %s ", &arg);
236
if (n) r = mamrule(pp, arg);
237
else if (!(r = getrule(pp, arg)) && !(r = alias(pp, arg)))
238
{
239
errorf(mp, mp, 1, "%s: reference to undefined rule", arg);
240
continue;
241
}
242
mamprereq(pp, pp->fp->rule, r, attributes(pp, r, s));
243
if (n)
244
{
245
if (!pp->fp->next)
246
{
247
if (!(pp->fp->next = newof(0, struct frame, 1, 0)))
248
{
249
errorf(mp, mp, 2, "out of space");
250
return(-1);
251
}
252
pp->fp->next->prev = pp->fp;
253
}
254
pp->fp = pp->fp->next;
255
pp->fp->rule = r;
256
}
257
}
258
else if (streq(op, "exec"))
259
{
260
tokscan(s, &s, " %s ", &arg);
261
if (streq(arg, "-"))
262
{
263
if (!pp->fp->prev) goto missing;
264
r = pp->fp->rule;
265
}
266
else r = mamrule(pp, arg);
267
while (isspace(*s)) s++;
268
if (!(a = newof(0, struct block, 1, 0)))
269
{
270
errorf(mp, mp, 2, "out of space");
271
return(-1);
272
}
273
a->data = strdup(s);
274
if (r->atail) r->atail->next = a;
275
else r->action = a;
276
r->atail = a;
277
}
278
else if (streq(op, "done"))
279
{
280
if (!pp->fp->prev) goto missing;
281
tokscan(s, &s, " %s ", &arg);
282
if (!streq(pp->fp->rule->name, arg) && !alias(pp, arg))
283
errorf(mp, mp, 1, "%s: %s %s expected", arg, op, pp->fp->rule->name);
284
attributes(pp, pp->fp->rule, s);
285
pp->fp = pp->fp->prev;
286
}
287
else if (streq(op, "bind"))
288
{
289
tokscan(s, NiL, " %s %lu %s ", &arg, &t, &val);
290
if (!(r = getrule(pp, arg)) && !(r = alias(pp, arg)))
291
{
292
errorf(mp, mp, 1, "%s: reference to undefined rule", arg);
293
continue;
294
}
295
if (val) r->bound = strdup(val);
296
r->time = t;
297
}
298
else if (streq(op, "code"))
299
{
300
tokscan(s, NiL, " %s %d ", &arg, &n);
301
if (!(r = getrule(pp, arg)) && !(r = alias(pp, arg)))
302
{
303
errorf(mp, mp, 1, "%s: reference to undefined rule", arg);
304
continue;
305
}
306
r->status = n;
307
}
308
else if (streq(op, "info"))
309
{
310
tokscan(s, &s, " %s ", &arg);
311
if (streq(arg, "mam"))
312
{
313
tokscan(s, NiL, " %s ", &arg);
314
if (mp->version) free(mp->version);
315
mp->version = strdup(arg);
316
}
317
else if (streq(arg, "start"))
318
{
319
tokscan(s, NiL, " %lu %d ", &pp->start, &n);
320
if (!pp->pid) pp->pid = n;
321
else if (pp->parent = getproc(mp, n))
322
{
323
register struct proc* ppp = pp->parent;
324
325
if (!ppp->child) ppp->child = pp;
326
else if (!ppp->child->sibling) ppp->child->sibling = ppp->child->stail = pp;
327
else ppp->child->stail = ppp->child->stail->sibling = pp;
328
}
329
}
330
else if (streq(arg, "finish"))
331
{
332
register struct frame* fp;
333
334
tokscan(s, NiL, " %lu %d ", &pp->finish, &pp->status);
335
if (pp->fp != pp->bp)
336
errorf(mp, mp, 1, "%s: not enough done ops", arg);
337
while (fp = pp->bp)
338
{
339
pp->bp = fp->next;
340
free(fp);
341
}
342
}
343
else if (streq(arg, "pwd"))
344
{
345
tokscan(s, NiL, " %s ", &val);
346
pp->pwd = strdup(val);
347
}
348
else if (streq(arg, "view"))
349
{
350
tokscan(s, NiL, " %s ", &val);
351
pp->view = strdup(val);
352
}
353
else errorf(mp, mp, 1, "%s: unknown %s attribute", arg, op);
354
}
355
else errorf(mp, mp, 1, "%s: unknown op ignored", op);
356
continue;
357
missing:
358
errorf(mp, mp, 1, "%s: missing make op", op);
359
}
360
if (input != sfstdin) sfclose(input);
361
error_info.file = ofile;
362
error_info.line = oline;
363
return(0);
364
}
365
366
/*
367
* return old rule pointer if found
368
* otherwise make a new rule
369
*/
370
371
struct rule*
372
mamrule(register struct proc* pp, const char* name)
373
{
374
struct rule* r;
375
376
if (!(r = getrule(pp, name)) && (r = newof(0, struct rule, 1, 0)))
377
r->name = putrule(pp, 0, r);
378
return(r);
379
}
380
381
/*
382
* return old var pointer if found
383
* otherwise make a new var
384
* if value!=0 then var value is set
385
*/
386
387
struct var*
388
mamvar(register struct proc* pp, const char* name, const char* value)
389
{
390
struct var* v;
391
392
if (!(v = getvar(pp, name)))
393
{
394
if (!(v = newof(0, struct var, 1, 0))) return(0);
395
v->name = putvar(pp, 0, v);
396
}
397
if (value) v->value = (char*)value;
398
return(v);
399
}
400
401
/*
402
* add x to r prereq list
403
*/
404
405
void
406
mamprereq(struct proc* pp, struct rule* r, struct rule* x, struct list** p)
407
{
408
struct list* q;
409
410
NoP(pp);
411
if (x != r)
412
{
413
if (!p) p = &r->prereqs;
414
if (q = *p)
415
{
416
while (q)
417
{
418
if (x == q->rule) break;
419
if (!q->next)
420
{
421
if (!(q->next = newof(0, struct list, 1, 0))) return;
422
q->next->rule = x;
423
break;
424
}
425
q = q->next;
426
}
427
}
428
else if (!(*p = newof(0, struct list, 1, 0))) return;
429
else (*p)->rule = x;
430
}
431
}
432
433