source: trunk/third/perl/stab.c @ 9009

Revision 9009, 23.2 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9008, which included commits to RCS files with non-trunk default branches.
Line 
1/* $RCSfile: stab.c,v $$Revision: 1.1.1.1 $$Date: 1996-10-02 06:39:59 $
2 *
3 *    Copyright (c) 1991, Larry Wall
4 *
5 *    You may distribute under the terms of either the GNU General Public
6 *    License or the Artistic License, as specified in the README file.
7 *
8 * $Log: not supported by cvs2svn $
9 * Revision 4.0.1.5  1993/02/05  19:42:47  lwall
10 * patch36: length returned wrong value on certain semi-magical variables
11 *
12 * Revision 4.0.1.4  92/06/08  15:32:19  lwall
13 * patch20: fixed confusion between a *var's real name and its effective name
14 * patch20: the debugger now warns you on lines that can't set a breakpoint
15 * patch20: the debugger made perl forget the last pattern used by //
16 * patch20: paragraph mode now skips extra newlines automatically
17 * patch20: ($<,$>) = ... didn't work on some architectures
18 *
19 * Revision 4.0.1.3  91/11/05  18:35:33  lwall
20 * patch11: length($x) was sometimes wrong for numeric $x
21 * patch11: perl now issues warning if $SIG{'ALARM'} is referenced
22 * patch11: *foo = undef coredumped
23 * patch11: solitary subroutine references no longer trigger typo warnings
24 * patch11: local(*FILEHANDLE) had a memory leak
25 *
26 * Revision 4.0.1.2  91/06/07  11:55:53  lwall
27 * patch4: new copyright notice
28 * patch4: added $^P variable to control calling of perldb routines
29 * patch4: added $^F variable to specify maximum system fd, default 2
30 * patch4: $` was busted inside s///
31 * patch4: default top-of-form format is now FILEHANDLE_TOP
32 * patch4: length($`), length($&), length($') now optimized to avoid string copy
33 * patch4: $^D |= 1024 now does syntax tree dump at run-time
34 *
35 * Revision 4.0.1.1  91/04/12  09:10:24  lwall
36 * patch1: Configure now differentiates getgroups() type from getgid() type
37 * patch1: you may now use "die" and "caller" in a signal handler
38 *
39 * Revision 4.0  91/03/20  01:39:41  lwall
40 * 4.0 baseline.
41 *
42 */
43
44#include "EXTERN.h"
45#include "perl.h"
46
47#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
48#include <signal.h>
49#endif
50
51static char *sig_name[] = {
52    SIG_NAME,0
53};
54
55#ifdef VOIDSIG
56#define handlertype void
57#else
58#define handlertype int
59#endif
60
61static handlertype sighandler();
62
63static int origalen = 0;
64
65STR *
66stab_str(str)
67STR *str;
68{
69    STAB *stab = str->str_u.str_stab;
70    register int paren;
71    register char *s;
72    register int i;
73
74    if (str->str_rare)
75        return stab_val(stab);
76
77    switch (*stab->str_magic->str_ptr) {
78    case '\004':                /* ^D */
79#ifdef DEBUGGING
80        str_numset(stab_val(stab),(double)(debug & 32767));
81#endif
82        break;
83    case '\006':                /* ^F */
84        str_numset(stab_val(stab),(double)maxsysfd);
85        break;
86    case '\t':                  /* ^I */
87        if (inplace)
88            str_set(stab_val(stab), inplace);
89        else
90            str_sset(stab_val(stab),&str_undef);
91        break;
92    case '\020':                /* ^P */
93        str_numset(stab_val(stab),(double)perldb);
94        break;
95    case '\024':                /* ^T */
96        str_numset(stab_val(stab),(double)basetime);
97        break;
98    case '\027':                /* ^W */
99        str_numset(stab_val(stab),(double)dowarn);
100        break;
101    case '1': case '2': case '3': case '4':
102    case '5': case '6': case '7': case '8': case '9': case '&':
103        if (curspat) {
104            paren = atoi(stab_ename(stab));
105          getparen:
106            if (curspat->spat_regexp &&
107              paren <= curspat->spat_regexp->nparens &&
108              (s = curspat->spat_regexp->startp[paren]) ) {
109                i = curspat->spat_regexp->endp[paren] - s;
110                if (i >= 0)
111                    str_nset(stab_val(stab),s,i);
112                else
113                    str_sset(stab_val(stab),&str_undef);
114            }
115            else
116                str_sset(stab_val(stab),&str_undef);
117        }
118        break;
119    case '+':
120        if (curspat) {
121            paren = curspat->spat_regexp->lastparen;
122            goto getparen;
123        }
124        break;
125    case '`':
126        if (curspat) {
127            if (curspat->spat_regexp &&
128              (s = curspat->spat_regexp->subbeg) ) {
129                i = curspat->spat_regexp->startp[0] - s;
130                if (i >= 0)
131                    str_nset(stab_val(stab),s,i);
132                else
133                    str_nset(stab_val(stab),"",0);
134            }
135            else
136                str_nset(stab_val(stab),"",0);
137        }
138        break;
139    case '\'':
140        if (curspat) {
141            if (curspat->spat_regexp &&
142              (s = curspat->spat_regexp->endp[0]) ) {
143                str_nset(stab_val(stab),s, curspat->spat_regexp->subend - s);
144            }
145            else
146                str_nset(stab_val(stab),"",0);
147        }
148        break;
149    case '.':
150#ifndef lint
151        if (last_in_stab && stab_io(last_in_stab)) {
152            str_numset(stab_val(stab),(double)stab_io(last_in_stab)->lines);
153        }
154#endif
155        break;
156    case '?':
157        str_numset(stab_val(stab),(double)statusvalue);
158        break;
159    case '^':
160        s = stab_io(curoutstab)->top_name;
161        if (s)
162            str_set(stab_val(stab),s);
163        else {
164            str_set(stab_val(stab),stab_ename(curoutstab));
165            str_cat(stab_val(stab),"_TOP");
166        }
167        break;
168    case '~':
169        s = stab_io(curoutstab)->fmt_name;
170        if (!s)
171            s = stab_ename(curoutstab);
172        str_set(stab_val(stab),s);
173        break;
174#ifndef lint
175    case '=':
176        str_numset(stab_val(stab),(double)stab_io(curoutstab)->page_len);
177        break;
178    case '-':
179        str_numset(stab_val(stab),(double)stab_io(curoutstab)->lines_left);
180        break;
181    case '%':
182        str_numset(stab_val(stab),(double)stab_io(curoutstab)->page);
183        break;
184#endif
185    case ':':
186        break;
187    case '/':
188        break;
189    case '[':
190        str_numset(stab_val(stab),(double)arybase);
191        break;
192    case '|':
193        if (!stab_io(curoutstab))
194            stab_io(curoutstab) = stio_new();
195        str_numset(stab_val(stab),
196           (double)((stab_io(curoutstab)->flags & IOF_FLUSH) != 0) );
197        break;
198    case ',':
199        str_nset(stab_val(stab),ofs,ofslen);
200        break;
201    case '\\':
202        str_nset(stab_val(stab),ors,orslen);
203        break;
204    case '#':
205        str_set(stab_val(stab),ofmt);
206        break;
207    case '!':
208        str_numset(stab_val(stab), (double)errno);
209        str_set(stab_val(stab), errno ? strerror(errno) : "");
210        stab_val(stab)->str_nok = 1;    /* what a wonderful hack! */
211        break;
212    case '<':
213        str_numset(stab_val(stab),(double)uid);
214        break;
215    case '>':
216        str_numset(stab_val(stab),(double)euid);
217        break;
218    case '(':
219        s = buf;
220        (void)sprintf(s,"%d",(int)gid);
221        goto add_groups;
222    case ')':
223        s = buf;
224        (void)sprintf(s,"%d",(int)egid);
225      add_groups:
226        while (*s) s++;
227#ifdef HAS_GETGROUPS
228#ifndef NGROUPS
229#define NGROUPS 32
230#endif
231        {
232            GROUPSTYPE gary[NGROUPS];
233
234            i = getgroups(NGROUPS,gary);
235            while (--i >= 0) {
236                (void)sprintf(s," %ld", (long)gary[i]);
237                while (*s) s++;
238            }
239        }
240#endif
241        str_set(stab_val(stab),buf);
242        break;
243    case '*':
244        break;
245    case '0':
246        break;
247    default:
248        {
249            struct ufuncs *uf = (struct ufuncs *)str->str_ptr;
250
251            if (uf && uf->uf_val)
252                (*uf->uf_val)(uf->uf_index, stab_val(stab));
253        }
254        break;
255    }
256    return stab_val(stab);
257}
258
259STRLEN
260stab_len(str)
261STR *str;
262{
263    STAB *stab = str->str_u.str_stab;
264    int paren;
265    int i;
266    char *s;
267
268    if (str->str_rare)
269        return str_len(stab_val(stab));
270
271    switch (*stab->str_magic->str_ptr) {
272    case '1': case '2': case '3': case '4':
273    case '5': case '6': case '7': case '8': case '9': case '&':
274        if (curspat) {
275            paren = atoi(stab_ename(stab));
276          getparen:
277            if (curspat->spat_regexp &&
278              paren <= curspat->spat_regexp->nparens &&
279              (s = curspat->spat_regexp->startp[paren]) ) {
280                i = curspat->spat_regexp->endp[paren] - s;
281                if (i >= 0)
282                    return i;
283                else
284                    return 0;
285            }
286            else
287                return 0;
288        }
289        break;
290    case '+':
291        if (curspat) {
292            paren = curspat->spat_regexp->lastparen;
293            goto getparen;
294        }
295        break;
296    case '`':
297        if (curspat) {
298            if (curspat->spat_regexp &&
299              (s = curspat->spat_regexp->subbeg) ) {
300                i = curspat->spat_regexp->startp[0] - s;
301                if (i >= 0)
302                    return i;
303                else
304                    return 0;
305            }
306            else
307                return 0;
308        }
309        break;
310    case '\'':
311        if (curspat) {
312            if (curspat->spat_regexp &&
313              (s = curspat->spat_regexp->endp[0]) ) {
314                return (STRLEN) (curspat->spat_regexp->subend - s);
315            }
316            else
317                return 0;
318        }
319        break;
320    case ',':
321        return (STRLEN)ofslen;
322    case '\\':
323        return (STRLEN)orslen;
324    }
325    return str_len(stab_str(str));
326}
327
328void
329stabset(mstr,str)
330register STR *mstr;
331STR *str;
332{
333    STAB *stab;
334    register char *s;
335    int i;
336
337    switch (mstr->str_rare) {
338    case 'E':
339        my_setenv(mstr->str_ptr,str_get(str));
340                                /* And you'll never guess what the dog had */
341                                /*   in its mouth... */
342#ifdef TAINT
343        if (strEQ(mstr->str_ptr,"PATH")) {
344            char *strend = str->str_ptr + str->str_cur;
345
346            s = str->str_ptr;
347            while (s < strend) {
348                s = cpytill(tokenbuf,s,strend,':',&i);
349                s++;
350                if (*tokenbuf != '/'
351                  || (stat(tokenbuf,&statbuf) && (statbuf.st_mode & 2)) )
352                    str->str_tainted = 2;
353            }
354        }
355#endif
356        break;
357    case 'S':
358        s = str_get(str);
359        i = whichsig(mstr->str_ptr);    /* ...no, a brick */
360        if (!i && (dowarn || strEQ(mstr->str_ptr,"ALARM")))
361            warn("No such signal: SIG%s", mstr->str_ptr);
362        if (strEQ(s,"IGNORE"))
363#ifndef lint
364            (void)signal(i,SIG_IGN);
365#else
366            ;
367#endif
368        else if (strEQ(s,"DEFAULT") || !*s)
369            (void)signal(i,SIG_DFL);
370        else {
371            (void)signal(i,sighandler);
372            if (!index(s,'\'')) {
373                sprintf(tokenbuf, "main'%s",s);
374                str_set(str,tokenbuf);
375            }
376        }
377        break;
378#ifdef SOME_DBM
379    case 'D':
380        stab = mstr->str_u.str_stab;
381        hdbmstore(stab_hash(stab),mstr->str_ptr,mstr->str_cur,str);
382        break;
383#endif
384    case 'L':
385        {
386            CMD *cmd;
387
388            stab = mstr->str_u.str_stab;
389            i = str_true(str);
390            str = afetch(stab_xarray(stab),atoi(mstr->str_ptr), FALSE);
391            if (str->str_magic && (cmd = str->str_magic->str_u.str_cmd)) {
392                cmd->c_flags &= ~CF_OPTIMIZE;
393                cmd->c_flags |= i? CFT_D1 : CFT_D0;
394            }
395            else
396                warn("Can't break at that line\n");
397        }
398        break;
399    case '#':
400        stab = mstr->str_u.str_stab;
401        afill(stab_array(stab), (int)str_gnum(str) - arybase);
402        break;
403    case 'X':   /* merely a copy of a * string */
404        break;
405    case '*':
406        s = str->str_pok ? str_get(str) : "";
407        if (strNE(s,"StB") || str->str_cur != sizeof(STBP)) {
408            stab = mstr->str_u.str_stab;
409            if (!*s) {
410                STBP *stbp;
411
412                /*SUPPRESS 701*/
413                (void)savenostab(stab); /* schedule a free of this stab */
414                if (stab->str_len)
415                    Safefree(stab->str_ptr);
416                Newz(601,stbp, 1, STBP);
417                stab->str_ptr = stbp;
418                stab->str_len = stab->str_cur = sizeof(STBP);
419                stab->str_pok = 1;
420                strcpy(stab_magic(stab),"StB");
421                stab_val(stab) = Str_new(70,0);
422                stab_line(stab) = curcmd->c_line;
423                stab_estab(stab) = stab;
424            }
425            else {
426                stab = stabent(s,TRUE);
427                if (!stab_xarray(stab))
428                    aadd(stab);
429                if (!stab_xhash(stab))
430                    hadd(stab);
431                if (!stab_io(stab))
432                    stab_io(stab) = stio_new();
433            }
434            str_sset(str, (STR*) stab);
435        }
436        break;
437    case 's': {
438            struct lstring *lstr = (struct lstring*)str;
439            char *tmps;
440
441            mstr->str_rare = 0;
442            str->str_magic = Nullstr;
443            tmps = str_get(str);
444            str_insert(mstr,lstr->lstr_offset,lstr->lstr_len,
445              tmps,str->str_cur);
446        }
447        break;
448
449    case 'v':
450        do_vecset(mstr,str);
451        break;
452
453    case 0:
454        /*SUPPRESS 560*/
455        if (!(stab = mstr->str_u.str_stab))
456            break;
457        switch (*stab->str_magic->str_ptr) {
458        case '\004':    /* ^D */
459#ifdef DEBUGGING
460            debug = (int)(str_gnum(str)) | 32768;
461            if (debug & 1024)
462                dump_all();
463#endif
464            break;
465        case '\006':    /* ^F */
466            maxsysfd = (int)str_gnum(str);
467            break;
468        case '\t':      /* ^I */
469            if (inplace)
470                Safefree(inplace);
471            if (str->str_pok || str->str_nok)
472                inplace = savestr(str_get(str));
473            else
474                inplace = Nullch;
475            break;
476        case '\020':    /* ^P */
477            i = (int)str_gnum(str);
478            if (i != perldb) {
479                static SPAT *oldlastspat;
480
481                if (perldb)
482                    oldlastspat = lastspat;
483                else
484                    lastspat = oldlastspat;
485            }
486            perldb = i;
487            break;
488        case '\024':    /* ^T */
489            basetime = (time_t)str_gnum(str);
490            break;
491        case '\027':    /* ^W */
492            dowarn = (bool)str_gnum(str);
493            break;
494        case '.':
495            if (localizing)
496                savesptr((STR**)&last_in_stab);
497            break;
498        case '^':
499            Safefree(stab_io(curoutstab)->top_name);
500            stab_io(curoutstab)->top_name = s = savestr(str_get(str));
501            stab_io(curoutstab)->top_stab = stabent(s,TRUE);
502            break;
503        case '~':
504            Safefree(stab_io(curoutstab)->fmt_name);
505            stab_io(curoutstab)->fmt_name = s = savestr(str_get(str));
506            stab_io(curoutstab)->fmt_stab = stabent(s,TRUE);
507            break;
508        case '=':
509            stab_io(curoutstab)->page_len = (long)str_gnum(str);
510            break;
511        case '-':
512            stab_io(curoutstab)->lines_left = (long)str_gnum(str);
513            if (stab_io(curoutstab)->lines_left < 0L)
514                stab_io(curoutstab)->lines_left = 0L;
515            break;
516        case '%':
517            stab_io(curoutstab)->page = (long)str_gnum(str);
518            break;
519        case '|':
520            if (!stab_io(curoutstab))
521                stab_io(curoutstab) = stio_new();
522            stab_io(curoutstab)->flags &= ~IOF_FLUSH;
523            if (str_gnum(str) != 0.0) {
524                stab_io(curoutstab)->flags |= IOF_FLUSH;
525            }
526            break;
527        case '*':
528            i = (int)str_gnum(str);
529            multiline = (i != 0);
530            break;
531        case '/':
532            if (str->str_pok) {
533                rs = str_get(str);
534                rslen = str->str_cur;
535                if (rspara = !rslen) {
536                    rs = "\n\n";
537                    rslen = 2;
538                }
539                rschar = rs[rslen - 1];
540            }
541            else {
542                rschar = 0777;  /* fake a non-existent char */
543                rslen = 1;
544            }
545            break;
546        case '\\':
547            if (ors)
548                Safefree(ors);
549            ors = savestr(str_get(str));
550            orslen = str->str_cur;
551            break;
552        case ',':
553            if (ofs)
554                Safefree(ofs);
555            ofs = savestr(str_get(str));
556            ofslen = str->str_cur;
557            break;
558        case '#':
559            if (ofmt)
560                Safefree(ofmt);
561            ofmt = savestr(str_get(str));
562            break;
563        case '[':
564            arybase = (int)str_gnum(str);
565            break;
566        case '?':
567            statusvalue = U_S(str_gnum(str));
568            break;
569        case '!':
570            errno = (int)str_gnum(str);         /* will anyone ever use this? */
571            break;
572        case '<':
573            uid = (int)str_gnum(str);
574            if (delaymagic) {
575                delaymagic |= DM_RUID;
576                break;                          /* don't do magic till later */
577            }
578#ifdef HAS_SETRUID
579            (void)setruid((UIDTYPE)uid);
580#else
581#ifdef HAS_SETREUID
582            (void)setreuid((UIDTYPE)uid, (UIDTYPE)-1);
583#else
584            if (uid == euid)            /* special case $< = $> */
585                (void)setuid(uid);
586            else
587                fatal("setruid() not implemented");
588#endif
589#endif
590            uid = (int)getuid();
591            break;
592        case '>':
593            euid = (int)str_gnum(str);
594            if (delaymagic) {
595                delaymagic |= DM_EUID;
596                break;                          /* don't do magic till later */
597            }
598#ifdef HAS_SETEUID
599            (void)seteuid((UIDTYPE)euid);
600#else
601#ifdef HAS_SETREUID
602            (void)setreuid((UIDTYPE)-1, (UIDTYPE)euid);
603#else
604            if (euid == uid)            /* special case $> = $< */
605                setuid(euid);
606            else
607                fatal("seteuid() not implemented");
608#endif
609#endif
610            euid = (int)geteuid();
611            break;
612        case '(':
613            gid = (int)str_gnum(str);
614            if (delaymagic) {
615                delaymagic |= DM_RGID;
616                break;                          /* don't do magic till later */
617            }
618#ifdef HAS_SETRGID
619            (void)setrgid((GIDTYPE)gid);
620#else
621#ifdef HAS_SETREGID
622            (void)setregid((GIDTYPE)gid, (GIDTYPE)-1);
623#else
624            if (gid == egid)                    /* special case $( = $) */
625                (void)setgid(gid);
626            else
627                fatal("setrgid() not implemented");
628#endif
629#endif
630            gid = (int)getgid();
631            break;
632        case ')':
633            egid = (int)str_gnum(str);
634            if (delaymagic) {
635                delaymagic |= DM_EGID;
636                break;                          /* don't do magic till later */
637            }
638#ifdef HAS_SETEGID
639            (void)setegid((GIDTYPE)egid);
640#else
641#ifdef HAS_SETREGID
642            (void)setregid((GIDTYPE)-1, (GIDTYPE)egid);
643#else
644            if (egid == gid)                    /* special case $) = $( */
645                (void)setgid(egid);
646            else
647                fatal("setegid() not implemented");
648#endif
649#endif
650            egid = (int)getegid();
651            break;
652        case ':':
653            chopset = str_get(str);
654            break;
655        case '0':
656            if (!origalen) {
657                s = origargv[0];
658                s += strlen(s);
659                /* See if all the arguments are contiguous in memory */
660                for (i = 1; i < origargc; i++) {
661                    if (origargv[i] == s + 1)
662                        s += strlen(++s);       /* this one is ok too */
663                }
664                if (origenviron[0] == s + 1) {  /* can grab env area too? */
665                    my_setenv("NoNeSuCh", Nullch);
666                                                /* force copy of environment */
667                    for (i = 0; origenviron[i]; i++)
668                        if (origenviron[i] == s + 1)
669                            s += strlen(++s);
670                }
671                origalen = s - origargv[0];
672            }
673            s = str_get(str);
674            i = str->str_cur;
675            if (i >= origalen) {
676                i = origalen;
677                str->str_cur = i;
678                str->str_ptr[i] = '\0';
679                Copy(s, origargv[0], i, char);
680            }
681            else {
682                Copy(s, origargv[0], i, char);
683                s = origargv[0]+i;
684                *s++ = '\0';
685                while (++i < origalen)
686                    *s++ = ' ';
687            }
688            break;
689        default:
690            {
691                struct ufuncs *uf = (struct ufuncs *)str->str_magic->str_ptr;
692
693                if (uf && uf->uf_set)
694                    (*uf->uf_set)(uf->uf_index, str);
695            }
696            break;
697        }
698        break;
699    }
700}
701
702int
703whichsig(sig)
704char *sig;
705{
706    register char **sigv;
707
708    for (sigv = sig_name+1; *sigv; sigv++)
709        if (strEQ(sig,*sigv))
710            return sigv - sig_name;
711#ifdef SIGCLD
712    if (strEQ(sig,"CHLD"))
713        return SIGCLD;
714#endif
715#ifdef SIGCHLD
716    if (strEQ(sig,"CLD"))
717        return SIGCHLD;
718#endif
719    return 0;
720}
721
722static handlertype
723sighandler(sig)
724int sig;
725{
726    STAB *stab;
727    STR *str;
728    int oldsave = savestack->ary_fill;
729    int oldtmps_base = tmps_base;
730    register CSV *csv;
731    SUBR *sub;
732
733#ifdef OS2              /* or anybody else who requires SIG_ACK */
734    signal(sig, SIG_ACK);
735#endif
736    stab = stabent(
737        str_get(hfetch(stab_hash(sigstab),sig_name[sig],strlen(sig_name[sig]),
738          TRUE)), TRUE);
739    sub = stab_sub(stab);
740    if (!sub && *sig_name[sig] == 'C' && instr(sig_name[sig],"LD")) {
741        if (sig_name[sig][1] == 'H')
742            stab = stabent(str_get(hfetch(stab_hash(sigstab),"CLD",3,TRUE)),
743              TRUE);
744        else
745            stab = stabent(str_get(hfetch(stab_hash(sigstab),"CHLD",4,TRUE)),
746              TRUE);
747        sub = stab_sub(stab);   /* gag */
748    }
749    if (!sub) {
750        if (dowarn)
751            warn("SIG%s handler \"%s\" not defined.\n",
752                sig_name[sig], stab_ename(stab) );
753        return;
754    }
755    /*SUPPRESS 701*/
756    saveaptr(&stack);
757    str = Str_new(15, sizeof(CSV));
758    str->str_state = SS_SCSV;
759    (void)apush(savestack,str);
760    csv = (CSV*)str->str_ptr;
761    csv->sub = sub;
762    csv->stab = stab;
763    csv->curcsv = curcsv;
764    csv->curcmd = curcmd;
765    csv->depth = sub->depth;
766    csv->wantarray = G_SCALAR;
767    csv->hasargs = TRUE;
768    csv->savearray = stab_xarray(defstab);
769    csv->argarray = stab_xarray(defstab) = stack = anew(defstab);
770    stack->ary_flags = 0;
771    curcsv = csv;
772    str = str_mortal(&str_undef);
773    str_set(str,sig_name[sig]);
774    (void)apush(stab_xarray(defstab),str);
775    sub->depth++;
776    if (sub->depth >= 2) {      /* save temporaries on recursion? */
777        if (sub->depth == 100 && dowarn)
778            warn("Deep recursion on subroutine \"%s\"",stab_ename(stab));
779        savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
780    }
781
782    tmps_base = tmps_max;               /* protect our mortal string */
783    (void)cmd_exec(sub->cmd,G_SCALAR,0);                /* so do it already */
784    tmps_base = oldtmps_base;
785
786    restorelist(oldsave);               /* put everything back */
787}
788
789STAB *
790aadd(stab)
791register STAB *stab;
792{
793    if (!stab_xarray(stab))
794        stab_xarray(stab) = anew(stab);
795    return stab;
796}
797
798STAB *
799hadd(stab)
800register STAB *stab;
801{
802    if (!stab_xhash(stab))
803        stab_xhash(stab) = hnew(COEFFSIZE);
804    return stab;
805}
806
807STAB *
808fstab(name)
809char *name;
810{
811    char tmpbuf[1200];
812    STAB *stab;
813
814    sprintf(tmpbuf,"'_<%s", name);
815    stab = stabent(tmpbuf, TRUE);
816    str_set(stab_val(stab), name);
817    if (perldb)
818        (void)hadd(aadd(stab));
819    return stab;
820}
821
822STAB *
823stabent(name,add)
824register char *name;
825int add;
826{
827    register STAB *stab;
828    register STBP *stbp;
829    int len;
830    register char *namend;
831    HASH *stash;
832    char *sawquote = Nullch;
833    char *prevquote = Nullch;
834    bool global = FALSE;
835
836    if (isUPPER(*name)) {
837        if (*name > 'I') {
838            if (*name == 'S' && (
839              strEQ(name, "SIG") ||
840              strEQ(name, "STDIN") ||
841              strEQ(name, "STDOUT") ||
842              strEQ(name, "STDERR") ))
843                global = TRUE;
844        }
845        else if (*name > 'E') {
846            if (*name == 'I' && strEQ(name, "INC"))
847                global = TRUE;
848        }
849        else if (*name > 'A') {
850            if (*name == 'E' && strEQ(name, "ENV"))
851                global = TRUE;
852        }
853        else if (*name == 'A' && (
854          strEQ(name, "ARGV") ||
855          strEQ(name, "ARGVOUT") ))
856            global = TRUE;
857    }
858    for (namend = name; *namend; namend++) {
859        if (*namend == '\'' && namend[1])
860            prevquote = sawquote, sawquote = namend;
861    }
862    if (sawquote == name && name[1]) {
863        stash = defstash;
864        sawquote = Nullch;
865        name++;
866    }
867    else if (!isALPHA(*name) || global)
868        stash = defstash;
869    else if ((CMD*)curcmd == &compiling)
870        stash = curstash;
871    else
872        stash = curcmd->c_stash;
873    if (sawquote) {
874        char tmpbuf[256];
875        char *s, *d;
876
877        *sawquote = '\0';
878        /*SUPPRESS 560*/
879        if (s = prevquote) {
880            strncpy(tmpbuf,name,s-name+1);
881            d = tmpbuf+(s-name+1);
882            *d++ = '_';
883            strcpy(d,s+1);
884        }
885        else {
886            *tmpbuf = '_';
887            strcpy(tmpbuf+1,name);
888        }
889        stab = stabent(tmpbuf,TRUE);
890        if (!(stash = stab_xhash(stab)))
891            stash = stab_xhash(stab) = hnew(0);
892        if (!stash->tbl_name)
893            stash->tbl_name = savestr(name);
894        name = sawquote+1;
895        *sawquote = '\'';
896    }
897    len = namend - name;
898    stab = (STAB*)hfetch(stash,name,len,add);
899    if (stab == (STAB*)&str_undef)
900        return Nullstab;
901    if (stab->str_pok) {
902        stab->str_pok |= SP_MULTI;
903        return stab;
904    }
905    else {
906        if (stab->str_len)
907            Safefree(stab->str_ptr);
908        Newz(602,stbp, 1, STBP);
909        stab->str_ptr = stbp;
910        stab->str_len = stab->str_cur = sizeof(STBP);
911        stab->str_pok = 1;
912        strcpy(stab_magic(stab),"StB");
913        stab_val(stab) = Str_new(72,0);
914        stab_line(stab) = curcmd->c_line;
915        stab_estab(stab) = stab;
916        str_magic((STR*)stab, stab, '*', name, len);
917        stab_stash(stab) = stash;
918        if (isDIGIT(*name) && *name != '0') {
919            stab_flags(stab) = SF_VMAGIC;
920            str_magic(stab_val(stab), stab, 0, Nullch, 0);
921        }
922        if (add & 2)
923            stab->str_pok |= SP_MULTI;
924        return stab;
925    }
926}
927
928void
929stab_fullname(str,stab)
930STR *str;
931STAB *stab;
932{
933    HASH *tb = stab_stash(stab);
934
935    if (!tb)
936        return;
937    str_set(str,tb->tbl_name);
938    str_ncat(str,"'", 1);
939    str_scat(str,stab->str_magic);
940}
941
942void
943stab_efullname(str,stab)
944STR *str;
945STAB *stab;
946{
947    HASH *tb = stab_estash(stab);
948
949    if (!tb)
950        return;
951    str_set(str,tb->tbl_name);
952    str_ncat(str,"'", 1);
953    str_scat(str,stab_estab(stab)->str_magic);
954}
955
956STIO *
957stio_new()
958{
959    STIO *stio;
960
961    Newz(603,stio,1,STIO);
962    stio->page_len = 60;
963    return stio;
964}
965
966void
967stab_check(min,max)
968int min;
969register int max;
970{
971    register HENT *entry;
972    register int i;
973    register STAB *stab;
974
975    for (i = min; i <= max; i++) {
976        for (entry = defstash->tbl_array[i]; entry; entry = entry->hent_next) {
977            stab = (STAB*)entry->hent_val;
978            if (stab->str_pok & SP_MULTI)
979                continue;
980            curcmd->c_line = stab_line(stab);
981            warn("Possible typo: \"%s\"", stab_name(stab));
982        }
983    }
984}
985
986static int gensym = 0;
987
988STAB *
989genstab()
990{
991    (void)sprintf(tokenbuf,"_GEN_%d",gensym++);
992    return stabent(tokenbuf,TRUE);
993}
994
995/* hopefully this is only called on local symbol table entries */
996
997void
998stab_clear(stab)
999register STAB *stab;
1000{
1001    STIO *stio;
1002    SUBR *sub;
1003
1004    if (!stab || !stab->str_ptr)
1005        return;
1006    afree(stab_xarray(stab));
1007    stab_xarray(stab) = Null(ARRAY*);
1008    (void)hfree(stab_xhash(stab), FALSE);
1009    stab_xhash(stab) = Null(HASH*);
1010    str_free(stab_val(stab));
1011    stab_val(stab) = Nullstr;
1012    /*SUPPRESS 560*/
1013    if (stio = stab_io(stab)) {
1014        do_close(stab,FALSE);
1015        Safefree(stio->top_name);
1016        Safefree(stio->fmt_name);
1017        Safefree(stio);
1018    }
1019    /*SUPPRESS 560*/
1020    if (sub = stab_sub(stab)) {
1021        afree(sub->tosave);
1022        cmd_free(sub->cmd);
1023    }
1024    Safefree(stab->str_ptr);
1025    stab->str_ptr = Null(STBP*);
1026    stab->str_len = 0;
1027    stab->str_cur = 0;
1028}
1029
1030#if defined(CRIPPLED_CC) && (defined(iAPX286) || defined(M_I286) || defined(I80286))
1031#define MICROPORT
1032#endif
1033
1034#ifdef  MICROPORT       /* Microport 2.4 hack */
1035ARRAY *stab_array(stab)
1036register STAB *stab;
1037{
1038    if (((STBP*)(stab->str_ptr))->stbp_array)
1039        return ((STBP*)(stab->str_ptr))->stbp_array;
1040    else
1041        return ((STBP*)(aadd(stab)->str_ptr))->stbp_array;
1042}
1043
1044HASH *stab_hash(stab)
1045register STAB *stab;
1046{
1047    if (((STBP*)(stab->str_ptr))->stbp_hash)
1048        return ((STBP*)(stab->str_ptr))->stbp_hash;
1049    else
1050        return ((STBP*)(hadd(stab)->str_ptr))->stbp_hash;
1051}
1052#endif                  /* Microport 2.4 hack */
Note: See TracBrowser for help on using the repository browser.