source: trunk/third/tcsh/sh.exp.c @ 9006

Revision 9006, 17.3 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9005, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/sh.exp.c,v 1.1.1.1 1996-10-02 06:09:20 ghudson Exp $ */
2/*
3 * sh.exp.c: Expression evaluations
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed by the University of
20 *      California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37#include "sh.h"
38
39RCSID("$Id: sh.exp.c,v 1.1.1.1 1996-10-02 06:09:20 ghudson Exp $")
40
41/*
42 * C shell
43 */
44
45#define IGNORE  1       /* in ignore, it means to ignore value, just parse */
46#define NOGLOB  2       /* in ignore, it means not to globone */
47
48#define ADDOP   1
49#define MULOP   2
50#define EQOP    4
51#define RELOP   8
52#define RESTOP  16
53#define ANYOP   31
54
55#define EQEQ    1
56#define GTR     2
57#define LSS     4
58#define NOTEQ   6
59#define EQMATCH 7
60#define NOTEQMATCH 8
61
62static  int      sh_access      __P((Char *, int));
63static  int      exp1           __P((Char ***, bool));
64static  int      exp2           __P((Char ***, bool));
65static  int      exp2a          __P((Char ***, bool));
66static  int      exp2b          __P((Char ***, bool));
67static  int      exp2c          __P((Char ***, bool));
68static  Char    *exp3           __P((Char ***, bool));
69static  Char    *exp3a          __P((Char ***, bool));
70static  Char    *exp4           __P((Char ***, bool));
71static  Char    *exp5           __P((Char ***, bool));
72static  Char    *exp6           __P((Char ***, bool));
73static  void     evalav         __P((Char **));
74static  int      isa            __P((Char *, int));
75static  int      egetn          __P((Char *));
76
77#ifdef EDEBUG
78static  void     etracc         __P((char *, Char *, Char ***));
79static  void     etraci         __P((char *, int, Char ***));
80#endif
81
82
83/*
84 * shell access function according to POSIX and non POSIX
85 * From Beto Appleton (beto@aixwiz.aix.ibm.com)
86 */
87static int
88sh_access(fname, mode)
89    Char *fname;
90    int mode;
91{
92#ifdef POSIX
93    struct stat     statb;
94#endif /* POSIX */
95    char *name = short2str(fname);
96
97    if (*name == '\0')
98        return 1;
99
100#ifndef POSIX
101    return access(name, mode);
102#else /* POSIX */
103
104    /*
105     * POSIX 1003.2-d11.2
106     *  -r file         True if file exists and is readable.
107     *  -w file         True if file exists and is writable.
108     *                  True shall indicate only that the write flag is on.
109     *                  The file shall not be writable on a read-only file
110     *                  system even if this test indicates true.
111     *  -x file         True if file exists and is executable.
112     *                  True shall indicate only that the execute flag is on.
113     *                  If file is a directory, true indicates that the file
114     *                  can be searched.
115     */
116    if (mode != W_OK && mode != X_OK)
117        return access(name, mode);
118
119    if (stat(name, &statb) == -1)
120        return 1;
121
122    if (access(name, mode) == 0) {
123#ifdef S_ISDIR
124        if (S_ISDIR(statb.st_mode) && mode == X_OK)
125            return 0;
126#endif /* S_ISDIR */
127
128        /* root needs permission for someone */
129        switch (mode) {
130        case W_OK:
131            mode = S_IWUSR | S_IWGRP | S_IWOTH;
132            break;
133        case X_OK:
134            mode = S_IXUSR | S_IXGRP | S_IXOTH;
135            break;
136        default:
137            abort();
138            break;
139        }
140
141    }
142
143    else if (euid == statb.st_uid)
144        mode <<= 6;
145
146    else if (egid == statb.st_gid)
147        mode <<= 3;
148
149# ifdef NGROUPS_MAX
150    else {
151#  if defined(__386BSD__) || defined(BSD4_4)
152    /*
153     * These two decided that setgroup() should take an array of int's
154     * and they define _SC_NGROUPS_MAX without having sysconf
155     */
156#   undef _SC_NGROUPS_MAX       
157#   define GID_T int
158#  else
159#   define GID_T gid_t
160#  endif /* __386BSD__ || BSD4_4 */
161        /* you can be in several groups */
162        int     n;
163        GID_T   *groups;
164
165        /*
166         * Try these things to find a positive maximum groups value:
167         *   1) sysconf(_SC_NGROUPS_MAX)
168         *   2) NGROUPS_MAX
169         *   3) getgroups(0, unused)
170         * Then allocate and scan the groups array if one of these worked.
171         */
172#  ifdef _SC_NGROUPS_MAX
173        if ((n = sysconf(_SC_NGROUPS_MAX)) == -1)
174#  endif /* _SC_NGROUPS_MAX */
175            n = NGROUPS_MAX;
176        if (n <= 0)
177            n = getgroups(0, (GID_T *) NULL);
178
179        if (n > 0) {
180            groups = (GID_T *) xmalloc((size_t) (n * sizeof(GID_T)));
181            n = getgroups(n, groups);
182            while (--n >= 0)
183                if (groups[n] == statb.st_gid) {
184                    mode <<= 3;
185                    break;
186                }
187        }
188    }
189# endif /* NGROUPS_MAX */
190
191    if (statb.st_mode & mode)
192        return 0;
193    else
194        return 1;
195#endif /* !POSIX */
196}
197
198int
199expr(vp)
200    register Char ***vp;
201{
202    return (exp0(vp, 0));
203}
204
205int
206exp0(vp, ignore)
207    register Char ***vp;
208    bool    ignore;
209{
210    register int p1 = exp1(vp, ignore);
211
212#ifdef EDEBUG
213    etraci("exp0 p1", p1, vp);
214#endif
215    if (**vp && eq(**vp, STRor2)) {
216        register int p2;
217
218        (*vp)++;
219        p2 = exp0(vp, (ignore & IGNORE) || p1);
220#ifdef EDEBUG
221        etraci("exp0 p2", p2, vp);
222#endif
223        return (p1 || p2);
224    }
225    return (p1);
226}
227
228static int
229exp1(vp, ignore)
230    register Char ***vp;
231    bool    ignore;
232{
233    register int p1 = exp2(vp, ignore);
234
235#ifdef EDEBUG
236    etraci("exp1 p1", p1, vp);
237#endif
238    if (**vp && eq(**vp, STRand2)) {
239        register int p2;
240
241        (*vp)++;
242        p2 = exp1(vp, (ignore & IGNORE) || !p1);
243#ifdef EDEBUG
244        etraci("exp1 p2", p2, vp);
245#endif
246        return (p1 && p2);
247    }
248    return (p1);
249}
250
251static int
252exp2(vp, ignore)
253    register Char ***vp;
254    bool    ignore;
255{
256    register int p1 = exp2a(vp, ignore);
257
258#ifdef EDEBUG
259    etraci("exp3 p1", p1, vp);
260#endif
261    if (**vp && eq(**vp, STRor)) {
262        register int p2;
263
264        (*vp)++;
265        p2 = exp2(vp, ignore);
266#ifdef EDEBUG
267        etraci("exp3 p2", p2, vp);
268#endif
269        return (p1 | p2);
270    }
271    return (p1);
272}
273
274static int
275exp2a(vp, ignore)
276    register Char ***vp;
277    bool    ignore;
278{
279    register int p1 = exp2b(vp, ignore);
280
281#ifdef EDEBUG
282    etraci("exp2a p1", p1, vp);
283#endif
284    if (**vp && eq(**vp, STRcaret)) {
285        register int p2;
286
287        (*vp)++;
288        p2 = exp2a(vp, ignore);
289#ifdef EDEBUG
290        etraci("exp2a p2", p2, vp);
291#endif
292        return (p1 ^ p2);
293    }
294    return (p1);
295}
296
297static int
298exp2b(vp, ignore)
299    register Char ***vp;
300    bool    ignore;
301{
302    register int p1 = exp2c(vp, ignore);
303
304#ifdef EDEBUG
305    etraci("exp2b p1", p1, vp);
306#endif
307    if (**vp && eq(**vp, STRand)) {
308        register int p2;
309
310        (*vp)++;
311        p2 = exp2b(vp, ignore);
312#ifdef EDEBUG
313        etraci("exp2b p2", p2, vp);
314#endif
315        return (p1 & p2);
316    }
317    return (p1);
318}
319
320static int
321exp2c(vp, ignore)
322    register Char ***vp;
323    bool    ignore;
324{
325    register Char *p1 = exp3(vp, ignore);
326    register Char *p2;
327    register int i;
328
329#ifdef EDEBUG
330    etracc("exp2c p1", p1, vp);
331#endif
332    if ((i = isa(**vp, EQOP)) != 0) {
333        (*vp)++;
334        if (i == EQMATCH || i == NOTEQMATCH)
335            ignore |= NOGLOB;
336        p2 = exp3(vp, ignore);
337#ifdef EDEBUG
338        etracc("exp2c p2", p2, vp);
339#endif
340        if (!(ignore & IGNORE))
341            switch (i) {
342
343            case EQEQ:
344                i = eq(p1, p2);
345                break;
346
347            case NOTEQ:
348                i = !eq(p1, p2);
349                break;
350
351            case EQMATCH:
352                i = Gmatch(p1, p2);
353                break;
354
355            case NOTEQMATCH:
356                i = !Gmatch(p1, p2);
357                break;
358            }
359        xfree((ptr_t) p1);
360        xfree((ptr_t) p2);
361        return (i);
362    }
363    i = egetn(p1);
364    xfree((ptr_t) p1);
365    return (i);
366}
367
368static Char *
369exp3(vp, ignore)
370    register Char ***vp;
371    bool    ignore;
372{
373    register Char *p1, *p2;
374    register int i;
375
376    p1 = exp3a(vp, ignore);
377#ifdef EDEBUG
378    etracc("exp3 p1", p1, vp);
379#endif
380    if ((i = isa(**vp, RELOP)) != 0) {
381        (*vp)++;
382        if (**vp && eq(**vp, STRequal))
383            i |= 1, (*vp)++;
384        p2 = exp3(vp, ignore);
385#ifdef EDEBUG
386        etracc("exp3 p2", p2, vp);
387#endif
388        if (!(ignore & IGNORE))
389            switch (i) {
390
391            case GTR:
392                i = egetn(p1) > egetn(p2);
393                break;
394
395            case GTR | 1:
396                i = egetn(p1) >= egetn(p2);
397                break;
398
399            case LSS:
400                i = egetn(p1) < egetn(p2);
401                break;
402
403            case LSS | 1:
404                i = egetn(p1) <= egetn(p2);
405                break;
406            }
407        xfree((ptr_t) p1);
408        xfree((ptr_t) p2);
409        return (putn(i));
410    }
411    return (p1);
412}
413
414static Char *
415exp3a(vp, ignore)
416    register Char ***vp;
417    bool    ignore;
418{
419    register Char *p1, *p2, *op;
420    register int i;
421
422    p1 = exp4(vp, ignore);
423#ifdef EDEBUG
424    etracc("exp3a p1", p1, vp);
425#endif
426    op = **vp;
427    if (op && any("<>", op[0]) && op[0] == op[1]) {
428        (*vp)++;
429        p2 = exp3a(vp, ignore);
430#ifdef EDEBUG
431        etracc("exp3a p2", p2, vp);
432#endif
433        if (op[0] == '<')
434            i = egetn(p1) << egetn(p2);
435        else
436            i = egetn(p1) >> egetn(p2);
437        xfree((ptr_t) p1);
438        xfree((ptr_t) p2);
439        return (putn(i));
440    }
441    return (p1);
442}
443
444static Char *
445exp4(vp, ignore)
446    register Char ***vp;
447    bool    ignore;
448{
449    register Char *p1, *p2;
450    register int i = 0;
451
452    p1 = exp5(vp, ignore);
453#ifdef EDEBUG
454    etracc("exp4 p1", p1, vp);
455#endif
456    if (isa(**vp, ADDOP)) {
457        register Char *op = *(*vp)++;
458
459        p2 = exp4(vp, ignore);
460#ifdef EDEBUG
461        etracc("exp4 p2", p2, vp);
462#endif
463        if (!(ignore & IGNORE))
464            switch (op[0]) {
465
466            case '+':
467                i = egetn(p1) + egetn(p2);
468                break;
469
470            case '-':
471                i = egetn(p1) - egetn(p2);
472                break;
473            }
474        xfree((ptr_t) p1);
475        xfree((ptr_t) p2);
476        return (putn(i));
477    }
478    return (p1);
479}
480
481static Char *
482exp5(vp, ignore)
483    register Char ***vp;
484    bool    ignore;
485{
486    register Char *p1, *p2;
487    register int i = 0;
488
489    p1 = exp6(vp, ignore);
490#ifdef EDEBUG
491    etracc("exp5 p1", p1, vp);
492#endif
493    if (isa(**vp, MULOP)) {
494        register Char *op = *(*vp)++;
495
496        p2 = exp5(vp, ignore);
497#ifdef EDEBUG
498        etracc("exp5 p2", p2, vp);
499#endif
500        if (!(ignore & IGNORE))
501            switch (op[0]) {
502
503            case '*':
504                i = egetn(p1) * egetn(p2);
505                break;
506
507            case '/':
508                i = egetn(p2);
509                if (i == 0)
510                    stderror(ERR_DIV0);
511                i = egetn(p1) / i;
512                break;
513
514            case '%':
515                i = egetn(p2);
516                if (i == 0)
517                    stderror(ERR_MOD0);
518                i = egetn(p1) % i;
519                break;
520            }
521        xfree((ptr_t) p1);
522        xfree((ptr_t) p2);
523        return (putn(i));
524    }
525    return (p1);
526}
527
528static Char *
529exp6(vp, ignore)
530    register Char ***vp;
531    bool    ignore;
532{
533    int     ccode, i = 0;
534    register Char *cp, *dp, *ep;
535
536    if (**vp == 0)
537        stderror(ERR_NAME | ERR_EXPRESSION);
538    if (eq(**vp, STRbang)) {
539        (*vp)++;
540        cp = exp6(vp, ignore);
541#ifdef EDEBUG
542        etracc("exp6 ! cp", cp, vp);
543#endif
544        i = egetn(cp);
545        xfree((ptr_t) cp);
546        return (putn(!i));
547    }
548    if (eq(**vp, STRtilde)) {
549        (*vp)++;
550        cp = exp6(vp, ignore);
551#ifdef EDEBUG
552        etracc("exp6 ~ cp", cp, vp);
553#endif
554        i = egetn(cp);
555        xfree((ptr_t) cp);
556        return (putn(~i));
557    }
558    if (eq(**vp, STRLparen)) {
559        (*vp)++;
560        ccode = exp0(vp, ignore);
561#ifdef EDEBUG
562        etraci("exp6 () ccode", ccode, vp);
563#endif
564        if (*vp == 0 || **vp == 0 || ***vp != ')')
565            stderror(ERR_NAME | ERR_EXPRESSION);
566        (*vp)++;
567        return (putn(ccode));
568    }
569    if (eq(**vp, STRLbrace)) {
570        register Char **v;
571        struct command faket;
572        Char   *fakecom[2];
573
574        faket.t_dtyp = NODE_COMMAND;
575        faket.t_dflg = F_BACKQ;
576        faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
577        faket.t_dcom = fakecom;
578        fakecom[0] = STRfakecom;
579        fakecom[1] = NULL;
580        (*vp)++;
581        v = *vp;
582        for (;;) {
583            if (!**vp)
584                stderror(ERR_NAME | ERR_MISSING, '}');
585            if (eq(*(*vp)++, STRRbrace))
586                break;
587        }
588        if (ignore & IGNORE)
589            return (Strsave(STRNULL));
590        psavejob();
591        if (pfork(&faket, -1) == 0) {
592            *--(*vp) = 0;
593            evalav(v);
594            exitstat();
595        }
596        pwait();
597        prestjob();
598#ifdef EDEBUG
599        etraci("exp6 {} status", egetn(value(STRstatus)), vp);
600#endif
601        return (putn(egetn(value(STRstatus)) == 0));
602    }
603    if (isa(**vp, ANYOP))
604        return (Strsave(STRNULL));
605    cp = *(*vp)++;
606#define FILETESTS "erwxfdzoplstX"
607    if (*cp == '-' && any(FILETESTS, cp[1])) {
608        struct stat stb;
609        Char *ft;
610
611        for (ft = &cp[2]; *ft; ft++)
612            if (!any(FILETESTS, *ft))
613                stderror(ERR_NAME | ERR_FILEINQ);
614        /*
615         * Detect missing file names by checking for operator in the file name
616         * position.  However, if an operator name appears there, we must make
617         * sure that there's no file by that name (e.g., "/") before announcing
618         * an error.  Even this check isn't quite right, since it doesn't take
619         * globbing into account.
620         */
621        if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
622            stderror(ERR_NAME | ERR_FILENAME);
623
624        dp = *(*vp)++;
625        if (ignore & IGNORE)
626            return (Strsave(STRNULL));
627        ep = globone(dp, G_ERROR);
628        ft = &cp[1];
629        do
630            switch (*ft) {
631
632            case 'r':
633                i = !sh_access(ep, R_OK);
634                break;
635
636            case 'w':
637                i = !sh_access(ep, W_OK);
638                break;
639
640            case 'x':
641                i = !sh_access(ep, X_OK);
642                break;
643
644            case 'X':   /* tcsh extension, name is an executable in the path
645                         * or a tcsh builtin command
646                         */
647                i = find_cmd(ep, 0);
648                break;
649
650            case 't':   /* SGI extension, true when file is a tty */
651                i = isatty(atoi(short2str(ep)));
652                break;
653
654            default:
655                if (
656#ifdef S_IFLNK
657                    *ft == 'l' ? lstat(short2str(ep), &stb) :
658#endif
659                    stat(short2str(ep), &stb)) {
660                    xfree((ptr_t) ep);
661                    return (Strsave(STR0));
662                }
663                switch (*ft) {
664
665                case 'f':
666#ifdef S_ISREG
667                    i = S_ISREG(stb.st_mode);
668#else
669                    i = 0;
670#endif
671                    break;
672
673                case 'd':
674#ifdef S_ISDIR
675                    i = S_ISDIR(stb.st_mode);
676#else
677                    i = 0;
678#endif
679                    break;
680
681                case 'p':
682#ifdef S_ISFIFO
683                    i = S_ISFIFO(stb.st_mode);
684#else
685                    i = 0;
686#endif
687                    break;
688
689                case 'l':
690#ifdef S_ISLNK
691                    i = S_ISLNK(stb.st_mode);
692#else
693                    i = 0;
694#endif
695                    break;
696
697                /*
698                 * ARGH!!! sgi defines (-s == ! -z) Why? Can you change it?
699                 * Here I am not going to be compatible; they should fix it!
700                 */
701                case 's':
702# ifdef S_ISSOCK
703                    i = S_ISSOCK(stb.st_mode);
704# else
705                    i = 0;
706# endif
707                    break;
708
709                case 'b':
710#ifdef S_ISBLK
711                    i = S_ISBLK(stb.st_mode);
712#else
713                    i = 0;
714#endif
715                    break;
716
717                case 'c':
718#ifdef S_ISCHR
719                    i = S_ISCHR(stb.st_mode);
720#else
721                    i = 0;
722#endif
723                    break;
724
725                case 'u':
726#ifdef S_ISUID
727                    i = (S_ISUID & stb.st_mode) != 0;
728#else
729                    i = 0;
730#endif
731                    break;
732
733                case 'g':
734#ifdef S_ISGID
735                    i = (S_ISGID & stb.st_mode) != 0;
736#else
737                    i = 0;
738#endif
739                    break;
740
741                case 'k':
742#ifdef S_ISVTX
743                    i = (S_ISVTX & stb.st_mode) != 0;
744#else
745                    i = 0;
746#endif
747                    break;
748
749                case 'z':
750                    i = stb.st_size == 0;
751                    break;
752
753                case 'e':
754                    i = 1;
755                    break;
756
757                case 'o':
758                    i = stb.st_uid == uid;
759                    break;
760                }
761            }
762        while (*++ft && i);
763#ifdef EDEBUG
764        etraci("exp6 -? i", i, vp);
765#endif
766        xfree((ptr_t) ep);
767        return (putn(i));
768    }
769#ifdef EDEBUG
770    etracc("exp6 default", cp, vp);
771#endif
772    return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
773}
774
775static void
776evalav(v)
777    register Char **v;
778{
779    struct wordent paraml1;
780    register struct wordent *hp = &paraml1;
781    struct command *t;
782    register struct wordent *wdp = hp;
783
784    set(STRstatus, Strsave(STR0));
785    hp->prev = hp->next = hp;
786    hp->word = STRNULL;
787    while (*v) {
788        register struct wordent *new =
789        (struct wordent *) xcalloc(1, sizeof *wdp);
790
791        new->prev = wdp;
792        new->next = hp;
793        wdp->next = new;
794        wdp = new;
795        wdp->word = Strsave(*v++);
796    }
797    hp->prev = wdp;
798    alias(&paraml1);
799    t = syntax(paraml1.next, &paraml1, 0);
800    if (seterr)
801        stderror(ERR_OLD);
802    execute(t, -1, NULL, NULL);
803    freelex(&paraml1), freesyn(t);
804}
805
806static int
807isa(cp, what)
808    register Char *cp;
809    register int what;
810{
811    if (cp == 0)
812        return ((what & RESTOP) != 0);
813    if (cp[1] == 0) {
814        if (what & ADDOP && (*cp == '+' || *cp == '-'))
815            return (1);
816        if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
817            return (1);
818        if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
819                              *cp == '~' || *cp == '^' || *cp == '"'))
820            return (1);
821    }
822    else if (cp[2] == 0) {
823        if (what & RESTOP) {
824            if (cp[0] == '|' && cp[1] == '&')
825                return (1);
826            if (cp[0] == '<' && cp[1] == '<')
827                return (1);
828            if (cp[0] == '>' && cp[1] == '>')
829                return (1);
830        }
831        if (what & EQOP) {
832            if (cp[0] == '=') {
833                if (cp[1] == '=')
834                    return (EQEQ);
835                if (cp[1] == '~')
836                    return (EQMATCH);
837            }
838            else if (cp[0] == '!') {
839                if (cp[1] == '=')
840                    return (NOTEQ);
841                if (cp[1] == '~')
842                    return (NOTEQMATCH);
843            }
844        }
845    }
846    if (what & RELOP) {
847        if (*cp == '<')
848            return (LSS);
849        if (*cp == '>')
850            return (GTR);
851    }
852    return (0);
853}
854
855static int
856egetn(cp)
857    register Char *cp;
858{
859    if (*cp && *cp != '-' && !Isdigit(*cp))
860        stderror(ERR_NAME | ERR_EXPRESSION);
861    return (getn(cp));
862}
863
864/* Phew! */
865
866#ifdef EDEBUG
867static void
868etraci(str, i, vp)
869    char   *str;
870    int     i;
871    Char ***vp;
872{
873    xprintf("%s=%d\t", str, i);
874    blkpr(*vp);
875    xputchar('\n');
876}
877static void
878etracc(str, cp, vp)
879    char   *str;
880    Char   *cp;
881    Char ***vp;
882{
883    xprintf("%s=%s\t", str, cp);
884    blkpr(*vp);
885    xputchar('\n');
886}
887#endif
Note: See TracBrowser for help on using the repository browser.