|
|
1.1 root 1: /*
2: * File: lmisc.c
3: * Contents: create, keywd, limit, llist
4: */
5:
6: #include "../h/rt.h"
7: #include "../h/keyword.h"
8: #include "../h/version.h"
9:
10: #ifndef VMS
11: #ifndef MSDOS
12: #include <sys/types.h>
13: #include <sys/times.h>
14: #include SysTime
15: #else MSDOS
16:
17: #ifdef LATTICE
18: #include <time.h>
19: #endif LATTICE
20: #ifdef MSoft
21: #include <sys/types.h>
22: #include <time.h>
23: #endif MSoft
24: #endif MSDOS
25:
26: #else VMS
27: #include <types.h>
28: #include <time.h>
29: struct tms {
30: time_t tms_utime; /* user time */
31: time_t tms_stime; /* system time */
32: time_t tms_cutime; /* user time, children */
33: time_t tms_cstime; /* system time, children */
34: };
35: #endif VMS
36:
37: /*
38: * create - return an entry block for a co-expression.
39: */
40:
41: OpBlock(create, 1, "create", 0)
42:
43: create(entryp, cargp)
44: word *entryp;
45: register struct descrip *cargp;
46: {
47: register struct b_coexpr *sblkp;
48: register struct b_refresh *rblkp;
49: register struct descrip *dp, *ndp, *dsp;
50: register word *newsp;
51: int na, nl, i;
52: struct b_proc *cproc;
53: extern struct b_coexpr *alcstk();
54: extern struct b_refresh *alceblk();
55:
56: /*
57: * Get a new co-expression stack and initialize.
58: */
59: sblkp = alcstk();
60: sblkp->activator = nulldesc;
61: sblkp->size = 0;
62: sblkp->nextstk = stklist;
63: stklist = sblkp;
64: /*
65: * Icon stack starts at word after co-expression stack block. C stack
66: * starts at end of stack region on machines with down-growing C stacks
67: * and somewhere in the middle of the region.
68: *
69: * The C stack is aligned on a doubleword boundary. For upgrowing
70: * stacks, the C stack starts in the middle of the stack portion
71: * of the static block. For downgrowing stacks, the C stack starts
72: * at the end of the static block.
73: */
74: newsp = (word *)((char *)sblkp + sizeof(struct b_coexpr));
75: #ifdef UpStack
76: sblkp->cstate[0] =
77: ((word)((char *)sblkp + (stksize - sizeof(*sblkp))/2)
78: &~(WordSize*2-1));
79: #else
80: sblkp->cstate[0] =
81: ((word)((char *)sblkp + stksize - WordSize)&~(WordSize*2-1));
82: #endif UpStack
83: sblkp->es_argp = (struct descrip *)newsp;
84: /*
85: * Calculate number of arguments and number of local variables.
86: * na is nargs + 1 to include Arg0.
87: */
88: na = pfp->pf_nargs + 1;
89: cproc = (struct b_proc *)BlkLoc(argp[0]);
90: nl = cproc->ndynam;
91:
92: /*
93: * Get a refresh block for the new co-expression.
94: */
95: blkreq((word)sizeof(struct b_refresh) + (na + nl) * sizeof(struct descrip));
96: rblkp = alceblk(entryp, na, nl);
97: sblkp->freshblk.dword = D_Refresh;
98: BlkLoc(sblkp->freshblk) = (union block *) rblkp;
99:
100: /*
101: * Copy current procedure frame marker into refresh block.
102: */
103: rblkp->pfmkr = *pfp;
104: rblkp->pfmkr.pf_pfp = 0;
105:
106: /*
107: * Copy arguments into refresh block and onto new stack.
108: */
109: dp = &argp[0];
110: ndp = &rblkp->elems[0];
111: dsp = (struct descrip *)newsp;
112: for (i = 1; i <= na; i++) {
113: *dsp++ = *dp;
114: *ndp++ = *dp++;
115: }
116:
117: /*
118: * Copy procedure frame to new stack and point dsp to word after frame.
119: */
120: *((struct pf_marker *)dsp) = *pfp;
121: sblkp->es_pfp = (struct pf_marker *)dsp;
122: sblkp->es_pfp->pf_pfp = 0;
123: dsp = (struct descrip *)((word *)dsp + Vwsizeof(*pfp));
124: sblkp->es_ipc = entryp;
125: sblkp->es_gfp = 0;
126: sblkp->es_efp = 0;
127: sblkp->es_ilevel = 0;
128: sblkp->tvalloc = NULL;
129:
130: /*
131: * Copy locals to new stack and refresh block.
132: */
133: dp = &(pfp->pf_locals)[0];
134: for (i = 1; i <= nl; i++) {
135: *dsp++ = *dp;
136: *ndp++ = *dp++;
137: }
138: /*
139: * Push two null descriptors on the stack.
140: */
141: *dsp++ = nulldesc;
142: *dsp++ = nulldesc;
143:
144: sblkp->es_sp = (word *)dsp - 1;
145:
146: /*
147: * Establish line and file values and clear location for transmitted value.
148: */
149: sblkp->es_line = line;
150:
151: /*
152: * Return the new co-expression.
153: */
154: Arg0.dword = D_Coexpr;
155: BlkLoc(Arg0) = (union block *) sblkp;
156: Return;
157: }
158:
159: static char *day[] = {
160: "Sunday", "Monday", "Tuesday", "Wednesday",
161: "Thursday", "Friday", "Saturday"
162: };
163:
164: static char *month[] = {
165: "January", "February", "March", "April", "May", "June",
166: "July", "August", "September", "October", "November", "December"
167: };
168:
169: /*
170: * keywd - process keyword.
171: */
172:
173: LibDcl(keywd,0,"&keywd")
174: {
175: register int hour;
176: register word i;
177: register char *merid;
178: char sbuf[MaxCvtLen];
179: struct tm *tbuf, *localtime();
180: #ifndef MSDOS
181: struct tms tp;
182: #endif MSDOS
183: long time();
184: long clock, runtim;
185: char *alcstr();
186:
187: /*
188: * This is just plug and chug code. For whatever keyword is desired,
189: * the appropriate value is dug out of the system and made into
190: * a suitable Icon value.
191: *
192: * A few special cases are worth noting:
193: * &pos, &random, &trace - built-in trapped variables are returned
194: */
195: switch (IntVal(Arg0)) {
196: case K_ASCII:
197: Arg0.dword = D_Cset;
198: BlkLoc(Arg0) = (union block *) &k_ascii;
199: break;
200: case K_CLOCK:
201: strreq((word)8);
202: time(&clock);
203: tbuf = localtime(&clock);
204: sprintf(sbuf,"%02d:%02d:%02d",tbuf->tm_hour,tbuf->tm_min,tbuf->tm_sec);
205: StrLen(Arg0) = 8;
206: StrLoc(Arg0) = alcstr(sbuf,(word)8);
207: break;
208: case K_CSET:
209: Arg0.dword = D_Cset;
210: BlkLoc(Arg0) = (union block *) &k_cset;
211: break;
212: case K_DATE:
213: strreq((word)10);
214: time(&clock);
215: tbuf = localtime(&clock);
216: sprintf(sbuf, "%04d/%02d/%02d",
217: (tbuf->tm_year)+1900,tbuf->tm_mon+1,tbuf->tm_mday);
218: StrLen(Arg0) = 10;
219: StrLoc(Arg0) = alcstr(sbuf,(word)10);
220: break;
221: case K_DATELINE:
222: time(&clock);
223: tbuf = localtime(&clock);
224: if ((hour = tbuf->tm_hour) >= 12) {
225: merid = "pm";
226: if (hour > 12)
227: hour -= 12;
228: }
229: else {
230: merid = "am";
231: if (hour < 1)
232: hour += 12;
233: }
234: sprintf(sbuf, "%s, %s %d, %d %d:%02d %s",
235: day[tbuf->tm_wday], month[tbuf->tm_mon], tbuf->tm_mday,
236: 1900 + tbuf->tm_year, hour, tbuf->tm_min, merid);
237: strreq(i = strlen(sbuf));
238: StrLen(Arg0) = i;
239: StrLoc(Arg0) = alcstr(sbuf, i);
240: break;
241: case K_ERROUT:
242: Arg0.dword = D_File;
243: BlkLoc(Arg0) = (union block *) &k_errout;
244: break;
245: case K_HOST:
246: iconhost(sbuf);
247: strreq(i = strlen(sbuf));
248: StrLen(Arg0) = i;
249: StrLoc(Arg0) = alcstr(sbuf, i);
250: break;
251: case K_INPUT:
252: Arg0.dword = D_File;
253: BlkLoc(Arg0) = (union block *) &k_input;
254: break;
255: case K_LCASE:
256: Arg0.dword = D_Cset;
257: BlkLoc(Arg0) = (union block *) &k_lcase;
258: break;
259: case K_LEVEL:
260: Arg0.dword = D_Integer;
261: IntVal(Arg0) = k_level;
262: break;
263: case K_MAIN:
264: Arg0 = k_main;
265: break;
266: case K_OUTPUT:
267: Arg0.dword = D_File;
268: BlkLoc(Arg0) = (union block *) &k_output;
269: break;
270: case K_POS:
271: Arg0.dword = D_Tvkywd;
272: BlkLoc(Arg0) = (union block *) &tvky_pos;
273: break;
274: case K_RANDOM:
275: Arg0.dword = D_Tvkywd;
276: BlkLoc(Arg0) = (union block *) &tvky_ran;
277: break;
278: case K_SOURCE:
279: Arg0 = BlkLoc(current)->coexpr.activator;
280: break;
281: case K_SUBJECT:
282: Arg0.dword = D_Tvkywd;
283: BlkLoc(Arg0) = (union block *) &tvky_sub;
284: break;
285: case K_TIME:
286: #ifndef MSDOS
287: times(&tp);
288: runtim =
289: 1000 * ((tp.tms_utime - starttime) / (double)Hz);
290: #else MSDOS
291: runtim = time() - starttime;
292: #endif MSDOS
293: Mkint(runtim, &Arg0);
294: break;
295: case K_TRACE:
296: Arg0.dword = D_Tvkywd;
297: BlkLoc(Arg0) = (union block *) &tvky_trc;
298: break;
299: case K_UCASE:
300: Arg0.dword = D_Cset;
301: BlkLoc(Arg0) = (union block *) &k_ucase;
302: break;
303: case K_VERSION:
304: strreq(i = strlen(VERSION));
305: StrLen(Arg0) = i;
306: StrLoc(Arg0) = VERSION;
307: break;
308: default:
309: syserr("keyword: unknown keyword type.");
310: }
311: Return;
312: }
313:
314:
315: /*
316: * limit - explicit limitation initialization.
317: */
318:
319: LibDcl(limit,0,"limit")
320: {
321: long l;
322:
323: /*
324: * The limit is both passed and returned in Arg0. The limit must
325: * be an integer. If the limit is 0, the expression being evaluated
326: * fails. If the limit is < 0, it is an error. Note that the
327: * result produced by limit is ultimately picked up by the lsusp
328: * function.
329: */
330: DeRef(Arg0);
331: switch (cvint(&Arg0, &l)) {
332:
333: case T_Integer:
334: Mkint(l, &Arg0);
335: break;
336:
337: case T_Longint:
338: runerr(205, &Arg0);
339:
340: default:
341: runerr(101, &Arg0);
342: }
343:
344: if (l < 0)
345: runerr(205, &Arg0);
346: if (l == 0)
347: Fail;
348: Return;
349: }
350:
351:
352: /*
353: * [ ... ] - create an explicitly specified list.
354: */
355:
356: LibDcl(llist,-1,"[...]")
357: {
358: register word i;
359: register struct b_list *hp;
360: register struct b_lelem *bp;
361: extern struct b_list *alclist();
362: extern struct b_lelem *alclstb();
363: word nelem;
364:
365: /*
366: * Round the number of elements in the list (as indicated by nargs)
367: * up to MinListSlots and ensure space for the list.
368: */
369: nelem = nargs;
370: if (nelem < MinListSlots)
371: nelem = MinListSlots;
372: blkreq((word)sizeof(struct b_list) + sizeof(struct b_lelem) +
373: nelem * sizeof(struct descrip));
374:
375: /*
376: * Allocate the list and a list block.
377: */
378: hp = alclist((word)nargs);
379: bp = alclstb(nelem, (word)0, (word)nargs);
380:
381: /*
382: * Make the list block just allocated into the first and last blocks
383: * for the list.
384: */
385: hp->listhead.dword = hp->listtail.dword = D_Lelem;
386: BlkLoc(hp->listhead) = BlkLoc(hp->listtail) = (union block *) bp;
387: /*
388: * Dereference each argument in turn and assign it to a list element.
389: */
390: for (i = 1; i <= nargs; i++) {
391: DeRef(Arg(i));
392: bp->lslots[i-1] = Arg(i);
393: }
394: /*
395: * Point Arg0 at the new list and return it.
396: */
397: ArgType(0) = D_List;
398: Arg(0).vword.bptr = (union block *)hp;
399: Return;
400: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.