perl 2.0 (no announcement message available)
[p5sagit/p5-mst-13.2.git] / x2p / a2py.c
1 /* $Header: a2py.c,v 2.0 88/06/05 00:15:41 root Exp $
2  *
3  * $Log:        a2py.c,v $
4  * Revision 2.0  88/06/05  00:15:41  root
5  * Baseline version 2.0.
6  * 
7  */
8
9 #include "util.h"
10 char *index();
11
12 char *filename;
13
14 int checkers = 0;
15
16 main(argc,argv,env)
17 register int argc;
18 register char **argv;
19 register char **env;
20 {
21     register STR *str;
22     register char *s;
23     int i;
24     STR *walk();
25     STR *tmpstr;
26
27     linestr = str_new(80);
28     str = str_new(0);           /* first used for -I flags */
29     for (argc--,argv++; argc; argc--,argv++) {
30         if (argv[0][0] != '-' || !argv[0][1])
31             break;
32       reswitch:
33         switch (argv[0][1]) {
34 #ifdef DEBUGGING
35         case 'D':
36             debug = atoi(argv[0]+2);
37 #ifdef YYDEBUG
38             yydebug = (debug & 1);
39 #endif
40             break;
41 #endif
42         case '0': case '1': case '2': case '3': case '4':
43         case '5': case '6': case '7': case '8': case '9':
44             maxfld = atoi(argv[0]+1);
45             absmaxfld = TRUE;
46             break;
47         case 'F':
48             fswitch = argv[0][2];
49             break;
50         case 'n':
51             namelist = savestr(argv[0]+2);
52             break;
53         case '-':
54             argc--,argv++;
55             goto switch_end;
56         case 0:
57             break;
58         default:
59             fatal("Unrecognized switch: %s\n",argv[0]);
60         }
61     }
62   switch_end:
63
64     /* open script */
65
66     if (argv[0] == Nullch)
67         argv[0] = "-";
68     filename = savestr(argv[0]);
69     if (strEQ(filename,"-"))
70         argv[0] = "";
71     if (!*argv[0])
72         rsfp = stdin;
73     else
74         rsfp = fopen(argv[0],"r");
75     if (rsfp == Nullfp)
76         fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
77
78     /* init tokener */
79
80     bufptr = str_get(linestr);
81     symtab = hnew();
82
83     /* now parse the report spec */
84
85     if (yyparse())
86         fatal("Translation aborted due to syntax errors.\n");
87
88 #ifdef DEBUGGING
89     if (debug & 2) {
90         int type, len;
91
92         for (i=1; i<mop;) {
93             type = ops[i].ival;
94             len = type >> 8;
95             type &= 255;
96             printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
97             if (type == OSTRING)
98                 printf("\t\"%s\"\n",ops[i].cval),i++;
99             else {
100                 while (len--) {
101                     printf("\t%d",ops[i].ival),i++;
102                 }
103                 putchar('\n');
104             }
105         }
106     }
107     if (debug & 8)
108         dump(root);
109 #endif
110
111     /* first pass to look for numeric variables */
112
113     prewalk(0,0,root,&i);
114
115     /* second pass to produce new program */
116
117     tmpstr = walk(0,0,root,&i);
118     str = str_make("#!/usr/bin/perl\neval \"exec /usr/bin/perl -S $0 $*\"\n\
119     if $running_under_some_shell;\n\
120                         # this emulates #! processing on NIH machines.\n\
121                         # (remove #! line above if indigestible)\n\n");
122     str_cat(str,
123       "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;\n");
124     str_cat(str,
125       "                 # process any FOO=bar switches\n\n");
126     if (do_opens && opens) {
127         str_scat(str,opens);
128         str_free(opens);
129         str_cat(str,"\n");
130     }
131     str_scat(str,tmpstr);
132     str_free(tmpstr);
133 #ifdef DEBUGGING
134     if (!(debug & 16))
135 #endif
136     fixup(str);
137     putlines(str);
138     if (checkers) {
139         fprintf(stderr,
140           "Please check my work on the %d line%s I've marked with \"#???\".\n",
141                 checkers, checkers == 1 ? "" : "s" );
142         fprintf(stderr,
143           "The operation I've selected may be wrong for the operand types.\n");
144     }
145     exit(0);
146 }
147
148 #define RETURN(retval) return (bufptr = s,retval)
149 #define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
150 #define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
151 #define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,VAR)
152
153 yylex()
154 {
155     register char *s = bufptr;
156     register char *d;
157     register int tmp;
158
159   retry:
160 #ifdef YYDEBUG
161     if (yydebug)
162         if (index(s,'\n'))
163             fprintf(stderr,"Tokener at %s",s);
164         else
165             fprintf(stderr,"Tokener at %s\n",s);
166 #endif
167     switch (*s) {
168     default:
169         fprintf(stderr,
170             "Unrecognized character %c in file %s line %d--ignoring.\n",
171              *s++,filename,line);
172         goto retry;
173     case '\\':
174     case 0:
175         s = str_get(linestr);
176         *s = '\0';
177         if (!rsfp)
178             RETURN(0);
179         line++;
180         if ((s = str_gets(linestr, rsfp)) == Nullch) {
181             if (rsfp != stdin)
182                 fclose(rsfp);
183             rsfp = Nullfp;
184             s = str_get(linestr);
185             RETURN(0);
186         }
187         goto retry;
188     case ' ': case '\t':
189         s++;
190         goto retry;
191     case '\n':
192         *s = '\0';
193         XTERM(NEWLINE);
194     case '#':
195         yylval = string(s,0);
196         *s = '\0';
197         XTERM(COMMENT);
198     case ';':
199         tmp = *s++;
200         if (*s == '\n') {
201             s++;
202             XTERM(SEMINEW);
203         }
204         XTERM(tmp);
205     case '(':
206     case '{':
207     case '[':
208     case ')':
209     case ']':
210         tmp = *s++;
211         XOP(tmp);
212     case 127:
213         s++;
214         XTERM('}');
215     case '}':
216         for (d = s + 1; isspace(*d); d++) ;
217         if (!*d)
218             s = d - 1;
219         *s = 127;
220         XTERM(';');
221     case ',':
222         tmp = *s++;
223         XTERM(tmp);
224     case '~':
225         s++;
226         yylval = string("~",1);
227         XTERM(MATCHOP);
228     case '+':
229     case '-':
230         if (s[1] == *s) {
231             s++;
232             if (*s++ == '+')
233                 XTERM(INCR);
234             else
235                 XTERM(DECR);
236         }
237         /* FALL THROUGH */
238     case '*':
239     case '%':
240         tmp = *s++;
241         if (*s == '=') {
242             yylval = string(s-1,2);
243             s++;
244             XTERM(ASGNOP);
245         }
246         XTERM(tmp);
247     case '&':
248         s++;
249         tmp = *s++;
250         if (tmp == '&')
251             XTERM(ANDAND);
252         s--;
253         XTERM('&');
254     case '|':
255         s++;
256         tmp = *s++;
257         if (tmp == '|')
258             XTERM(OROR);
259         s--;
260         XTERM('|');
261     case '=':
262         s++;
263         tmp = *s++;
264         if (tmp == '=') {
265             yylval = string("==",2);
266             XTERM(RELOP);
267         }
268         s--;
269         yylval = string("=",1);
270         XTERM(ASGNOP);
271     case '!':
272         s++;
273         tmp = *s++;
274         if (tmp == '=') {
275             yylval = string("!=",2);
276             XTERM(RELOP);
277         }
278         if (tmp == '~') {
279             yylval = string("!~",2);
280             XTERM(MATCHOP);
281         }
282         s--;
283         XTERM(NOT);
284     case '<':
285         s++;
286         tmp = *s++;
287         if (tmp == '=') {
288             yylval = string("<=",2);
289             XTERM(RELOP);
290         }
291         s--;
292         yylval = string("<",1);
293         XTERM(RELOP);
294     case '>':
295         s++;
296         tmp = *s++;
297         if (tmp == '>') {
298             yylval = string(">>",2);
299             XTERM(GRGR);
300         }
301         if (tmp == '=') {
302             yylval = string(">=",2);
303             XTERM(RELOP);
304         }
305         s--;
306         yylval = string(">",1);
307         XTERM(RELOP);
308
309 #define SNARFWORD \
310         d = tokenbuf; \
311         while (isalpha(*s) || isdigit(*s) || *s == '_') \
312             *d++ = *s++; \
313         *d = '\0'; \
314         d = tokenbuf;
315
316     case '$':
317         s++;
318         if (*s == '0') {
319             s++;
320             do_chop = TRUE;
321             need_entire = TRUE;
322             ID("0");
323         }
324         do_split = TRUE;
325         if (isdigit(*s)) {
326             for (d = s; isdigit(*s); s++) ;
327             yylval = string(d,s-d);
328             tmp = atoi(d);
329             if (tmp > maxfld)
330                 maxfld = tmp;
331             XOP(FIELD);
332         }
333         split_to_array = set_array_base = TRUE;
334         XOP(VFIELD);
335
336     case '/':                   /* may either be division or pattern */
337         if (expectterm) {
338             s = scanpat(s);
339             XTERM(REGEX);
340         }
341         tmp = *s++;
342         if (*s == '=') {
343             yylval = string("/=",2);
344             s++;
345             XTERM(ASGNOP);
346         }
347         XTERM(tmp);
348
349     case '0': case '1': case '2': case '3': case '4':
350     case '5': case '6': case '7': case '8': case '9':
351         s = scannum(s);
352         XOP(NUMBER);
353     case '"':
354         s++;
355         s = cpy2(tokenbuf,s,s[-1]);
356         if (!*s)
357             fatal("String not terminated:\n%s",str_get(linestr));
358         s++;
359         yylval = string(tokenbuf,0);
360         XOP(STRING);
361
362     case 'a': case 'A':
363         SNARFWORD;
364         ID(d);
365     case 'b': case 'B':
366         SNARFWORD;
367         if (strEQ(d,"break"))
368             XTERM(BREAK);
369         if (strEQ(d,"BEGIN"))
370             XTERM(BEGIN);
371         ID(d);
372     case 'c': case 'C':
373         SNARFWORD;
374         if (strEQ(d,"continue"))
375             XTERM(CONTINUE);
376         ID(d);
377     case 'd': case 'D':
378         SNARFWORD;
379         ID(d);
380     case 'e': case 'E':
381         SNARFWORD;
382         if (strEQ(d,"END"))
383             XTERM(END);
384         if (strEQ(d,"else"))
385             XTERM(ELSE);
386         if (strEQ(d,"exit")) {
387             saw_line_op = TRUE;
388             XTERM(EXIT);
389         }
390         if (strEQ(d,"exp")) {
391             yylval = OEXP;
392             XTERM(FUN1);
393         }
394         ID(d);
395     case 'f': case 'F':
396         SNARFWORD;
397         if (strEQ(d,"FS")) {
398             saw_FS++;
399             if (saw_FS == 1 && in_begin) {
400                 for (d = s; *d && isspace(*d); d++) ;
401                 if (*d == '=') {
402                     for (d++; *d && isspace(*d); d++) ;
403                     if (*d == '"' && d[2] == '"')
404                         const_FS = d[1];
405                 }
406             }
407             ID(tokenbuf);
408         }
409         if (strEQ(d,"FILENAME"))
410             d = "ARGV";
411         if (strEQ(d,"for"))
412             XTERM(FOR);
413         ID(d);
414     case 'g': case 'G':
415         SNARFWORD;
416         if (strEQ(d,"getline"))
417             XTERM(GETLINE);
418         ID(d);
419     case 'h': case 'H':
420         SNARFWORD;
421         ID(d);
422     case 'i': case 'I':
423         SNARFWORD;
424         if (strEQ(d,"if"))
425             XTERM(IF);
426         if (strEQ(d,"in"))
427             XTERM(IN);
428         if (strEQ(d,"index")) {
429             set_array_base = TRUE;
430             XTERM(INDEX);
431         }
432         if (strEQ(d,"int")) {
433             yylval = OINT;
434             XTERM(FUN1);
435         }
436         ID(d);
437     case 'j': case 'J':
438         SNARFWORD;
439         ID(d);
440     case 'k': case 'K':
441         SNARFWORD;
442         ID(d);
443     case 'l': case 'L':
444         SNARFWORD;
445         if (strEQ(d,"length")) {
446             yylval = OLENGTH;
447             XTERM(FUN1);
448         }
449         if (strEQ(d,"log")) {
450             yylval = OLOG;
451             XTERM(FUN1);
452         }
453         ID(d);
454     case 'm': case 'M':
455         SNARFWORD;
456         ID(d);
457     case 'n': case 'N':
458         SNARFWORD;
459         if (strEQ(d,"NF"))
460             do_split = split_to_array = set_array_base = TRUE;
461         if (strEQ(d,"next")) {
462             saw_line_op = TRUE;
463             XTERM(NEXT);
464         }
465         ID(d);
466     case 'o': case 'O':
467         SNARFWORD;
468         if (strEQ(d,"ORS")) {
469             saw_ORS = TRUE;
470             d = "$\\";
471         }
472         if (strEQ(d,"OFS")) {
473             saw_OFS = TRUE;
474             d = "$,";
475         }
476         if (strEQ(d,"OFMT")) {
477             d = "$#";
478         }
479         ID(d);
480     case 'p': case 'P':
481         SNARFWORD;
482         if (strEQ(d,"print")) {
483             XTERM(PRINT);
484         }
485         if (strEQ(d,"printf")) {
486             XTERM(PRINTF);
487         }
488         ID(d);
489     case 'q': case 'Q':
490         SNARFWORD;
491         ID(d);
492     case 'r': case 'R':
493         SNARFWORD;
494         if (strEQ(d,"RS")) {
495             d = "$/";
496             saw_RS = TRUE;
497         }
498         ID(d);
499     case 's': case 'S':
500         SNARFWORD;
501         if (strEQ(d,"split")) {
502             set_array_base = TRUE;
503             XOP(SPLIT);
504         }
505         if (strEQ(d,"substr")) {
506             set_array_base = TRUE;
507             XTERM(SUBSTR);
508         }
509         if (strEQ(d,"sprintf"))
510             XTERM(SPRINTF);
511         if (strEQ(d,"sqrt")) {
512             yylval = OSQRT;
513             XTERM(FUN1);
514         }
515         ID(d);
516     case 't': case 'T':
517         SNARFWORD;
518         ID(d);
519     case 'u': case 'U':
520         SNARFWORD;
521         ID(d);
522     case 'v': case 'V':
523         SNARFWORD;
524         ID(d);
525     case 'w': case 'W':
526         SNARFWORD;
527         if (strEQ(d,"while"))
528             XTERM(WHILE);
529         ID(d);
530     case 'x': case 'X':
531         SNARFWORD;
532         ID(d);
533     case 'y': case 'Y':
534         SNARFWORD;
535         ID(d);
536     case 'z': case 'Z':
537         SNARFWORD;
538         ID(d);
539     }
540 }
541
542 char *
543 scanpat(s)
544 register char *s;
545 {
546     register char *d;
547
548     switch (*s++) {
549     case '/':
550         break;
551     default:
552         fatal("Search pattern not found:\n%s",str_get(linestr));
553     }
554
555     d = tokenbuf;
556     for (; *s; s++,d++) {
557         if (*s == '\\') {
558             if (s[1] == '/')
559                 *d++ = *s++;
560             else if (s[1] == '\\')
561                 *d++ = *s++;
562         }
563         else if (*s == '[') {
564             *d++ = *s++;
565             do {
566                 if (*s == '\\' && s[1])
567                     *d++ = *s++;
568                 if (*s == '/' || (*s == '-' && s[1] == ']'))
569                     *d++ = '\\';
570                 *d++ = *s++;
571             } while (*s && *s != ']');
572         }
573         else if (*s == '/')
574             break;
575         *d = *s;
576     }
577     *d = '\0';
578
579     if (!*s)
580         fatal("Search pattern not terminated:\n%s",str_get(linestr));
581     s++;
582     yylval = string(tokenbuf,0);
583     return s;
584 }
585
586 yyerror(s)
587 char *s;
588 {
589     fprintf(stderr,"%s in file %s at line %d\n",
590       s,filename,line);
591 }
592
593 char *
594 scannum(s)
595 register char *s;
596 {
597     register char *d;
598
599     switch (*s) {
600     case '1': case '2': case '3': case '4': case '5':
601     case '6': case '7': case '8': case '9': case '0' : case '.':
602         d = tokenbuf;
603         while (isdigit(*s)) {
604             *d++ = *s++;
605         }
606         if (*s == '.' && index("0123456789eE",s[1])) {
607             *d++ = *s++;
608             while (isdigit(*s)) {
609                 *d++ = *s++;
610             }
611         }
612         if (index("eE",*s) && index("+-0123456789",s[1])) {
613             *d++ = *s++;
614             if (*s == '+' || *s == '-')
615                 *d++ = *s++;
616             while (isdigit(*s))
617                 *d++ = *s++;
618         }
619         *d = '\0';
620         yylval = string(tokenbuf,0);
621         break;
622     }
623     return s;
624 }
625
626 string(ptr,len)
627 char *ptr;
628 {
629     int retval = mop;
630
631     ops[mop++].ival = OSTRING + (1<<8);
632     if (!len)
633         len = strlen(ptr);
634     ops[mop].cval = safemalloc(len+1);
635     strncpy(ops[mop].cval,ptr,len);
636     ops[mop++].cval[len] = '\0';
637     return retval;
638 }
639
640 oper0(type)
641 int type;
642 {
643     int retval = mop;
644
645     if (type > 255)
646         fatal("type > 255 (%d)\n",type);
647     ops[mop++].ival = type;
648     return retval;
649 }
650
651 oper1(type,arg1)
652 int type;
653 int arg1;
654 {
655     int retval = mop;
656
657     if (type > 255)
658         fatal("type > 255 (%d)\n",type);
659     ops[mop++].ival = type + (1<<8);
660     ops[mop++].ival = arg1;
661     return retval;
662 }
663
664 oper2(type,arg1,arg2)
665 int type;
666 int arg1;
667 int arg2;
668 {
669     int retval = mop;
670
671     if (type > 255)
672         fatal("type > 255 (%d)\n",type);
673     ops[mop++].ival = type + (2<<8);
674     ops[mop++].ival = arg1;
675     ops[mop++].ival = arg2;
676     return retval;
677 }
678
679 oper3(type,arg1,arg2,arg3)
680 int type;
681 int arg1;
682 int arg2;
683 int arg3;
684 {
685     int retval = mop;
686
687     if (type > 255)
688         fatal("type > 255 (%d)\n",type);
689     ops[mop++].ival = type + (3<<8);
690     ops[mop++].ival = arg1;
691     ops[mop++].ival = arg2;
692     ops[mop++].ival = arg3;
693     return retval;
694 }
695
696 oper4(type,arg1,arg2,arg3,arg4)
697 int type;
698 int arg1;
699 int arg2;
700 int arg3;
701 int arg4;
702 {
703     int retval = mop;
704
705     if (type > 255)
706         fatal("type > 255 (%d)\n",type);
707     ops[mop++].ival = type + (4<<8);
708     ops[mop++].ival = arg1;
709     ops[mop++].ival = arg2;
710     ops[mop++].ival = arg3;
711     ops[mop++].ival = arg4;
712     return retval;
713 }
714
715 oper5(type,arg1,arg2,arg3,arg4,arg5)
716 int type;
717 int arg1;
718 int arg2;
719 int arg3;
720 int arg4;
721 int arg5;
722 {
723     int retval = mop;
724
725     if (type > 255)
726         fatal("type > 255 (%d)\n",type);
727     ops[mop++].ival = type + (5<<8);
728     ops[mop++].ival = arg1;
729     ops[mop++].ival = arg2;
730     ops[mop++].ival = arg3;
731     ops[mop++].ival = arg4;
732     ops[mop++].ival = arg5;
733     return retval;
734 }
735
736 int depth = 0;
737
738 dump(branch)
739 int branch;
740 {
741     register int type;
742     register int len;
743     register int i;
744
745     type = ops[branch].ival;
746     len = type >> 8;
747     type &= 255;
748     for (i=depth; i; i--)
749         printf(" ");
750     if (type == OSTRING) {
751         printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
752     }
753     else {
754         printf("(%-5d%s %d\n",branch,opname[type],len);
755         depth++;
756         for (i=1; i<=len; i++)
757             dump(ops[branch+i].ival);
758         depth--;
759         for (i=depth; i; i--)
760             printf(" ");
761         printf(")\n");
762     }
763 }
764
765 bl(arg,maybe)
766 int arg;
767 int maybe;
768 {
769     if (!arg)
770         return 0;
771     else if ((ops[arg].ival & 255) != OBLOCK)
772         return oper2(OBLOCK,arg,maybe);
773     else if ((ops[arg].ival >> 8) < 2)
774         return oper2(OBLOCK,ops[arg+1].ival,maybe);
775     else
776         return arg;
777 }
778
779 fixup(str)
780 STR *str;
781 {
782     register char *s;
783     register char *t;
784
785     for (s = str->str_ptr; *s; s++) {
786         if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
787             strcpy(s+1,s+2);
788             s++;
789         }
790         else if (*s == '\n') {
791             for (t = s+1; isspace(*t & 127); t++) ;
792             t--;
793             while (isspace(*t & 127) && *t != '\n') t--;
794             if (*t == '\n' && t-s > 1) {
795                 if (s[-1] == '{')
796                     s--;
797                 strcpy(s+1,t);
798             }
799             s++;
800         }
801     }
802 }
803
804 putlines(str)
805 STR *str;
806 {
807     register char *d, *s, *t, *e;
808     register int pos, newpos;
809
810     d = tokenbuf;
811     pos = 0;
812     for (s = str->str_ptr; *s; s++) {
813         *d++ = *s;
814         pos++;
815         if (*s == '\n') {
816             *d = '\0';
817             d = tokenbuf;
818             pos = 0;
819             putone();
820         }
821         else if (*s == '\t')
822             pos += 7;
823         if (pos > 78) {         /* split a long line? */
824             *d-- = '\0';
825             newpos = 0;
826             for (t = tokenbuf; isspace(*t & 127); t++) {
827                 if (*t == '\t')
828                     newpos += 8;
829                 else
830                     newpos += 1;
831             }
832             e = d;
833             while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
834                 d--;
835             if (d < t+10) {
836                 d = e;
837                 while (d > tokenbuf &&
838                   (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
839                     d--;
840             }
841             if (d < t+10) {
842                 d = e;
843                 while (d > tokenbuf &&
844                   (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
845                     d--;
846             }
847             if (d < t+10) {
848                 d = e;
849                 while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
850                     d--;
851             }
852             if (d < t+10) {
853                 d = e;
854                 while (d > tokenbuf && *d != ' ')
855                     d--;
856             }
857             if (d > t+3) {
858                 *d = '\0';
859                 putone();
860                 putchar('\n');
861                 if (d[-1] != ';' && !(newpos % 4)) {
862                     *t++ = ' ';
863                     *t++ = ' ';
864                     newpos += 2;
865                 }
866                 strcpy(t,d+1);
867                 newpos += strlen(t);
868                 d = t + strlen(t);
869                 pos = newpos;
870             }
871             else
872                 d = e + 1;
873         }
874     }
875 }
876
877 putone()
878 {
879     register char *t;
880
881     for (t = tokenbuf; *t; t++) {
882         *t &= 127;
883         if (*t == 127) {
884             *t = ' ';
885             strcpy(t+strlen(t)-1, "\t#???\n");
886             checkers++;
887         }
888     }
889     t = tokenbuf;
890     if (*t == '#') {
891         if (strnEQ(t,"#!/bin/awk",10) || strnEQ(t,"#! /bin/awk",11))
892             return;
893         if (strnEQ(t,"#!/usr/bin/awk",14) || strnEQ(t,"#! /usr/bin/awk",15))
894             return;
895     }
896     fputs(tokenbuf,stdout);
897 }
898
899 numary(arg)
900 int arg;
901 {
902     STR *key;
903     int dummy;
904
905     key = walk(0,0,arg,&dummy);
906     str_cat(key,"[]");
907     hstore(symtab,key->str_ptr,str_make("1"));
908     str_free(key);
909     set_array_base = TRUE;
910     return arg;
911 }