Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libjcl/parse.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2003-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
/*
23
* Glenn Fowler
24
* AT&T Research
25
*
26
* jcl step parser from the description in
27
* http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/iea2b600/
28
*/
29
30
#include "jcllib.h"
31
32
#include <error.h>
33
#include <tm.h>
34
35
#define DDLIB(s) (streq((s),"JCLLIB")||streq((s),"JOBLIB")||streq((s),"PROCLIB"))
36
#define ID1(c) (isalpha(c)||(c)=='_'||(c)=='$'||(c)=='@'||(c)=='#')
37
#define ID(c) (isalnum(c)||(c)=='_'||(c)=='$'||(c)=='@'||(c)=='#')
38
39
static char null_data[2];
40
static char* null = &null_data[1];
41
42
static char dummy[] = "/dev/null";
43
44
/* vendor SS in the standard namespace -- great */
45
46
#undef SS
47
#undef ST
48
49
static char EQ[] = "=";
50
static char END[] = "\\\\";
51
static char SS[] = "//";
52
static char ST[] = "*";
53
54
/*
55
* common syntax error message
56
*/
57
58
static void
59
syntax(Jcl_t* jcl, int level, char* token, char* expected, char* type)
60
{
61
if (jcl->disc->errorf && (level > 1 || (jcl->flags & JCL_WARN)))
62
{
63
if (expected)
64
(*jcl->disc->errorf)(NiL, jcl->disc, level, "%s: %s expected", token ? token : "EOF", expected);
65
else if (token)
66
(*jcl->disc->errorf)(NiL, jcl->disc, level, "%s: unknown %s", token, type ? type : "keyword");
67
else
68
(*jcl->disc->errorf)(NiL, jcl->disc, level, "unexpected EOF");
69
}
70
}
71
72
/*
73
* push a string on the input token stream
74
*/
75
76
static int
77
push(Jcl_t* jcl, char* s)
78
{
79
if (jcl->pushed >= elementsof(jcl->push))
80
{
81
if (jcl->disc->errorf)
82
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "%s: too much pushback", s);
83
return -1;
84
}
85
memcpy(&jcl->push[jcl->pushed++], &jcl->data, sizeof(Push_t));
86
memset(&jcl->data, 0, sizeof(Push_t));
87
jcl->data = s;
88
return 0;
89
}
90
91
/*
92
* push back one token or entire card if tok==0
93
*/
94
95
static void
96
xel(register Jcl_t* jcl, register char* tok)
97
{
98
if (tok)
99
{
100
jcl->peekpeek = jcl->peek;
101
jcl->peek = tok;
102
}
103
else
104
{
105
jcl->data = strcpy(jcl->card, jcl->record ? jcl->record : null);
106
jcl->peek = jcl->peekpeek = 0;
107
jcl->last = 0;
108
}
109
}
110
111
/*
112
* read the next input card
113
*/
114
115
static char*
116
card(register Jcl_t* jcl)
117
{
118
register char* s;
119
size_t n;
120
121
for (;;)
122
{
123
if (s = jcl->peekcard)
124
{
125
jcl->peekcard = 0;
126
break;
127
}
128
if (!jcl->sp)
129
break;
130
if (s = sfgetr(jcl->sp, '\n', 1))
131
{
132
error_info.line++;
133
if (!jcl->canon && (n = sfvalue(jcl->sp)) > 1)
134
{
135
if (s[n - 1] == '\r')
136
s[n - 1] = 0;
137
if (n > CARD)
138
s[CARD] = 0;
139
}
140
message((-6, "card %4d %s", error_info.line, s));
141
break;
142
}
143
if (!jcl->include->prev || jclpop(jcl) <= 0)
144
break;
145
}
146
return s;
147
}
148
149
/*
150
* expand control-m variable s with leading %% stripped
151
* pointer to next char in s returned
152
*/
153
154
static char*
155
autoexpand(register Jcl_t* jcl, register char* s, Sfio_t* sp)
156
{
157
register char* t;
158
register char* v;
159
register int c;
160
int o;
161
Sfio_t* tp;
162
163
if (*s == '.')
164
return s + 1;
165
tp = 0;
166
o = sfstrtell(jcl->vp);
167
sfputr(jcl->vp, JCL_AUTO, -1);
168
for (;;)
169
{
170
if (!(c = *s++) || c == '.')
171
{
172
s--;
173
break;
174
}
175
else if (c == '%' && *s == '%')
176
{
177
if (*++s == '.')
178
{
179
s++;
180
break;
181
}
182
if (!tp && !(tp = sfstropen()))
183
nospace(jcl, NiL);
184
s = autoexpand(jcl, s, tp);
185
if (!(t = sfstruse(tp)))
186
nospace(jcl, NiL);
187
if (!ID(*t))
188
break;
189
sfputr(jcl->vp, t, -1);
190
*t = 0;
191
}
192
else if (ID(c))
193
sfputc(jcl->vp, c);
194
else
195
{
196
s--;
197
break;
198
}
199
}
200
sfputc(jcl->vp, 0);
201
t = sfstrseek(jcl->vp, o, SEEK_SET);
202
if (jcl->flags & JCL_PARAMETERIZE)
203
sfprintf(sp, "${%s}", t);
204
else
205
{
206
if (jcl->flags & JCL_LISTAUTOEDITS)
207
uniq(t + sizeof(JCL_AUTO) - 1, NiL, 0, jcl->disc);
208
if (v = lookup(jcl, t, NiL, 0, DEFAULT|MUST))
209
sfputr(sp, v, -1);
210
else
211
sfprintf(sp, "%%%%%s.", t);
212
}
213
if (tp)
214
{
215
sfputr(sp, sfstrbase(tp), -1);
216
sfstrclose(tp);
217
}
218
return s;
219
}
220
221
/*
222
* set *r to point to the next token in s
223
* pointer to next char in s returned
224
*/
225
226
static char*
227
autotoken(register Jcl_t* jcl, register char* s, char** r, int set)
228
{
229
char* t;
230
int o;
231
232
o = sfstrtell(jcl->tp);
233
while (*s == ' ')
234
s++;
235
for (t = s; *s; s++)
236
if (*s == ' ')
237
{
238
*s++ = 0;
239
break;
240
}
241
else if (*s == '%' && *(s + 1) == '%')
242
{
243
if (set)
244
{
245
set = 0;
246
s++;
247
}
248
else
249
{
250
if (s - t)
251
sfwrite(jcl->tp, t, s - t);
252
s = autoexpand(jcl, s + 2, jcl->tp);
253
if (*s != '.')
254
{
255
sfputc(jcl->tp, 0);
256
t = fmtbuf(sfstrtell(jcl->tp) - o);
257
strcpy(t, sfstrseek(jcl->tp, o, SEEK_SET));
258
break;
259
}
260
t = s + 1;
261
}
262
}
263
*r = t;
264
return s;
265
}
266
267
/*
268
* set *p to point to the next number token value in s
269
* pointer to next char in s returned
270
*/
271
272
static char*
273
autonumber(register Jcl_t* jcl, char* s, long* r)
274
{
275
char* t;
276
char* b;
277
278
while (*s == ' ')
279
s++;
280
b = s;
281
*r = strtol(s, &t, 10);
282
if (s == t && jcl->disc->errorf)
283
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%s: invalid control-m numeric operand", b);
284
return t;
285
}
286
287
#define NOOPERAND() do { \
288
if (p) \
289
{ \
290
p = sfstrseek(jcl->tp, o, SEEK_SET); \
291
if (jcl->disc->errorf) \
292
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s: %s: left operand not expected", f, p); \
293
} \
294
} while (0)
295
296
#define OPERAND() do { \
297
if (p) \
298
{ \
299
p = 0; \
300
t = sfstrseek(jcl->tp, o, SEEK_SET); \
301
} \
302
else \
303
{ \
304
t = ""; \
305
if (jcl->disc->errorf) \
306
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s: left operand expected", f); \
307
} \
308
} while (0)
309
310
/*
311
* expand control-m expression from s into sp
312
* pointer to next char in s returned
313
*/
314
315
static char*
316
autoeval(register Jcl_t* jcl, register char* s, char** r)
317
{
318
char* b;
319
char* e;
320
char* f;
321
char* p;
322
char* t;
323
char* v;
324
int o;
325
int y;
326
long i;
327
long j;
328
time_t x;
329
Tm_t* tm;
330
331
o = sfstrtell(jcl->tp);
332
p = 0;
333
for (;;)
334
{
335
while (*s == ' ')
336
s++;
337
if (!*s)
338
break;
339
if (*s == '%' && *(s + 1) == '%')
340
{
341
b = s += 2;
342
if (*s == '$')
343
{
344
s++;
345
y = 1;
346
}
347
else
348
y = 0;
349
for (f = s; ID(*s); s++);
350
if (*s)
351
*s++ = 0;
352
switch (*f)
353
{
354
case 'C':
355
if (streq(f, "CALCDATE") || streq(f, "CALCDTE"))
356
{
357
NOOPERAND();
358
s = autotoken(jcl, s, &t, 0);
359
s = autonumber(jcl, s, &i);
360
x = tmscan(t, &e, y ? "%Y%m%d" : "%y%m%d", &v, NiL, 0);
361
if (jcl->disc->errorf && (*e || *v))
362
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s: %s: invalid control-m date operand", f, t);
363
tm = tmmake(&x);
364
tm->tm_mday += i;
365
x = tmtime(tm, 0);
366
sfputr(jcl->tp, fmttime(y ? "%Y%m%d" : "%y%m%d", x), -1);
367
goto done;
368
}
369
break;
370
case 'G':
371
if (streq(f, "GREG"))
372
{
373
NOOPERAND();
374
s = autotoken(jcl, s, &t, 0);
375
x = tmscan(t, &e, y ? "%Y%j" : "%y%j", &v, NiL, 0);
376
if (jcl->disc->errorf && (*e || *v))
377
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s: %s: invalid control-m date operand", f, t);
378
sfputr(jcl->tp, fmttime(y ? "%Y%m%d" : "%y%m%d", x), -1);
379
goto done;
380
}
381
break;
382
case 'J':
383
if (streq(f, "JULIAN"))
384
{
385
NOOPERAND();
386
s = autotoken(jcl, s, &t, 0);
387
x = tmscan(t, &e, y ? "%Y%m%d" : "%y%m%d", &v, NiL, 0);
388
if (jcl->disc->errorf && (*e || *v))
389
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s: %s: invalid control-m date operand", f, t);
390
sfputr(jcl->tp, fmttime(y ? "%Y%j" : "%y%j", x), -1);
391
goto done;
392
}
393
break;
394
case 'L':
395
if (streq(f, "LEAP"))
396
{
397
NOOPERAND();
398
s = autotoken(jcl, s, &t, 0);
399
x = tmscan(t, &e, y ? "%Y%m%d" : "%y%m%d", &v, NiL, 0);
400
if (jcl->disc->errorf && (*e || *v))
401
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s: %s: invalid control-m date operand", f, t);
402
sfprintf(jcl->tp, "%d", tmisleapyear((int)strtol(fmttime("%Y", x), NiL, 10)));
403
goto done;
404
}
405
break;
406
case 'M':
407
if (streq(f, "MINUS"))
408
{
409
NOOPERAND();
410
autonumber(jcl, t, &i);
411
s = autonumber(jcl, s, &j);
412
sfprintf(jcl->tp, "%ld", i - j);
413
goto done;
414
}
415
break;
416
case 'P':
417
if (streq(f, "PLUS"))
418
{
419
OPERAND();
420
autonumber(jcl, t, &i);
421
s = autonumber(jcl, s, &j);
422
sfprintf(jcl->tp, "%ld", i + j);
423
goto done;
424
}
425
break;
426
case 'S':
427
if (streq(f, "SUBSTR"))
428
{
429
NOOPERAND();
430
s = autotoken(jcl, s, &t, 0);
431
s = autonumber(jcl, s, &i);
432
s = autonumber(jcl, s, &j);
433
while (--i > 0 && *t)
434
t++;
435
for (v = t; j-- > 0 && *v; v++);
436
sfwrite(jcl->tp, t, v - t);
437
goto done;
438
}
439
break;
440
case 'W':
441
if (streq(f, "WCALC"))
442
{
443
NOOPERAND();
444
goto notyet;
445
}
446
else if (streq(f, "WEEK#"))
447
{
448
NOOPERAND();
449
s = autotoken(jcl, s, &t, 0);
450
x = tmscan(t, &e, y ? "%Y%m%d" : "%y%m%d", &v, NiL, 0);
451
if (jcl->disc->errorf && (*e || *v))
452
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s: %s: invalid control-m date operand", f, t);
453
sfputr(jcl->tp, fmttime("%W", x), -1);
454
goto done;
455
}
456
else if (streq(f, "WEEKDAY"))
457
{
458
NOOPERAND();
459
s = autotoken(jcl, s, &t, 0);
460
x = tmscan(t, &e, y ? "%Y%m%d" : "%y%m%d", &v, NiL, 0);
461
if (jcl->disc->errorf && (*e || *v))
462
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s: %s: invalid control-m date operand", f, t);
463
sfputr(jcl->tp, fmttime("%w", x), -1);
464
goto done;
465
}
466
break;
467
}
468
if (p)
469
sfputc(jcl->tp, ' ');
470
s = autoexpand(jcl, b, jcl->tp);
471
}
472
else
473
{
474
if (p)
475
sfputc(jcl->tp, ' ');
476
s = autotoken(jcl, s, &p, 0);
477
sfputr(jcl->tp, p, -1);
478
}
479
sfputc(jcl->tp, 0);
480
sfstrseek(jcl->tp, -1, SEEK_CUR);
481
p = sfstrbase(jcl->tp) + o;
482
}
483
done:
484
sfputc(jcl->tp, 0);
485
*r = fmtbuf(sfstrtell(jcl->tp) - o);
486
strcpy(*r, sfstrseek(jcl->tp, o, SEEK_SET));
487
return s;
488
notyet:
489
if (jcl->disc->errorf)
490
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s: control-m function not implemented", f);
491
return s;
492
}
493
494
#define CMD_DD 2
495
#define CMD_EXEC 4
496
497
/*
498
* return the next token
499
*/
500
501
static char*
502
lex(register Jcl_t* jcl)
503
{
504
register char* s;
505
register char* t;
506
register char* p;
507
register int n;
508
register int a;
509
register int q;
510
register int x;
511
register int c;
512
register int m;
513
char* v;
514
char* w;
515
int j;
516
int e;
517
#if DEBUG
518
long line;
519
#endif
520
521
if (s = jcl->peek)
522
{
523
jcl->peek = jcl->peekpeek;
524
jcl->peekpeek = 0;
525
goto token;
526
}
527
again:
528
while (*jcl->data == 0)
529
{
530
if (jcl->pushed)
531
{
532
memcpy(&jcl->data, &jcl->push[--jcl->pushed], sizeof(Push_t));
533
if (jcl->last == END)
534
{
535
s = END;
536
goto token;
537
}
538
}
539
else if (jcl->data != null)
540
{
541
jcl->data = null;
542
s = END;
543
goto token;
544
}
545
else
546
{
547
a = 0;
548
e = 0;
549
j = 0;
550
n = 0;
551
q = 0;
552
x = 0;
553
for (;;)
554
{
555
if (!(s = card(jcl)))
556
{
557
if (x && jcl->disc->errorf)
558
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "unexpected EOF in continuation");
559
jcl->data = null;
560
return 0;
561
}
562
if (!sfstrtell(jcl->cp))
563
line = error_info.line;
564
if (*s == '/' && (*(s + 1) == '*' || *(s + 1) == '/' && *(s + 2) == '*'))
565
{
566
if (*++s == '/')
567
s++;
568
if (*s == '*')
569
s++;
570
while (*s == ' ')
571
s++;
572
if (*s == '%' && *(s + 1) == '%')
573
{
574
for (t = s += 2; *s && *s != ' '; s++);
575
if (*s)
576
for (*s++ = 0; *s == ' '; s++);
577
if (streq(t, "SET") && *s == '%' && *(s + 1) == '%')
578
{
579
for (s = autotoken(jcl, s, &v, 1); *s == ' '; s++);
580
if (*s == '=')
581
{
582
while (*++s == ' ');
583
s = autoeval(jcl, s, &w);
584
jclsym(jcl, v, w, 0);
585
t = 0;
586
}
587
}
588
if (t && jcl->disc->errorf)
589
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%s: %s: not implemented", t - 2, s);
590
}
591
if (x < 0)
592
break;
593
continue;
594
}
595
if (*s != '/' || *(s + 1) != '/')
596
{
597
if (jcl->disc->errorf)
598
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "%-.*s...: invalid card: // expected", 8, s);
599
return 0;
600
}
601
m = sfvalue(jcl->sp) > CARD && !isspace(s[CARD-1]) && !jcl->canon;
602
if (x)
603
{
604
if (*(s += 2))
605
{
606
if (!isspace(*s))
607
{
608
jcl->peekcard = s - 2;
609
break;
610
}
611
while (isspace(*++s));
612
}
613
if (x < 1)
614
{
615
if (m)
616
continue;
617
break;
618
}
619
if (*s == 0)
620
{
621
x = 0;
622
continue;
623
}
624
}
625
p = 0;
626
for (;;)
627
{
628
switch (c = *s++)
629
{
630
case 0:
631
if (p)
632
{
633
s = p;
634
p = 0;
635
continue;
636
}
637
break;
638
case '=':
639
if (!q && *s == '\'' && *(s + 1) == '\'' && (*(s + 2) == ',' || isspace(*(s + 2)) || *(s + 2) == 0))
640
s += 2;
641
sfputc(jcl->cp, c);
642
if (!q)
643
switch (j)
644
{
645
case CMD_DD:
646
if (*(s - 2) == 'P' && *(s - 3) == 'M' && *(s - 4) == 'A' && !ID(*(s - 5)) ||
647
*(s - 2) == 'H' && *(s - 3) == 'T' && *(s - 4) == 'A' && *(s - 5) == 'P' && !ID(*(s - 6)) ||
648
*(s - 2) == 'S' && *(s - 3) == 'Y' && *(s - 4) == 'S' && *(s - 5) == 'B' && *(s - 6) == 'U' && *(s - 7) == 'T' && !ID(*(s - 8)))
649
e = 1;
650
break;
651
case CMD_EXEC:
652
if (*(s - 2) == 'T' && *(s - 3) == 'C' && *(s - 4) == 'C' && *(s - 5) == 'A' && !ID(*(s - 6)) ||
653
*(s - 2) == 'M' && *(s - 3) == 'R' && *(s - 4) == 'A' && *(s - 5) == 'P' && !ID(*(s - 6)))
654
e = 1;
655
break;
656
}
657
continue;
658
case '\'':
659
if (!p)
660
{
661
if (!q)
662
q = e ? -1 : 1;
663
else if (*s == '\'')
664
{
665
s++;
666
sfputc(jcl->cp, c);
667
}
668
else
669
q = 0;
670
}
671
sfputc(jcl->cp, c);
672
continue;
673
case '&':
674
if (p)
675
sfputc(jcl->cp, c);
676
else if (*s == '&')
677
{
678
s++;
679
if (q > 0)
680
sfputc(jcl->cp, c);
681
sfputc(jcl->cp, c);
682
}
683
else if (!ID(*s))
684
sfputc(jcl->cp, c);
685
else
686
{
687
for (t = s; ID(*s); s++);
688
c = *s;
689
*s = 0;
690
v = lookup(jcl, t, NiL, 0, MUST);
691
*s = c;
692
if (v)
693
{
694
if (c == '.')
695
s++;
696
p = s;
697
s = v;
698
}
699
else
700
for (t--; t < s; t++)
701
sfputc(jcl->cp, *t);
702
}
703
continue;
704
case '%':
705
if (p || *s != '%' || *(s + 1) == '#')
706
sfputc(jcl->cp, c);
707
else
708
{
709
p = autotoken(jcl, s - 1, &v, 0);
710
s = v;
711
}
712
continue;
713
default:
714
if (!q)
715
{
716
if (e && !ID(c))
717
e = 0;
718
if (isspace(c))
719
{
720
if ((x = sfstrtell(jcl->cp)) && *(t = sfstrbase(jcl->cp) + x - 1) == ' ')
721
continue;
722
if (!n && ++a >= 3)
723
break;
724
725
/*
726
* { CMD_DD IF } don't follow the norm
727
*/
728
729
if (a == 2)
730
{
731
/*
732
* a DD may override/augment DD in another procedures so
733
* variable expansion must be delayed until the other
734
* procedure context is active
735
*/
736
737
if (*t == 'D' && *(t - 1) == 'D' && *(t - 2) == ' ')
738
{
739
j = CMD_DD;
740
if (memchr(sfstrbase(jcl->cp), '.', x))
741
p = null;
742
}
743
else if (*t == 'C' && *(t - 1) == 'E' && *(t - 2) == 'X' && *(t - 3) == 'E' && *(t - 4) == ' ')
744
j = CMD_EXEC;
745
else if (*t == 'F' && *(t - 1) == 'I' && *(t - 2) == ' ')
746
n = 1;
747
}
748
c = ' ';
749
}
750
}
751
sfputc(jcl->cp, c);
752
continue;
753
}
754
break;
755
}
756
if (q)
757
x = 1;
758
else
759
{
760
t = sfstrbase(jcl->cp);
761
for (s = sfstrseek(jcl->cp, 0, SEEK_CUR); s > t && *(s - 1) == ' '; s--);
762
sfstrseek(jcl->cp, s - t, SEEK_SET);
763
if (a < 2 || s == t || *(s - 1) != ',')
764
{
765
if (!m)
766
break;
767
x = -1;
768
}
769
else
770
x = 1;
771
}
772
}
773
if (!(jcl->data = jcl->card = sfstruse(jcl->cp)))
774
nospace(jcl, NiL);
775
sfputr(jcl->rp, jcl->card, -1);
776
if (!(jcl->record = sfstruse(jcl->rp)))
777
nospace(jcl, NiL);
778
message((-4, "record %4d %s", line, jcl->record));
779
}
780
}
781
s = jcl->data;
782
n = 0;
783
q = 0;
784
for (;;)
785
{
786
switch (*jcl->data++)
787
{
788
case 0:
789
jcl->data--;
790
if (q)
791
{
792
if (jcl->disc->errorf)
793
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "unbalanced '...'");
794
return 0;
795
}
796
if (n)
797
{
798
if (jcl->disc->errorf)
799
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "unbalanced (...)");
800
return 0;
801
}
802
goto token;
803
case '/':
804
if (s == jcl->card)
805
{
806
if (*jcl->data == '/')
807
{
808
jcl->data++;
809
if (*jcl->data == '*')
810
{
811
jcl->data = null;
812
goto again;
813
}
814
if (*jcl->data == ' ' || *jcl->data == 0)
815
{
816
xel(jcl, null);
817
if (*jcl->data == ' ')
818
jcl->data++;
819
else
820
xel(jcl, null);
821
}
822
s = SS;
823
goto token;
824
}
825
else if (*jcl->data == '*')
826
{
827
jcl->data = null;
828
goto again;
829
}
830
}
831
continue;
832
case '=':
833
if (!n && !q && jcl->last != EQ)
834
{
835
if (*jcl->data == '\'' && *(jcl->data + 1) == '\'' && (*(jcl->data + 2) == ',' || isspace(*(jcl->data + 2)) || *(jcl->data + 2) == 0))
836
{
837
*(jcl->data - 1) = 0;
838
jcl->data += 2;
839
xel(jcl, null);
840
if ((jcl->data - s) == 3)
841
{
842
s = EQ;
843
goto token;
844
}
845
}
846
else
847
{
848
if (*jcl->data == ',' || *jcl->data == ' ' || *jcl->data == 0)
849
xel(jcl, null);
850
if ((jcl->data - s) == 1)
851
{
852
s = EQ;
853
goto token;
854
}
855
}
856
xel(jcl, EQ);
857
break;
858
}
859
continue;
860
case '*':
861
if (!n && !q && (jcl->data - s) == 1 && (*jcl->data == ',' || *jcl->data == ' ' || *jcl->data == 0))
862
{
863
s = ST;
864
goto token;
865
}
866
continue;
867
case '(':
868
if (!q)
869
n++;
870
continue;
871
case ')':
872
if (!q)
873
{
874
if (n > 0)
875
n--;
876
else if (jcl->pushed && *jcl->data == 0)
877
break;
878
}
879
continue;
880
case ',':
881
if (!n && !q)
882
{
883
if ((jcl->data - s) > 1)
884
break;
885
s = jcl->data;
886
}
887
continue;
888
case ' ':
889
if (!n && !q)
890
break;
891
continue;
892
case '\'':
893
if (!q)
894
q = 1;
895
else if (*jcl->data == '\'')
896
jcl->data++;
897
else
898
q = 0;
899
s++;
900
t = jcl->data;
901
while (--t >= s)
902
*t = *(t - 1);
903
continue;
904
default:
905
continue;
906
}
907
break;
908
}
909
*(jcl->data - 1) = 0;
910
token:
911
message((-8, "lex %4d %s", error_info.line, s));
912
return jcl->last = s;
913
}
914
915
/*
916
* eat the remainder of the card and its continuations
917
*/
918
919
static void
920
eat(Jcl_t* jcl)
921
{
922
register char* tok;
923
924
if (jcl->last != END)
925
while ((tok = lex(jcl)) && tok != END);
926
}
927
928
/*
929
* parse a COND [sub]expression
930
*/
931
932
static Jclcond_t*
933
cond(register Jcl_t* jcl, char* b, char** p)
934
{
935
register char* s;
936
register char* t;
937
register Jclcond_t* x;
938
register Jclcond_t* y;
939
char* e;
940
941
s = b;
942
y = 0;
943
for (;;)
944
{
945
if (*s == '(')
946
{
947
if (!(x = cond(jcl, s + 1, &e)))
948
return 0;
949
s = e;
950
}
951
else if (!(x = vmnewof(jcl->vs, NiL, Jclcond_t, 1, 0)))
952
{
953
nospace(jcl, NiL);
954
return 0;
955
}
956
else
957
{
958
x->code = (short)strtol(s, &e, 10);
959
if (*e == ',')
960
{
961
s = e + 2;
962
switch (*(e + 1))
963
{
964
case 'E':
965
switch (*s)
966
{
967
case 'Q':
968
x->op = JCL_COND_EQ;
969
break;
970
default:
971
goto bad;
972
}
973
break;
974
case 'G':
975
switch (*s)
976
{
977
case 'E':
978
x->op = JCL_COND_GE;
979
break;
980
case 'T':
981
x->op = JCL_COND_GT;
982
break;
983
default:
984
goto bad;
985
}
986
break;
987
case 'L':
988
switch (*s)
989
{
990
case 'E':
991
x->op = JCL_COND_LE;
992
break;
993
case 'T':
994
x->op = JCL_COND_LT;
995
break;
996
default:
997
goto bad;
998
}
999
break;
1000
case 'N':
1001
switch (*s)
1002
{
1003
case 'E':
1004
x->op = JCL_COND_NE;
1005
break;
1006
default:
1007
goto bad;
1008
}
1009
break;
1010
default:
1011
goto bad;
1012
}
1013
if (*++s == ',')
1014
{
1015
for (t = ++s; *s && *s != ',' && *s != ')'; s++);
1016
if (!(x->step = vmnewof(jcl->vs, 0, char, s - t, 1)))
1017
{
1018
nospace(jcl, NiL);
1019
return 0;
1020
}
1021
memcpy(x->step, t, s - t);
1022
}
1023
}
1024
else
1025
{
1026
for (t = s; *s && *s != ',' && *s != ')'; s++);
1027
if ((s - t) != 4)
1028
goto bad;
1029
if (strneq(t, "EVEN", 4))
1030
x->op = JCL_COND_EVEN;
1031
else if (strneq(t, "ONLY", 4))
1032
x->op = JCL_COND_ONLY;
1033
else
1034
goto bad;
1035
}
1036
}
1037
if (y)
1038
y->next = x;
1039
else
1040
y = x;
1041
if (*s == 0)
1042
break;
1043
if (*s == ')')
1044
{
1045
s++;
1046
break;
1047
}
1048
if (*s++ != ',')
1049
goto bad;
1050
}
1051
if (p)
1052
*p = s;
1053
else if (*s)
1054
goto bad;
1055
return y;
1056
bad:
1057
syntax(jcl, 2, b, "(CODE,LT|LE|EQ|NE|GE|GT[,STEP])|EVEN|ONLY", NiL);
1058
return 0;
1059
}
1060
1061
/*
1062
* return next arg token
1063
* *p points to optional =val
1064
*/
1065
1066
static char*
1067
arg(Jcl_t* jcl, char** p)
1068
{
1069
char* tok;
1070
char* val;
1071
1072
if (!(tok = lex(jcl)))
1073
syntax(jcl, 2, NiL, NiL, NiL);
1074
else if (tok == END)
1075
return 0;
1076
else if ((val = lex(jcl)) == EQ)
1077
val = lex(jcl);
1078
else
1079
{
1080
xel(jcl, val);
1081
val = 0;
1082
}
1083
*p = val;
1084
return tok;
1085
}
1086
1087
/*
1088
* return next parm from single token or (...,...,...) list *p
1089
* list modified in place and not restored
1090
*/
1091
1092
char*
1093
jclparm(char** p)
1094
{
1095
register char* s;
1096
register char* t;
1097
register int q;
1098
register int n;
1099
register int x;
1100
int empty;
1101
char* b;
1102
1103
s = *p;
1104
if (*s == '(')
1105
{
1106
s++;
1107
x = -1;
1108
}
1109
else
1110
x = '\'';
1111
q = 0;
1112
n = 0;
1113
for (b = t = s; *s; s++)
1114
if (*s == x)
1115
q = !q;
1116
else if (!q)
1117
{
1118
if (*s == '(')
1119
n++;
1120
else if (*s == ')')
1121
{
1122
if (--n < 0)
1123
break;
1124
}
1125
else if (!n && *s == ',')
1126
break;
1127
*t++ = *s;
1128
}
1129
if (*s)
1130
{
1131
empty = *s == ',';
1132
*s++ = 0;
1133
}
1134
else
1135
empty = 0;
1136
*p = s;
1137
if (*b == ' ')
1138
{
1139
s = b;
1140
for (s = b; *++s == ' ';);
1141
for (t = s; ID(*s); s++);
1142
if (*s == '=')
1143
b = t;
1144
}
1145
if (!*b && !empty)
1146
return 0;
1147
return b;
1148
}
1149
1150
/*
1151
* parse a DD statement
1152
*/
1153
1154
static int
1155
DD(register Jcl_t* jcl, register Jclstep_t* step, char* name)
1156
{
1157
register char* tok;
1158
register char* op;
1159
register Jcldd_t* dd;
1160
register Jclcat_t* cat;
1161
char* val;
1162
char* s;
1163
Jcldd_t* pd;
1164
Jclout_t* out;
1165
Jcloutput_t* output;
1166
int i;
1167
int n;
1168
int d0;
1169
int d1;
1170
int d2;
1171
int change;
1172
1173
if (!step->name && !jcl->lastdd && !DDLIB(name))
1174
{
1175
if (jcl->disc->errorf && (jcl->flags & JCL_WARN))
1176
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "//%s DD appears before EXEC", name);
1177
return -1;
1178
}
1179
change = 0;
1180
if (*name)
1181
{
1182
if (dd = (Jcldd_t*)dtmatch(step->dd, name))
1183
{
1184
jcl->lastdd = dd;
1185
change = 1;
1186
}
1187
else if (!(dd = vmnewof(jcl->vs, NiL, Jcldd_t, 1, 0)))
1188
{
1189
nospace(jcl, NiL);
1190
return -1;
1191
}
1192
else if (!(dd->name = stash(jcl, jcl->vs, name, 0)))
1193
return -1;
1194
else if (tok = strchr(dd->name, '.'))
1195
{
1196
dd->reference = tok - dd->name;
1197
dd->flags |= JCL_DD_REFERENCE;
1198
}
1199
else if (streq(name, "SYSIN"))
1200
{
1201
dd->flags |= JCL_DD_SYSIN;
1202
if (!dd->disp[0])
1203
dd->disp[0] = JCL_DISP_OLD;
1204
}
1205
else if (streq(name, "SYSOUT"))
1206
{
1207
dd->flags |= JCL_DD_SYSOUT;
1208
if (!dd->disp[0])
1209
dd->disp[0] = JCL_DISP_NEW;
1210
}
1211
else if (streq(name, "SYSERR"))
1212
{
1213
dd->flags |= JCL_DD_SYSERR;
1214
if (!dd->disp[0])
1215
dd->disp[0] = JCL_DISP_NEW;
1216
}
1217
else if (DDLIB(name))
1218
dd->flags |= JCL_DD_INCLUDE;
1219
}
1220
else if (!(dd = jcl->lastdd))
1221
{
1222
syntax(jcl, 2, name, "NAME", NiL);
1223
return -1;
1224
}
1225
d0 = '/';
1226
d1 = '/';
1227
d2 = '*';
1228
while (tok = arg(jcl, &val))
1229
{
1230
if (val && (val[0] == '*' && val[1] == '.' || val[0] == '(' && val[1] == '*' && val[2] == '.'))
1231
{
1232
op = val;
1233
if (*op == '(')
1234
op++;
1235
op += 2;
1236
if (streq(tok, "OUTPUT"))
1237
{
1238
for (;;)
1239
{
1240
if (*op == '*')
1241
op++;
1242
if (*op == '.')
1243
op++;
1244
for (val = op; *op && *op != ',' && *op != ')'; op++);
1245
if (n = *op)
1246
*op = 0;
1247
if (*val)
1248
{
1249
sfprintf(jcl->tp, "%s.%s", step->name, val);
1250
if (!(s = sfstruse(jcl->tp)))
1251
nospace(jcl, NiL);
1252
if (!(output = (Jcloutput_t*)dtmatch(jcl->output, s)))
1253
output = (Jcloutput_t*)dtmatch(jcl->output, val);
1254
if (output)
1255
{
1256
if (!(out = vmnewof(jcl->vs, NiL, Jclout_t, 1, 0)))
1257
{
1258
nospace(jcl, NiL);
1259
return -1;
1260
}
1261
out->output = output;
1262
out->next = dd->out;
1263
dd->out = out;
1264
}
1265
else if (jcl->disc->errorf && (jcl->flags & JCL_WARN))
1266
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%s: OUTPUT not defined", val);
1267
}
1268
if (!n)
1269
break;
1270
*op++ = n;
1271
if (n != ',')
1272
break;
1273
}
1274
continue;
1275
}
1276
for (val = op; *op && *op != '.'; op++);
1277
if (*op)
1278
{
1279
*op = 0;
1280
if (!streq(val, step->name))
1281
{
1282
if (jcl->disc->errorf)
1283
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "%s: step back reference not supported", val);
1284
return -1;
1285
}
1286
*op++ = '.';
1287
val = op;
1288
op += strlen(op);
1289
}
1290
if (*--op == ')')
1291
*op = 0;
1292
else
1293
op = 0;
1294
pd = (Jcldd_t*)dtmatch(step->dd, val);
1295
if (op)
1296
*op = ')';
1297
if (!pd)
1298
{
1299
if (jcl->disc->errorf && (jcl->flags & JCL_WARN))
1300
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%s: DD not defined", val);
1301
continue;
1302
}
1303
}
1304
else
1305
pd = 0;
1306
if (val && (streq(tok, "DSN") || streq(tok, "DSNAME")) || !val && (streq(tok, "DUMMY") && (val = dummy) && (dd->flags |= JCL_DD_DUMMY) || !jcl->pushed && tok != ST && (val = tok)))
1307
{
1308
if (dd->flags & JCL_DD_DUMMY)
1309
{
1310
dd->path = (char*)dummy;
1311
dd->cat = dd->last = 0;
1312
}
1313
else
1314
{
1315
if (pd)
1316
name = pd->path;
1317
else if (!(name = stash(jcl, jcl->vs, jclpath(jcl, val), 1)))
1318
return -1;
1319
if (!dd->path || change)
1320
dd->path = name;
1321
else if (!(cat = vmnewof(jcl->vs, NiL, Jclcat_t, 1, 0)))
1322
{
1323
nospace(jcl, NiL);
1324
return -1;
1325
}
1326
else
1327
{
1328
cat->path = name;
1329
if (dd->last)
1330
dd->last->next = cat;
1331
else
1332
dd->cat = cat;
1333
dd->last = cat;
1334
}
1335
}
1336
}
1337
else if (val)
1338
{
1339
if (streq(tok, "AVGREC"))
1340
{
1341
if (!(dd->recfm & (JCL_RECFM_F|JCL_RECFM_V)))
1342
{
1343
if (pd && (pd->recfm & (JCL_RECFM_F|JCL_RECFM_V)))
1344
{
1345
dd->recfm = pd->recfm;
1346
dd->lrecl = pd->lrecl;
1347
}
1348
#if _2005_06_10__NOT_RELIBALE
1349
else if (n = pd ? pd->space : dd->space)
1350
{
1351
dd->lrecl = n;
1352
dd->recfm |= JCL_RECFM_F;
1353
}
1354
#endif
1355
}
1356
}
1357
else if (streq(tok, "DCB"))
1358
{
1359
if (pd)
1360
{
1361
memcpy(dd->disp, pd->disp, sizeof(dd->disp));
1362
dd->lrecl = pd->lrecl;
1363
dd->recfm = pd->recfm;
1364
}
1365
else if (push(jcl, val + (*val == '(')))
1366
return -1;
1367
}
1368
else if (streq(tok, "DDNAME"))
1369
{
1370
dd->flags |= JCL_DD_ALIAS;
1371
dd->path = stash(jcl, jcl->vs, pd ? ((pd->flags & JCL_DD_ALIAS) ? pd->path : pd->name) : val, 0);
1372
}
1373
else if (streq(tok, "DISP"))
1374
{
1375
if (pd)
1376
memcpy(dd->disp, pd->disp, sizeof(dd->disp));
1377
else if (tok = jclparm(&val))
1378
{
1379
if (streq(tok, "NEW"))
1380
dd->disp[0] = JCL_DISP_NEW;
1381
else if (streq(tok, "OLD"))
1382
dd->disp[0] = JCL_DISP_OLD;
1383
else if (streq(tok, "SHR"))
1384
dd->disp[0] = JCL_DISP_SHR;
1385
else if (streq(tok, "MOD"))
1386
dd->disp[0] = JCL_DISP_MOD;
1387
else if (*tok && jcl->disc->errorf && (jcl->flags & JCL_WARN))
1388
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%s: unknown DISP", tok);
1389
for (i = 1; i < elementsof(dd->disp) && (tok = jclparm(&val)); i++)
1390
{
1391
if (streq(tok, "DELETE"))
1392
dd->disp[i] = JCL_DISP_DELETE;
1393
else if (streq(tok, "KEEP"))
1394
dd->disp[i] = JCL_DISP_KEEP;
1395
else if (streq(tok, "PASS"))
1396
dd->disp[i] = JCL_DISP_PASS;
1397
else if (streq(tok, "CATLG"))
1398
dd->disp[i] = JCL_DISP_CATLG;
1399
else if (streq(tok, "UNCATLG"))
1400
dd->disp[i] = JCL_DISP_UNCATLG;
1401
else if (*tok && jcl->disc->errorf && (jcl->flags & JCL_WARN))
1402
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%s: unknown DISP", tok);
1403
}
1404
}
1405
}
1406
else if (streq(tok, "DLM"))
1407
{
1408
d0 = 0;
1409
if (d1 = val[0])
1410
d2 = val[1];
1411
else
1412
d2 = 0;
1413
}
1414
else if (streq(tok, "LRECL"))
1415
dd->lrecl = pd ? pd->lrecl : (int)strtol(val, NiL, 10);
1416
else if (streq(tok, "RECFM"))
1417
{
1418
if (pd)
1419
dd->recfm = pd->recfm;
1420
else
1421
for (;;)
1422
{
1423
switch (*val++)
1424
{
1425
case 0:
1426
break;
1427
case 'A':
1428
dd->recfm |= JCL_RECFM_A;
1429
continue;
1430
case 'B':
1431
dd->recfm |= JCL_RECFM_B;
1432
continue;
1433
case 'D':
1434
dd->recfm |= JCL_RECFM_D;
1435
continue;
1436
case 'F':
1437
dd->recfm |= JCL_RECFM_F;
1438
continue;
1439
case 'M':
1440
dd->recfm |= JCL_RECFM_M;
1441
continue;
1442
case 'S':
1443
dd->recfm |= JCL_RECFM_S;
1444
continue;
1445
case 'U':
1446
dd->recfm |= JCL_RECFM_U;
1447
continue;
1448
case 'V':
1449
dd->recfm |= JCL_RECFM_V;
1450
continue;
1451
default:
1452
if (jcl->disc->errorf && (jcl->flags & JCL_WARN))
1453
(*jcl->disc->errorf)(NiL, jcl->disc, 1, "%c: unknown RECFM", *(val - 1));
1454
continue;
1455
}
1456
break;
1457
}
1458
}
1459
else if (streq(tok, "SPACE"))
1460
{
1461
if (pd)
1462
{
1463
dd->flags |= pd->flags & JCL_DD_DIR;
1464
dd->space = pd->space;
1465
}
1466
else
1467
for (n = 0;;)
1468
{
1469
switch (*val++)
1470
{
1471
case 0:
1472
break;
1473
case '(':
1474
n++;
1475
i = 0;
1476
continue;
1477
case ',':
1478
i++;
1479
continue;
1480
case ')':
1481
if (n == 2)
1482
{
1483
if (i == 2)
1484
dd->flags |= JCL_DD_DIR;
1485
break;
1486
}
1487
continue;
1488
default:
1489
if (!dd->space)
1490
dd->space = (int)strtol(val - 1, NiL, 10);
1491
continue;
1492
}
1493
break;
1494
}
1495
}
1496
else if (streq(tok, "SUBSYS"))
1497
{
1498
if (*val == '(' && push(jcl, val + 1))
1499
return -1;
1500
}
1501
}
1502
else if (tok == ST)
1503
{
1504
while (tok = card(jcl))
1505
{
1506
if (tok[0] == d1 && tok[1] == d2 || tok[0] == d0 && tok[1] == d1 && tok[2] == d2)
1507
break;
1508
sfputr(jcl->tp, tok, '\n');
1509
}
1510
if (!(s = sfstruse(jcl->tp)))
1511
nospace(jcl, NiL);
1512
if (!(dd->here = stash(jcl, jcl->vs, s, 0)))
1513
return -1;
1514
dd->dlm[0] = d1;
1515
dd->dlm[1] = d2;
1516
jcl->record = tok;
1517
xel(jcl, NiL);
1518
if (tok)
1519
xel(jcl, END);
1520
}
1521
}
1522
if ((dd->flags & JCL_DD_INCLUDE) && dd->path && jclinclude(jcl, dd->path, JCL_PROC, NiL))
1523
return -1;
1524
if (dd->reference)
1525
{
1526
if (dd->card)
1527
sfputr(jcl->tp, dd->card, -1);
1528
val = jcl->record;
1529
if (val[0] == '/' && val[1] == '/' && val[2] != ' ' && (op = strchr(val, '.')))
1530
{
1531
val = op + 1;
1532
sfputc(jcl->tp, '/');
1533
sfputc(jcl->tp, '/');
1534
}
1535
sfputr(jcl->tp, val, '\n');
1536
if (!(s = sfstruse(jcl->tp)))
1537
nospace(jcl, NiL);
1538
if (!(dd->card = stash(jcl, jcl->vs, s, 0)))
1539
{
1540
nospace(jcl, NiL);
1541
return -1;
1542
}
1543
}
1544
else if (dd != jcl->lastdd && (dd->path || dd->here))
1545
{
1546
if ((jcl->flags & JCL_MARKLENGTH) && dd->path && !dd->recfm && !dd->lrecl)
1547
marked(dd->path, dd, jcl->disc);
1548
}
1549
else if (!(dd->flags & JCL_DD_ALIAS))
1550
return 0;
1551
jcl->lastdd = dd;
1552
dtinsert(step->dd, dd);
1553
return 0;
1554
}
1555
1556
/*
1557
* parse an OUTPUT statement
1558
*/
1559
1560
static int
1561
OUTPUT(register Jcl_t* jcl, register Jclstep_t* step, char* name)
1562
{
1563
Jcloutput_t* output;
1564
char* s;
1565
char* tok;
1566
char* val;
1567
1568
if (!*name)
1569
{
1570
syntax(jcl, 2, NiL, "NAME", NiL);
1571
return -1;
1572
}
1573
if (step->name)
1574
{
1575
sfprintf(jcl->tp, "%s.%s", step->name, name);
1576
if (!(name = sfstruse(jcl->tp)))
1577
nospace(jcl, NiL);
1578
}
1579
if (output = (Jcloutput_t*)dtmatch(jcl->output, name))
1580
{
1581
if (jcl->disc->errorf)
1582
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "%s: OUTPUT alread defined", name);
1583
return 0;
1584
}
1585
if (!(output = vmnewof(jcl->vs, NiL, Jcloutput_t, 1, 0)))
1586
{
1587
nospace(jcl, NiL);
1588
return 0;
1589
}
1590
else if (!(output->name = stash(jcl, jcl->vs, name, 0)))
1591
return 0;
1592
while (tok = arg(jcl, &val))
1593
{
1594
sfprintf(jcl->tp, ",%s", tok);
1595
if (val)
1596
sfprintf(jcl->tp, "=%s", val);
1597
}
1598
if (!(s = sfstruse(jcl->tp)))
1599
nospace(jcl, 0);
1600
if (!(output->parm = stash(jcl, jcl->vs, s, 0)))
1601
return 0;
1602
dtinsert(jcl->output, output);
1603
return 0;
1604
}
1605
1606
static int eval(Jcl_t*, char*, char**, int);
1607
1608
/*
1609
* return the next IF expression operand value
1610
*/
1611
1612
static int
1613
operand(Jcl_t* jcl, register char* s, char** e)
1614
{
1615
register char* t;
1616
register char* u;
1617
register char* v;
1618
Rc_t* p;
1619
int c;
1620
int d;
1621
int n;
1622
int abend;
1623
int run;
1624
int rc;
1625
1626
while (*s == ' ')
1627
s++;
1628
if ((n = *s == '!') && *++s == ' ')
1629
s++;
1630
if (*s == '(')
1631
{
1632
if ((rc = eval(jcl, s + 1, e, 99)) < 0)
1633
return rc;
1634
s = *e;
1635
while (*s == ' ')
1636
s++;
1637
if (*s++ != ')')
1638
{
1639
if (jcl->disc->errorf)
1640
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "unbalanced (...)");
1641
return -1;
1642
}
1643
}
1644
else if (isdigit(*s))
1645
{
1646
rc = (int)strtol(s, e, 10);
1647
s = *e;
1648
}
1649
else if (*s == 0 || *s == ')')
1650
rc = 0;
1651
else
1652
{
1653
v = 0;
1654
for (t = s; ID(*s) || *s == '.' && (v = s); s++);
1655
if (v)
1656
{
1657
*v = 0;
1658
p = (Rc_t*)dtmatch(jcl->rcs, t);
1659
*v = '.';
1660
if (p)
1661
{
1662
run = 1;
1663
if (p->rc < 0)
1664
{
1665
abend = 1;
1666
rc = 0;
1667
}
1668
else
1669
{
1670
abend = 0;
1671
rc = p->rc;
1672
}
1673
}
1674
else
1675
{
1676
abend = 0;
1677
rc = 0;
1678
run = 0;
1679
}
1680
t = v + 1;
1681
}
1682
else
1683
{
1684
abend = jcl->abend;
1685
rc = jcl->rc;
1686
run = 1;
1687
}
1688
c = *s;
1689
*s = 0;
1690
if (!*t)
1691
/*ok*/;
1692
else if (streq(t, "ABEND"))
1693
rc = abend;
1694
else if (streq(t, "ABENDCC"))
1695
rc = 0;
1696
else if (streq(t, "FALSE"))
1697
rc = 0;
1698
else if (streq(t, "RUN"))
1699
rc = run;
1700
else if (streq(t, "TRUE"))
1701
rc = 1;
1702
else if (*t == 'S' && (s - t) == 5 && (rc = (int)strtol(t + 1, e, 10), !*e))
1703
/*OK*/;
1704
else if (*t == 'U' && (s - t) == 4 && (rc = (int)strtol(t + 1, e, 16), !*e))
1705
/*OK*/;
1706
else if (!streq(t, "RC"))
1707
{
1708
if (c)
1709
{
1710
u = s;
1711
while (*++u == ' ');
1712
if (*u == '=' || *u == '!' && *(u + 1) == '=')
1713
{
1714
if (n = *u == '!')
1715
u++;
1716
while (*++u == ' ');
1717
v = u;
1718
while (*++u && *u != ' ');
1719
d = *u;
1720
*u = 0;
1721
rc = streq(s, v) != n;
1722
*u = d;
1723
*s = c;
1724
s = u;
1725
goto done;
1726
}
1727
}
1728
if (jcl->disc->errorf)
1729
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "%s: unknown IF expression token", t);
1730
return -1;
1731
}
1732
*s = c;
1733
}
1734
done:
1735
if (n)
1736
rc = !rc;
1737
while (*s == ' ')
1738
s++;
1739
*e = s;
1740
return rc;
1741
}
1742
1743
/*
1744
* evaluate an IF [sub]expression
1745
*/
1746
1747
static int
1748
eval(register Jcl_t* jcl, register char* s, char** e, int prec)
1749
{
1750
register char* t;
1751
int a;
1752
int op;
1753
int b;
1754
#if DEBUG
1755
int o;
1756
1757
static const char* opname[] = { "NOP", "ONLY", "EVEN", "LT", "LE", "EQ", "NE", "GE", "GT", "OR", "AND" };
1758
#endif
1759
1760
if ((a = operand(jcl, s, e)) < 0)
1761
return -1;
1762
s = *e;
1763
for (;;)
1764
{
1765
if (*s == 0 || *s == ')')
1766
break;
1767
op = 0;
1768
t = s;
1769
switch (*s++)
1770
{
1771
case 'A':
1772
if (*s++ == 'N' && *s++ == 'D')
1773
op = JCL_COND_AND;
1774
break;
1775
case 'E':
1776
if (*s++ == 'Q')
1777
op = JCL_COND_EQ;
1778
break;
1779
case 'G':
1780
switch (*s)
1781
{
1782
case 'E':
1783
op = JCL_COND_GE;
1784
s++;
1785
break;
1786
case 'T':
1787
op = JCL_COND_GT;
1788
s++;
1789
break;
1790
}
1791
break;
1792
case 'L':
1793
switch (*s)
1794
{
1795
case 'E':
1796
op = JCL_COND_LE;
1797
s++;
1798
break;
1799
case 'T':
1800
op = JCL_COND_LT;
1801
s++;
1802
break;
1803
}
1804
break;
1805
case 'N':
1806
if (*s++ == 'E')
1807
op = JCL_COND_NE;
1808
break;
1809
case 'O':
1810
if (*s++ == 'R')
1811
op = JCL_COND_OR;
1812
break;
1813
case '&':
1814
op = JCL_COND_AND;
1815
break;
1816
case '=':
1817
op = JCL_COND_EQ;
1818
break;
1819
case '>':
1820
if (*s == '=')
1821
{
1822
op = JCL_COND_GE;
1823
s++;
1824
}
1825
else
1826
op = JCL_COND_GT;
1827
break;
1828
case '<':
1829
if (*s == '=')
1830
{
1831
op = JCL_COND_LE;
1832
s++;
1833
}
1834
else
1835
op = JCL_COND_LT;
1836
break;
1837
case '!':
1838
if (*s++ == '=')
1839
op = JCL_COND_NE;
1840
break;
1841
case '|':
1842
op = JCL_COND_OR;
1843
break;
1844
}
1845
if (!op || isupper(*t) && ID(*s))
1846
{
1847
if (jcl->disc->errorf)
1848
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "%s: operator expected in IF expression", t);
1849
return -1;
1850
}
1851
if (op > prec)
1852
{
1853
s = t;
1854
break;
1855
}
1856
if ((b = eval(jcl, s, e, op)) < 0)
1857
return -1;
1858
s = *e;
1859
o = a;
1860
switch (op)
1861
{
1862
case JCL_COND_AND:
1863
a = a && b;
1864
break;
1865
case JCL_COND_OR:
1866
a = a || b;
1867
break;
1868
case JCL_COND_LT:
1869
a = a < b;
1870
break;
1871
case JCL_COND_LE:
1872
a = a <= b;
1873
break;
1874
case JCL_COND_EQ:
1875
a = a == b;
1876
break;
1877
case JCL_COND_NE:
1878
a = a != b;
1879
break;
1880
case JCL_COND_GE:
1881
a = a >= b;
1882
break;
1883
case JCL_COND_GT:
1884
a = a > b;
1885
break;
1886
}
1887
message((-7, "eval %2d %2s %2d => %d", o, opname[op], b, a));
1888
}
1889
while (*s == ' ')
1890
s++;
1891
*e = s;
1892
return a;
1893
}
1894
1895
/*
1896
* parse and evaluate an IF expression
1897
* return:
1898
* <0 fatal error
1899
* 0 false
1900
* >0 true
1901
*/
1902
1903
static int
1904
IF(register Jcl_t* jcl)
1905
{
1906
register char* s;
1907
char* e;
1908
int r;
1909
1910
while (s = lex(jcl))
1911
if (s == END)
1912
{
1913
if (jcl->disc->errorf)
1914
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "THEN expected");
1915
return -1;
1916
}
1917
else if (streq(s, "THEN"))
1918
break;
1919
else
1920
sfputr(jcl->tp, s, ' ');
1921
sfstrseek(jcl->tp, -1, SEEK_CUR);
1922
if (!(s = sfstruse(jcl->tp)))
1923
nospace(jcl, NiL);
1924
if ((r = eval(jcl, s, &e, 99)) < 0)
1925
return r;
1926
if (*e)
1927
{
1928
if (jcl->disc->errorf)
1929
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "%s: invalid IF expression", e);
1930
return -1;
1931
}
1932
message((-5, "if %4d %s == %d", jcl->ie->line, sfstrbase(jcl->tp), r));
1933
return r;
1934
}
1935
1936
/*
1937
* main parse loop
1938
*/
1939
1940
static int
1941
parse(register Jcl_t* jcl, register Jclstep_t* step)
1942
{
1943
register char* tok;
1944
register char* name;
1945
register char* op;
1946
char* val;
1947
Ie_t* ie;
1948
Sfio_t* sp;
1949
char* t;
1950
char* v;
1951
int i;
1952
1953
while (tok = lex(jcl))
1954
{
1955
if (tok != SS)
1956
{
1957
syntax(jcl, 2, tok, SS, NiL);
1958
return -1;
1959
}
1960
if (!(name = lex(jcl)))
1961
{
1962
syntax(jcl, 2, NiL, "NAME", NiL);
1963
return -1;
1964
}
1965
if (!(op = lex(jcl)))
1966
{
1967
syntax(jcl, 2, NiL, "OP", NiL);
1968
return -1;
1969
}
1970
if (!*op)
1971
/*NOP*/;
1972
else if (streq(op, "DD"))
1973
{
1974
if (DD(jcl, step, name))
1975
return -1;
1976
}
1977
else if (streq(op, "ELSE"))
1978
{
1979
if (step->name || jcl->vs == jcl->vm)
1980
{
1981
xel(jcl, NiL);
1982
break;
1983
}
1984
if (!jcl->ie)
1985
{
1986
if (jcl->disc->errorf)
1987
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "no IF for ELSE");
1988
return -1;
1989
}
1990
if (jcl->ie->flags & IE_KEEP)
1991
jcl->ie->flags |= IE_SKIP;
1992
else
1993
jcl->ie->flags |= IE_KEEP;
1994
while (arg(jcl, &val));
1995
}
1996
else if (streq(op, "ENDIF"))
1997
{
1998
if (!jcl->ie)
1999
{
2000
if (jcl->disc->errorf)
2001
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "no IF for ENDIF");
2002
return -1;
2003
}
2004
if (step->name || jcl->vs == jcl->vm)
2005
{
2006
xel(jcl, NiL);
2007
break;
2008
}
2009
jcl->ie = jcl->ie->prev;
2010
while (arg(jcl, &val));
2011
}
2012
else if (streq(op, "EXEC"))
2013
{
2014
if (step->name || jcl->vs == jcl->vm)
2015
{
2016
xel(jcl, NiL);
2017
break;
2018
}
2019
if (!(step->name = stash(jcl, jcl->vs, name, 0)))
2020
return -1;
2021
while (tok = arg(jcl, &val))
2022
{
2023
if (val && (streq(tok, "PGM") && (step->flags |= JCL_PGM) || streq(tok, "PROC")) || !val && !step->command && (val = tok))
2024
{
2025
if (!(step->command = stash(jcl, jcl->vs, val, 0)))
2026
return -1;
2027
if (!(step->flags & JCL_PGM))
2028
step->flags |= JCL_PROC;
2029
}
2030
else if (val)
2031
{
2032
if (streq(tok, "COND"))
2033
{
2034
if (*val && !(step->cond = cond(jcl, val, NiL)))
2035
return -1;
2036
}
2037
else if (streq(tok, "PARM"))
2038
{
2039
if (*val && !(step->parm = stash(jcl, jcl->vs, val, 0)))
2040
return -1;
2041
}
2042
else if (!jclsym(jcl, tok, val, 0))
2043
return -1;
2044
}
2045
}
2046
}
2047
else if (streq(op, "IF"))
2048
{
2049
if (step->name || jcl->vs == jcl->vm)
2050
{
2051
xel(jcl, NiL);
2052
break;
2053
}
2054
if (!jcl->ie && !(ie = jcl->iefree) || jcl->ie && !(ie = jcl->ie->next))
2055
{
2056
if (!(ie = vmnewof(jcl->vm, 0, Ie_t, 1, 0)))
2057
{
2058
nospace(jcl, 0);
2059
return -1;
2060
}
2061
if (ie->prev = jcl->ie)
2062
jcl->ie->next = ie;
2063
else
2064
jcl->iefree = ie;
2065
}
2066
ie->line = error_info.line;
2067
jcl->ie = ie;
2068
if ((i = IF(jcl)) < 0)
2069
return -1;
2070
ie->flags = ie->prev && (ie->prev->flags & (IE_KEEP|IE_SKIP)) != IE_KEEP ? IE_SKIP : i ? IE_KEEP : 0;
2071
}
2072
else if (streq(op, "INCLUDE"))
2073
{
2074
while (tok = arg(jcl, &val))
2075
if (val && streq(tok, "MEMBER") && (!(tok = jclfind(jcl, val, JCL_PROC, 2, &sp)) || jclpush(jcl, sp, tok, 0)))
2076
return -1;
2077
}
2078
else if (streq(op, "JCLLIB"))
2079
{
2080
while (tok = arg(jcl, &val))
2081
if (val && streq(tok, "ORDER"))
2082
while (tok = jclparm(&val))
2083
if (jclinclude(jcl, tok, JCL_PROC, NiL))
2084
return -1;
2085
}
2086
else if (streq(op, "JOB"))
2087
{
2088
if (!(jcl->name = stash(jcl, jcl->vm, name, 0)))
2089
return -1;
2090
while (tok = arg(jcl, &val))
2091
if (val)
2092
{
2093
if (streq(tok, "COND"))
2094
{
2095
if (*val && !(jcl->cond = cond(jcl, val, NiL)))
2096
return -1;
2097
}
2098
else if (!lookup(jcl, tok, val, 0, DEFAULT))
2099
return -1;
2100
}
2101
}
2102
else if (streq(op, "OUTPUT"))
2103
{
2104
if (OUTPUT(jcl, step, name))
2105
return -1;
2106
}
2107
else if (streq(op, "PEND"))
2108
{
2109
/*HERE check for PROC on line 1, check that this is last? */
2110
}
2111
else if ((i = streq(op, "PROC") ? DEFAULT : 0) || streq(op, "SET"))
2112
{
2113
if (i && jcl->name)
2114
{
2115
sfprintf(jcl->vp, "(PROC)%s", name);
2116
sfputr(jcl->tp, jcl->record, '\n');
2117
while (tok = card(jcl))
2118
{
2119
if (sfvalue(jcl->sp) > 10 && tok[0] == '/' && tok[1] == '/' && tok[2] != '*')
2120
{
2121
for (val = tok + 2; isspace(*val); val++);
2122
if (strneq(val, "PEND", 4) && (!val[4] || isspace(val[4])))
2123
break;
2124
}
2125
sfputr(jcl->tp, tok, '\n');
2126
}
2127
if (!(v = sfstruse(jcl->vp)) || !(t = sfstruse(jcl->tp)))
2128
nospace(jcl, NiL);
2129
if (!lookup(jcl, v, t, 0, 0))
2130
return -1;
2131
}
2132
else
2133
{
2134
if (i && !(jcl->name = stash(jcl, jcl->vm, name, 0)))
2135
return -1;
2136
while (tok = arg(jcl, &val))
2137
if (val)
2138
{
2139
if (*tok == '?' && *(tok + strlen(tok) - 1) == '?')
2140
{
2141
if (streq(tok + 1, "ABEND?"))
2142
jcl->abend = (int)strtol(val, NiL, 0);
2143
else if (streq(tok + 1, "RC?"))
2144
jcl->rc = (int)strtol(val, NiL, 0);
2145
}
2146
else if (!lookup(jcl, tok, val, 0, i))
2147
return -1;
2148
}
2149
}
2150
}
2151
else
2152
syntax(jcl, 1, op, NiL, "OP");
2153
eat(jcl);
2154
}
2155
return 0;
2156
}
2157
2158
/*
2159
* return the next jcl job step
2160
*/
2161
2162
Jclstep_t*
2163
jclstep(register Jcl_t* jcl)
2164
{
2165
register Jclstep_t* step;
2166
register Jcldd_t* dd;
2167
register Jclcat_t* cat;
2168
Jcl_t* scope;
2169
Sfio_t* sp;
2170
char* ofile;
2171
int oline;
2172
int i;
2173
2174
errno = 0;
2175
for (;;)
2176
{
2177
step = jcl->step;
2178
if (jcl->vs != jcl->vm)
2179
{
2180
vmclear(jcl->vs);
2181
dtclear(jcl->ss);
2182
}
2183
memset(step, 0, sizeof(*step));
2184
step->dd = jcl->ds;
2185
step->syms = jcl->ss;
2186
dtclear(step->dd);
2187
step->vm = jcl->vs;
2188
jcl->lastdd = 0;
2189
if (!jcl->data)
2190
jcl->data = null;
2191
if (parse(jcl, step))
2192
break;
2193
if (!step->name && jcl->vs != jcl->vm)
2194
break;
2195
if (jcl->ie && (jcl->ie->flags & (IE_KEEP|IE_SKIP)) != IE_KEEP)
2196
continue;
2197
if (step->name)
2198
for (scope = jcl->scope; scope; scope = scope->scope)
2199
for (dd = (Jcldd_t*)dtfirst(scope->step->dd); dd; dd = (Jcldd_t*)dtnext(scope->step->dd, dd))
2200
if (dd->reference && strneq(dd->name, step->name, dd->reference) && dd->name[dd->reference] == '.')
2201
{
2202
if (!jcl->dp && !(jcl->dp = sfstropen()) || sfstrbuf(jcl->dp, dd->card, strlen(dd->card), 0))
2203
{
2204
nospace(jcl, 0);
2205
return 0;
2206
}
2207
sp = jcl->sp;
2208
jcl->sp = jcl->dp;
2209
oline = error_info.line;
2210
ofile = error_info.file;
2211
error_info.line = 0;
2212
error_info.file = "DD-addition/override";
2213
jcl->canon++;
2214
i = parse(jcl, step);
2215
jcl->canon--;
2216
error_info.line = oline;
2217
error_info.file = ofile;
2218
jcl->sp = sp;
2219
if (i)
2220
return 0;
2221
}
2222
if (jcl->flags & JCL_MARKLENGTH)
2223
for (dd = (Jcldd_t*)dtfirst(step->dd); dd; dd = (Jcldd_t*)dtnext(step->dd, dd))
2224
if (dd->path && (dd->recfm & (JCL_RECFM_F|JCL_RECFM_V)) && dd->lrecl && !(dd->flags & JCL_DD_DIR))
2225
{
2226
if (!streq(dd->path, dummy))
2227
{
2228
dd->path = mark(dd->path, dd->recfm, dd->lrecl, jcl->disc);
2229
dd->flags |= JCL_DD_MARKED;
2230
}
2231
for (cat = dd->cat; cat; cat = cat->next)
2232
if (!streq(cat->path, dummy))
2233
cat->path = mark(cat->path, 0, dd->lrecl, jcl->disc);
2234
}
2235
return step;
2236
}
2237
if (jcl->disc->errorf && jcl->eof && jcl->ie)
2238
(*jcl->disc->errorf)(NiL, jcl->disc, 2, "IF on line %d has no ENDIF", jcl->ie->line);
2239
return 0;
2240
}
2241
2242
/*
2243
* return >0 if condition is true
2244
*/
2245
2246
int
2247
jcleval(Jcl_t* jcl, register Jclcond_t* cond, int code)
2248
{
2249
if (!cond)
2250
return !code;
2251
while (cond)
2252
{
2253
switch (cond->op)
2254
{
2255
case JCL_COND_ONLY:
2256
if (jcl->failed)
2257
return 0;
2258
break;
2259
case JCL_COND_LT:
2260
if (cond->code < code)
2261
return 0;
2262
break;
2263
case JCL_COND_LE:
2264
if (cond->code <= code)
2265
return 0;
2266
break;
2267
case JCL_COND_EQ:
2268
if (cond->code == code)
2269
return 0;
2270
break;
2271
case JCL_COND_NE:
2272
if (cond->code != code)
2273
return 0;
2274
break;
2275
case JCL_COND_GE:
2276
if (cond->code >= code)
2277
return 0;
2278
break;
2279
case JCL_COND_GT:
2280
if (cond->code > code)
2281
return 0;
2282
break;
2283
}
2284
cond = cond->next;
2285
}
2286
return 1;
2287
}
2288
2289
/*
2290
* set step return code
2291
* rc<0 for abend
2292
*/
2293
2294
int
2295
jclrc(register Jcl_t* jcl, register Jclstep_t* step, int rc)
2296
{
2297
register Rc_t* rp;
2298
2299
/*
2300
* map unix signal codes to abend
2301
*/
2302
2303
if (rc > 128 && rc < 192)
2304
rc -= 128;
2305
else if (rc > 256 && rc < 320)
2306
rc -= 256;
2307
if (step && step->name)
2308
{
2309
if (!(rp = (Rc_t*)dtmatch(jcl->rcs, step->name)))
2310
{
2311
if (!(rp = vmnewof(jcl->vm, 0, Rc_t, 1, strlen(step->name))))
2312
{
2313
nospace(jcl, NiL);
2314
return -1;
2315
}
2316
strcpy(rp->name, step->name);
2317
dtinsert(jcl->rcs, rp);
2318
}
2319
if (rc < 0 && rp->rc > rc || rc > 0 && rp->rc < rc)
2320
rp->rc = rc;
2321
if (!jcl)
2322
return rp->rc;
2323
}
2324
if (jcl)
2325
{
2326
if (rc < 0)
2327
jcl->abend++;
2328
if (rc < 0 && jcl->rc > rc || rc > 0 && jcl->rc < rc)
2329
jcl->rc = rc;
2330
return jcl->rc;
2331
}
2332
return 0;
2333
}
2334
2335