remove xvm/ipagent
[unleashed.git] / usr / src / cmd / tic / tic_parse.c
bloba07e6d1d85d6d0cb7445289b85c4f752044b4a73
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
28 /* Copyright (c) 1988 AT&T */
29 /* All Rights Reserved */
33 * University Copyright- Copyright (c) 1982, 1986, 1988
34 * The Regents of the University of California
35 * All Rights Reserved
37 * University Acknowledgment- Portions of this document are derived from
38 * software developed by the University of California, Berkeley, and its
39 * contributors.
43 * *******************************************************************
44 * COPYRIGHT NOTICE *
45 * ********************************************************************
46 * This software is copyright (C) 1982 by Pavel Curtis *
47 * *
48 * Permission is granted to reproduce and distribute *
49 * this file by any means so long as no fee is charged *
50 * above a nominal handling fee and so long as this *
51 * notice is always included in the copies. *
52 * *
53 * Other rights are reserved except as explicitly granted *
54 * by written permission of the author. *
55 * Pavel Curtis *
56 * Computer Science Dept. *
57 * 405 Upson Hall *
58 * Cornell University *
59 * Ithaca, NY 14853 *
60 * *
61 * Ph- (607) 256-4934 *
62 * *
63 * Pavel.Cornell@Udel-Relay (ARPAnet) *
64 * decvax!cornell!pavel (UUCPnet) *
65 * ********************************************************************
69 * comp_parse.c -- The high-level (ha!) parts of the compiler,
70 * that is, the routines which drive the scanner,
71 * etc.
73 * $Log: RCS/comp_parse.v $
74 * Revision 2.1 82/10/25 14:45:43 pavel
75 * Added Copyright Notice
77 * Revision 2.0 82/10/24 15:16:39 pavel
78 * Beta-one Test Release
80 * Revision 1.3 82/08/23 22:29:39 pavel
81 * The REAL Alpha-one Release Version
83 * Revision 1.2 82/08/19 19:09:53 pavel
84 * Alpha Test Release One
86 * Revision 1.1 82/08/12 18:37:12 pavel
87 * Initial revision
92 #include <sys/types.h>
93 #include <sys/stat.h>
94 #include <stdio.h>
95 #include <ctype.h>
96 #include <stdlib.h>
97 #include <strings.h>
98 #include <unistd.h>
99 #include "curses_inc.h"
100 #include "compiler.h"
101 #include "object.h"
103 extern char check_only;
104 extern char *progname;
106 char *string_table;
107 int next_free; /* next free character in string_table */
108 unsigned int table_size = 0; /* current string_table size */
109 short term_names; /* string table offset - current terminal */
110 int part2 = 0; /* set to allow old compiled defns to be used */
111 int complete = 0; /* 1 if entry done with no forward uses */
113 struct use_item {
114 long offset;
115 struct use_item *fptr, *bptr;
118 struct use_header {
119 struct use_item *head, *tail;
122 struct use_header use_list = {NULL, NULL};
123 int use_count = 0;
125 void dequeue(struct use_item *);
126 void init_structure(short Booleans[], short Numbers[], short Strings[]);
127 void dump_structure(short Booleans[], short Numbers[], short Strings[]);
129 void err_abort(char *fmt, ...);
130 void syserr_abort(char *fmt, ...);
131 void warning(char *fmt, ...);
132 int get_token();
133 int do_entry(struct use_item *item_ptr);
134 int read_entry(char *filename, struct _bool_struct *bptr,
135 struct _num_struct *nptr, struct _str_struct *sptr);
136 void reset_input(void);
137 int save_str(char *string);
138 int handle_use(struct use_item *item_ptr, long entry_offset, short Booleans[],
139 short Numbers[], short Strings[]);
140 void panic_mode(int ch);
141 void check_dir(char dirletter);
142 int write_object(FILE *fp, short Booleans[], short Numbers[], short Strings[]);
143 int must_swap(void);
145 * The use_list is a doubly-linked list with NULLs terminating the lists:
147 * use_item use_item use_item
148 * --------- --------- ---------
149 * | | | | | | offset
150 * |-------| |-------| |-------|
151 * | ----+-->| ----+-->| NULL | fptr
152 * |-------| |-------| |-------|
153 * | NULL |<--+---- |<--+---- | bptr
154 * --------- --------- ---------
155 * ^ ^
156 * | ------------------ |
157 * | | | | |
158 * +--+---- | ----+---+
159 * | | |
160 * ------------------
161 * head tail
162 * use_list
168 * compile()
170 * Main loop of the compiler.
172 * get_token()
173 * if curr_token != NAMES
174 * err_abort()
175 * while (not at end of file)
176 * do an entry
180 void
181 compile()
183 char line[1024];
184 int token_type;
185 struct use_item *ptr;
186 int old_use_count;
188 token_type = get_token();
190 if (token_type != NAMES)
191 err_abort(
192 "File does not start with terminal names in column one");
194 while (token_type != EOF)
195 token_type = do_entry(NULL);
197 DEBUG(2, "Starting handling of forward USE's\n", "");
199 for (part2 = 0; part2 < 2; part2++) {
200 old_use_count = -1;
201 DEBUG(2, "\n\nPART %d\n\n", part2);
202 while (use_list.head != NULL && old_use_count != use_count) {
203 old_use_count = use_count;
204 for (ptr = use_list.tail; ptr != NULL;
205 ptr = ptr->bptr) {
206 fseek(stdin, ptr->offset, 0);
207 reset_input();
208 if ((token_type = get_token()) != NAMES)
209 syserr_abort(
210 "Token after a seek not NAMES");
211 (void) do_entry(ptr);
212 if (complete)
213 dequeue(ptr);
216 for (ptr = use_list.head; ptr != NULL;
217 ptr = ptr->fptr) {
218 fseek(stdin, ptr->offset, 0);
219 reset_input();
220 if ((token_type = get_token()) != NAMES)
221 syserr_abort(
222 "Token after a seek not NAMES");
223 (void) do_entry(ptr);
224 if (complete)
225 dequeue(ptr);
228 DEBUG(2,
229 "Finished a pass through enqueued forward USE's\n", "");
233 if (use_list.head != NULL && !check_only) {
234 fprintf(stderr,
235 "\nError in following use-links. Either there is a loop in the links\n"
236 "or they reference non-existent terminals. The following is a list of\n"
237 "the entries involved:\n\n");
239 for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) {
240 fseek(stdin, ptr->offset, 0);
241 fgets(line, 1024, stdin);
242 fprintf(stderr, "%s", line);
245 exit(1);
249 void
250 dump_list(char *str)
252 struct use_item *ptr;
253 char line[1024];
255 fprintf(stderr, "dump_list %s\n", str);
256 for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) {
257 fseek(stdin, ptr->offset, 0);
258 fgets(line, 1024, stdin);
259 fprintf(stderr, "ptr %x off %d bptr %x fptr %x str %s",
260 ptr, ptr->offset, ptr->bptr, ptr->fptr, line);
262 fprintf(stderr, "\n");
266 * int
267 * do_entry(item_ptr)
269 * Compile one entry. During the first pass, item_ptr is NULL. In pass
270 * two, item_ptr points to the current entry in the use_list.
272 * found-forward-use = FALSE
273 * re-initialise internal arrays
274 * save names in string_table
275 * get_token()
276 * while (not EOF and not NAMES)
277 * if found-forward-use
278 * do nothing
279 * else if 'use'
280 * if handle_use() < 0
281 * found-forward-use = TRUE
282 * else
283 * check for existance and type-correctness
284 * enter cap into structure
285 * if STRING
286 * save string in string_table
287 * get_token()
288 * if ! found-forward-use
289 * dump compiled entry into filesystem
294 do_entry(item_ptr)
295 struct use_item *item_ptr;
297 long entry_offset;
298 int token_type;
299 struct name_table_entry *entry_ptr;
300 int found_forward_use = FALSE;
301 short Booleans[MAXBOOLS],
302 Numbers[MAXNUMS],
303 Strings[MAXSTRINGS];
305 init_structure(Booleans, Numbers, Strings);
306 complete = 0;
307 term_names = save_str(curr_token.tk_name);
308 DEBUG(2, "Starting '%s'\n", curr_token.tk_name);
309 entry_offset = curr_file_pos;
311 for (token_type = get_token();
312 token_type != EOF && token_type != NAMES;
313 token_type = get_token()) {
314 /* LINTED E_NOP_IF_STMT */
315 if (found_forward_use)
316 /* do nothing */;
317 else if (strcmp(curr_token.tk_name, "use") == 0) {
318 if (handle_use(item_ptr, entry_offset,
319 Booleans, Numbers, Strings) < 0)
320 found_forward_use = TRUE;
321 } else {
322 entry_ptr = find_entry(curr_token.tk_name);
324 if (entry_ptr == NOTFOUND) {
325 warning("Unknown Capability - '%s'",
326 curr_token.tk_name);
327 continue;
331 if (token_type != CANCEL &&
332 entry_ptr->nte_type != token_type)
333 warning("Wrong type used for capability '%s'",
334 curr_token.tk_name);
335 switch (token_type) {
336 case CANCEL:
337 switch (entry_ptr->nte_type) {
338 case BOOLEAN:
339 Booleans[entry_ptr->nte_index] = -2;
340 break;
342 case NUMBER:
343 Numbers[entry_ptr->nte_index] = -2;
344 break;
346 case STRING:
347 Strings[entry_ptr->nte_index] = -2;
348 break;
350 break;
352 case BOOLEAN:
353 if (Booleans[entry_ptr->nte_index] == 0)
354 Booleans[entry_ptr->nte_index] = TRUE;
355 break;
357 case NUMBER:
358 if (Numbers[entry_ptr->nte_index] == -1)
359 Numbers[entry_ptr->nte_index] =
360 curr_token.tk_valnumber;
361 break;
363 case STRING:
364 if (Strings[entry_ptr->nte_index] == -1)
365 Strings[entry_ptr->nte_index] =
366 save_str(curr_token.tk_valstring);
367 break;
369 default:
370 warning("Unknown token type");
371 panic_mode(',');
372 continue;
374 } /* end else cur_token.name != "use" */
376 } /* endwhile (not EOF and not NAMES) */
378 if (found_forward_use)
379 return (token_type);
381 dump_structure(Booleans, Numbers, Strings);
383 complete = 1;
384 return (token_type);
388 * Change all cancellations to a non-entry.
389 * For booleans, @ -> false
390 * For nums, @ -> -1
391 * For strings, @ -> -1
393 * This only has to be done for entries which
394 * have to be compatible with the pre-Vr3 format.
396 #ifndef NOCANCELCOMPAT
397 void
398 elim_cancellations(short Booleans[], short Numbers[], short Strings[])
400 int i;
401 for (i = 0; i < BoolCount; i++) {
402 if (Booleans[i] == -2)
403 Booleans[i] = FALSE;
406 for (i = 0; i < NumCount; i++) {
407 if (Numbers[i] == -2)
408 Numbers[i] = -1;
411 for (i = 0; i < StrCount; i++) {
412 if (Strings[i] == -2)
413 Strings[i] = -1;
416 #endif /* NOCANCELCOMPAT */
418 * Change the cancellation signal from the -2 used internally to
419 * the 2 used within the binary.
421 void
422 change_cancellations(short Booleans[])
424 int i;
425 for (i = 0; i < BoolCount; i++) {
426 if (Booleans[i] == -2)
427 Booleans[i] = 2;
433 * enqueue(offset)
435 * Put a record of the given offset onto the use-list.
439 void
440 enqueue(long offset)
442 struct use_item *item;
444 item = (struct use_item *)malloc(sizeof (struct use_item));
446 if (item == NULL)
447 syserr_abort("Not enough memory for use_list element");
449 item->offset = offset;
451 if (use_list.head != NULL) {
452 item->bptr = use_list.tail;
453 use_list.tail->fptr = item;
454 item->fptr = NULL;
455 use_list.tail = item;
456 } else {
457 use_list.tail = use_list.head = item;
458 item->fptr = item->bptr = NULL;
461 use_count ++;
465 * dequeue(ptr)
467 * remove the pointed-to item from the use_list
471 void
472 dequeue(struct use_item *ptr)
474 if (ptr->fptr == NULL)
475 use_list.tail = ptr->bptr;
476 else
477 (ptr->fptr)->bptr = ptr->bptr;
479 if (ptr->bptr == NULL)
480 use_list.head = ptr->fptr;
481 else
482 (ptr->bptr)->fptr = ptr->fptr;
484 use_count --;
488 * invalid_term_name(name)
490 * Look for invalid characters in a term name. These include
491 * space, tab and '/'.
493 * Generate an error message if given name does not begin with a
494 * digit or letter, then exit.
496 * return TRUE if name is invalid.
500 static int
501 invalid_term_name(char *name)
503 int error = 0;
504 if (! isdigit(*name) && ! islower(*name) && ! isupper(*name))
505 error++;
507 for (; *name; name++)
508 if (isalnum(*name))
509 continue;
510 else if (isspace(*name) || (*name == '/'))
511 return (1);
512 if (error) {
513 fprintf(stderr, "%s: Line %d: Illegal terminal name - '%s'\n",
514 progname, curr_line, name);
515 fprintf(stderr,
516 "Terminal names must start with a letter or digit\n");
517 exit(1);
519 return (0);
523 * dump_structure()
525 * Save the compiled version of a description in the filesystem.
527 * make a copy of the name-list
528 * break it up into first-name and all-but-last-name
529 * if necessary
530 * clear CANCELS out of the structure
531 * creat(first-name)
532 * write object information to first-name
533 * close(first-name)
534 * for each valid name
535 * link to first-name
539 void
540 dump_structure(short Booleans[], short Numbers[], short Strings[])
542 struct stat64 statbuf;
543 FILE *fp = NULL;
544 char name_list[1024];
545 char *first_name, *other_names, *cur_name;
546 char filename[128 + 2 + 1];
547 char linkname[128 + 2 + 1];
548 int len;
549 int alphastart = 0;
551 strcpy(name_list, term_names + string_table);
552 DEBUG(7, "Name list = '%s'\n", name_list);
554 first_name = name_list;
555 /* Set othernames to 1 past first '|' in the list. */
556 /* Null out that '|' in the process. */
557 other_names = strchr(first_name, '|');
558 if (other_names)
559 *other_names++ = '\0';
561 if (invalid_term_name(first_name))
562 warning("'%s': bad first term name.", first_name);
565 DEBUG(7, "First name = '%s'\n", first_name);
566 DEBUG(7, "Other names = '%s'\n", other_names ? other_names : "NULL");
568 if ((len = strlen(first_name)) > 128)
569 warning("'%s': terminal name too long.", first_name);
570 else if (len == 1)
571 warning("'%s': terminal name too short.", first_name);
573 check_dir(first_name[0]);
575 sprintf(filename, "%c/%s", first_name[0], first_name);
577 if (stat64(filename, &statbuf) >= 0 && statbuf.st_mtime >= start_time) {
578 warning("'%s' defined in more than one entry.", first_name);
579 fprintf(stderr, "Entry being used is '%s'.\n",
580 (unsigned)term_names + string_table);
583 if (!check_only) {
584 unlink(filename);
585 fp = fopen(filename, "w");
586 if (fp == NULL) {
587 perror(filename);
588 syserr_abort("Can't open %s/%s\n", destination,
589 filename);
591 DEBUG(1, "Created %s\n", filename);
592 } else DEBUG(1, "Would have created %s\n", filename);
594 #ifndef NOCANCELCOMPAT
595 /* eliminate cancellation markings if there is no '+' in the name */
596 if (strchr(first_name, '+') == 0)
597 elim_cancellations(Booleans, Numbers, Strings);
598 else
599 #endif /* NOCANCELCOMPAT */
600 change_cancellations(Booleans);
602 if (!check_only) {
603 if (write_object(fp, Booleans, Numbers, Strings) < 0) {
604 syserr_abort("Error writing %s/%s", destination,
605 filename);
607 fclose(fp);
610 alphastart = isalpha(first_name[0]);
612 while (other_names) {
613 cur_name = other_names;
614 other_names = strchr(cur_name, '|');
615 if (other_names)
616 *other_names++ = '\0';
617 if (*cur_name == '\0')
618 continue;
620 if ((len = strlen(cur_name)) > 128) {
621 warning("'%s': terminal name too long.", cur_name);
622 continue;
623 } else if (len == 1) {
624 warning("'%s': terminal name too short.", first_name);
625 continue;
628 if (invalid_term_name(cur_name)) {
629 if (other_names)
630 warning("'%s': bad term name found in list.",
631 cur_name);
632 continue;
635 check_dir(cur_name[0]);
637 sprintf(linkname, "%c/%s", cur_name[0], cur_name);
639 alphastart |= isalpha(cur_name[0]);
641 if (strcmp(first_name, cur_name) == 0) {
642 warning("Terminal name '%s' synonym for itself",
643 first_name);
644 } else {
645 if (!check_only) {
646 if (stat64(linkname, &statbuf) >= 0 &&
647 statbuf.st_mtime >= start_time) {
648 warning(
649 "'%s' defined in more than one entry.", cur_name);
650 fprintf(stderr,
651 "Entry being used is '%s'.\n",
652 (unsigned)term_names +
653 string_table);
655 unlink(linkname);
656 if (link(filename, linkname) < 0)
657 syserr_abort("Can't link %s to %s",
658 filename, linkname);
659 DEBUG(1, "Linked %s\n", linkname);
660 } else DEBUG(1, "Would have linked %s\n", linkname);
664 if (!alphastart) {
665 warning("At least one synonym should begin with a letter.");
670 * int
671 * write_object(fp, Booleans, Numbers, Strings)
673 * Write out the compiled entry to the given file.
674 * Return 0 if OK or -1 if not.
678 #define swap(x) (((x >> 8) & 0377) + 256 * (x & 0377))
680 #define might_swap(x) (must_swap() ? swap(x) : (x))
684 write_object(fp, Booleans, Numbers, Strings)
685 FILE *fp;
686 short Booleans[];
687 short Numbers[];
688 short Strings[];
690 struct header header;
691 char *namelist;
692 short namelen;
693 char zero = '\0';
694 int i;
695 char cBooleans[MAXBOOLS];
696 int l_next_free;
698 namelist = term_names + string_table;
699 namelen = strlen(namelist) + 1;
701 l_next_free = next_free;
702 if (l_next_free % 256 == 255)
703 l_next_free++;
705 if (must_swap()) {
706 header.magic = swap(MAGIC);
707 header.name_size = swap(namelen);
708 header.bool_count = swap(BoolCount);
709 header.num_count = swap(NumCount);
710 header.str_count = swap(StrCount);
711 header.str_size = swap(l_next_free);
712 } else {
713 header.magic = MAGIC;
714 header.name_size = namelen;
715 header.bool_count = BoolCount;
716 header.num_count = NumCount;
717 header.str_count = StrCount;
718 header.str_size = l_next_free;
721 for (i = 0; i < BoolCount; i++)
722 cBooleans[i] = Booleans[i];
724 if (fwrite(&header, sizeof (header), 1, fp) != 1 ||
725 fwrite(namelist, sizeof (char), namelen, fp) != namelen ||
726 fwrite(cBooleans, sizeof (char), BoolCount, fp) !=
727 BoolCount)
728 return (-1);
730 if ((namelen+BoolCount) % 2 != 0 &&
731 fwrite(&zero, sizeof (char), 1, fp) != 1)
732 return (-1);
734 if (must_swap()) {
735 for (i = 0; i < NumCount; i++)
736 Numbers[i] = swap(Numbers[i]);
737 for (i = 0; i < StrCount; i++)
738 Strings[i] = swap(Strings[i]);
741 if (fwrite((char *)Numbers, sizeof (short), NumCount, fp) != NumCount ||
742 fwrite((char *)Strings, sizeof (short), StrCount, fp)
743 != StrCount ||
744 fwrite(string_table, sizeof (char), l_next_free, fp)
745 != l_next_free)
746 return (-1);
748 return (0);
752 * int
753 * save_str(string)
755 * copy string into next free part of string_table, doing a realloc()
756 * if necessary. return offset of beginning of string from start of
757 * string_table.
762 save_str(string)
763 char *string;
765 int old_next_free;
767 /* Do not let an offset be 255. It reads as -1 in Vr2 binaries. */
768 if (next_free % 256 == 255)
769 next_free++;
771 old_next_free = next_free;
773 if (table_size == 0) {
774 if ((string_table = malloc(1024)) == NULL)
775 syserr_abort("Out of memory");
776 table_size = 1024;
777 DEBUG(5, "Made initial string table allocation. Size is %u\n",
778 table_size);
781 while (table_size <= next_free + strlen(string)) {
782 if ((string_table = realloc(string_table, table_size + 1024))
783 == NULL)
784 syserr_abort("Out of memory");
785 table_size += 1024;
786 DEBUG(5, "Extended string table. Size now %u\n", table_size);
789 strcpy(&string_table[next_free], string);
790 DEBUG(7, "Saved string '%s' ", string);
791 DEBUG(7, "at location %d\n", next_free);
792 next_free += strlen(string) + 1;
794 return (old_next_free);
798 * init_structure(Booleans, Numbers, Strings)
800 * Initialise the given arrays
801 * Reset the next_free counter to zero.
805 void
806 init_structure(short Booleans[], short Numbers[], short Strings[])
808 int i;
810 for (i = 0; i < BoolCount; i++)
811 Booleans[i] = FALSE;
813 for (i = 0; i < NumCount; i++)
814 Numbers[i] = -1;
816 for (i = 0; i < StrCount; i++)
817 Strings[i] = -1;
819 next_free = 0;
823 * int
824 * handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)
826 * Merge the compiled file whose name is in cur_token.valstring
827 * with the current entry.
829 * if it's a forward use-link
830 * if item_ptr == NULL
831 * queue it up for later handling
832 * else
833 * ignore it (we're already going through the queue)
834 * else it's a backward use-link
835 * read in the object file for that terminal
836 * merge contents with current structure
838 * Returned value is 0 if it was a backward link and we
839 * successfully read it in, -1 if a forward link.
843 handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)
844 long entry_offset;
845 struct use_item *item_ptr;
846 short Booleans[];
847 short Numbers[];
848 short Strings[];
850 struct _bool_struct use_bools;
851 struct _num_struct use_nums;
852 struct _str_struct use_strs;
853 struct stat64 statbuf;
854 char filename[50];
855 int i;
856 char *UB = &use_bools._auto_left_margin; /* first bool */
857 short *UN = &use_nums._columns; /* first num */
858 char **US = &use_strs.strs._back_tab; /* first str */
860 if (invalid_term_name(curr_token.tk_valstring))
861 warning("%s: bad term name", curr_token.tk_valstring);
863 sprintf(filename, "%c/%s", curr_token.tk_valstring[0],
864 curr_token.tk_valstring);
866 if (stat64(filename, &statbuf) < 0 ||
867 (part2 == 0 && statbuf.st_mtime < start_time)) {
868 DEBUG(2, "Forward USE to %s", curr_token.tk_valstring);
870 if (item_ptr == NULL) {
871 DEBUG(2, " (enqueued)\n", "");
872 enqueue(entry_offset);
873 } else DEBUG(2, " (skipped)\n", "");
875 return (-1);
876 } else {
877 DEBUG(2, "Backward USE to %s\n", curr_token.tk_valstring);
878 if (read_entry(filename, &use_bools, &use_nums, &use_strs) < 0)
879 syserr_abort("Error in re-reading compiled file %s",
880 filename);
882 for (i = 0; i < BoolCount; i++) {
883 if (Booleans[i] == FALSE) {
884 if (UB[i] == TRUE) /* now true */
885 Booleans[i] = TRUE;
886 else if (UB[i] > TRUE) /* cancelled */
887 Booleans[i] = -2;
891 for (i = 0; i < NumCount; i++) {
892 if (Numbers[i] == -1)
893 Numbers[i] = UN[i];
896 for (i = 0; i < StrCount; i++) {
897 if (Strings[i] == -1) {
898 if (US[i] == (char *)-1)
899 Strings[i] = -2;
900 else if (US[i] != (char *)0)
901 Strings[i] = save_str(US[i]);
906 return (0);