Fix LTO build
[platform/upstream/expect.git] / exp_clib.c
1 /* exp_clib.c - top-level functions in the expect C library, libexpect.a
2
3 Written by: Don Libes, libes@cme.nist.gov, NIST, 12/3/90
4
5 Design and implementation of this program was paid for by U.S. tax
6 dollars.  Therefore it is public domain.  However, the author and NIST
7 would appreciate credit if this program or parts of it are used.
8 */
9
10 #include "expect_cf.h"
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <setjmp.h>
14 #ifdef HAVE_INTTYPES_H
15 #  include <inttypes.h>
16 #endif
17 #include <sys/types.h>
18 #include <sys/ioctl.h>
19
20 #ifdef TIME_WITH_SYS_TIME
21 # include <sys/time.h>
22 # include <time.h>
23 #else
24 # if HAVE_SYS_TIME_H
25 #  include <sys/time.h>
26 # else
27 #  include <time.h>
28 # endif
29 #endif
30
31 #ifdef CRAY
32 # ifndef TCSETCTTY
33 #  if defined(HAVE_TERMIOS)
34 #   include <termios.h>
35 #  else
36 #   include <termio.h>
37 #  endif
38 # endif
39 #endif
40
41 #ifdef HAVE_SYS_FCNTL_H
42 #  include <sys/fcntl.h>
43 #else
44 #  include <fcntl.h>
45 #endif
46
47 #ifdef HAVE_STRREDIR_H
48 #include <sys/strredir.h>
49 # ifdef SRIOCSREDIR
50 #  undef TIOCCONS
51 # endif
52 #endif
53
54 #include <signal.h>
55 /*#include <memory.h> - deprecated - ANSI C moves them into string.h */
56 #include "string.h"
57
58 #include <errno.h>
59
60 #ifdef NO_STDLIB_H
61
62 /*
63  * Tcl's compat/stdlib.h
64  */
65
66 /*
67  * stdlib.h --
68  *
69  *      Declares facilities exported by the "stdlib" portion of
70  *      the C library.  This file isn't complete in the ANSI-C
71  *      sense;  it only declares things that are needed by Tcl.
72  *      This file is needed even on many systems with their own
73  *      stdlib.h (e.g. SunOS) because not all stdlib.h files
74  *      declare all the procedures needed here (such as strtod).
75  *
76  * Copyright (c) 1991 The Regents of the University of California.
77  * Copyright (c) 1994 Sun Microsystems, Inc.
78  *
79  * See the file "license.terms" for information on usage and redistribution
80  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
81  *
82  * RCS: @(#) $Id: exp_clib.c,v 5.39 2010/08/31 22:20:27 andreas_kupries Exp $
83  */
84
85 #ifndef _STDLIB
86 #define _STDLIB
87
88 extern void             abort _ANSI_ARGS_((void));
89 extern double           atof _ANSI_ARGS_((CONST char *string));
90 extern int              atoi _ANSI_ARGS_((CONST char *string));
91 extern long             atol _ANSI_ARGS_((CONST char *string));
92 extern char *           calloc _ANSI_ARGS_((unsigned int numElements,
93                             unsigned int size));
94 extern void             exit _ANSI_ARGS_((int status));
95 extern int              free _ANSI_ARGS_((char *blockPtr));
96 extern char *           getenv _ANSI_ARGS_((CONST char *name));
97 extern char *           malloc _ANSI_ARGS_((unsigned int numBytes));
98 extern void             qsort _ANSI_ARGS_((VOID *base, int n, int size,
99                             int (*compar)(CONST VOID *element1, CONST VOID
100                             *element2)));
101 extern char *           realloc _ANSI_ARGS_((char *ptr, unsigned int numBytes));
102 extern double           strtod _ANSI_ARGS_((CONST char *string, char **endPtr));
103 extern long             strtol _ANSI_ARGS_((CONST char *string, char **endPtr,
104                             int base));
105 extern unsigned long    strtoul _ANSI_ARGS_((CONST char *string,
106                             char **endPtr, int base));
107
108 #endif /* _STDLIB */
109
110 /*
111  * end of Tcl's compat/stdlib.h
112  */
113
114 #else
115 #include <stdlib.h>             /* for malloc */
116 #endif
117
118 #include <tcl.h>
119 #include "expect.h"
120 #define TclRegError exp_TclRegError
121
122 /*
123  * regexp code - from tcl8.0.4/generic/regexp.c
124  */
125
126 /*
127  * TclRegComp and TclRegExec -- TclRegSub is elsewhere
128  *
129  *      Copyright (c) 1986 by University of Toronto.
130  *      Written by Henry Spencer.  Not derived from licensed software.
131  *
132  *      Permission is granted to anyone to use this software for any
133  *      purpose on any computer system, and to redistribute it freely,
134  *      subject to the following restrictions:
135  *
136  *      1. The author is not responsible for the consequences of use of
137  *              this software, no matter how awful, even if they arise
138  *              from defects in it.
139  *
140  *      2. The origin of this software must not be misrepresented, either
141  *              by explicit claim or by omission.
142  *
143  *      3. Altered versions must be plainly marked as such, and must not
144  *              be misrepresented as being the original software.
145  *
146  * Beware that some of this code is subtly aware of the way operator
147  * precedence is structured in regular expressions.  Serious changes in
148  * regular-expression syntax might require a total rethink.
149  *
150  * *** NOTE: this code has been altered slightly for use in Tcl: ***
151  * *** 1. Use ckalloc and ckfree instead of  malloc and free.    ***
152  * *** 2. Add extra argument to regexp to specify the real       ***
153  * ***    start of the string separately from the start of the   ***
154  * ***    current search. This is needed to search for multiple  ***
155  * ***    matches within a string.                               ***
156  * *** 3. Names have been changed, e.g. from regcomp to          ***
157  * ***    TclRegComp, to avoid clashes with other                ***
158  * ***    regexp implementations used by applications.           ***
159  * *** 4. Added errMsg declaration and TclRegError procedure     ***
160  * *** 5. Various lint-like things, such as casting arguments    ***
161  * ***    in procedure calls.                                    ***
162  *
163  * *** NOTE: This code has been altered for use in MT-Sturdy Tcl ***
164  * *** 1. All use of static variables has been changed to access ***
165  * ***    fields of a structure.                                 ***
166  * *** 2. This in addition to changes to TclRegError makes the   ***
167  * ***    code multi-thread safe.                                ***
168  *
169  * RCS: @(#) $Id: exp_clib.c,v 5.39 2010/08/31 22:20:27 andreas_kupries Exp $
170  */
171
172 #if 0
173 #include "tclInt.h"
174 #include "tclPort.h"
175 #endif
176
177 /*
178  * The variable below is set to NULL before invoking regexp functions
179  * and checked after those functions.  If an error occurred then TclRegError
180  * will set the variable to point to a (static) error message.  This
181  * mechanism unfortunately does not support multi-threading, but the
182  * procedures TclRegError and TclGetRegError can be modified to use
183  * thread-specific storage for the variable and thereby make the code
184  * thread-safe.
185  */
186
187 static char *errMsg = NULL;
188
189 /*
190  * The "internal use only" fields in regexp.h are present to pass info from
191  * compile to execute that permits the execute phase to run lots faster on
192  * simple cases.  They are:
193  *
194  * regstart     char that must begin a match; '\0' if none obvious
195  * reganch      is the match anchored (at beginning-of-line only)?
196  * regmust      string (pointer into program) that match must include, or NULL
197  * regmlen      length of regmust string
198  *
199  * Regstart and reganch permit very fast decisions on suitable starting points
200  * for a match, cutting down the work a lot.  Regmust permits fast rejection
201  * of lines that cannot possibly match.  The regmust tests are costly enough
202  * that TclRegComp() supplies a regmust only if the r.e. contains something
203  * potentially expensive (at present, the only such thing detected is * or +
204  * at the start of the r.e., which can involve a lot of backup).  Regmlen is
205  * supplied because the test in TclRegExec() needs it and TclRegComp() is
206  * computing it anyway.
207  */
208
209 /*
210  * Structure for regexp "program".  This is essentially a linear encoding
211  * of a nondeterministic finite-state machine (aka syntax charts or
212  * "railroad normal form" in parsing technology).  Each node is an opcode
213  * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
214  * all nodes except BRANCH implement concatenation; a "next" pointer with
215  * a BRANCH on both ends of it is connecting two alternatives.  (Here we
216  * have one of the subtle syntax dependencies:  an individual BRANCH (as
217  * opposed to a collection of them) is never concatenated with anything
218  * because of operator precedence.)  The operand of some types of node is
219  * a literal string; for others, it is a node leading into a sub-FSM.  In
220  * particular, the operand of a BRANCH node is the first node of the branch.
221  * (NB this is *not* a tree structure:  the tail of the branch connects
222  * to the thing following the set of BRANCHes.)  The opcodes are:
223  */
224
225 /* definition   number  opnd?   meaning */
226 #define END     0       /* no   End of program. */
227 #define BOL     1       /* no   Match "" at beginning of line. */
228 #define EOL     2       /* no   Match "" at end of line. */
229 #define ANY     3       /* no   Match any one character. */
230 #define ANYOF   4       /* str  Match any character in this string. */
231 #define ANYBUT  5       /* str  Match any character not in this string. */
232 #define BRANCH  6       /* node Match this alternative, or the next... */
233 #define BACK    7       /* no   Match "", "next" ptr points backward. */
234 #define EXACTLY 8       /* str  Match this string. */
235 #define NOTHING 9       /* no   Match empty string. */
236 #define STAR    10      /* node Match this (simple) thing 0 or more times. */
237 #define PLUS    11      /* node Match this (simple) thing 1 or more times. */
238 #define OPEN    20      /* no   Mark this point in input as start of #n. */
239                         /*      OPEN+1 is number 1, etc. */
240 #define CLOSE   (OPEN+NSUBEXP)  /* no   Analogous to OPEN. */
241
242 /*
243  * Opcode notes:
244  *
245  * BRANCH       The set of branches constituting a single choice are hooked
246  *              together with their "next" pointers, since precedence prevents
247  *              anything being concatenated to any individual branch.  The
248  *              "next" pointer of the last BRANCH in a choice points to the
249  *              thing following the whole choice.  This is also where the
250  *              final "next" pointer of each individual branch points; each
251  *              branch starts with the operand node of a BRANCH node.
252  *
253  * BACK         Normal "next" pointers all implicitly point forward; BACK
254  *              exists to make loop structures possible.
255  *
256  * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
257  *              BRANCH structures using BACK.  Simple cases (one character
258  *              per match) are implemented with STAR and PLUS for speed
259  *              and to minimize recursive plunges.
260  *
261  * OPEN,CLOSE   ...are numbered at compile time.
262  */
263
264 /*
265  * A node is one char of opcode followed by two chars of "next" pointer.
266  * "Next" pointers are stored as two 8-bit pieces, high order first.  The
267  * value is a positive offset from the opcode of the node containing it.
268  * An operand, if any, simply follows the node.  (Note that much of the
269  * code generation knows about this implicit relationship.)
270  *
271  * Using two bytes for the "next" pointer is vast overkill for most things,
272  * but allows patterns to get big without disasters.
273  */
274 #define OP(p)   (*(p))
275 #define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
276 #define OPERAND(p)      ((p) + 3)
277
278 /*
279  * See regmagic.h for one further detail of program structure.
280  */
281
282
283 /*
284  * Utility definitions.
285  */
286 #ifndef CHARBITS
287 #define UCHARAT(p)      ((int)*(unsigned char *)(p))
288 #else
289 #define UCHARAT(p)      ((int)*(p)&CHARBITS)
290 #endif
291
292 #define FAIL(m) { TclRegError(m); return(NULL); }
293 #define ISMULT(c)       ((c) == '*' || (c) == '+' || (c) == '?')
294 #define META    "^$.[()|?+*\\"
295
296 /*
297  * Flags to be passed up and down.
298  */
299 #define HASWIDTH        01      /* Known never to match null string. */
300 #define SIMPLE          02      /* Simple enough to be STAR/PLUS operand. */
301 #define SPSTART         04      /* Starts with * or +. */
302 #define WORST           0       /* Worst case. */
303
304 /*
305  * Global work variables for TclRegComp().
306  */
307 struct regcomp_state  {
308     char *regparse;             /* Input-scan pointer. */
309     int regnpar;                /* () count. */
310     char *regcode;              /* Code-emit pointer; &regdummy = don't. */
311     long regsize;               /* Code size. */
312 };
313
314 static char regdummy;
315
316 /*
317  * The first byte of the regexp internal "program" is actually this magic
318  * number; the start node begins in the second byte.
319  */
320 #define MAGIC   0234
321
322
323 /*
324  * Forward declarations for TclRegComp()'s friends.
325  */
326
327 static char *           reg _ANSI_ARGS_((int paren, int *flagp,
328                             struct regcomp_state *rcstate));
329 static char *           regatom _ANSI_ARGS_((int *flagp,
330                             struct regcomp_state *rcstate));
331 static char *           regbranch _ANSI_ARGS_((int *flagp,
332                             struct regcomp_state *rcstate));
333 static void             regc _ANSI_ARGS_((int b,
334                             struct regcomp_state *rcstate));
335 static void             reginsert _ANSI_ARGS_((int op, char *opnd,
336                             struct regcomp_state *rcstate));
337 static char *           regnext _ANSI_ARGS_((char *p));
338 static char *           regnode _ANSI_ARGS_((int op,
339                             struct regcomp_state *rcstate));
340 static void             regoptail _ANSI_ARGS_((char *p, char *val));
341 static char *           regpiece _ANSI_ARGS_((int *flagp,
342                             struct regcomp_state *rcstate));
343 static void             regtail _ANSI_ARGS_((char *p, char *val));
344
345 #ifdef STRCSPN
346 static int strcspn _ANSI_ARGS_((char *s1, char *s2));
347 #endif
348
349 /*
350  - TclRegComp - compile a regular expression into internal code
351  *
352  * We can't allocate space until we know how big the compiled form will be,
353  * but we can't compile it (and thus know how big it is) until we've got a
354  * place to put the code.  So we cheat:  we compile it twice, once with code
355  * generation turned off and size counting turned on, and once "for real".
356  * This also means that we don't allocate space until we are sure that the
357  * thing really will compile successfully, and we never have to move the
358  * code and thus invalidate pointers into it.  (Note that it has to be in
359  * one piece because free() must be able to free it all.)
360  *
361  * Beware that the optimization-preparation code in here knows about some
362  * of the structure of the compiled regexp.
363  */
364 regexp *
365 TclRegComp(exp)
366 char *exp;
367 {
368         register regexp *r;
369         register char *scan;
370         register char *longest;
371         register int len;
372         int flags;
373         struct regcomp_state state;
374         struct regcomp_state *rcstate= &state;
375
376         if (exp == NULL)
377                 FAIL("NULL argument");
378
379         /* First pass: determine size, legality. */
380         rcstate->regparse = exp;
381         rcstate->regnpar = 1;
382         rcstate->regsize = 0L;
383         rcstate->regcode = &regdummy;
384         regc(MAGIC, rcstate);
385         if (reg(0, &flags, rcstate) == NULL)
386                 return(NULL);
387
388         /* Small enough for pointer-storage convention? */
389         if (rcstate->regsize >= 32767L)         /* Probably could be 65535L. */
390                 FAIL("regexp too big");
391
392         /* Allocate space. */
393         r = (regexp *)ckalloc(sizeof(regexp) + (unsigned)rcstate->regsize);
394         if (r == NULL)
395                 FAIL("out of space");
396
397         /* Second pass: emit code. */
398         rcstate->regparse = exp;
399         rcstate->regnpar = 1;
400         rcstate->regcode = r->program;
401         regc(MAGIC, rcstate);
402         if (reg(0, &flags, rcstate) == NULL) {
403           ckfree ((char*) r);
404           return(NULL);
405         }
406
407         /* Dig out information for optimizations. */
408         r->regstart = '\0';     /* Worst-case defaults. */
409         r->reganch = 0;
410         r->regmust = NULL;
411         r->regmlen = 0;
412         scan = r->program+1;                    /* First BRANCH. */
413         if (OP(regnext(scan)) == END) {         /* Only one top-level choice. */
414                 scan = OPERAND(scan);
415
416                 /* Starting-point info. */
417                 if (OP(scan) == EXACTLY)
418                         r->regstart = *OPERAND(scan);
419                 else if (OP(scan) == BOL)
420                         r->reganch++;
421
422                 /*
423                  * If there's something expensive in the r.e., find the
424                  * longest literal string that must appear and make it the
425                  * regmust.  Resolve ties in favor of later strings, since
426                  * the regstart check works with the beginning of the r.e.
427                  * and avoiding duplication strengthens checking.  Not a
428                  * strong reason, but sufficient in the absence of others.
429                  */
430                 if (flags&SPSTART) {
431                         longest = NULL;
432                         len = 0;
433                         for (; scan != NULL; scan = regnext(scan))
434                                 if (OP(scan) == EXACTLY && ((int) strlen(OPERAND(scan))) >= len) {
435                                         longest = OPERAND(scan);
436                                         len = strlen(OPERAND(scan));
437                                 }
438                         r->regmust = longest;
439                         r->regmlen = len;
440                 }
441         }
442
443         return(r);
444 }
445
446 /*
447  - reg - regular expression, i.e. main body or parenthesized thing
448  *
449  * Caller must absorb opening parenthesis.
450  *
451  * Combining parenthesis handling with the base level of regular expression
452  * is a trifle forced, but the need to tie the tails of the branches to what
453  * follows makes it hard to avoid.
454  */
455 static char *
456 reg(paren, flagp, rcstate)
457 int paren;                      /* Parenthesized? */
458 int *flagp;
459 struct regcomp_state *rcstate;
460 {
461         register char *ret;
462         register char *br;
463         register char *ender;
464         register int parno = 0;
465         int flags;
466
467         *flagp = HASWIDTH;      /* Tentatively. */
468
469         /* Make an OPEN node, if parenthesized. */
470         if (paren) {
471                 if (rcstate->regnpar >= NSUBEXP)
472                         FAIL("too many ()");
473                 parno = rcstate->regnpar;
474                 rcstate->regnpar++;
475                 ret = regnode(OPEN+parno,rcstate);
476         } else
477                 ret = NULL;
478
479         /* Pick up the branches, linking them together. */
480         br = regbranch(&flags,rcstate);
481         if (br == NULL)
482                 return(NULL);
483         if (ret != NULL)
484                 regtail(ret, br);       /* OPEN -> first. */
485         else
486                 ret = br;
487         if (!(flags&HASWIDTH))
488                 *flagp &= ~HASWIDTH;
489         *flagp |= flags&SPSTART;
490         while (*rcstate->regparse == '|') {
491                 rcstate->regparse++;
492                 br = regbranch(&flags,rcstate);
493                 if (br == NULL)
494                         return(NULL);
495                 regtail(ret, br);       /* BRANCH -> BRANCH. */
496                 if (!(flags&HASWIDTH))
497                         *flagp &= ~HASWIDTH;
498                 *flagp |= flags&SPSTART;
499         }
500
501         /* Make a closing node, and hook it on the end. */
502         ender = regnode((paren) ? CLOSE+parno : END,rcstate);   
503         regtail(ret, ender);
504
505         /* Hook the tails of the branches to the closing node. */
506         for (br = ret; br != NULL; br = regnext(br))
507                 regoptail(br, ender);
508
509         /* Check for proper termination. */
510         if (paren && *rcstate->regparse++ != ')') {
511                 FAIL("unmatched ()");
512         } else if (!paren && *rcstate->regparse != '\0') {
513                 if (*rcstate->regparse == ')') {
514                         FAIL("unmatched ()");
515                 } else
516                         FAIL("junk on end");    /* "Can't happen". */
517                 /* NOTREACHED */
518         }
519
520         return(ret);
521 }
522
523 /*
524  - regbranch - one alternative of an | operator
525  *
526  * Implements the concatenation operator.
527  */
528 static char *
529 regbranch(flagp, rcstate)
530 int *flagp;
531 struct regcomp_state *rcstate;
532 {
533         register char *ret;
534         register char *chain;
535         register char *latest;
536         int flags;
537
538         *flagp = WORST;         /* Tentatively. */
539
540         ret = regnode(BRANCH,rcstate);
541         chain = NULL;
542         while (*rcstate->regparse != '\0' && *rcstate->regparse != '|' &&
543                                 *rcstate->regparse != ')') {
544                 latest = regpiece(&flags, rcstate);
545                 if (latest == NULL)
546                         return(NULL);
547                 *flagp |= flags&HASWIDTH;
548                 if (chain == NULL)      /* First piece. */
549                         *flagp |= flags&SPSTART;
550                 else
551                         regtail(chain, latest);
552                 chain = latest;
553         }
554         if (chain == NULL)      /* Loop ran zero times. */
555                 (void) regnode(NOTHING,rcstate);
556
557         return(ret);
558 }
559
560 /*
561  - regpiece - something followed by possible [*+?]
562  *
563  * Note that the branching code sequences used for ? and the general cases
564  * of * and + are somewhat optimized:  they use the same NOTHING node as
565  * both the endmarker for their branch list and the body of the last branch.
566  * It might seem that this node could be dispensed with entirely, but the
567  * endmarker role is not redundant.
568  */
569 static char *
570 regpiece(flagp, rcstate)
571 int *flagp;
572 struct regcomp_state *rcstate;
573 {
574         register char *ret;
575         register char op;
576         register char *next;
577         int flags;
578
579         ret = regatom(&flags,rcstate);
580         if (ret == NULL)
581                 return(NULL);
582
583         op = *rcstate->regparse;
584         if (!ISMULT(op)) {
585                 *flagp = flags;
586                 return(ret);
587         }
588
589         if (!(flags&HASWIDTH) && op != '?')
590                 FAIL("*+ operand could be empty");
591         *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
592
593         if (op == '*' && (flags&SIMPLE))
594                 reginsert(STAR, ret, rcstate);
595         else if (op == '*') {
596                 /* Emit x* as (x&|), where & means "self". */
597                 reginsert(BRANCH, ret, rcstate);                        /* Either x */
598                 regoptail(ret, regnode(BACK,rcstate));          /* and loop */
599                 regoptail(ret, ret);                    /* back */
600                 regtail(ret, regnode(BRANCH,rcstate));          /* or */
601                 regtail(ret, regnode(NOTHING,rcstate));         /* null. */
602         } else if (op == '+' && (flags&SIMPLE))
603                 reginsert(PLUS, ret, rcstate);
604         else if (op == '+') {
605                 /* Emit x+ as x(&|), where & means "self". */
606                 next = regnode(BRANCH,rcstate);                 /* Either */
607                 regtail(ret, next);
608                 regtail(regnode(BACK,rcstate), ret);            /* loop back */
609                 regtail(next, regnode(BRANCH,rcstate));         /* or */
610                 regtail(ret, regnode(NOTHING,rcstate));         /* null. */
611         } else if (op == '?') {
612                 /* Emit x? as (x|) */
613                 reginsert(BRANCH, ret, rcstate);                        /* Either x */
614                 regtail(ret, regnode(BRANCH,rcstate));          /* or */
615                 next = regnode(NOTHING,rcstate);                /* null. */
616                 regtail(ret, next);
617                 regoptail(ret, next);
618         }
619         rcstate->regparse++;
620         if (ISMULT(*rcstate->regparse))
621                 FAIL("nested *?+");
622
623         return(ret);
624 }
625
626 /*
627  - regatom - the lowest level
628  *
629  * Optimization:  gobbles an entire sequence of ordinary characters so that
630  * it can turn them into a single node, which is smaller to store and
631  * faster to run.  Backslashed characters are exceptions, each becoming a
632  * separate node; the code is simpler that way and it's not worth fixing.
633  */
634 static char *
635 regatom(flagp, rcstate)
636 int *flagp;
637 struct regcomp_state *rcstate;
638 {
639         register char *ret;
640         int flags;
641
642         *flagp = WORST;         /* Tentatively. */
643
644         switch (*rcstate->regparse++) {
645         case '^':
646                 ret = regnode(BOL,rcstate);
647                 break;
648         case '$':
649                 ret = regnode(EOL,rcstate);
650                 break;
651         case '.':
652                 ret = regnode(ANY,rcstate);
653                 *flagp |= HASWIDTH|SIMPLE;
654                 break;
655         case '[': {
656                         register int clss;
657                         register int classend;
658
659                         if (*rcstate->regparse == '^') {        /* Complement of range. */
660                                 ret = regnode(ANYBUT,rcstate);
661                                 rcstate->regparse++;
662                         } else
663                                 ret = regnode(ANYOF,rcstate);
664                         if (*rcstate->regparse == ']' || *rcstate->regparse == '-')
665                                 regc(*rcstate->regparse++,rcstate);
666                         while (*rcstate->regparse != '\0' && *rcstate->regparse != ']') {
667                                 if (*rcstate->regparse == '-') {
668                                         rcstate->regparse++;
669                                         if (*rcstate->regparse == ']' || *rcstate->regparse == '\0')
670                                                 regc('-',rcstate);
671                                         else {
672                                                 clss = UCHARAT(rcstate->regparse-2)+1;
673                                                 classend = UCHARAT(rcstate->regparse);
674                                                 if (clss > classend+1)
675                                                         FAIL("invalid [] range");
676                                                 for (; clss <= classend; clss++)
677                                                         regc((char)clss,rcstate);
678                                                 rcstate->regparse++;
679                                         }
680                                 } else
681                                         regc(*rcstate->regparse++,rcstate);
682                         }
683                         regc('\0',rcstate);
684                         if (*rcstate->regparse != ']')
685                                 FAIL("unmatched []");
686                         rcstate->regparse++;
687                         *flagp |= HASWIDTH|SIMPLE;
688                 }
689                 break;
690         case '(':
691                 ret = reg(1, &flags, rcstate);
692                 if (ret == NULL)
693                         return(NULL);
694                 *flagp |= flags&(HASWIDTH|SPSTART);
695                 break;
696         case '\0':
697         case '|':
698         case ')':
699                 FAIL("internal urp");   /* Supposed to be caught earlier. */
700                 /* NOTREACHED */
701         case '?':
702         case '+':
703         case '*':
704                 FAIL("?+* follows nothing");
705                 /* NOTREACHED */
706         case '\\':
707                 if (*rcstate->regparse == '\0')
708                         FAIL("trailing \\");
709                 ret = regnode(EXACTLY,rcstate);
710                 regc(*rcstate->regparse++,rcstate);
711                 regc('\0',rcstate);
712                 *flagp |= HASWIDTH|SIMPLE;
713                 break;
714         default: {
715                         register int len;
716                         register char ender;
717
718                         rcstate->regparse--;
719                         len = strcspn(rcstate->regparse, META);
720                         if (len <= 0)
721                                 FAIL("internal disaster");
722                         ender = *(rcstate->regparse+len);
723                         if (len > 1 && ISMULT(ender))
724                                 len--;          /* Back off clear of ?+* operand. */
725                         *flagp |= HASWIDTH;
726                         if (len == 1)
727                                 *flagp |= SIMPLE;
728                         ret = regnode(EXACTLY,rcstate);
729                         while (len > 0) {
730                                 regc(*rcstate->regparse++,rcstate);
731                                 len--;
732                         }
733                         regc('\0',rcstate);
734                 }
735                 break;
736         }
737
738         return(ret);
739 }
740
741 /*
742  - regnode - emit a node
743  */
744 static char *                   /* Location. */
745 regnode(op, rcstate)
746 int op;
747 struct regcomp_state *rcstate;
748 {
749         register char *ret;
750         register char *ptr;
751
752         ret = rcstate->regcode;
753         if (ret == &regdummy) {
754                 rcstate->regsize += 3;
755                 return(ret);
756         }
757
758         ptr = ret;
759         *ptr++ = (char)op;
760         *ptr++ = '\0';          /* Null "next" pointer. */
761         *ptr++ = '\0';
762         rcstate->regcode = ptr;
763
764         return(ret);
765 }
766
767 /*
768  - regc - emit (if appropriate) a byte of code
769  */
770 static void
771 regc(b, rcstate)
772 int b;
773 struct regcomp_state *rcstate;
774 {
775         if (rcstate->regcode != &regdummy)
776                 *rcstate->regcode++ = (char)b;
777         else
778                 rcstate->regsize++;
779 }
780
781 /*
782  - reginsert - insert an operator in front of already-emitted operand
783  *
784  * Means relocating the operand.
785  */
786 static void
787 reginsert(op, opnd, rcstate)
788 int op;
789 char *opnd;
790 struct regcomp_state *rcstate;
791 {
792         register char *src;
793         register char *dst;
794         register char *place;
795
796         if (rcstate->regcode == &regdummy) {
797                 rcstate->regsize += 3;
798                 return;
799         }
800
801         src = rcstate->regcode;
802         rcstate->regcode += 3;
803         dst = rcstate->regcode;
804         while (src > opnd)
805                 *--dst = *--src;
806
807         place = opnd;           /* Op node, where operand used to be. */
808         *place++ = (char)op;
809         *place++ = '\0';
810         *place = '\0';
811 }
812
813 /*
814  - regtail - set the next-pointer at the end of a node chain
815  */
816 static void
817 regtail(p, val)
818 char *p;
819 char *val;
820 {
821         register char *scan;
822         register char *temp;
823         register int offset;
824
825         if (p == &regdummy)
826                 return;
827
828         /* Find last node. */
829         scan = p;
830         for (;;) {
831                 temp = regnext(scan);
832                 if (temp == NULL)
833                         break;
834                 scan = temp;
835         }
836
837         if (OP(scan) == BACK)
838                 offset = scan - val;
839         else
840                 offset = val - scan;
841         *(scan+1) = (char)((offset>>8)&0377);
842         *(scan+2) = (char)(offset&0377);
843 }
844
845 /*
846  - regoptail - regtail on operand of first argument; nop if operandless
847  */
848 static void
849 regoptail(p, val)
850 char *p;
851 char *val;
852 {
853         /* "Operandless" and "op != BRANCH" are synonymous in practice. */
854         if (p == NULL || p == &regdummy || OP(p) != BRANCH)
855                 return;
856         regtail(OPERAND(p), val);
857 }
858
859 /*
860  * TclRegExec and friends
861  */
862
863 /*
864  * Global work variables for TclRegExec().
865  */
866 struct regexec_state  {
867     char *reginput;             /* String-input pointer. */
868     char *regbol;               /* Beginning of input, for ^ check. */
869     char **regstartp;   /* Pointer to startp array. */
870     char **regendp;             /* Ditto for endp. */
871 };
872
873 /*
874  * Forwards.
875  */
876 static int              regtry _ANSI_ARGS_((regexp *prog, char *string,
877                             struct regexec_state *restate));
878 static int              regmatch _ANSI_ARGS_((char *prog,
879                             struct regexec_state *restate));
880 static int              regrepeat _ANSI_ARGS_((char *p,
881                             struct regexec_state *restate));
882
883 #ifdef DEBUG
884 int regnarrate = 0;
885 void regdump _ANSI_ARGS_((regexp *r));
886 static char *regprop _ANSI_ARGS_((char *op));
887 #endif
888
889 /*
890  - TclRegExec - match a regexp against a string
891  */
892 int
893 TclRegExec(prog, string, start)
894 register regexp *prog;
895 register char *string;
896 char *start;
897 {
898         register char *s;
899         struct regexec_state state;
900         struct regexec_state *restate= &state;
901
902         /* Be paranoid... */
903         if (prog == NULL || string == NULL) {
904                 TclRegError("NULL parameter");
905                 return(0);
906         }
907
908         /* Check validity of program. */
909         if (UCHARAT(prog->program) != MAGIC) {
910                 TclRegError("corrupted program");
911                 return(0);
912         }
913
914         /* If there is a "must appear" string, look for it. */
915         if (prog->regmust != NULL) {
916                 s = string;
917                 while ((s = strchr(s, prog->regmust[0])) != NULL) {
918                         if (strncmp(s, prog->regmust, (size_t) prog->regmlen)
919                             == 0)
920                                 break;  /* Found it. */
921                         s++;
922                 }
923                 if (s == NULL)  /* Not present. */
924                         return(0);
925         }
926
927         /* Mark beginning of line for ^ . */
928         restate->regbol = start;
929
930         /* Simplest case:  anchored match need be tried only once. */
931         if (prog->reganch)
932                 return(regtry(prog, string, restate));
933
934         /* Messy cases:  unanchored match. */
935         s = string;
936         if (prog->regstart != '\0')
937                 /* We know what char it must start with. */
938                 while ((s = strchr(s, prog->regstart)) != NULL) {
939                         if (regtry(prog, s, restate))
940                                 return(1);
941                         s++;
942                 }
943         else
944                 /* We don't -- general case. */
945                 do {
946                         if (regtry(prog, s, restate))
947                                 return(1);
948                 } while (*s++ != '\0');
949
950         /* Failure. */
951         return(0);
952 }
953
954 /*
955  - regtry - try match at specific point
956  */
957 static int                      /* 0 failure, 1 success */
958 regtry(prog, string, restate)
959 regexp *prog;
960 char *string;
961 struct regexec_state *restate;
962 {
963         register int i;
964         register char **sp;
965         register char **ep;
966
967         restate->reginput = string;
968         restate->regstartp = prog->startp;
969         restate->regendp = prog->endp;
970
971         sp = prog->startp;
972         ep = prog->endp;
973         for (i = NSUBEXP; i > 0; i--) {
974                 *sp++ = NULL;
975                 *ep++ = NULL;
976         }
977         if (regmatch(prog->program + 1,restate)) {
978                 prog->startp[0] = string;
979                 prog->endp[0] = restate->reginput;
980                 return(1);
981         } else
982                 return(0);
983 }
984
985 /*
986  - regmatch - main matching routine
987  *
988  * Conceptually the strategy is simple:  check to see whether the current
989  * node matches, call self recursively to see whether the rest matches,
990  * and then act accordingly.  In practice we make some effort to avoid
991  * recursion, in particular by going through "ordinary" nodes (that don't
992  * need to know whether the rest of the match failed) by a loop instead of
993  * by recursion.
994  */
995 static int                      /* 0 failure, 1 success */
996 regmatch(prog, restate)
997 char *prog;
998 struct regexec_state *restate;
999 {
1000     register char *scan;        /* Current node. */
1001     char *next;         /* Next node. */
1002
1003     scan = prog;
1004 #ifdef DEBUG
1005     if (scan != NULL && regnarrate)
1006         fprintf(stderr, "%s(\n", regprop(scan));
1007 #endif
1008     while (scan != NULL) {
1009 #ifdef DEBUG
1010         if (regnarrate)
1011             fprintf(stderr, "%s...\n", regprop(scan));
1012 #endif
1013         next = regnext(scan);
1014
1015         switch (OP(scan)) {
1016             case BOL:
1017                 if (restate->reginput != restate->regbol) {
1018                     return 0;
1019                 }
1020                 break;
1021             case EOL:
1022                 if (*restate->reginput != '\0') {
1023                     return 0;
1024                 }
1025                 break;
1026             case ANY:
1027                 if (*restate->reginput == '\0') {
1028                     return 0;
1029                 }
1030                 restate->reginput++;
1031                 break;
1032             case EXACTLY: {
1033                 register int len;
1034                 register char *opnd;
1035
1036                 opnd = OPERAND(scan);
1037                 /* Inline the first character, for speed. */
1038                 if (*opnd != *restate->reginput) {
1039                     return 0 ;
1040                 }
1041                 len = strlen(opnd);
1042                 if (len > 1 && strncmp(opnd, restate->reginput, (size_t) len)
1043                         != 0) {
1044                     return 0;
1045                 }
1046                 restate->reginput += len;
1047                 break;
1048             }
1049             case ANYOF:
1050                 if (*restate->reginput == '\0'
1051                         || strchr(OPERAND(scan), *restate->reginput) == NULL) {
1052                     return 0;
1053                 }
1054                 restate->reginput++;
1055                 break;
1056             case ANYBUT:
1057                 if (*restate->reginput == '\0'
1058                         || strchr(OPERAND(scan), *restate->reginput) != NULL) {
1059                     return 0;
1060                 }
1061                 restate->reginput++;
1062                 break;
1063             case NOTHING:
1064                 break;
1065             case BACK:
1066                 break;
1067             case OPEN+1:
1068             case OPEN+2:
1069             case OPEN+3:
1070             case OPEN+4:
1071             case OPEN+5:
1072             case OPEN+6:
1073             case OPEN+7:
1074             case OPEN+8:
1075             case OPEN+9: {
1076                 register int no;
1077                 register char *save;
1078
1079         doOpen:
1080                 no = OP(scan) - OPEN;
1081                 save = restate->reginput;
1082
1083                 if (regmatch(next,restate)) {
1084                     /*
1085                      * Don't set startp if some later invocation of the
1086                      * same parentheses already has.
1087                      */
1088                     if (restate->regstartp[no] == NULL) {
1089                         restate->regstartp[no] = save;
1090                     }
1091                     return 1;
1092                 } else {
1093                     return 0;
1094                 }
1095             }
1096             case CLOSE+1:
1097             case CLOSE+2:
1098             case CLOSE+3:
1099             case CLOSE+4:
1100             case CLOSE+5:
1101             case CLOSE+6:
1102             case CLOSE+7:
1103             case CLOSE+8:
1104             case CLOSE+9: {
1105                 register int no;
1106                 register char *save;
1107
1108         doClose:
1109                 no = OP(scan) - CLOSE;
1110                 save = restate->reginput;
1111
1112                 if (regmatch(next,restate)) {
1113                                 /*
1114                                  * Don't set endp if some later
1115                                  * invocation of the same parentheses
1116                                  * already has.
1117                                  */
1118                     if (restate->regendp[no] == NULL)
1119                         restate->regendp[no] = save;
1120                     return 1;
1121                 } else {
1122                     return 0;
1123                 }
1124             }
1125             case BRANCH: {
1126                 register char *save;
1127
1128                 if (OP(next) != BRANCH) { /* No choice. */
1129                     next = OPERAND(scan); /* Avoid recursion. */
1130                 } else {
1131                     do {
1132                         save = restate->reginput;
1133                         if (regmatch(OPERAND(scan),restate))
1134                             return(1);
1135                         restate->reginput = save;
1136                         scan = regnext(scan);
1137                     } while (scan != NULL && OP(scan) == BRANCH);
1138                     return 0;
1139                 }
1140                 break;
1141             }
1142             case STAR:
1143             case PLUS: {
1144                 register char nextch;
1145                 register int no;
1146                 register char *save;
1147                 register int min;
1148
1149                 /*
1150                  * Lookahead to avoid useless match attempts
1151                  * when we know what character comes next.
1152                  */
1153                 nextch = '\0';
1154                 if (OP(next) == EXACTLY)
1155                     nextch = *OPERAND(next);
1156                 min = (OP(scan) == STAR) ? 0 : 1;
1157                 save = restate->reginput;
1158                 no = regrepeat(OPERAND(scan),restate);
1159                 while (no >= min) {
1160                     /* If it could work, try it. */
1161                     if (nextch == '\0' || *restate->reginput == nextch)
1162                         if (regmatch(next,restate))
1163                             return(1);
1164                     /* Couldn't or didn't -- back up. */
1165                     no--;
1166                     restate->reginput = save + no;
1167                 }
1168                 return(0);
1169             }
1170             case END:
1171                 return(1);      /* Success! */
1172             default:
1173                 if (OP(scan) > OPEN && OP(scan) < OPEN+NSUBEXP) {
1174                     goto doOpen;
1175                 } else if (OP(scan) > CLOSE && OP(scan) < CLOSE+NSUBEXP) {
1176                     goto doClose;
1177                 }
1178                 TclRegError("memory corruption");
1179                 return 0;
1180         }
1181
1182         scan = next;
1183     }
1184
1185     /*
1186      * We get here only if there's trouble -- normally "case END" is
1187      * the terminating point.
1188      */
1189     TclRegError("corrupted pointers");
1190     return(0);
1191 }
1192
1193 /*
1194  - regrepeat - repeatedly match something simple, report how many
1195  */
1196 static int
1197 regrepeat(p, restate)
1198 char *p;
1199 struct regexec_state *restate;
1200 {
1201         register int count = 0;
1202         register char *scan;
1203         register char *opnd;
1204
1205         scan = restate->reginput;
1206         opnd = OPERAND(p);
1207         switch (OP(p)) {
1208         case ANY:
1209                 count = strlen(scan);
1210                 scan += count;
1211                 break;
1212         case EXACTLY:
1213                 while (*opnd == *scan) {
1214                         count++;
1215                         scan++;
1216                 }
1217                 break;
1218         case ANYOF:
1219                 while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
1220                         count++;
1221                         scan++;
1222                 }
1223                 break;
1224         case ANYBUT:
1225                 while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
1226                         count++;
1227                         scan++;
1228                 }
1229                 break;
1230         default:                /* Oh dear.  Called inappropriately. */
1231                 TclRegError("internal foulup");
1232                 count = 0;      /* Best compromise. */
1233                 break;
1234         }
1235         restate->reginput = scan;
1236
1237         return(count);
1238 }
1239
1240 /*
1241  - regnext - dig the "next" pointer out of a node
1242  */
1243 static char *
1244 regnext(p)
1245 register char *p;
1246 {
1247         register int offset;
1248
1249         if (p == &regdummy)
1250                 return(NULL);
1251
1252         offset = NEXT(p);
1253         if (offset == 0)
1254                 return(NULL);
1255
1256         if (OP(p) == BACK)
1257                 return(p-offset);
1258         else
1259                 return(p+offset);
1260 }
1261
1262 #ifdef DEBUG
1263
1264 static char *regprop();
1265
1266 /*
1267  - regdump - dump a regexp onto stdout in vaguely comprehensible form
1268  */
1269 void
1270 regdump(r)
1271 regexp *r;
1272 {
1273         register char *s;
1274         register char op = EXACTLY;     /* Arbitrary non-END op. */
1275         register char *next;
1276
1277
1278         s = r->program + 1;
1279         while (op != END) {     /* While that wasn't END last time... */
1280                 op = OP(s);
1281                 printf("%2d%s", s-r->program, regprop(s));      /* Where, what. */
1282                 next = regnext(s);
1283                 if (next == NULL)               /* Next ptr. */
1284                         printf("(0)");
1285                 else 
1286                         printf("(%d)", (s-r->program)+(next-s));
1287                 s += 3;
1288                 if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
1289                         /* Literal string, where present. */
1290                         while (*s != '\0') {
1291                                 putchar(*s);
1292                                 s++;
1293                         }
1294                         s++;
1295                 }
1296                 putchar('\n');
1297         }
1298
1299         /* Header fields of interest. */
1300         if (r->regstart != '\0')
1301                 printf("start `%c' ", r->regstart);
1302         if (r->reganch)
1303                 printf("anchored ");
1304         if (r->regmust != NULL)
1305                 printf("must have \"%s\"", r->regmust);
1306         printf("\n");
1307 }
1308
1309 /*
1310  - regprop - printable representation of opcode
1311  */
1312 static char *
1313 regprop(op)
1314 char *op;
1315 {
1316         register char *p;
1317         static char buf[50];
1318
1319         (void) strcpy(buf, ":");
1320
1321         switch (OP(op)) {
1322         case BOL:
1323                 p = "BOL";
1324                 break;
1325         case EOL:
1326                 p = "EOL";
1327                 break;
1328         case ANY:
1329                 p = "ANY";
1330                 break;
1331         case ANYOF:
1332                 p = "ANYOF";
1333                 break;
1334         case ANYBUT:
1335                 p = "ANYBUT";
1336                 break;
1337         case BRANCH:
1338                 p = "BRANCH";
1339                 break;
1340         case EXACTLY:
1341                 p = "EXACTLY";
1342                 break;
1343         case NOTHING:
1344                 p = "NOTHING";
1345                 break;
1346         case BACK:
1347                 p = "BACK";
1348                 break;
1349         case END:
1350                 p = "END";
1351                 break;
1352         case OPEN+1:
1353         case OPEN+2:
1354         case OPEN+3:
1355         case OPEN+4:
1356         case OPEN+5:
1357         case OPEN+6:
1358         case OPEN+7:
1359         case OPEN+8:
1360         case OPEN+9:
1361                 sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
1362                 p = NULL;
1363                 break;
1364         case CLOSE+1:
1365         case CLOSE+2:
1366         case CLOSE+3:
1367         case CLOSE+4:
1368         case CLOSE+5:
1369         case CLOSE+6:
1370         case CLOSE+7:
1371         case CLOSE+8:
1372         case CLOSE+9:
1373                 sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
1374                 p = NULL;
1375                 break;
1376         case STAR:
1377                 p = "STAR";
1378                 break;
1379         case PLUS:
1380                 p = "PLUS";
1381                 break;
1382         default:
1383                 if (OP(op) > OPEN && OP(op) < OPEN+NSUBEXP) {
1384                     sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
1385                     p = NULL;
1386                     break;
1387                 } else if (OP(op) > CLOSE && OP(op) < CLOSE+NSUBEXP) {
1388                     sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
1389                     p = NULL;
1390                 } else {
1391                     TclRegError("corrupted opcode");
1392                 }
1393                 break;
1394         }
1395         if (p != NULL)
1396                 (void) strcat(buf, p);
1397         return(buf);
1398 }
1399 #endif
1400
1401 /*
1402  * The following is provided for those people who do not have strcspn() in
1403  * their C libraries.  They should get off their butts and do something
1404  * about it; at least one public-domain implementation of those (highly
1405  * useful) string routines has been published on Usenet.
1406  */
1407 #ifdef STRCSPN
1408 /*
1409  * strcspn - find length of initial segment of s1 consisting entirely
1410  * of characters not from s2
1411  */
1412
1413 static int
1414 strcspn(s1, s2)
1415 char *s1;
1416 char *s2;
1417 {
1418         register char *scan1;
1419         register char *scan2;
1420         register int count;
1421
1422         count = 0;
1423         for (scan1 = s1; *scan1 != '\0'; scan1++) {
1424                 for (scan2 = s2; *scan2 != '\0';)       /* ++ moved down. */
1425                         if (*scan1 == *scan2++)
1426                                 return(count);
1427                 count++;
1428         }
1429         return(count);
1430 }
1431 #endif
1432 \f
1433 /*
1434  *----------------------------------------------------------------------
1435  *
1436  * TclRegError --
1437  *
1438  *      This procedure is invoked by the regexp code when an error
1439  *      occurs.  It saves the error message so it can be seen by the
1440  *      code that called Spencer's code.
1441  *
1442  * Results:
1443  *      None.
1444  *
1445  * Side effects:
1446  *      The value of "string" is saved in "errMsg".
1447  *
1448  *----------------------------------------------------------------------
1449  */
1450
1451 void
1452 exp_TclRegError(string)
1453     char *string;                       /* Error message. */
1454 {
1455     errMsg = string;
1456 }
1457
1458 char *
1459 TclGetRegError()
1460 {
1461     return errMsg;
1462 }
1463
1464 /*
1465  * end of regexp definitions and code
1466  */
1467
1468 /*
1469  * stolen from exp_log.c - this function is called from the Expect library
1470  * but the one that the library supplies calls Tcl functions.  So we supply
1471  * our own.
1472  */
1473
1474 static
1475 void
1476 expDiagLogU(str)
1477      char *str;
1478 {
1479   if (exp_is_debugging) {
1480     fprintf(stderr,str);
1481     if (exp_logfile) fprintf(exp_logfile,str);
1482   }
1483 }
1484
1485 /*
1486  * expect-specific definitions and code
1487  */
1488
1489 #include "expect.h"
1490 #include "exp_int.h"
1491
1492 /* exp_glob.c - expect functions for doing glob
1493  *
1494  * Based on Tcl's glob functions but modified to support anchors and to
1495  * return information about the possibility of future matches
1496  *
1497  * Modifications by: Don Libes, NIST, 2/6/90
1498  */
1499
1500 /* The following functions implement expect's glob-style string
1501  * matching Exp_StringMatch allow's implements the unanchored front
1502  * (or conversely the '^') feature.  Exp_StringMatch2 does the rest of
1503  * the work.
1504  */
1505
1506 /* Exp_StringMatch2 --
1507  *
1508  * Like Tcl_StringMatch except that
1509  * 1) returns number of characters matched, -1 if failed.
1510  *      (Can return 0 on patterns like "" or "$")
1511  * 2) does not require pattern to match to end of string
1512  * 3) much of code is stolen from Tcl_StringMatch
1513  * 4) front-anchor is assumed (Tcl_StringMatch retries for non-front-anchor)
1514  */
1515 static
1516 int
1517 Exp_StringMatch2(string,pattern)
1518     register char *string;      /* String. */
1519     register char *pattern;     /* Pattern, which may contain
1520                                  * special characters. */
1521 {
1522     char c2;
1523     int match = 0;      /* # of chars matched */
1524
1525     while (1) {
1526         /* If at end of pattern, success! */
1527         if (*pattern == 0) {
1528                 return match;
1529         }
1530
1531         /* If last pattern character is '$', verify that entire
1532          * string has been matched.
1533          */
1534         if ((*pattern == '$') && (pattern[1] == 0)) {
1535                 if (*string == 0) return(match);
1536                 else return(-1);                
1537         }
1538
1539         /* Check for a "*" as the next pattern character.  It matches
1540          * any substring.  We handle this by calling ourselves
1541          * recursively for each postfix of string, until either we
1542          * match or we reach the end of the string.
1543          */
1544         
1545         if (*pattern == '*') {
1546             int head_len;
1547             char *tail;
1548             pattern += 1;
1549             if (*pattern == 0) {
1550                 return(strlen(string)+match); /* DEL */
1551             }
1552             /* find longest match - switched to this on 12/31/93 */
1553             head_len = strlen(string);  /* length before tail */
1554             tail = string + head_len;
1555             while (head_len >= 0) {
1556                 int rc;
1557
1558                 if (-1 != (rc = Exp_StringMatch2(tail, pattern))) {
1559                     return rc + match + head_len;       /* DEL */
1560                 }
1561                 tail--;
1562                 head_len--;
1563             }
1564             return -1;                                  /* DEL */
1565         }
1566     
1567         /*
1568          * after this point, all patterns must match at least one
1569          * character, so check this
1570          */
1571
1572         if (*string == 0) return -1;
1573
1574         /* Check for a "?" as the next pattern character.  It matches
1575          * any single character.
1576          */
1577
1578         if (*pattern == '?') {
1579             goto thisCharOK;
1580         }
1581
1582         /* Check for a "[" as the next pattern character.  It is followed
1583          * by a list of characters that are acceptable, or by a range
1584          * (two characters separated by "-").
1585          */
1586         
1587         if (*pattern == '[') {
1588             pattern += 1;
1589             while (1) {
1590                 if ((*pattern == ']') || (*pattern == 0)) {
1591                     return -1;                  /* was 0; DEL */
1592                 }
1593                 if (*pattern == *string) {
1594                     break;
1595                 }
1596                 if (pattern[1] == '-') {
1597                     c2 = pattern[2];
1598                     if (c2 == 0) {
1599                         return -1;              /* DEL */
1600                     }
1601                     if ((*pattern <= *string) && (c2 >= *string)) {
1602                         break;
1603                     }
1604                     if ((*pattern >= *string) && (c2 <= *string)) {
1605                         break;
1606                     }
1607                     pattern += 2;
1608                 }
1609                 pattern += 1;
1610             }
1611
1612             while (*pattern != ']') {
1613                 if (*pattern == 0) {
1614                     pattern--;
1615                     break;
1616                 }
1617                 pattern += 1;
1618             }
1619             goto thisCharOK;
1620         }
1621     
1622         /* If the next pattern character is backslash, strip it off
1623          * so we do exact matching on the character that follows.
1624          */
1625         
1626         if (*pattern == '\\') {
1627             pattern += 1;
1628             if (*pattern == 0) {
1629                 return -1;
1630             }
1631         }
1632
1633         /* There's no special character.  Just make sure that the next
1634          * characters of each string match.
1635          */
1636         
1637         if (*pattern != *string) {
1638             return -1;
1639         }
1640
1641         thisCharOK: pattern += 1;
1642         string += 1;
1643         match++;
1644     }
1645 }
1646
1647
1648 static
1649 int     /* returns # of chars that matched */
1650 Exp_StringMatch(string, pattern,offset)
1651 char *string;
1652 char *pattern;
1653 int *offset;    /* offset from beginning of string where pattern matches */
1654 {
1655         char *s;
1656         int sm; /* count of chars matched or -1 */
1657         int caret = FALSE;
1658         int star = FALSE;
1659
1660         *offset = 0;
1661
1662         if (pattern[0] == '^') {
1663                 caret = TRUE;
1664                 pattern++;
1665         } else if (pattern[0] == '*') {
1666                 star = TRUE;
1667         }
1668
1669         /*
1670          * test if pattern matches in initial position.
1671          * This handles front-anchor and 1st iteration of non-front-anchor.
1672          * Note that 1st iteration must be tried even if string is empty.
1673          */
1674
1675         sm = Exp_StringMatch2(string,pattern);
1676         if (sm >= 0) return(sm);
1677
1678         if (caret) return -1;
1679         if (star) return -1;
1680
1681         if (*string == '\0') return -1;
1682
1683         for (s = string+1;*s;s++) {
1684                 sm = Exp_StringMatch2(s,pattern);
1685                 if (sm != -1) {
1686                         *offset = s-string;
1687                         return(sm);
1688                 }
1689         }
1690         return -1;
1691 }
1692
1693
1694 #define EXP_MATCH_MAX   2000
1695 /* public */
1696 char *exp_buffer = 0;
1697 char *exp_buffer_end = 0;
1698 char *exp_match = 0;
1699 char *exp_match_end = 0;
1700 int exp_match_max = EXP_MATCH_MAX;      /* bytes */
1701 int exp_full_buffer = FALSE;            /* don't return on full buffer */
1702 int exp_remove_nulls = TRUE;
1703 int exp_timeout = 10;                   /* seconds */
1704 int exp_pty_timeout = 5;                /* seconds - see CRAY below */
1705 int exp_autoallocpty = TRUE;            /* if TRUE, we do allocation */
1706 int exp_pty[2];                         /* master is [0], slave is [1] */
1707 int exp_pid;
1708 char *exp_stty_init = 0;                /* initial stty args */
1709 int exp_ttycopy = TRUE;                 /* copy tty parms from /dev/tty */
1710 int exp_ttyinit = TRUE;                 /* set tty parms to sane state */
1711 int exp_console = FALSE;                /* redirect console */
1712 void (*exp_child_exec_prelude)() = 0;
1713 void (*exp_close_in_child)() = 0;
1714
1715 #ifdef HAVE_SIGLONGJMP
1716 sigjmp_buf exp_readenv;         /* for interruptable read() */
1717 #else
1718 jmp_buf exp_readenv;            /* for interruptable read() */
1719 #endif /* HAVE_SIGLONGJMP */
1720
1721 int exp_reading = FALSE;        /* whether we can longjmp or not */
1722
1723 int exp_is_debugging = FALSE;
1724 FILE *exp_debugfile = 0;
1725
1726 FILE *exp_logfile = 0;
1727 int exp_logfile_all = FALSE;    /* if TRUE, write log of all interactions */
1728 int exp_loguser = TRUE;         /* if TRUE, user sees interactions on stdout */
1729
1730
1731 char *exp_printify();
1732 int exp_getptymaster();
1733 int exp_getptyslave();
1734
1735 #define sysreturn(x)    return(errno = x, -1)
1736
1737 void exp_init_pty();
1738
1739 /*
1740    The following functions are linked from the Tcl library.  They
1741    don't cause anything else in the library to be dragged in, so it
1742    shouldn't cause any problems (e.g., bloat).
1743
1744    The functions are relatively small but painful enough that I don't care
1745    to recode them.  You may, if you absolutely want to get rid of any
1746    vestiges of Tcl.
1747 */
1748
1749 static unsigned int bufsiz = 2*EXP_MATCH_MAX;
1750
1751 static struct f {
1752         int valid;
1753
1754         char *buffer;           /* buffer of matchable chars */
1755         char *buffer_end;       /* one beyond end of matchable chars */
1756         char *match_end;        /* one beyond end of matched string */
1757         int msize;              /* size of allocate space */
1758                                 /* actual size is one larger for null */
1759 } *fs = 0;
1760
1761 static int fd_alloc_max = -1;   /* max fd allocated */
1762
1763 /* translate fd or fp to fd */
1764 static struct f *
1765 fdfp2f(fd,fp)
1766 int fd;
1767 FILE *fp;
1768 {
1769         if (fd == -1) return(fs + fileno(fp));
1770         else return(fs + fd);
1771 }
1772
1773 static struct f *
1774 fd_new(fd)
1775 int fd;
1776 {
1777         int i, low;
1778         struct f *fp;
1779         struct f *newfs;        /* temporary, so we don't lose old fs */
1780
1781         if (fd > fd_alloc_max) {
1782                 if (!fs) {      /* no fd's yet allocated */
1783                         newfs = (struct f *)malloc(sizeof(struct f)*(fd+1));
1784                         low = 0;
1785                 } else {                /* enlarge fd table */
1786                         newfs = (struct f *)realloc((char *)fs,sizeof(struct f)*(fd+1));
1787                         low = fd_alloc_max+1;
1788                 }
1789                 fs = newfs;
1790                 fd_alloc_max = fd;
1791                 for (i = low; i <= fd_alloc_max; i++) { /* init new entries */
1792                         fs[i].valid = FALSE;
1793                 }
1794         }
1795
1796         fp = fs+fd;
1797
1798         if (!fp->valid) {
1799                 /* initialize */
1800                 fp->buffer = malloc((unsigned)(bufsiz+1));
1801                 if (!fp->buffer) return 0;
1802                 fp->msize = bufsiz;
1803                 fp->valid = TRUE;
1804         }
1805         fp->buffer_end = fp->buffer;
1806         fp->match_end = fp->buffer;
1807         return fp;
1808
1809 }
1810
1811 static
1812 void
1813 exp_setpgrp()
1814 {
1815 #ifdef MIPS_BSD
1816     /* required on BSD side of MIPS OS <jmsellen@watdragon.waterloo.edu> */
1817 #   include <sysv/sys.s>
1818     syscall(SYS_setpgrp);
1819 #endif
1820
1821 #ifdef SETPGRP_VOID
1822     (void) setpgrp();
1823 #else
1824     (void) setpgrp(0,0);
1825 #endif
1826 }
1827
1828 /* returns fd of master side of pty */
1829 int
1830 exp_spawnv(file,argv)
1831 char *file;
1832 char *argv[];   /* some compiler complains about **argv? */
1833 {
1834         int cc;
1835         int errorfd;    /* place to stash fileno(stderr) in child */
1836                         /* while we're setting up new stderr */
1837         int ttyfd;
1838         int sync_fds[2];
1839         int sync2_fds[2];
1840         int status_pipe[2];
1841         int child_errno;
1842         char sync_byte;
1843 #ifdef PTYTRAP_DIES
1844         int slave_write_ioctls = 1;
1845                 /* by default, slave will be write-ioctled this many times */
1846 #endif
1847
1848         static int first_time = TRUE;
1849
1850         if (first_time) {
1851                 first_time = FALSE;
1852                 exp_init_pty();
1853                 exp_init_tty();
1854                 expDiagLogPtrSet(expDiagLogU);
1855
1856                 /*
1857                  * TIP 27; It is unclear why this code produces a
1858                  * warning. The equivalent code in exp_main_sub.c
1859                  * (line 512) does not generate a warning !
1860                  */
1861
1862                 expErrnoMsgSet(Tcl_ErrnoMsg);
1863         }
1864
1865         if (!file || !argv) sysreturn(EINVAL);
1866         if (!argv[0] || strcmp(file,argv[0])) {
1867                 exp_debuglog("expect: warning: file (%s) != argv[0] (%s)\n",
1868                         file,
1869                         argv[0]?argv[0]:"");
1870         }
1871
1872 #ifdef PTYTRAP_DIES
1873 /* any extraneous ioctl's that occur in slave must be accounted for
1874 when trapping, see below in child half of fork */
1875 #if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300)
1876         slave_write_ioctls++;
1877 #endif
1878 #endif /*PTYTRAP_DIES*/
1879
1880         if (exp_autoallocpty) {
1881                 if (0 > (exp_pty[0] = exp_getptymaster())) sysreturn(ENODEV);
1882         }
1883         fcntl(exp_pty[0],F_SETFD,1);    /* close on exec */
1884 #ifdef PTYTRAP_DIES
1885         exp_slave_control(exp_pty[0],1);*/
1886 #endif
1887
1888         if (!fd_new(exp_pty[0])) {
1889                 errno = ENOMEM;
1890                 return -1;
1891         }
1892
1893         if (-1 == (pipe(sync_fds))) {
1894                 return -1;
1895         }
1896         if (-1 == (pipe(sync2_fds))) {
1897                 close(sync_fds[0]);
1898                 close(sync_fds[1]);
1899                 return -1;
1900         }
1901
1902         if (-1 == pipe(status_pipe)) {
1903                 close(sync_fds[0]);
1904                 close(sync_fds[1]);
1905                 close(sync2_fds[0]);
1906                 close(sync2_fds[1]);
1907                 return -1;
1908         }
1909
1910         if ((exp_pid = fork()) == -1) return(-1);
1911         if (exp_pid) {
1912                 /* parent */
1913                 close(sync_fds[1]);
1914                 close(sync2_fds[0]);
1915                 close(status_pipe[1]);
1916
1917                 if (!exp_autoallocpty) close(exp_pty[1]);
1918
1919 #ifdef PTYTRAP_DIES
1920 #ifdef HAVE_PTYTRAP
1921                 if (exp_autoallocpty) {
1922                         /* trap initial ioctls in a feeble attempt to not */
1923                         /* block the initially.  If the process itself */
1924                         /* ioctls /dev/tty, such blocks will be trapped */
1925                         /* later during normal event processing */
1926
1927                         while (slave_write_ioctls) {
1928                                 int cc;
1929
1930                                 cc = exp_wait_for_slave_open(exp_pty[0]);
1931 #if defined(TIOCSCTTY) && !defined(CIBAUD) && !defined(sun) && !defined(hp9000s300)
1932                                 if (cc == TIOCSCTTY) slave_write_ioctls = 0;
1933 #endif
1934                                 if (cc & IOC_IN) slave_write_ioctls--;
1935                                 else if (cc == -1) {
1936                                         printf("failed to trap slave pty");
1937                                         return -1;
1938                                 }
1939                         }
1940                 }
1941 #endif
1942 #endif /*PTYTRAP_DIES*/
1943
1944                 /*
1945                  * wait for slave to initialize pty before allowing
1946                  * user to send to it
1947                  */ 
1948
1949                 exp_debuglog("parent: waiting for sync byte\r\n");
1950                 cc = read(sync_fds[0],&sync_byte,1);
1951                 if (cc == -1) {
1952                   exp_errorlog("parent sync byte read: %s\r\n",Tcl_ErrnoMsg(errno));
1953                   return -1;
1954                 }
1955
1956                 /* turn on detection of eof */
1957                 exp_slave_control(exp_pty[0],1);
1958
1959                 /*
1960                  * tell slave to go on now now that we have initialized pty
1961                  */
1962
1963                 exp_debuglog("parent: telling child to go ahead\r\n");
1964                 cc = write(sync2_fds[1]," ",1);
1965                 if (cc == -1) {
1966                   exp_errorlog("parent sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
1967                   return -1;
1968                 }
1969
1970                 exp_debuglog("parent: now unsynchronized from child\r\n");
1971
1972                 close(sync_fds[0]);
1973                 close(sync2_fds[1]);
1974
1975                 /* see if child's exec worked */
1976
1977         retry:
1978                 switch (read(status_pipe[0],&child_errno,sizeof child_errno)) {
1979                 case -1:
1980                         if (errno == EINTR) goto retry;
1981                         /* well it's not really the child's errno */
1982                         /* but it can be treated that way */
1983                         child_errno = errno;
1984                         break;
1985                 case 0:
1986                         /* child's exec succeeded */
1987                         child_errno = 0;
1988                         break;
1989                 default:
1990                         /* child's exec failed; err contains exec's errno  */
1991                         waitpid(exp_pid, NULL, 0);
1992                         errno = child_errno;
1993                         exp_pty[0] = -1;
1994                 }
1995                 close(status_pipe[0]);
1996                 return(exp_pty[0]);
1997         }
1998
1999         /*
2000          * child process - do not return from here!  all errors must exit()
2001          */
2002
2003         close(sync_fds[0]);
2004         close(sync2_fds[1]);
2005         close(status_pipe[0]);
2006         fcntl(status_pipe[1],F_SETFD,1);        /* close on exec */
2007
2008 #ifdef CRAY
2009         (void) close(exp_pty[0]);
2010 #endif
2011
2012 /* ultrix (at least 4.1-2) fails to obtain controlling tty if setsid */
2013 /* is called.  setpgrp works though.  */
2014 #if defined(POSIX) && !defined(ultrix)
2015 #define DO_SETSID
2016 #endif
2017 #ifdef __convex__
2018 #define DO_SETSID
2019 #endif
2020
2021 #ifdef DO_SETSID
2022         setsid();
2023 #else
2024 #ifdef SYSV3
2025 #ifndef CRAY
2026         exp_setpgrp();
2027 #endif /* CRAY */
2028 #else /* !SYSV3 */
2029         exp_setpgrp();
2030
2031 #ifdef TIOCNOTTY
2032         ttyfd = open("/dev/tty", O_RDWR);
2033         if (ttyfd >= 0) {
2034                 (void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
2035                 (void) close(ttyfd);
2036         }
2037 #endif /* TIOCNOTTY */
2038
2039 #endif /* SYSV3 */
2040 #endif /* DO_SETSID */
2041
2042         /* save error fd while we're setting up new one */
2043         errorfd = fcntl(2,F_DUPFD,3);
2044         /* and here is the macro to restore it */
2045 #define restore_error_fd {close(2);fcntl(errorfd,F_DUPFD,2);}
2046
2047         if (exp_autoallocpty) {
2048
2049             close(0);
2050             close(1);
2051             close(2);
2052
2053             /* since we closed fd 0, open of pty slave must return fd 0 */
2054
2055             if (0 > (exp_pty[1] = exp_getptyslave(exp_ttycopy,exp_ttyinit,
2056                                                 exp_stty_init))) {
2057                 restore_error_fd
2058                 fprintf(stderr,"open(slave pty): %s\n",Tcl_ErrnoMsg(errno));
2059                 exit(-1);
2060             }
2061             /* sanity check */
2062             if (exp_pty[1] != 0) {
2063                 restore_error_fd
2064                 fprintf(stderr,"exp_getptyslave: slave = %d but expected 0\n",
2065                                                                 exp_pty[1]);
2066                 exit(-1);
2067             }
2068         } else {
2069                 if (exp_pty[1] != 0) {
2070                         close(0);       fcntl(exp_pty[1],F_DUPFD,0);
2071                 }
2072                 close(1);               fcntl(0,F_DUPFD,1);
2073                 close(2);               fcntl(0,F_DUPFD,1);
2074                 close(exp_pty[1]);
2075         }
2076
2077
2078
2079 /* The test for hpux may have to be more specific.  In particular, the */
2080 /* code should be skipped on the hp9000s300 and hp9000s720 (but there */
2081 /* is no documented define for the 720!) */
2082
2083 #if defined(TIOCSCTTY) && !defined(sun) && !defined(hpux)
2084         /* 4.3+BSD way to acquire controlling terminal */
2085         /* according to Stevens - Adv. Prog..., p 642 */
2086 #ifdef __QNX__ /* posix in general */
2087         if (tcsetct(0, getpid()) == -1) {
2088           restore_error_fd
2089           expErrorLog("failed to get controlling terminal using TIOCSCTTY");
2090           exit(-1);
2091         }
2092 #else
2093         (void) ioctl(0,TIOCSCTTY,(char *)0);
2094         /* ignore return value - on some systems, it is defined but it
2095          * fails and it doesn't seem to cause any problems.  Or maybe
2096          * it works but returns a bogus code.  Noone seems to be able
2097          * to explain this to me.  The systems are an assortment of
2098          * different linux systems (and FreeBSD 2.5), RedHat 5.2 and
2099          * Debian 2.0
2100          */
2101 #endif
2102 #endif
2103
2104 #ifdef CRAY
2105         (void) setsid();
2106         (void) ioctl(0,TCSETCTTY,0);
2107         (void) close(0);
2108         if (open("/dev/tty", O_RDWR) < 0) {
2109                 restore_error_fd
2110                 fprintf(stderr,"open(/dev/tty): %s\r\n",Tcl_ErrnoMsg(errno));
2111                 exit(-1);
2112         }
2113         (void) close(1);
2114         (void) close(2);
2115         (void) dup(0);
2116         (void) dup(0);
2117         setptyutmp();   /* create a utmp entry */
2118
2119         /* _CRAY2 code from Hal Peterson <hrp@cray.com>, Cray Research, Inc. */
2120 #ifdef _CRAY2
2121         /*
2122          * Interpose a process between expect and the spawned child to
2123          * keep the slave side of the pty open to allow time for expect
2124          * to read the last output.  This is a workaround for an apparent
2125          * bug in the Unicos pty driver on Cray-2's under Unicos 6.0 (at
2126          * least).
2127          */
2128         if ((pid = fork()) == -1) {
2129                 restore_error_fd
2130                 fprintf(stderr,"second fork: %s\r\n",Tcl_ErrnoMsg(errno));
2131                 exit(-1);
2132         }
2133
2134         if (pid) {
2135                 /* Intermediate process. */
2136                 int status;
2137                 int timeout;
2138                 char *t;
2139
2140                 /* How long should we wait? */
2141                 timeout = exp_pty_timeout;
2142
2143                 /* Let the spawned process run to completion. */
2144                 while (wait(&status) < 0 && errno == EINTR)
2145                         /* empty body */;
2146
2147                 /* Wait for the pty to clear. */
2148                 sleep(timeout);
2149
2150                 /* Duplicate the spawned process's status. */
2151                 if (WIFSIGNALED(status))
2152                         kill(getpid(), WTERMSIG(status));
2153
2154                 /* The kill may not have worked, but this will. */
2155                 exit(WEXITSTATUS(status));
2156         }
2157 #endif /* _CRAY2 */
2158 #endif /* CRAY */
2159
2160         if (exp_console) {
2161 #ifdef SRIOCSREDIR
2162                 int fd;
2163
2164                 if ((fd = open("/dev/console", O_RDONLY)) == -1) {
2165                         restore_error_fd
2166                         fprintf(stderr, "spawn %s: cannot open console, check permissions of /dev/console\n",argv[0]);
2167                         exit(-1);
2168                 }
2169                 if (ioctl(fd, SRIOCSREDIR, 0) == -1) {
2170                         restore_error_fd
2171                         fprintf(stderr, "spawn %s: cannot redirect console, check permissions of /dev/console\n",argv[0]);
2172                 }
2173                 close(fd);
2174 #endif
2175
2176 #ifdef TIOCCONS
2177                 int on = 1;
2178                 if (ioctl(0,TIOCCONS,(char *)&on) == -1) {
2179                         restore_error_fd
2180                         fprintf(stderr, "spawn %s: cannot open console, check permissions of /dev/console\n",argv[0]);
2181                         exit(-1);
2182                 }
2183 #endif /* TIOCCONS */
2184         }
2185
2186         /* tell parent that we are done setting up pty */
2187         /* The actual char sent back is irrelevant. */
2188
2189         /* exp_debuglog("child: telling parent that pty is initialized\r\n");*/
2190         cc = write(sync_fds[1]," ",1);
2191         if (cc == -1) {
2192                 restore_error_fd
2193                 fprintf(stderr,"child: sync byte write: %s\r\n",Tcl_ErrnoMsg(errno));
2194                 exit(-1);
2195         }
2196         close(sync_fds[1]);
2197
2198         /* wait for master to let us go on */
2199         cc = read(sync2_fds[0],&sync_byte,1);
2200         if (cc == -1) {
2201                 restore_error_fd
2202                 exp_errorlog("child: sync byte read: %s\r\n",Tcl_ErrnoMsg(errno));
2203                 exit(-1);
2204         }
2205         close(sync2_fds[0]);
2206
2207         /* exp_debuglog("child: now unsynchronized from parent\r\n"); */
2208
2209         /* (possibly multiple) masters are closed automatically due to */
2210         /* earlier fcntl(,,CLOSE_ON_EXEC); */
2211
2212         /* just in case, allow user to explicitly close other files */
2213         if (exp_close_in_child) (*exp_close_in_child)();
2214
2215         /* allow user to do anything else to child */
2216         if (exp_child_exec_prelude) (*exp_child_exec_prelude)();
2217
2218         (void) execvp(file,argv);
2219
2220         /* Unfortunately, by now we've closed fd's to stderr, logfile
2221          * and debugfile.  The only reasonable thing to do is to send
2222          * *back the error as part of the program output.  This will
2223          * be *picked up in an expect or interact command.
2224          */
2225
2226         write(status_pipe[1], &errno, sizeof errno);
2227         exit(-1);
2228         /*NOTREACHED*/
2229 }
2230
2231 /* returns fd of master side of pty */
2232 /*VARARGS*/
2233 int
2234 exp_spawnl TCL_VARARGS_DEF(char *,arg1)
2235 /*exp_spawnl(va_alist)*/
2236 /*va_dcl*/
2237 {
2238         va_list args; /* problematic line here */
2239         int i;
2240         char *arg, **argv;
2241
2242         arg = TCL_VARARGS_START(char *,arg1,args);
2243         /*va_start(args);*/
2244         for (i=1;;i++) {
2245                 arg = va_arg(args,char *);
2246                 if (!arg) break;
2247         }
2248         va_end(args);
2249         if (i == 0) sysreturn(EINVAL);
2250         if (!(argv = (char **)malloc((i+1)*sizeof(char *)))) sysreturn(ENOMEM);
2251         argv[0] = TCL_VARARGS_START(char *,arg1,args);
2252         /*va_start(args);*/
2253         for (i=1;;i++) {
2254                 argv[i] = va_arg(args,char *);
2255                 if (!argv[i]) break;
2256         }
2257         i = exp_spawnv(argv[0],argv+1);
2258         free((char *)argv);
2259         return(i);
2260 }
2261
2262 /* allow user-provided fd to be passed to expect funcs */
2263 int
2264 exp_spawnfd(fd)
2265 int fd;
2266 {
2267         if (!fd_new(fd)) {
2268                 errno = ENOMEM;
2269                 return -1;
2270         }
2271         return fd;      
2272 }
2273
2274 /* remove nulls from s.  Initially, the number of chars in s is c, */
2275 /* not strlen(s).  This count does not include the trailing null. */
2276 /* returns number of nulls removed. */
2277 static int
2278 rm_nulls(s,c)
2279 char *s;
2280 int c;
2281 {
2282         char *s2 = s;   /* points to place in original string to put */
2283                         /* next non-null character */
2284         int count = 0;
2285         int i;
2286
2287         for (i=0;i<c;i++,s++) {
2288                 if (0 == *s) {
2289                         count++;
2290                         continue;
2291                 }
2292                 if (count) *s2 = *s;
2293                 s2++;
2294         }
2295         return(count);
2296 }
2297
2298 static int i_read_errno;/* place to save errno, if i_read() == -1, so it
2299                            doesn't get overwritten before we get to read it */
2300
2301 /*ARGSUSED*/
2302 static void
2303 sigalarm_handler(n)
2304 int n;                  /* signal number, unused by us */
2305 {
2306 #ifdef REARM_SIG
2307         signal(SIGALRM,sigalarm_handler);
2308 #endif
2309
2310 #ifdef HAVE_SIGLONGJMP
2311         siglongjmp(exp_readenv,1);
2312 #else
2313         longjmp(exp_readenv,1);
2314 #endif /* HAVE_SIGLONGJMP */
2315 }
2316
2317 /* interruptable read */
2318 static int
2319 i_read(fd,fp,buffer,length,timeout)
2320 int fd;
2321 FILE *fp;
2322 char *buffer;
2323 int length;
2324 int timeout;
2325 {
2326         int cc = -2;
2327
2328         /* since setjmp insists on returning 1 upon longjmp(,0), */
2329         /* longjmp(,2 (EXP_RESTART)) instead. */
2330
2331         /* no need to set alarm if -1 (infinite) or 0 (poll with */
2332         /* guaranteed data) */
2333
2334         if (timeout > 0) alarm(timeout);
2335
2336         /* restart read if setjmp returns 0 (first time) or 2 (EXP_RESTART). */
2337         /* abort if setjmp returns 1 (EXP_ABORT). */
2338 #ifdef HAVE_SIGLONGJMP
2339         if (EXP_ABORT != sigsetjmp(exp_readenv,1)) {
2340 #else
2341         if (EXP_ABORT != setjmp(exp_readenv)) {
2342 #endif /* HAVE_SIGLONGJMP */
2343                 exp_reading = TRUE;
2344                 if (fd == -1) {
2345                         int c;
2346                         c = getc(fp);
2347                         if (c == EOF) {
2348 /*fprintf(stderr,"<<EOF>>",c);fflush(stderr);*/
2349                                 if (feof(fp)) cc = 0;
2350                                 else cc = -1;
2351                         } else {
2352 /*fprintf(stderr,"<<%c>>",c);fflush(stderr);*/
2353                                 buffer[0] = c;
2354                                 cc = 1;
2355                         }
2356                 } else {
2357 #ifndef HAVE_PTYTRAP
2358                         cc = read(fd,buffer,length);
2359 #else
2360 #  include <sys/ptyio.h>
2361
2362                         fd_set rdrs;
2363                         fd_set excep;
2364
2365                 restart:
2366                         FD_ZERO(&rdrs);
2367                         FD_ZERO(&excep);
2368                         FD_SET(fd,&rdrs);
2369                         FD_SET(fd,&excep);
2370                         if (-1 == (cc = select(fd+1,
2371                                          (SELECT_MASK_TYPE *)&rdrs,
2372                                          (SELECT_MASK_TYPE *)0,
2373                                          (SELECT_MASK_TYPE *)&excep,
2374                                          (struct timeval *)0))) {
2375                                 /* window refreshes trigger EINTR, ignore */
2376                                 if (errno == EINTR) goto restart;
2377                         }
2378                         if (FD_ISSET(fd,&rdrs)) {
2379                                 cc = read(fd,buffer,length);
2380                         } else if (FD_ISSET(fd,&excep)) {
2381                                 struct request_info ioctl_info;
2382                                 ioctl(fd,TIOCREQCHECK,&ioctl_info);
2383                                 if (ioctl_info.request == TIOCCLOSE) {
2384                                         cc = 0; /* indicate eof */
2385                                 } else {
2386                                         ioctl(fd, TIOCREQSET, &ioctl_info);
2387                                         /* presumably, we trapped an open here */
2388                                         goto restart;
2389                                 }
2390                         }
2391 #endif /* HAVE_PTYTRAP */
2392                 }
2393 #if 0
2394                 /* can't get fread to return early! */
2395                 else {
2396                         if (!(cc = fread(buffer,1,length,fp))) {
2397                                 if (ferror(fp)) cc = -1;
2398                         }
2399                 }
2400 #endif
2401                 i_read_errno = errno;   /* errno can be overwritten by the */
2402                                         /* time we return */
2403         }
2404         exp_reading = FALSE;
2405
2406         if (timeout > 0) alarm(0);
2407         return(cc);
2408 }
2409
2410 /* I tried really hard to make the following two functions share the code */
2411 /* that makes the ecase array, but I kept running into a brick wall when */
2412 /* passing var args into the funcs and then again into a make_cases func */
2413 /* I would very much appreciate it if someone showed me how to do it right */
2414
2415 /* takes triplets of args, with a final "exp_last" arg */
2416 /* triplets are type, pattern, and then int to return */
2417 /* returns negative value if error (or EOF/timeout) occurs */
2418 /* some negative values can also have an associated errno */
2419
2420 /* the key internal variables that this function depends on are:
2421         exp_buffer
2422         exp_buffer_end
2423         exp_match_end
2424 */
2425 static int
2426 expectv(fd,fp,ecases)
2427 int fd;
2428 FILE *fp;
2429 struct exp_case *ecases;
2430 {
2431         int cc = 0;             /* number of chars returned in a single read */
2432         int buf_length;         /* numbers of chars in exp_buffer */
2433         int old_length;         /* old buf_length */
2434         int first_time = TRUE;  /* force old buffer to be tested before */
2435                                 /* additional reads */
2436         int polled = 0;         /* true if poll has caused read() to occur */
2437
2438         struct exp_case *ec;    /* points to current ecase */
2439
2440         time_t current_time;    /* current time (when we last looked)*/
2441         time_t end_time;        /* future time at which to give up */
2442         int remtime;            /* remaining time in timeout */
2443
2444         struct f *f;
2445         int return_val;
2446         int sys_error = 0;
2447 #define return_normally(x)      {return_val = x; goto cleanup;}
2448 #define return_errno(x) {sys_error = x; goto cleanup;}
2449
2450         f = fdfp2f(fd,fp);
2451         if (!f) return_errno(ENOMEM);
2452
2453         exp_buffer = f->buffer;
2454         exp_buffer_end = f->buffer_end;
2455         exp_match_end = f->match_end;
2456
2457         buf_length = exp_buffer_end - exp_match_end;
2458         if (buf_length) {
2459                 /*
2460                  * take end of previous match to end of buffer
2461                  * and copy to beginning of buffer
2462                  */
2463                 memmove(exp_buffer,exp_match_end,buf_length);
2464         }                       
2465         exp_buffer_end = exp_buffer + buf_length;
2466         *exp_buffer_end = '\0';
2467
2468         if (!ecases) return_errno(EINVAL);
2469
2470         /* compile if necessary */
2471         for (ec=ecases;ec->type != exp_end;ec++) {
2472                 if ((ec->type == exp_regexp) && !ec->re) {
2473                         TclRegError((char *)0);
2474                         if (!(ec->re = TclRegComp(ec->pattern))) {
2475                                 fprintf(stderr,"regular expression %s is bad: %s",ec->pattern,TclGetRegError());
2476                                 return_errno(EINVAL);
2477                           }
2478                   }
2479         }
2480
2481         /* get the latest buffer size.  Double the user input for two */
2482         /* reasons.  1) Need twice the space in case the match */
2483         /* straddles two bufferfuls, 2) easier to hack the division by */
2484         /* two when shifting the buffers later on */
2485
2486         bufsiz = 2*exp_match_max;
2487         if (f->msize != bufsiz) {
2488                 /* if truncated, forget about some data */
2489                 if (buf_length > bufsiz) {
2490                         /* copy end of buffer down */
2491
2492                         /* copy one less than what buffer can hold to avoid */
2493                         /* triggering buffer-full handling code below */
2494                         /* which will immediately dump the first half */
2495                         /* of the buffer */
2496                         memmove(exp_buffer,exp_buffer+(buf_length - bufsiz)+1,
2497                                 bufsiz-1);
2498                         buf_length = bufsiz-1;
2499                 }
2500                 exp_buffer = realloc(exp_buffer,bufsiz+1);
2501                 if (!exp_buffer) return_errno(ENOMEM);
2502                 exp_buffer[buf_length] = '\0';
2503                 exp_buffer_end = exp_buffer + buf_length;
2504                 f->msize = bufsiz;
2505         }
2506
2507         /* some systems (i.e., Solaris) require fp be flushed when switching */
2508         /* directions - do this again afterwards */
2509         if (fd == -1) fflush(fp);
2510
2511         if (exp_timeout != -1) signal(SIGALRM,sigalarm_handler);
2512
2513         /* remtime and current_time updated at bottom of loop */
2514         remtime = exp_timeout;
2515
2516         time(&current_time);
2517         end_time = current_time + remtime;
2518
2519         for (;;) {
2520                 /* when buffer fills, copy second half over first and */
2521                 /* continue, so we can do matches over multiple buffers */
2522                 if (buf_length == bufsiz) {
2523                         int first_half, second_half;
2524
2525                         if (exp_full_buffer) {
2526                                 exp_debuglog("expect: full buffer\r\n");
2527                                 exp_match = exp_buffer;
2528                                 exp_match_end = exp_buffer + buf_length;
2529                                 exp_buffer_end = exp_match_end;
2530                                 return_normally(EXP_FULLBUFFER);
2531                         }
2532                         first_half = bufsiz/2;
2533                         second_half = bufsiz - first_half;
2534
2535                         memcpy(exp_buffer,exp_buffer+first_half,second_half);
2536                         buf_length = second_half;
2537                         exp_buffer_end = exp_buffer + second_half;
2538                 }
2539
2540                 /*
2541                  * always check first if pattern is already in buffer
2542                  */
2543                 if (first_time) {
2544                         first_time = FALSE;
2545                         goto after_read;
2546                 }
2547
2548                 /*
2549                  * check for timeout
2550                  * we should timeout if either
2551                  *   1) exp_timeout > remtime <= 0 (normal)
2552                  *   2) exp_timeout == 0 and we have polled at least once
2553                  * 
2554                  */
2555                 if (((exp_timeout > remtime) && (remtime <= 0)) ||
2556                     ((exp_timeout == 0) && polled)) {
2557                         exp_debuglog("expect: timeout\r\n");
2558                         exp_match_end = exp_buffer;
2559                         return_normally(EXP_TIMEOUT);
2560                 }
2561
2562                 /* remember that we have actually checked at least once */
2563                 polled = 1;
2564
2565                 cc = i_read(fd,fp,
2566                                 exp_buffer_end,
2567                                 bufsiz - buf_length,
2568                                 remtime);
2569
2570                 if (cc == 0) {
2571                         exp_debuglog("expect: eof\r\n");
2572                         return_normally(EXP_EOF);       /* normal EOF */
2573                 } else if (cc == -1) {                  /* abnormal EOF */
2574                         /* ptys produce EIO upon EOF - sigh */
2575                         if (i_read_errno == EIO) {
2576                                 /* convert to EOF indication */
2577                                 exp_debuglog("expect: eof\r\n");
2578                                 return_normally(EXP_EOF);
2579                         }
2580                         exp_debuglog("expect: error (errno = %d)\r\n",i_read_errno);
2581                         return_errno(i_read_errno);
2582                 } else if (cc == -2) {
2583                         exp_debuglog("expect: timeout\r\n");
2584                         exp_match_end = exp_buffer;
2585                         return_normally(EXP_TIMEOUT);
2586                 }
2587
2588                 old_length = buf_length;
2589                 buf_length += cc;
2590                 exp_buffer_end += buf_length;
2591
2592                 if (exp_logfile_all || (exp_loguser && exp_logfile)) {
2593                         fwrite(exp_buffer + old_length,1,cc,exp_logfile);
2594                 }
2595                 if (exp_loguser) fwrite(exp_buffer + old_length,1,cc,stdout);
2596                 if (exp_debugfile) fwrite(exp_buffer + old_length,1,cc,exp_debugfile);
2597
2598                 /* if we wrote to any logs, flush them */
2599                 if (exp_debugfile) fflush(exp_debugfile);
2600                 if (exp_loguser) {
2601                         fflush(stdout);
2602                         if (exp_logfile) fflush(exp_logfile);
2603                 }
2604
2605                 /* remove nulls from input, so we can use C-style strings */
2606                 /* doing it here lets them be sent to the screen, just */
2607                 /*  in case they are involved in formatting operations */
2608                 if (exp_remove_nulls) {
2609                         buf_length -= rm_nulls(exp_buffer + old_length, cc);
2610                 }
2611                 /* cc should be decremented as well, but since it will not */
2612                 /* be used before being set again, there is no need */
2613                 exp_buffer_end = exp_buffer + buf_length;
2614                 *exp_buffer_end = '\0';
2615                 exp_match_end = exp_buffer;
2616
2617         after_read:
2618                 exp_debuglog("expect: does {%s} match ",exp_printify(exp_buffer));
2619                 /* pattern supplied */
2620                 for (ec=ecases;ec->type != exp_end;ec++) {
2621                         int matched = -1;
2622
2623                         exp_debuglog("{%s}? ",exp_printify(ec->pattern));
2624                         if (ec->type == exp_glob) {
2625                                 int offset;
2626                                 matched = Exp_StringMatch(exp_buffer,ec->pattern,&offset);
2627                                 if (matched >= 0) {
2628                                         exp_match = exp_buffer + offset;
2629                                         exp_match_end = exp_match + matched;
2630                                 }
2631                         } else if (ec->type == exp_exact) {
2632                                 char *p = strstr(exp_buffer,ec->pattern);
2633                                 if (p) {
2634                                         matched = 1;
2635                                         exp_match = p;
2636                                         exp_match_end = p + strlen(ec->pattern);
2637                                 }
2638                         } else if (ec->type == exp_null) {
2639                                 char *p;
2640
2641                                 for (p=exp_buffer;p<exp_buffer_end;p++) {
2642                                         if (*p == 0) {
2643                                                 matched = 1;
2644                                                 exp_match = p;
2645                                                 exp_match_end = p+1;
2646                                         }
2647                                 }
2648                         } else {
2649                                 TclRegError((char *)0);
2650                                 if (TclRegExec(ec->re,exp_buffer,exp_buffer)) {
2651                                         matched = 1;
2652                                         exp_match = ec->re->startp[0];
2653                                         exp_match_end = ec->re->endp[0];
2654                                 } else if (TclGetRegError()) {
2655                                         fprintf(stderr,"r.e. match (pattern %s) failed: %s",ec->pattern,TclGetRegError());
2656                                 }
2657                         }
2658
2659                         if (matched != -1) {
2660                                 exp_debuglog("yes\nexp_buffer is {%s}\n",
2661                                                 exp_printify(exp_buffer));
2662                                 return_normally(ec->value);
2663                         } else exp_debuglog("no\n");
2664                 }
2665
2666                 /*
2667                  * Update current time and remaining time.
2668                  * Don't bother if we are waiting forever or polling.
2669                  */
2670                 if (exp_timeout > 0) {
2671                         time(&current_time);
2672                         remtime = end_time - current_time;
2673                 }
2674         }
2675  cleanup:
2676         f->buffer     = exp_buffer;
2677         f->buffer_end = exp_buffer_end;
2678         f->match_end  = exp_match_end;
2679
2680         /* some systems (i.e., Solaris) require fp be flushed when switching */
2681         /* directions - do this before as well */
2682         if (fd == -1) fflush(fp);
2683
2684         if (sys_error) {
2685                 errno = sys_error;
2686                 return -1;
2687         }
2688         return return_val;
2689 }
2690
2691 int
2692 exp_fexpectv(fp,ecases)
2693 FILE *fp;
2694 struct exp_case *ecases;
2695 {
2696         return(expectv(-1,fp,ecases));
2697 }
2698
2699 int
2700 exp_expectv(fd,ecases)
2701 int fd;
2702 struct exp_case *ecases;
2703 {
2704         return(expectv(fd,(FILE *)0,ecases));
2705 }
2706
2707 /*VARARGS*/
2708 int
2709 exp_expectl TCL_VARARGS_DEF(int,arg1)
2710 /*exp_expectl(va_alist)*/
2711 /*va_dcl*/
2712 {
2713         va_list args;
2714         int fd;
2715         struct exp_case *ec, *ecases;
2716         int i;
2717         enum exp_type type;
2718
2719         fd = TCL_VARARGS_START(int,arg1,args);
2720         /* va_start(args);*/
2721         /* fd = va_arg(args,int);*/
2722         /* first just count the arg sets */
2723         for (i=0;;i++) {
2724                 type = va_arg(args,enum exp_type);
2725                 if (type == exp_end) break;
2726
2727                 /* Ultrix 4.2 compiler refuses enumerations comparison!? */
2728                 if ((int)type < 0 || (int)type >= (int)exp_bogus) {
2729                         fprintf(stderr,"bad type (set %d) in exp_expectl\n",i);
2730                         sysreturn(EINVAL);
2731                 }
2732
2733                 va_arg(args,char *);            /* COMPUTED BUT NOT USED */
2734                 if (type == exp_compiled) {
2735                         va_arg(args,regexp *);  /* COMPUTED BUT NOT USED */
2736                 }
2737                 va_arg(args,int);               /* COMPUTED BUT NOT USED*/
2738         }
2739         va_end(args);
2740
2741         if (!(ecases = (struct exp_case *)
2742                                 malloc((1+i)*sizeof(struct exp_case))))
2743                 sysreturn(ENOMEM);
2744
2745         /* now set up the actual cases */
2746         fd = TCL_VARARGS_START(int,arg1,args);
2747         /*va_start(args);*/
2748         /*va_arg(args,int);*/           /*COMPUTED BUT NOT USED*/
2749         for (ec=ecases;;ec++) {
2750                 ec->type = va_arg(args,enum exp_type);
2751                 if (ec->type == exp_end) break;
2752                 ec->pattern = va_arg(args,char *);
2753                 if (ec->type == exp_compiled) {
2754                         ec->re = va_arg(args,regexp *);
2755                 } else {
2756                         ec->re = 0;
2757                 }
2758                 ec->value = va_arg(args,int);
2759         }
2760         va_end(args);
2761         i = expectv(fd,(FILE *)0,ecases);
2762
2763         for (ec=ecases;ec->type != exp_end;ec++) {
2764                 /* free only if regexp and we compiled it for user */
2765                 if (ec->type == exp_regexp) {
2766                         free((char *)ec->re);
2767                 }
2768         }
2769         free((char *)ecases);
2770         return(i);
2771 }
2772
2773 int
2774 exp_fexpectl TCL_VARARGS_DEF(FILE *,arg1)
2775 /*exp_fexpectl(va_alist)*/
2776 /*va_dcl*/
2777 {
2778         va_list args;
2779         FILE *fp;
2780         struct exp_case *ec, *ecases;
2781         int i;
2782         enum exp_type type;
2783
2784         fp = TCL_VARARGS_START(FILE *,arg1,args);
2785         /*va_start(args);*/
2786         /*fp = va_arg(args,FILE *);*/
2787         /* first just count the arg-pairs */
2788         for (i=0;;i++) {
2789                 type = va_arg(args,enum exp_type);
2790                 if (type == exp_end) break;
2791
2792                 /* Ultrix 4.2 compiler refuses enumerations comparison!? */
2793                 if ((int)type < 0 || (int)type >= (int)exp_bogus) {
2794                         fprintf(stderr,"bad type (set %d) in exp_expectl\n",i);
2795                         sysreturn(EINVAL);
2796                 }
2797
2798                 va_arg(args,char *);            /* COMPUTED BUT NOT USED */
2799                 if (type == exp_compiled) {
2800                         va_arg(args,regexp *);  /* COMPUTED BUT NOT USED */
2801                 }
2802                 va_arg(args,int);               /* COMPUTED BUT NOT USED*/
2803         }
2804         va_end(args);
2805
2806         if (!(ecases = (struct exp_case *)
2807                                         malloc((1+i)*sizeof(struct exp_case))))
2808                 sysreturn(ENOMEM);
2809
2810 #if 0
2811         va_start(args);
2812         va_arg(args,FILE *);            /*COMPUTED, BUT NOT USED*/
2813 #endif
2814         (void) TCL_VARARGS_START(FILE *,arg1,args);
2815
2816         for (ec=ecases;;ec++) {
2817                 ec->type = va_arg(args,enum exp_type);
2818                 if (ec->type == exp_end) break;
2819                 ec->pattern = va_arg(args,char *);
2820                 if (ec->type == exp_compiled) {
2821                         ec->re = va_arg(args,regexp *);
2822                 } else {
2823                         ec->re = 0;
2824                 }
2825                 ec->value = va_arg(args,int);
2826         }
2827         va_end(args);
2828         i = expectv(-1,fp,ecases);
2829
2830         for (ec=ecases;ec->type != exp_end;ec++) {
2831                 /* free only if regexp and we compiled it for user */
2832                 if (ec->type == exp_regexp) {
2833                         free((char *)ec->re);
2834                 }
2835         }
2836         free((char *)ecases);
2837         return(i);
2838 }
2839
2840 /* like popen(3) but works in both directions */
2841 FILE *
2842 exp_popen(program)
2843 char *program;
2844 {
2845         FILE *fp;
2846         int ec;
2847
2848         if (0 > (ec = exp_spawnl("sh","sh","-c",program,(char *)0))) return(0);
2849         if (!(fp = fdopen(ec,"r+"))) return(0);
2850         setbuf(fp,(char *)0);
2851         return(fp);
2852 }
2853
2854 int
2855 exp_disconnect()
2856 {
2857         int ttyfd;
2858
2859 #ifndef EALREADY
2860 #define EALREADY 37
2861 #endif
2862
2863         /* presumably, no stderr, so don't bother with error message */
2864         if (exp_disconnected) sysreturn(EALREADY);
2865         exp_disconnected = TRUE;
2866
2867         freopen("/dev/null","r",stdin);
2868         freopen("/dev/null","w",stdout);
2869         freopen("/dev/null","w",stderr);
2870
2871 #ifdef POSIX
2872         setsid();
2873 #else
2874 #ifdef SYSV3
2875         /* put process in our own pgrp, and lose controlling terminal */
2876         exp_setpgrp();
2877         signal(SIGHUP,SIG_IGN);
2878         if (fork()) exit(0);    /* first child exits (as per Stevens, */
2879         /* UNIX Network Programming, p. 79-80) */
2880         /* second child process continues as daemon */
2881 #else /* !SYSV3 */
2882         exp_setpgrp();
2883 /* Pyramid lacks this defn */
2884 #ifdef TIOCNOTTY
2885         ttyfd = open("/dev/tty", O_RDWR);
2886         if (ttyfd >= 0) {
2887                 /* zap controlling terminal if we had one */
2888                 (void) ioctl(ttyfd, TIOCNOTTY, (char *)0);
2889                 (void) close(ttyfd);
2890         }
2891 #endif /* TIOCNOTTY */
2892 #endif /* SYSV3 */
2893 #endif /* POSIX */
2894         return(0);
2895 }
2896
2897 /* send to log if open and debugging enabled */
2898 /* send to stderr if debugging enabled */
2899 /* use this function for recording unusual things in the log */
2900 /*VARARGS*/
2901 void
2902 exp_debuglog TCL_VARARGS_DEF(char *,arg1)
2903 {
2904     char *fmt;
2905     va_list args;
2906
2907     fmt = TCL_VARARGS_START(char *,arg1,args);
2908     if (exp_debugfile) vfprintf(exp_debugfile,fmt,args);
2909     if (exp_is_debugging) {
2910         vfprintf(stderr,fmt,args);
2911         if (exp_logfile) vfprintf(exp_logfile,fmt,args);
2912     }
2913
2914     va_end(args);
2915 }
2916
2917
2918 /* send to log if open */
2919 /* send to stderr */
2920 /* use this function for error conditions */
2921 /*VARARGS*/
2922 void
2923 exp_errorlog TCL_VARARGS_DEF(char *,arg1)
2924 {
2925     char *fmt;
2926     va_list args;
2927     
2928     fmt = TCL_VARARGS_START(char *,arg1,args);
2929     vfprintf(stderr,fmt,args);
2930     if (exp_debugfile) vfprintf(exp_debugfile,fmt,args);
2931     if (exp_logfile) vfprintf(exp_logfile,fmt,args);
2932     va_end(args);
2933 }
2934
2935 #include <ctype.h>
2936
2937 char *
2938 exp_printify(s)
2939 char *s;
2940 {
2941         static int destlen = 0;
2942         static char *dest = 0;
2943         char *d;                /* ptr into dest */
2944         unsigned int need;
2945
2946         if (s == 0) return("<null>");
2947
2948         /* worst case is every character takes 4 to printify */
2949         need = strlen(s)*4 + 1;
2950         if (need > destlen) {
2951                 if (dest) ckfree(dest);
2952                 dest = ckalloc(need);
2953                 destlen = need;
2954         }
2955
2956         for (d = dest;*s;s++) {
2957                 if (*s == '\r') {
2958                         strcpy(d,"\\r");                d += 2;
2959                 } else if (*s == '\n') {
2960                         strcpy(d,"\\n");                d += 2;
2961                 } else if (*s == '\t') {
2962                         strcpy(d,"\\t");                d += 2;
2963                 } else if (isascii(*s) && isprint(*s)) {
2964                         *d = *s;                        d += 1;
2965                 } else {
2966                         sprintf(d,"\\x%02x",*s & 0xff); d += 4;
2967                 }
2968         }
2969         *d = '\0';
2970         return(dest);
2971 }