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 <glenn.s.fowler@gmail.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21
22 /*
23 * jcl private library support
24 */
25
26 #include "jcllib.h"
27
28 #include <tm.h>
29
30 static char*
internal(register Jcl_t * jcl,const char * name)31 internal(register Jcl_t* jcl, const char* name)
32 {
33 register char* s;
34 register char* t;
35
36 if (streq(name, "CYCLE"))
37 return tmmake(NiL)->tm_mday <= 10 ? "10" : "31";
38 else if (streq(name, "JOBNAME"))
39 return jcl->name;
40 else if (streq(name, "USERID"))
41 return getlogin();
42 else if (streq(name, "VDATE"))
43 {
44 for (t = s = fmttime("%h%y", time(NiL)); *t; t++)
45 if (islower(*t))
46 *t = toupper(*t);
47 return s;
48 }
49 return 0;
50 }
51
52 /*
53 * return value for &name. variable
54 * if value!=0 then value is set
55 * if (set&DEFAULT) then no set if already defined
56 * if (set&MUST) then error message if not found
57 * no provision for delete
58 */
59
60 char*
lookup(register Jcl_t * jcl,const char * name,const char * value,int flags,int set)61 lookup(register Jcl_t* jcl, const char* name, const char* value, int flags, int set)
62 {
63 register Jclsym_t* v;
64 register Jcl_t* scope;
65 char* s;
66 char* b;
67 time_t t;
68 int j;
69 int f;
70
71 if (!value)
72 {
73 if (jcl->step->syms && (v = (Jclsym_t*)dtmatch(jcl->step->syms, name)))
74 goto found;
75 for (scope = jcl; scope; scope = scope->scope)
76 {
77 if (scope->scope && scope->scope->step->syms && (v = (Jclsym_t*)dtmatch(scope->scope->step->syms, name)))
78 goto found;
79 if (scope->syms && (v = (Jclsym_t*)dtmatch(scope->syms, name)))
80 goto found;
81 }
82 }
83 else if (!jcl->syms)
84 return 0;
85 else if ((v = (Jclsym_t*)dtmatch(jcl->syms, name)) && (!(flags & (JCL_SYM_EXPORT|JCL_SYM_SET)) || (v->flags & (JCL_SYM_EXPORT|JCL_SYM_SET))))
86 {
87 if (!(set & DEFAULT))
88 v->value = stash(jcl, jcl->vm, value, 0);
89 goto found;
90 }
91 if (!value)
92 {
93 if (strneq(name, JCL_AUTO, sizeof(JCL_AUTO) - 1))
94 {
95 b = (char*)name + sizeof(JCL_AUTO) - 1;
96 if ((s = getenv(name)) || (s = internal(jcl, b)))
97 return s;
98 s = b;
99 if (*s == '$')
100 {
101 s++;
102 f = 1;
103 }
104 else
105 f = 0;
106 switch (*s)
107 {
108 case 'O':
109 s++;
110 t = jcl->disc->odate;
111 break;
112 case 'R':
113 s++;
114 t = jcl->disc->rdate;
115 break;
116 default:
117 t = jcl->disc->date;
118 break;
119 }
120 if (s[0] == 'J' && s[1] == 'U' && s[2] == 'L')
121 {
122 s += 3;
123 j = 1;
124 }
125 else
126 j = 0;
127 switch (*s)
128 {
129 case 'C':
130 if (!strcmp(s, "CENT"))
131 return fmttime("%C", t);
132 break;
133 case 'D':
134 if (!strcmp(s, "DATE"))
135 return fmttime(f ? (j ? "%Y%j" : "%Y%m%d") : (j ? "%y%j" : "%y%m%d"), t);
136 else if (!strcmp(s, "DAY"))
137 return fmttime(j ? "%j" : "%d", t);
138 break;
139 case 'M':
140 if (!strcmp(s, "MONTH"))
141 return fmttime("%m", t);
142 break;
143 case 'W':
144 if (!strcmp(s, "WDAY"))
145 return fmttime("%u", t);
146 else if (!strcmp(s, "WEEK"))
147 return fmttime("%U", t);
148 break;
149 case 'Y':
150 if (!strcmp(s, "YEAR"))
151 return fmttime(f ? "%Y" : "%y", t);
152 break;
153 }
154 switch (*b)
155 {
156 case 'B':
157 if (!strncmp(b, "BLANK", 5))
158 {
159 if (!(j = (int)strtol(b, &s, 10)))
160 j = 1;
161 if (!*s)
162 {
163 s = fmtbuf(j + 1);
164 memset(s, ' ', j);
165 s[j] = 0;
166 return s;
167 }
168 }
169 break;
170 case 'R':
171 if (!strcmp(b, "RN"))
172 return "1";
173 break;
174 case 'T':
175 if (!strcmp(b, "TIME"))
176 return fmttime("%H%M%S", t);
177 break;
178 }
179 if ((set & MUST) && jcl->disc->errorf)
180 (*jcl->disc->errorf)(NiL, jcl->disc, 1, "%%%%%s operand value or %s environment value expected", b, name);
181 }
182 else if (s = internal(jcl, name))
183 return s;
184 else if ((set & MUST) && jcl->disc->errorf)
185 (*jcl->disc->errorf)(NiL, jcl->disc, 1, "&%s: undefined variable", name);
186 return 0;
187 }
188 if (!(v = vmnewof(jcl->vm, 0, Jclsym_t, 1, strlen(name))))
189 {
190 nospace(jcl, NiL);
191 return 0;
192 }
193 strcpy(v->name, name);
194 if (!(v->value = stash(jcl, jcl->vm, value, 0)))
195 return 0;
196 dtinsert(jcl->syms, v);
197 found:
198 if (jcl->flags & (JCL_PARAMETERIZE|JCL_LISTVARIABLES))
199 {
200 register char* s;
201
202 for (s = v->name; isalnum(*s) || *s == '_'; s++);
203 if (!*s)
204 {
205 if (jcl->flags & JCL_LISTVARIABLES)
206 uniq(v->name, NiL, 0, jcl->disc);
207 if (jcl->flags & JCL_PARAMETERIZE)
208 {
209 #if 0
210 if (diff(v->name, v->value))
211 sfprintf(sfstdout, "%s=%s\t# global\n", v->name, fmtquote(v->value, "$'", "'", strlen(v->value), 0));
212 #endif
213 sfprintf(jcl->vp, "${%s}", v->name);
214 if (!(s = sfstruse(jcl->vp)))
215 nospace(jcl, NiL);
216 return s;
217 }
218 }
219 }
220 return v->value;
221 }
222
223 /*
224 * save string in vm
225 * path==1 enables mvs => unix path conversion
226 */
227
228 char*
stash(Jcl_t * jcl,Vmalloc_t * vm,const char * str,int path)229 stash(Jcl_t* jcl, Vmalloc_t* vm, const char* str, int path)
230 {
231 char* s;
232 char* t;
233 char* e;
234 int n;
235
236 n = strlen(str);
237 if (!(s = vmnewof(vm, NiL, char, n, 1)))
238 nospace(jcl, NiL);
239 strcpy(s, str);
240 if (path && (*s != '$' || *(s + 1) != '(') && (t = strchr(s, '(')) && *(s + n - 1) == ')')
241 {
242 strtol(t + 1, &e, 10);
243 if (e == (s + n - 1))
244 *t = 0;
245 else
246 {
247 *t = '/';
248 *(s + n - 1) = 0;
249 }
250 }
251 return s;
252 }
253
254 /*
255 * out of space message
256 */
257
258 void
nospace(Jcl_t * jcl,Jcldisc_t * disc)259 nospace(Jcl_t* jcl, Jcldisc_t* disc)
260 {
261 if (!disc)
262 disc = jcl->disc;
263 if (disc->errorf)
264 (*disc->errorf)(jcl, disc, ERROR_SYSTEM|2, "out of space");
265 }
266