comparison interps/c-intercal/src/cesspool.c @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
comparison
equal deleted inserted replaced
995:6883f5911eb7 996:859f9b4339e6
1 /*****************************************************************************
2
3 NAME
4 cesspool.c -- storage management and runtime support for INTERCAL
5
6 LICENSE TERMS
7 Copyright (C) 1996 Eric S. Raymond
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23 ***************************************************************************/
24 /* LINTLIBRARY */
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <setjmp.h>
29 #include <limits.h>
30 #include <assert.h>
31
32 #include "config.h"
33 #ifdef HAVE_STDARG_H
34 #include <stdarg.h>
35 #else
36 #include <varargs.h>
37 #endif
38
39 #include "sizes.h"
40 /* AIS: To avoid a separate overloaded/nonoverloaded library, we import
41 the overloading defines here and ignore them if we don't need them. */
42 #define MULTITHREAD 0
43 #define OVEROPUSED 1
44 #include "abcess.h"
45 #include "ick_lose.h"
46
47 #include "numerals.c"
48
49 /* AIS: because BUFSIZ could theoretically be too large for an int... */
50 #if BUFSIZ < INT_MAX
51 #define INTBUFSIZ (int)BUFSIZ
52 #else
53 #define INTBUFSIZ (int)INT_MAX
54 #endif
55
56 /* and likewise, so that we can compare things to INT_MAX */
57 #ifndef min
58 #define min(x,y) ((x)>(y)?(y):(x))
59 #endif
60
61 /* and likewise, define SIZE_MAX */
62 #ifndef SIZE_MAX
63 #ifdef ULLONG_MAX
64 #define SIZE_MAX (sizeof(unsigned short )==sizeof(size_t)?(size_t) USHRT_MAX : \
65 sizeof(unsigned int )==sizeof(size_t)?(size_t) UINT_MAX : \
66 sizeof(unsigned long )==sizeof(size_t)?(size_t) ULONG_MAX : \
67 sizeof(unsigned long long)==sizeof(size_t)?(size_t)ULLONG_MAX : 0)
68 #else
69 #define SIZE_MAX (sizeof(unsigned short )==sizeof(size_t)?(size_t) USHRT_MAX : \
70 sizeof(unsigned int )==sizeof(size_t)?(size_t) UINT_MAX : \
71 sizeof(unsigned long )==sizeof(size_t)?(size_t) ULONG_MAX : 0)
72 #endif
73 #endif
74
75 /* AIS: These will be set to stdin/stdout at the first opportunity,
76 which is not necessarily here. The annotations are to tell splint
77 that we know what we're doing here with the assignments; the
78 set to stdin/stdout will be done whenever it's necessary.
79 */
80 /*@null@*/ FILE* ick_cesspoolin =0;
81 /*@null@*/ FILE* ick_cesspoolout=0;
82
83 /* AIS: To keep ld happy. This shouldn't ever actually get used, but
84 * give it a sane value just in case it does. (This is referenced by
85 * clc-cset.c, but due to the linking-in of the character sets
86 * themselves the reference should never be used.) */
87 /*@observer@*/ /*@dependent@*/ const char* ick_datadir=".";
88
89 /**********************************************************************
90 *
91 * The following functions manipulate the nexting stack
92 *
93 *********************************************************************/
94
95 unsigned* ick_next; /* AIS: now allocated by ick-wrap.c */
96 /*@null@*/ jmp_buf* ick_next_jmpbufs = NULL; /* AIS: for ick_ec, if needed */
97 int ick_nextindex = 0;
98
99 static int ick_clcsem = 0; /* AIS */
100
101 void ick_pushnext(unsigned n)
102 {
103 if (ick_nextindex < ick_MAXNEXT)
104 ick_next[ick_nextindex++] = n;
105 else
106 ick_lose(IE123, ick_lineno, (const char *)NULL);
107 }
108
109 unsigned int ick_popnext(unsigned int n)
110 {
111 ick_nextindex -= n;
112 if (ick_nextindex < 0) {
113 ick_nextindex = 0;
114 return (unsigned int)-1;
115 }
116 return ick_next[ick_nextindex];
117 }
118
119 /* AIS: This is not the ick_resume in ick_ec.h, which is a macro and therefore
120 technically speaking doesn't clash with this function as the header file
121 ick_ec.h isn't included. */
122 unsigned int ick_resume(unsigned int n)
123 {
124 if (n == 0)
125 {
126 ick_lose(IE621, ick_lineno, (const char *)NULL);
127 /*@-unreachable@*/ return 0; /*@=unreachable@*/
128 }
129 else if ((n = ick_popnext(n)) == (unsigned int)-1)
130 {
131 ick_lose(IE632, ick_lineno, (const char *)NULL);
132 /*@-unreachable@*/ return 0; /*@=unreachable@*/
133 }
134 return(n);
135 }
136
137 /**********************************************************************
138 *
139 * The following functions implement the INTERCAL I/O model
140 *
141 *********************************************************************/
142
143 unsigned int ick_pin(void)
144 {
145 char buf[INTBUFSIZ], *cp;
146 unsigned int result = 0;
147 size_t n;
148
149 assert(buf != NULL); /* AIS: splint seems unable of figuring this
150 out for itself */
151
152 if(!ick_cesspoolin) ick_cesspoolin=stdin; /* AIS */
153
154 if (fgets(buf, INTBUFSIZ, ick_cesspoolin) == (char *)NULL)
155 ick_lose(IE562, ick_lineno, (const char *)NULL);
156 n = strlen(buf) - 1;
157 if (n > 0 && buf[n-1] == '\r')
158 --n;
159 buf[n] = '\0';
160
161 if(ick_wimp_mode) {
162 result = (unsigned int)strtoul(buf, (char **)NULL, 10);
163 n = 1;
164 }
165 else
166 {
167 for(n=0,cp = strtok(buf, " ");cp;cp = strtok((char *)NULL, " "),n++)
168 {
169 int digit = -1;
170 const numeral *np;
171
172 for (np = ick_numerals; np < ick_numerals + sizeof(ick_numerals)/sizeof(numeral); np++)
173 if (strcmp(np->name, cp) == 0)
174 {
175 digit = np->value;
176 break;
177 }
178
179 if (digit == -1)
180 ick_lose(IE579, ick_lineno, cp);
181
182 if (result < 429496729 || (result == 429496729 && digit < 6))
183 result = result * 10 + digit;
184 else
185 ick_lose(IE533, ick_lineno, (const char *)NULL);
186 }
187 }
188 if (!n)
189 ick_lose(IE562, ick_lineno, (const char *)NULL);
190 if (result > (unsigned int)ick_Max_large)
191 ick_lose(IE533, ick_lineno, (const char *)NULL);
192 return(result);
193 }
194
195 /**********************************************************************
196 *
197 * Butchered Roman ick_numerals implemented by
198 * Michael Ernst, mernst@theory.lcs.mit.edu. May 7, 1990
199 *
200 * The INTERCAL manual hints that 3999 should translate to MMMIM
201 * (compare MMMCMXCIX) without specifying what the translation is.
202 * That may be a typo; in any case, this implementation isn't that
203 * butchered.
204 *
205 *********************************************************************/
206
207 #define MAXDIGITS 10 /* max base 10 digits */
208 #define MAXROMANS (MAXDIGITS*4+1) /* max chars in translation */
209
210 /*
211 * The ick_first column tells how many of the succeeding columns are used.
212 * The other columns refer to the columns of br_equiv and br_overbar.
213 */
214 static int ick_br_trans[10][5] =
215 {
216 {0, 0, 0, 0, 0},
217 {1, 0, 0, 0, 0},
218 {2, 0, 0, 0, 0},
219 {3, 0, 0, 0, 0},
220 {2, 1, 2, 0, 0}, /* or use {4, 0, 0, 0, 0} */
221 {1, 2, 0, 0, 0},
222 {2, 2, 1, 0, 0},
223 {3, 2, 1, 1, 0},
224 {4, 2, 1, 1, 1},
225 {2, 1, 3, 0, 0}
226 };
227
228 /*
229 * butcher places in the string result the "butchered" Roman numeral for val.
230 * This string should be printed at the beginning of a line; it spans two
231 * lines and already contains newlines.
232 *
233 * 11/24/91 LHH: Removed unnecessary final newline.
234 */
235
236 static void butcher(unsigned long val, /*@out@*/ char *result)
237 {
238 int i, j;
239 int digitsig, digitval;
240 char res[MAXROMANS], ovb[MAXROMANS];
241
242 /* We need FOUR columns because of the odd way that M and I interact. */
243 static const char br_equiv[MAXDIGITS][4] =
244 {
245 {'I', 'I', 'V', 'X'}, {'X', 'X', 'L', 'C'},
246 {'C', 'C', 'D', 'M'}, {'M', 'I', 'V', 'X'},
247 {'X', 'X', 'L', 'C'}, {'C', 'C', 'D', 'M'},
248 {'M', 'i', 'v', 'x'}, {'x', 'x', 'l', 'c'},
249 {'c', 'c', 'd', 'm'}, {'m', 'i', 'v', 'x'},
250 };
251
252 static const char br_overbar[MAXDIGITS][4] =
253 {
254 {' ', ' ', ' ', ' '},
255 {' ', ' ', ' ', ' '},
256 {' ', ' ', ' ', ' '},
257 {' ', '_', '_', '_'},
258 {'_', '_', '_', '_'},
259 {'_', '_', '_', '_'},
260 {'_', ' ', ' ', ' '},
261 {' ', ' ', ' ', ' '},
262 {' ', ' ', ' ', ' '},
263 {' ', '_', '_', '_'},
264 };
265
266 if (val == 0)
267 /* Final newline will be added by puts.
268 (void) strcpy(result, "_\n \n");
269 */
270 (void) strcpy(result, "_\n");
271 else
272 {
273 res[MAXROMANS-1] = '\0';
274 ovb[MAXROMANS-1] = '\0';
275 i = MAXROMANS-1;
276
277 /* the significance of the current digit is 10 ** digitsig */
278 for (digitsig = 0; (digitsig < MAXDIGITS) && (val > 0); digitsig++)
279 {
280 digitval = (int)(val % 10);
281 for (j = ick_br_trans[digitval][0]; j > 0; j--)
282 {
283 /* printf("In j loop: %d %d\n", j, i); */
284 res[--i] = br_equiv[digitsig][ick_br_trans[digitval][j]];
285 ovb[i] = br_overbar[digitsig][ick_br_trans[digitval][j]];
286 }
287 val = val / 10;
288 }
289
290 j = i;
291 while ((*result++ = ovb[j++]) != '\0')
292 continue;
293 *--result = '\n';
294
295 j = i;
296 while ((*++result = res[j++]) != '\0')
297 continue;
298 /* Final newline will be added by puts.
299 *result++ = '\n';
300 */
301 *result = '\0';
302 }
303 }
304
305 void ick_clockface(ick_bool mode)
306 /* enable or disable ick_clockface mode (output IIII instead of IV) */
307 {
308 if (mode)
309 {
310 /* ick_clockface mode */
311 ick_br_trans[4][0] = 4;
312 ick_br_trans[4][1] = 0;
313 ick_br_trans[4][2] = 0;
314 }
315 else
316 {
317 /* normal mode */
318 ick_br_trans[4][0] = 2;
319 ick_br_trans[4][1] = 1;
320 ick_br_trans[4][2] = 2;
321 }
322 }
323
324 void ick_setclcsemantics(ick_bool mode) /* AIS: CLC-INTERCAL semantics mode? */
325 {
326 ick_clcsem=mode;
327 }
328
329 void ick_pout(unsigned int val)
330 /* output in `butchered' Roman ick_numerals; see manual, part 4.4.13 */
331 {
332 char result[2*MAXROMANS+1];
333
334 if(!ick_cesspoolout) ick_cesspoolout=stdout; /* AIS */
335
336 if(ick_wimp_mode) {
337 (void) fprintf(ick_cesspoolout,"%u\n",val);
338 }
339 else {
340 butcher(val, result);
341 (void) fprintf(ick_cesspoolout,"%s\n",result);
342 }
343 (void) fflush(ick_cesspoolout);
344 }
345
346 /**********************************************************************
347 *
348 * AIS: CLC-INTERCAL bitwise I/O, only used in CLC-INTERCAL semantics
349 * mode. The I/O is done in extended Baudot for a tail ick_array, or in
350 * mingled form for a hybrid ick_array; for the Baudot, we rely on
351 * clc-cset.c and on the Baudot and Latin-1 character sets that are
352 * linked to libick.a (or libickmt.a), so the final executable doesn't
353 * reference the compiler's libraries. clc-cset.c is designed to
354 * handle this all transparently, though, so we don't have to worry
355 * about the details. I wrote the next two functions.
356 *
357 **********************************************************************/
358
359 /* AIS: From clc-cset.c */
360 extern int ick_clc_cset_convert(const char* in, /*@partial@*/ char* out, const char* incset,
361 const char* outcset, int padstyle, size_t outsize,
362 /*@null@*/ FILE* errsto);
363
364 static void clcbinin(unsigned int type, ick_array *a, ick_bool forget)
365 {
366 size_t i;
367 int ti;
368 char* buf, *tempcp;
369 /* Allocating one byte per element in the ick_array must be enough,
370 * because the Baudot version cannot possibly be shorter than the
371 * original Latin-1, plus one for the terminating NUL. There is one
372 * potential problem, which is that fgets takes an int for the
373 * number of bytes to read, so we cap the number of bytes to read
374 * at INT_MAX and hope that's enough. */
375 i=a->dims[0]; /* we already know that there's 1 dim only */
376 if(SIZE_MAX/6-2<=a->dims[0])
377 ick_lose(IE252, ick_lineno, (const char*)NULL); /* size is too large */
378 if(!i) i=1;
379 buf=malloc(i+1);
380 if(!buf) ick_lose(IE252, ick_lineno, (const char*)NULL);
381 if(!ick_cesspoolin) ick_cesspoolin=stdin;
382 if(!fgets(buf,(int)(min(a->dims[0],(size_t)INT_MAX)),ick_cesspoolin))
383 strcpy(buf,"\n"); /* EOF inputs the null string in CLC-INTERCAL */
384 tempcp=strrchr(buf,'\n'); /* still working in ASCII at this point */
385 if(!tempcp) /* input too long for the ick_array is an error */
386 {
387 free(buf);
388 ick_lose(IE241, ick_lineno, (const char*)NULL);
389 }
390 *tempcp='\0'; /* chomp the final newline */
391 tempcp=malloc(6*i+12); /* to be on the safe side, even though
392 * Baudot doesn't use 16-byte chars */
393 if(!tempcp) ick_lose(IE252, ick_lineno, (const char*)NULL);
394 /* Zero the ick_array now. */
395 i=a->dims[0];
396 if(!forget) while(i--)
397 if(type==ick_TAIL)
398 a->data.tail[i]=0;
399 else
400 a->data.hybrid[i]=0;
401 ti=ick_clc_cset_convert(buf,tempcp,"latin1","baudot",2,6*a->dims[0]+12,(FILE*)0);
402 /* Negative ti ought to be impossible here; check anyway, and cause
403 * an internal error if it has happened. */
404 if(ti<0) ick_lose(IE778, ick_lineno, (const char*)NULL);
405 i=(size_t)ti;
406 if(i>a->dims[0]) ick_lose(IE241, ick_lineno, (const char*)0);
407 if(!forget) while(i--)
408 if(type==ick_TAIL)
409 a->data.tail[i]=(ick_type16)tempcp[i]+
410 (ick_type16)((rand()%256)*256);
411 else
412 a->data.hybrid[i]=(ick_type32)tempcp[i]+
413 (ick_type32)((rand()%256)*256);
414 free(tempcp);
415 free(buf);
416 }
417
418 static void clcbinout(unsigned int type, const ick_array* a)
419 {
420 size_t i;
421 int ti;
422 char* buf, *tempcp;
423 if(SIZE_MAX/6-2<=a->dims[0])
424 ick_lose(IE252, ick_lineno, (const char*)NULL); /* size is too large */
425 buf=malloc(a->dims[0]+1);
426 if(!buf) ick_lose(IE252, ick_lineno, (const char*) NULL);
427 i=0; tempcp=buf;
428 while(i<a->dims[0])
429 {
430 /* Values above 31 are invalid in Baudot, so cap them at 33 to
431 avoid integer wraparound trouble. */
432 if(type==ick_TAIL)
433 *tempcp=(char)min(33,a->data.tail[i]);
434 else
435 *tempcp=(char)min(33,a->data.hybrid[i]);
436 i++;
437 if(*tempcp!='\0')
438 tempcp++; /* NULs are ignored for some reason, but
439 * that's the behaviour the CLC-INTERCAL
440 * specs specify */
441 }
442 *tempcp='\0';
443 /* tempcp is definitely overkill here, but the *6+6 rule is being
444 * obeyed because that way the code is robust against any future
445 * changes in character sets. */
446 tempcp=malloc(a->dims[0]*6+12);
447 if(!tempcp) ick_lose(IE252, ick_lineno, (const char*) NULL);
448 ti=ick_clc_cset_convert(buf,tempcp,"baudot","latin1",0,6*a->dims[0]+12,(FILE*)0);
449 if(ti<0) ick_lose(IE778, ick_lineno, (const char*)NULL);
450 i=(size_t)ti;
451 tempcp[i]='\0';
452 /* CLC-INTERCAL bails out on invalid characters. C-INTERCAL uses
453 * instead the behaviour of replacing them with character code 26.
454 * (This is actually the purpose of character code 26 in ASCII, I
455 * think, although this is derived from memory; I don't know of any
456 * other system that uses it for this purpose, though, and the
457 * ability to confuse Windows with it is worth what might be lost
458 * through standards compliance, because Windows nonstandardly
459 * treats it as an EOF character.) */
460 while(i--) if(tempcp[i] == '\0') tempcp[i]='\x1a';
461 if(!ick_cesspoolout) ick_cesspoolout=stdout;
462 fprintf(ick_cesspoolout,"%s\n",tempcp);
463 (void) fflush(ick_cesspoolout);
464 free(tempcp);
465 free(buf);
466 }
467
468 /**********************************************************************
469 *
470 * The following two routines implement bitwise I/O. They assume
471 * 8 bit characters, but there's no reason more general versions
472 * could not be written.
473 *
474 *********************************************************************/
475
476 void ick_binin(unsigned int type, ick_array *a, ick_bool forget)
477 {
478 static int lastin = 0;
479 int c, v;
480 size_t i;
481
482 if (a->rank != 1)
483 ick_lose(IE241, ick_lineno, (const char *)NULL);
484
485 if(!ick_cesspoolin) ick_cesspoolin=stdin; /* AIS */
486
487 if(ick_clcsem) {clcbinin(type, a, forget); return;} /* AIS */
488
489 for (i = 0 ; i < a->dims[0] ; i++) {
490 v = ((c=fgetc(ick_cesspoolin)) == EOF) ? 256 :
491 ((unsigned)c - lastin) % 256;
492 lastin = c;
493 if (!forget) {
494 if (type == ick_TAIL)
495 a->data.tail[i] = (ick_type16) v;
496 else
497 a->data.hybrid[i] = (ick_type32) v;
498 }
499 }
500 }
501
502 void ick_binout(unsigned int type, const ick_array *a)
503 {
504 static unsigned int lastout = 0;
505 unsigned int c;
506 size_t i;
507
508 if (a->rank != 1)
509 ick_lose(IE241, ick_lineno, (const char *)NULL);
510
511 if(!ick_cesspoolout) ick_cesspoolout=stdout; /* AIS */
512
513 if(ick_clcsem) {clcbinout(type, a); return;} /* AIS */
514
515 for (i = 0 ; i < a->dims[0] ; i++) {
516 if (type == ick_TAIL)
517 c = lastout - a->data.tail[i];
518 else
519 c = lastout - a->data.hybrid[i];
520 lastout = c;
521 c = (c & 0x0f) << 4 | (c & 0xf0) >> 4;
522 c = (c & 0x33) << 2 | (c & 0xcc) >> 2;
523 c = (c & 0x55) << 1 | (c & 0xaa) >> 1;
524 (void) fputc((int)c,ick_cesspoolout);
525 if (c == 10 /* \n in INTERCAL */ || /* AIS */ ick_instapipe)
526 (void) fflush(ick_cesspoolout);
527 }
528 }
529
530 /**********************************************************************
531 *
532 * The following assignment function performs IGNORE and type checks
533 *
534 *********************************************************************/
535
536 unsigned int ick_assign(char *dest, unsigned int type, ick_bool forget,
537 unsigned int value)
538 {
539 unsigned int retval = 0;
540 if (type == ick_ONESPOT || type == ick_TAIL) {
541 if (value > (unsigned int)ick_Max_small)
542 ick_lose(IE275, ick_lineno, (const char *)NULL);
543 if (forget)
544 retval = value;
545 else {
546 retval = *(ick_type16*)dest;
547 *(ick_type16*)dest = (ick_type16) value;
548 }
549 }
550 else if (type == ick_TWOSPOT || type == ick_HYBRID) {
551 if (forget)
552 retval = value;
553 else {
554 retval = *(ick_type32*)dest;
555 *(ick_type32*)dest = value;
556 }
557 }
558 return retval;
559 }
560
561 /**********************************************************************
562 *
563 * The following functions implement the INTERCAL ick_array model
564 * If HAVE_STDARG_H is defined, stdarg is used, otherwise varargs.
565 *
566 *********************************************************************/
567
568
569 #ifdef HAVE_STDARG_H
570 /*@dependent@*/ void *ick_aref(unsigned int type, ...)
571 #else
572 /*@dependent@*/ void *ick_aref(va_alist) va_dcl
573 #endif
574 /* return a pointer to the ick_array location specified by args */
575 {
576 #ifndef HAVE_STDARG_H
577 unsigned int type;
578 #endif
579 ick_array *a;
580 unsigned int v;
581 va_list ap;
582 size_t address = 0;
583 unsigned int i;
584
585 #ifdef HAVE_STDARG_H
586 va_start(ap, type);
587 #else
588 va_start(ap);
589 type = va_arg(ap, unsigned int);
590 #endif
591 a = va_arg(ap, ick_array*);
592
593 if (va_arg(ap, unsigned int) != a->rank)
594 ick_lose(IE241, ick_lineno, (const char *)NULL);
595
596 for (i = 0 ; i < a->rank ; i++) {
597 v = va_arg(ap, unsigned int);
598 if (v == 0 || (size_t)v > a->dims[i])
599 ick_lose(IE241, ick_lineno, (const char *)NULL);
600 address = address * a->dims[i] + v - 1;
601 }
602
603 va_end(ap);
604
605 if (type == ick_TAIL)
606 return (void*)&(a->data.tail[address]);
607 else
608 return (void*)&(a->data.hybrid[address]);
609 }
610
611 #ifdef HAVE_STDARG_H
612 void ick_resize(unsigned int type, ...)
613 #else
614 void ick_resize(va_alist) va_dcl
615 #endif
616 /* ick_resize an ick_array to the given shape */
617 {
618 #ifndef HAVE_STDARG_H
619 unsigned int type;
620 #endif
621 ick_array *a;
622 ick_bool forget;
623 unsigned int i, r;
624 size_t v;
625 va_list ap;
626 int prod = 1;
627
628 #ifdef HAVE_STDARG_H
629 va_start(ap, type);
630 #else
631 va_start(ap);
632 type = va_arg(ap, unsigned int);
633 #endif
634 a = va_arg(ap, ick_array*);
635 forget = va_arg(ap, ick_bool);
636
637 /* AIS: a->dims is no longer initialised. So initialise it here if
638 it isn't already initialised, with an annotation to explain that
639 we aren't freeing the old pointer (because it was never malloced in
640 the first place and is probably invalid anyway.) */
641 /*@-mustfreeonly@*/
642 if (!a->rank) a->dims = 0;
643 /*@-mustfreeonly@*/
644
645 r = va_arg(ap, unsigned int);
646 if (!forget) {
647 a->rank = r;
648 if (a->dims)
649 free((char*)a->dims);
650 a->dims = malloc(a->rank * sizeof(*(a->dims)));
651 if (a->dims == NULL)
652 ick_lose(IE241, ick_lineno, (const char *)NULL);
653 }
654
655 for (i = 0 ; i < r ; i++) {
656 v = va_arg(ap, size_t);
657 if (v == 0)
658 ick_lose(IE240, ick_lineno, (const char *)NULL);
659 if (!forget) {
660 assert(a->dims != NULL); /* AIS: it isn't, because !forget, but
661 splint doesn't know that */
662 a->dims[i] = v;
663 prod *= v;
664 }
665 }
666
667 if (!forget) {
668 if (type == ick_TAIL) {
669 if (a->data.tail)
670 free((char *)a->data.tail);
671 a->data.tail = (ick_type16*)malloc(prod * sizeof(ick_type16));
672 if (a->data.tail == NULL)
673 ick_lose(IE241, ick_lineno, (const char *)NULL);
674 }
675 else {
676 if (a->data.hybrid)
677 free((char *)a->data.hybrid);
678 a->data.hybrid = (ick_type32*)malloc(prod * sizeof(ick_type32));
679 if (a->data.hybrid == NULL)
680 ick_lose(IE241, ick_lineno, (const char *)NULL);
681 }
682 }
683
684 va_end(ap);
685 }
686
687 /**********************************************************************
688 *
689 * The following functions implement save/retrieve
690 *
691 *********************************************************************/
692
693 /*@null@*/ ick_stashbox *ick_first; /* AIS: made non-static so it can be seen by unravel.c */
694
695 void ick_stashinit(void)
696 {
697 ick_first = NULL;
698 }
699
700 static /*@null@*/ ick_stashbox *fetch(unsigned int type, unsigned int index)
701 /* find a stashed variable in the save stack and extract it */
702 {
703 ick_stashbox **pp = &ick_first, *sp = ick_first;
704
705 while (sp != NULL && (sp->type != type || sp->index != index)) {
706 pp = &sp->ick_next;
707 sp = sp->ick_next;
708 }
709 if (sp)
710 *pp = sp->ick_next;
711
712 /* The annotation here is because Splint can't figure out that
713 ick_first can be modified via pp, and because this function
714 is the place where storage marked 'dependent' is initialised
715 and deinitialised. */
716 /*@-globstate@*/ /*@-dependenttrans@*/
717 return (sp);
718 /*@=globstate@*/ /*@=dependenttrans@*/
719 }
720
721 void ick_stash(unsigned int type, unsigned int index, void *from, ick_overop* oo)
722 /* stash away the variable's value */
723 {
724 /*@-nullassign@*/
725 ick_overop dummyoo;
726 /*@=nullassign@*/
727 /* create a new ick_stashbox and push it onto the stack */
728 ick_stashbox *sp;
729 dummyoo.get = (ick_type32 (*)(ick_type32))NULL;
730 dummyoo.set = (void (*)(ick_type32, void(*)()))NULL;
731 sp = (ick_stashbox*)malloc(sizeof(ick_stashbox));
732 if (sp == NULL) ick_lose(IE222, ick_lineno, (const char *)NULL);
733 sp->ick_next = ick_first;
734 ick_first = sp;
735
736 /* store the variable in it */
737 ick_first->type = type;
738 ick_first->index = index;
739 if(oo) ick_first->overloadinfo=oo[index]; /* AIS */
740 else ick_first->overloadinfo=dummyoo; /* AIS */
741 if (type == ick_ONESPOT)
742 {
743 memcpy(&ick_first->save.onespot, from, sizeof(ick_type16));
744 }
745 else if (type == ick_TWOSPOT)
746 memcpy(&ick_first->save.twospot, from, sizeof(ick_type32));
747 else if (type == ick_TAIL || type == ick_HYBRID) {
748 ick_array *a = (ick_array*)from;
749 int prod;
750 unsigned int i;
751 ick_first->save.a = (ick_array*)malloc(sizeof(ick_array));
752 if (ick_first->save.a == NULL) ick_lose(IE222, ick_lineno, (const char *)NULL);
753 ick_first->save.a->rank = a->rank;
754 ick_first->save.a->dims = malloc(a->rank * sizeof(*(ick_first->save.a->dims)));
755 if (ick_first->save.a->dims == NULL) ick_lose(IE222, ick_lineno, (const char *)NULL);
756 memcpy(ick_first->save.a->dims, a->dims,
757 a->rank * sizeof(*(a->dims)));
758 prod = a->rank ? 1 : 0;
759 for (i = 0 ; i < a->rank ; i++) {
760 prod *= a->dims[i];
761 }
762 if (type == ick_TAIL) {
763 ick_first->save.a->data.tail =
764 (ick_type16*)malloc(prod * sizeof(ick_type16));
765 if (ick_first->save.a->data.tail == NULL) ick_lose(IE222, ick_lineno, (const char *)NULL);
766 memcpy(ick_first->save.a->data.tail,
767 a->data.tail, prod * sizeof(ick_type16));
768 }
769 else {
770 ick_first->save.a->data.hybrid =
771 (ick_type32*)malloc(prod * sizeof(ick_type32));
772 if (ick_first->save.a->data.hybrid == NULL) ick_lose(IE222, ick_lineno, (const char *)NULL);
773 memcpy(ick_first->save.a->data.hybrid,
774 a->data.hybrid, prod * sizeof(ick_type32));
775 }
776 }
777 return;
778 }
779
780 void ick_retrieve(void *to, unsigned int type, unsigned int index,
781 ick_bool forget, ick_overop* oo)
782 /* restore the value of a variable from the save stack */
783 {
784 ick_stashbox *sp;
785
786 if ((sp = fetch(type, index)) == (ick_stashbox *)NULL)
787 ick_lose(IE436, ick_lineno, (const char *)NULL);
788 else if (!forget) {
789 if(oo) oo[index]=sp->overloadinfo; /* AIS */
790 if (type == ick_ONESPOT)
791 memcpy(to, (const char *)&sp->save.onespot, sizeof(ick_type16));
792 else if (type == ick_TWOSPOT)
793 memcpy(to, (const char *)&sp->save.twospot, sizeof(ick_type32));
794 else if (type == ick_TAIL || type == ick_HYBRID) {
795 ick_array *a = (ick_array*)to;
796 /*@-branchstate@*/ /* it's a union, so one valid is correct */
797
798 if (a->rank) {
799 free(a->dims);
800 if (type == ick_TAIL)
801 free(a->data.tail);
802 else
803 free(a->data.hybrid);
804 memcpy(to, (const char*)sp->save.a, sizeof(ick_array));
805 }
806 /*@=branchstate@*/
807 /* AIS: there isn't a memory leak here, because we memcpyd the
808 pointers elsewhere and so they are yet accessible. You can't
809 expect Splint to figure out what's going on there, though, thus
810 the annotations. */
811 /*@-compdestroy@*/
812 free(sp->save.a);
813 /*@=compdestroy@*/
814 }
815 }
816 else if (type == ick_TAIL || type == ick_HYBRID) {
817 free(sp->save.a->dims);
818 if (type == ick_TAIL)
819 free(sp->save.a->data.tail);
820 else
821 free(sp->save.a->data.hybrid);
822 free(sp->save.a);
823 }
824 free(sp);
825 }
826
827 /**********************************************************************
828 *
829 * The following function is used for random decision making
830 *
831 *********************************************************************/
832
833 unsigned int ick_roll(unsigned int n)
834 /* return ick_TRUE on n% chance, ick_FALSE otherwise */
835 {
836 #ifdef USG
837 return((unsigned int)(lrand48() % 100) < n);
838 #else
839 return((unsigned int)(rand() % 100) < n);
840 #endif /* UNIX */
841 }
842
843 /**********************************************************************
844 *
845 * AIS: This function is called when two COME FROMs reference the same
846 * line at runtime. ick_multicome0 is used in a non-multithread
847 * program; it produces an error. For multicome1, see unravel.c.
848 *
849 *********************************************************************/
850
851 int ick_multicome0(int errlineno, jmp_buf pc)
852 {
853 /*@-noeffect@*/
854 (void) pc; /* it's ignored by this function */
855 /*@=noeffect@*/
856 ick_lose(IE555, errlineno, (const char *) NULL);
857 /* this line number is quite possibly going to be wildly inaccurate */
858 /*@-unreachable@*/
859 return 0;
860 /*@=unreachable@*/
861 }
862
863 /**********************************************************************
864 *
865 * AIS: The next two functions are mine, and handle CREATE statements.
866 *
867 **********************************************************************/
868
869 struct ick_jictype
870 {
871 /*@observer@*/ const char* sig; /* a shallow copy of a constant string */
872 unsigned long target;
873 /*@null@*/ /*@only@*/ struct ick_jictype* next;
874 };
875
876 /*@null@*/ /*@only@*/ static struct ick_jictype* jiclist = NULL;
877
878 /* Return a jic entry that matches the requested signature exactly,
879 creating one if there isn't one yet. */
880 static struct ick_jictype* jicextract(/*@observer@*/ const char* sig)
881 {
882 struct ick_jictype* jicptr = jiclist;
883 while(jicptr)
884 {
885 if(strcmp(jicptr->sig,sig)==0) return jicptr;
886 if(jicptr->next != NULL) jicptr = jicptr->next;
887 else break;
888 }
889 if(!jicptr)
890 {
891 jiclist=malloc(sizeof *jiclist);
892 jicptr=jiclist;
893 }
894 else
895 {
896 jicptr->next=malloc(sizeof *jiclist);
897 jicptr=jicptr->next;
898 }
899 jicptr->next = NULL;
900 jicptr->sig = sig;
901 jicptr->target = 0;
902 return jicptr;
903 }
904
905 void ick_registercreation(const char* sig, unsigned long target)
906 {
907 jicextract(sig)->target=target;
908 }
909
910 unsigned long ick_jicmatch(const char* sig)
911 {
912 return jicextract(sig)->target;
913 }
914
915 /* AIS: Used by the JIC code to error out when attempting to access an array */
916 ick_type32 ick_ieg277(ick_type32 ignored)
917 {
918 /*@-noeffect@*/
919 (void) ignored;
920 /*@=noeffect@*/
921 ick_lose(IE277, ick_lineno, (const char*) NULL);
922 }
923
924 void ick_ies277(ick_type32 ignored, void(*ignored2)())
925 {
926 /*@-noeffect@*/
927 (void) ignored;
928 (void) ignored2;
929 /*@=noeffect@*/
930 ick_lose(IE277, ick_lineno, (const char*) NULL);
931 }
932
933 /* cesspool.c ends here */