w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

sh4.c
Go to the documentation of this file.
1 /*
2  * MS-DOS SHELL - 'word' Interpretator
3  *
4  * MS-DOS SHELL - Copyright (c) 1990,4 Data Logic Limited and Charles Forsyth
5  *
6  * This code is based on (in part) the shell program written by Charles
7  * Forsyth and the subsequence modifications made by Simon J. Gerraty (for
8  * his Public Domain Korn Shell) and is subject to the following copyright
9  * restrictions:
10  *
11  * 1. Redistribution and use in source and binary forms are permitted
12  * provided that the above copyright notice is duplicated in the
13  * source form and the copyright notice in file sh6.c is displayed
14  * on entry to the program.
15  *
16  * 2. The sources (or parts thereof) or objects generated from the sources
17  * (or parts of sources) cannot be sold under any circumstances.
18  *
19  * $Header: /usr/users/istewart/shell/sh2.3/Release/RCS/sh4.c,v 2.13 1994/08/25 20:49:11 istewart Exp $
20  *
21  * $Log: sh4.c,v $
22  * Revision 2.13 1994/08/25 20:49:11 istewart
23  * MS Shell 2.3 Release
24  *
25  * Revision 2.12 1994/02/01 10:25:20 istewart
26  * Release 2.3 Beta 2, including first NT port
27  *
28  * Revision 2.11 1994/01/11 17:55:25 istewart
29  * Release 2.3 Beta 0 patches
30  *
31  * Revision 2.10 1993/08/25 16:03:57 istewart
32  * Beta 225 - see Notes file
33  *
34  * Revision 2.9 1993/07/02 10:21:35 istewart
35  * 224 Beta fixes
36  *
37  * Revision 2.8 1993/06/14 11:00:12 istewart
38  * More changes for 223 beta
39  *
40  * Revision 2.7 1993/06/02 09:52:35 istewart
41  * Beta 223 Updates - see Notes file
42  *
43  * Revision 2.6 1993/02/16 16:03:15 istewart
44  * Beta 2.22 Release
45  *
46  * Revision 2.5 1993/01/26 18:35:09 istewart
47  * Release 2.2 beta 0
48  *
49  * Revision 2.4 1992/12/14 10:54:56 istewart
50  * BETA 215 Fixes and 2.1 Release
51  *
52  * Revision 2.3 1992/11/06 10:03:44 istewart
53  * 214 Beta test updates
54  *
55  * Revision 2.2 1992/09/03 18:54:45 istewart
56  * Beta 213 Updates
57  *
58  * Revision 2.1 1992/07/10 10:52:48 istewart
59  * 211 Beta updates
60  *
61  * Revision 2.0 1992/04/13 17:39:09 Ian_Stewartson
62  * MS-Shell 2.0 Baseline release
63  *
64  */
65 
66 #include <sys/types.h>
67 #include <sys/stat.h>
68 #include <stdio.h>
69 #include <limits.h> /* String library functions */
70 #include <signal.h>
71 #include <errno.h>
72 #include <setjmp.h>
73 #include <dirent.h>
74 #include <string.h>
75 #include <stdlib.h>
76 #include <unistd.h>
77 #include <ctype.h>
78 #include <fcntl.h>
79 #include "sh.h"
80 
81 /*
82  * string expansion
83  *
84  * first pass: quoting, IFS separation, ${} and $() substitution.
85  * second pass: filename expansion (*?[]~).
86  */
87 
88 /*
89  * expansion generator state
90  */
91 
92 typedef struct Expand {
93  /* int type; */ /* see ExpandAWord() */
94  char *str; /* string */
95  union {
96  char **strv; /* string[] */
97  FILE *file; /* file */
98  } u; /* source */
99 
100  bool split; /* split "$@" */
102 
103 #define XBASE 0 /* scanning original */
104 #define XSUB 1 /* expanding ${} string */
105 #define XARGSEP 2 /* ifs0 between "$@" */
106 #define XARG 3 /* expanding $*, $@ */
107 #define XCOM 4 /* expanding $() */
108 
109 /*
110  * Quote processing
111  */
112 
113 #define QUOTE_NONE 0 /* None */
114 #define QUOTE_INSIDE 1 /* Inside quotes */
115 #define QUOTE_TEMP 2 /* Mark a temporary quote */
116 
117 /*
118  * for nested substitution: ${var:=$var2}
119  */
120 
121 typedef struct SubType {
122  short type; /* [=+-?%#] action after expanded word */
123  short base; /* begin position of expanded word */
124  char *name; /* name for ${var=word} */
125  int index; /* index ${var[index]=word} */
127 
128 static void F_LOCAL ExpandAWord (char *, Word_B **, int);
129 static int F_LOCAL VariableSubstitute (Expand *, char *, int, int);
130 static int F_LOCAL CommandSubstitute (Expand *, char *);
131 static char * F_LOCAL TrimSubstitute (SubType *, char *);
132 static int F_LOCAL MathsSubstitute (Expand *, char *);
133 static void F_LOCAL ExpandGlobCharacters (char *, Word_B **);
134 static void F_LOCAL GlobAWord (char *, char *, char *, Word_B **, bool);
135 static char * F_LOCAL RemoveMagicMarkers (unsigned char *);
136 static char * F_LOCAL TildeSubstitution (unsigned char *);
137 static unsigned char * F_LOCAL CheckForMultipleDrives (unsigned char *);
138 static bool F_LOCAL ProcessCommandTree (C_Op *, int);
139 static char * F_LOCAL WordScan (char *, int);
140 static int F_LOCAL HandleArrayValue (char *, char **, int);
141 static void F_LOCAL CheckForUnset (char *, int);
142 static void F_LOCAL AlternationExpand (char *, Word_B **, int);
143 static int F_LOCAL AlternationScan (char **, char **, char, int);
144 static void BuildVariableEntryList (const void *, VISIT, int);
145 static int F_LOCAL GetNumberofFloppyDrives (void);
146 
147 static char *PNullNSet = "%s: parameter null or not set";
148 static char *GVAV_Name; /* Name for building a */
149  /* list of Variable */
150  /* Array values */
151 static Word_B *GVAV_WordList; /* Word block for list */
152 
153 
154 /*
155  * compile and expand word
156  */
157 
158 char *substitute (char *cp, int ExpandMode)
159 {
160  struct source *sold = source;
161  char *res;
162 
163  source = pushs (SWSTR);
164  source->str = (char *) cp;
165 
167  PrintErrorMessage ("eval: substitute error");
168 
169  res = ExpandAString (yylval.cp, ExpandMode);
170  source = sold;
171  return res;
172 }
173 
174 /*
175  * expand arg-list
176  */
177 
178 char **ExpandWordList (char **ap, int ExpandMode, ExeMode *PMode)
179 {
180  Word_B *w = (Word_B *)NULL;
181  bool FoundProgram = FALSE;
182  int i;
183  int InitialCount;
184  char *CurrentAp;
185 
186  if ((ap == NOWORDS) || (*ap == NOWORD))
187  return ap;
188 
189 /* Expand the arguments */
190 
191  while (*ap != NOWORD)
192  {
193  InitialCount = WordBlockSize (w);
194  ExpandAWord (CurrentAp = *(ap++), &w, ExpandMode);
195 
196 /*
197  * Get the program mode for expansion of words and globs. Update the
198  * current mode to reflect it.
199  */
200 
201  if ((!FoundProgram) && (PMode != (ExeMode *)NULL) && WordBlockSize (w))
202  {
203  CheckProgramMode (w->w_words[0], PMode);
204 
205  if (PMode->Flags & EP_NOEXPAND)
206  ExpandMode &= ~~EXPAND_GLOBBING;
207 
208  if (PMode->Flags & EP_NOWORDS)
209  ExpandMode &= ~~EXPAND_SPLITIFS;
210 
211  if (PMode->Flags & EP_CONVERT)
212  ExpandMode |= EXPAND_CONVERT;
213  }
214 
215 /* Convert UNIX directories to DOS and - to / ?, except for first
216  * argument
217  */
218 
219  if (ExpandMode & EXPAND_CONVERT)
220  {
221  for (i = max (InitialCount, 1); i < WordBlockSize (w); i++)
222  {
223  PATH_TO_DOS (w->w_words[i]);
224 
225 /* Convert - to /, if the string is not quoted */
226 
227  if ((*(w->w_words[i]) == CHAR_SWITCH) &&
228  ((*CurrentAp != WORD_OQUOTE) ||
229  (*CurrentAp != WORD_QTCHAR)))
230  *(w->w_words[i]) = '/';
231  }
232  }
233  }
234 
235 /* Return the word list */
236 
237  return GetWordList (AddWordToBlock (NOWORD, w));
238 }
239 
240 /*
241  * expand string
242  */
243 
244 char *ExpandAString (char *cp, int ExpandMode)
245 {
246  Word_B *w = (Word_B *)NULL;
247 
248  ExpandAWord (cp, &w, ExpandMode);
249 
250  return (WordBlockSize (w) == 0) ? null : w->w_words[0];
251 }
252 
253 /*
254  * expand string - return only one component
255  * used from iosetup to expand redirection files
256  */
257 
258 char *ExpandOneStringFirstComponent (char *cp, int ExpandMode)
259 {
260  Word_B *w = (Word_B *)NULL;
261 
262  ExpandAWord (cp, &w, ExpandMode);
263 
264  switch (WordBlockSize (w))
265  {
266  case 0:
267  return null;
268 
269  case 1:
270  return w->w_words[0];
271  }
272 
273  return ExpandAString (cp, ExpandMode & ~EXPAND_GLOBBING);
274 }
275 
276 /*
277  * Expand a word or two!
278  */
279 
280 static void F_LOCAL ExpandAWord (char *OriginalWord, /* input word */
281  Word_B **WordList, /* output word list*/
282  int ExpandMode) /* Expand Flags */
283 {
284  int c;
285  int type = XBASE; /* expansion type */
286  int QuoteStatus = 0; /* quoted */
287  int quotestack[11]; /* Keep this bigger than the */
288  /* subtype stack */
289  int *qst = quotestack + 11;
290  XString ds; /* Expandable destination string*/
291  unsigned char *dp; /* Pointer into Destination S. */
292  char *sp; /* source */
293  int fdo; /* second pass flags; have word */
294  int word;
295  int combase;
296  int ArrayIndex;
297  Expand x; /* expansion variables */
298  SubType subtype [10]; /* substitution type stack */
299  SubType *st = subtype + 10;
300  int newlines; /* For trailing newlines in COMSUB */
301  int trimming = 0; /* flag if expanding ${var#pat} */
302  /* or ${var%pat} */
303  char ifs0 = *GetVariableAsString (IFS, FALSE);
304 
305  if (OriginalWord == NULL)
306  PrintErrorMessage ("eval: expanding a NULL");
307 
308 
310  ExpandMode &= (~~EXPAND_GLOBBING);
311 
312 /*
313  * Look for '{' in the input word
314  */
315 
317  (!(ExpandMode & EXPAND_NOALTS)) &&
318  (ExpandMode & EXPAND_GLOBBING) &&
319  ((sp = strchr (OriginalWord, CHAR_OPEN_BRACES)) != (char *)NULL) &&
320  (sp[-1] == WORD_CHAR) &&
321  (!(sp[1] == WORD_CHAR && sp[2] == CHAR_CLOSE_BRACES)))
322  {
323  AlternationExpand (OriginalWord, WordList, ExpandMode);
324  return;
325  }
326 
327  ExpandMode &= ~~EXPAND_NOALTS;
328 
329 /* Initialise */
330 
331  dp = (unsigned char *)XCreate (&ds, 128); /* destination string */
332  type = XBASE;
333  sp = OriginalWord;
334  fdo = 0;
335  word = !(ExpandMode & EXPAND_SPLITIFS);
336 
337 /* The Main loop!! */
338 
339  while (1)
340  {
341  XCheck (&ds, (unsigned char **)(&dp));
342 
343  switch (type)
344  {
345  case XBASE: /* original prefixed string */
346 
347  switch ((c = *(sp++)))
348  {
349  case WORD_EOS: /* End - Hurray */
350  c = 0;
351  break;
352 
353  case WORD_CHAR: /* Normal char */
354  c = *(sp++);
355  break;
356 
357  case WORD_QCHAR: /* Escaped char */
358  case WORD_QTCHAR:
359  QuoteStatus |= QUOTE_TEMP;/* temporary quote */
360  c = *(sp++);
361  break;
362 
363  case WORD_OQUOTE: /* Start quoted */
364  case WORD_ODQUOTE:
365  word = 1;
366  QuoteStatus = QUOTE_INSIDE;
367  continue;
368 
369  case WORD_CQUOTE: /* End quoted */
370  case WORD_CDQUOTE:
371  QuoteStatus = QUOTE_NONE;
372  continue;
373 
374  case WORD_COMSUB: /* $(....) */
375  type = CommandSubstitute (&x, sp);
376  sp = strchr (sp, 0) + 1;
377  combase = XCurrentOffset (ds, dp);
378  newlines = 0;
379  continue;
380 
381  case WORD_OMATHS: /* $((....)) */
382  type = MathsSubstitute (&x, sp);
383  sp = strchr (sp, 0) + 1;
384  continue;
385 
386  case WORD_OSUBST: /* ${var{:}[=+-?]word} */
387  OriginalWord = sp; /* variable */
388  sp = strchr (sp, 0) + 1; /* skip variable */
389 
390 /* Check for Array Variable */
391 
392  ArrayIndex = 0;
393  if (*sp == WORD_OARRAY)
394  ArrayIndex = HandleArrayValue (OriginalWord, &sp,
395  ExpandMode);
396 
397  c = (*sp == WORD_CSUBST) ? 0 : *(sp++);
398 
399 /* Check for match option */
400 
401  if (((c & 0x7f) == CHAR_MATCH_START) ||
402  ((c & 0x7f) == CHAR_MATCH_END))
403  {
404  CheckForUnset (OriginalWord, ArrayIndex);
405  trimming++;
406  type = XBASE;
407  *--qst = QuoteStatus;
408  QuoteStatus = QUOTE_NONE;
409  }
410 
411  else
412  type = VariableSubstitute (&x, OriginalWord,
413  c, ArrayIndex);
414 
415 /* expand? */
416 
417  if (type == XBASE)
418  {
419  if (st == subtype)
420  ShellErrorMessage ("ridiculous ${} nesting");
421 
422  --st;
423  st->type = c;
424  st->base = XCurrentOffset (ds, dp);
425  st->name = OriginalWord;
426  st->index = ArrayIndex;
427  }
428 
429  else
430  sp = WordScan (sp, WORD_CSUBST); /* skip word */
431 
432  continue;
433 
434  case WORD_CSUBST: /* only get here if expanding word */
435  *dp = 0;
436 
437  if (ExpandMode & EXPAND_GLOBBING)
438  ExpandMode &= (~~EXPAND_PATTERN);
439 
440 /*
441  * Check that full functionality is here!
442  */
443  switch (st->type & 0x7f)
444  {
445  case CHAR_MATCH_START:
446  case CHAR_MATCH_END:
447  *dp = 0;
448  dp = XResetOffset (ds, st->base);
449 
450  QuoteStatus = *(qst++);
451  x.str = TrimSubstitute (st, (char *)dp);
452  type = XSUB;
453  trimming--;
454  continue;
455 
456  case CHAR_ASSIGN:
458  (st->name, st->index,
459  (char *)XResetOffset (ds, st->base));
460  break;
461 
462  case '?':
463  if (dp == XResetOffset (ds, st->base))
464  ShellErrorMessage (PNullNSet, OriginalWord);
465 
466  else
467  ShellErrorMessage ("%s",
468  XResetOffset (ds,
469  st->base));
470  }
471 
472  st++;
473  type = XBASE;
474  continue;
475  }
476 
477  break;
478 
479  case XSUB:
480  if ((c = *(x.str++)) == 0)
481  {
482  type = XBASE;
483  continue;
484  }
485 
486  break;
487 
488  case XARGSEP:
489  type = XARG;
490  QuoteStatus = QUOTE_INSIDE;
491 
492  case XARG:
493  if ((c = *(x.str++)) == 0)
494  {
495  if ((x.str = *(x.u.strv++)) == NULL)
496  {
497  type = XBASE;
498  continue;
499  }
500 
501  else if (QuoteStatus && x.split)
502  {
503  type = XARGSEP; /* terminate word for "$@" */
504  QuoteStatus = QUOTE_NONE;
505  }
506 
507  c = ifs0;
508  }
509 
510  break;
511 
512  case XCOM:
513  if (newlines) /* Spit out saved nl's */
514  {
515  c = CHAR_NEW_LINE;
516  --newlines;
517  }
518 
519  else
520  {
521  while ((c = getc (x.u.file)) == CHAR_NEW_LINE)
522  newlines++; /* Save newlines */
523 
524  if (newlines && (c != EOF))
525  {
526  ungetc (c, x.u.file);
527  c = CHAR_NEW_LINE;
528  --newlines;
529  }
530  }
531 
532  if (c == EOF)
533  {
534  OriginalWord = (char *)XResetOffset (ds, combase);
535  newlines = 0;
536  S_fclose (x.u.file, TRUE);
537  type = XBASE;
538  continue;
539  }
540 
541  break;
542  }
543 
544 /* check for end of word or IFS separation */
545 
546  if ((c == 0) || (!QuoteStatus && (ExpandMode & EXPAND_SPLITIFS) &&
547  IS_IFS (c)))
548  {
549  if (word)
550  {
551  *(dp++) = 0;
552  OriginalWord = XClose (&ds, dp);
553 
554  if (fdo & EXPAND_TILDE)
555  OriginalWord =
556  TildeSubstitution ((unsigned char *)OriginalWord);
557 
558  if (fdo & EXPAND_GLOBBING)
559  ExpandGlobCharacters (OriginalWord, WordList);
560 
561  else
562  *WordList = AddWordToBlock (OriginalWord, *WordList);
563 
564 /* Re-set */
565  fdo = 0;
566  word = 0;
567 
568  if (c != 0)
569  dp = (unsigned char *)XCreate (&ds, 128);
570  }
571 
572  if (c == 0)
573  return;
574  }
575 
576 /*
577  * Mark any special second pass chars
578  */
579  else
580  {
581  if (!QuoteStatus)
582  {
583  switch (c)
584  {
585  case CHAR_MATCH_ALL:
586  case CHAR_MATCH_ANY:
587  case CHAR_OPEN_BRACKETS:
588  if ((ExpandMode & (EXPAND_PATTERN | EXPAND_GLOBBING)) ||
589  trimming)
590  {
591  fdo |= (ExpandMode & EXPAND_GLOBBING);
592  *dp++ = CHAR_MAGIC;
593  }
594 
595  break;
596 
597 /*
598  * Check for [^...
599  */
600 
601  case CHAR_NOT:
602  if (((ExpandMode & (EXPAND_PATTERN | EXPAND_GLOBBING))
603  || trimming) &&
604  ((dp[-1] == CHAR_OPEN_BRACKETS) &&
605  (dp[-2] == CHAR_MAGIC)))
606  *dp++ = CHAR_MAGIC;
607  break;
608 
609  case CHAR_TILDE:
610  if (((ExpandMode & EXPAND_TILDE) &&
611  (dp == XStart (ds))) ||
612  (!(ExpandMode & EXPAND_SPLITIFS) &&
613  (dp[-1] == '=' || dp[-1] == ':')))
614  {
615  fdo |= EXPAND_TILDE;
616  *dp++ = CHAR_MAGIC;
617  }
618 
619  break;
620  }
621  }
622 
623  else
624  QuoteStatus &= ~~QUOTE_TEMP; /* undo temporary */
625 
626  word = 1;
627  *dp++ = (char)c; /* save output char */
628  }
629  }
630 }
631 
632 /*
633  * Prepare to generate the string returned by ${} substitution.
634  */
635 
637  char *name,
638  int stype,
639  int Index)
640 {
641  int c;
642  int type;
643 
644 /* Handle ${#*|@}
645  * ${#name[*]}
646  * ${#name[value]}
647  *
648  * String length or argc
649  */
650 
651  if ((*name == '#') && ((c = name[1]) != 0))
652  {
653  if ((c == '*') || (c == '@'))
654  c = ParameterCount - 1;
655 
656  else if (Index < 0)
657  c = CountVariableArraySize (name + 1);
658 
659  else
660  c = strlen (GetVariableArrayAsString (name + 1, Index, FALSE));
661 
662  xp->str = StringCopy (IntegerToString (c));
663  return XSUB;
664  }
665 
666  c = *name;
667 
668 /* Handle ${*|@}
669  * ${*|@[*|@]}
670  *
671  * Use Parameter list
672  */
673 
674  if (c == '*' || c == '@')
675  {
676  if (ParameterCount == 0)
677  {
678  xp->str = null;
679  type = XSUB;
680  }
681 
682  else
683  {
684  xp->u.strv = ParameterArray + 1 + ((Index >= 0) ? Index : 0);
685  xp->str = *(xp->u.strv++);
686  xp->split = C2bool (c == '@'); /* $@ */
687  type = XARG;
688  }
689  }
690 
691 /* ${name[*|@]} */
692 
693  else if (Index < 0)
694  {
695 
696 /* Build list of values */
697 
698  if (isdigit (*name))
699  {
700  for (c = 0; isdigit (*name) && (c < 1000); name++)
701  c = c * 10 + *name - '0';
702 
703  xp->u.strv = (c <= ParameterCount) ? ParameterArray + c
704  : NOWORDS;
705  }
706 
707  else
708  {
709  GVAV_Name = name;
712  xp->u.strv = WordBlockSize (GVAV_WordList)
714  GVAV_WordList))
715  : NOWORDS;
716  }
717 
718 /* Set up list. Check to see if there any any entries */
719 
720  if (xp->u.strv == NOWORDS)
721  {
722  xp->str = null;
723  type = XSUB;
724  }
725 
726  else
727  {
728  xp->str = *(xp->u.strv++);
729  xp->split = C2bool (Index == -2); /* ${name[@]} */
730  type = XARG;
731  }
732  }
733 
734 /* ${name[num]} */
735 
736  else
737  {
738  xp->str = GetVariableArrayAsString (name, Index, TRUE);
739  type = XSUB;
740  }
741 
742  c = stype & 0x7F;
743 
744 /* test the compiler's code generator */
745 
746  if ((c == CHAR_MATCH_END) || (c == CHAR_MATCH_START) ||
747  (((stype & CHAR_MAGIC) ? (*xp->str == 0)
748  : (xp->str == null))
749  ? (c == '=') || (c == '-') || (c == '?')
750  : (c == '+')))
751  type = XBASE; /* expand word instead of variable value */
752 
753 /* Check for unset value */
754 
755  if ((type != XBASE) && FL_TEST (FLAG_UNSET_ERROR) &&
756  (xp->str == null) && (c != '+'))
757  ShellErrorMessage ("unset variable %s", name);
758 
759  return type;
760 }
761 
762 /*
763  * Run the command in $(...) and read its output.
764  */
765 
766 static int F_LOCAL CommandSubstitute (Expand *xp, char *cp)
767 {
768  Source *s;
769  C_Op *t;
770  FILE *fi;
771  jmp_buf ReturnPoint;
772  int localpipe;
773 
774  if ((localpipe = OpenAPipe ()) < 0)
775  return XBASE;
776 
777 /* Create a new environment */
778 
780  MemoryAreaLevel++;
781 
782  if (SetErrorPoint (ReturnPoint))
783  {
785  ReleaseMemoryArea (MemoryAreaLevel--); /* free old space */
787  S_close (localpipe, TRUE);
788  return XBASE;
789  }
790 
791 /* Create line buffer */
792 
794 
795 /* Parse the command */
796 
797  s = pushs (SSTRING);
798  s->str = cp;
799 
800 /* Check for $(<file) */
801 
802  if (((t = BuildParseTree (s)) != (C_Op *)NULL) &&
803  (t->type == TCOM) && (*t->args == NOWORD) &&
804  (*t->vars == NOWORD) && (t->ioact != (IO_Actions **)NULL))
805  {
806  IO_Actions *io = *t->ioact;
807  char *name;
808 
809 /* We don't need the pipe - so get rid of it */
810 
811  S_close (localpipe, TRUE);
812 
813 /* OK - terminate the created environment */
814 
816 
817  if ((io->io_flag & IOTYPE) != IOREAD)
818  ShellErrorMessage ("funny $() command");
819 
820  if ((localpipe = S_open (FALSE, name = ExpandAString (io->io_name,
821  EXPAND_TILDE),
822  O_RMASK)) < 0)
823  ShellErrorMessage ("cannot open %s", name);
824  }
825 
826 /* Execute the command */
827 
828  else
829  {
830  if (!ProcessCommandTree (t, localpipe))
831  longjmp (ReturnPoint, 1);
832 
833 
835  }
836 
837 /* Open the IO Stream */
838 
839  if ((fi = MyReOpenFile (ReMapIOHandler (localpipe),
840  sOpenReadMode)) == (FILE *)NULL)
841  ShellErrorMessage ("cannot open $() input");
842 
843 /*
844  * Free old memory area
845  */
846 
848  xp->u.file = fi;
849  return XCOM;
850 }
851 
852 /*
853  * perform #pattern and %pattern substitution in ${}
854  */
855 
856 static char * F_LOCAL TrimSubstitute (SubType *st, char *pat)
857 {
858  int mode = GM_SHORTEST;
859  char *pos;
860  char *tsp;
861  char *str = GetVariableArrayAsString (st->name, st->index,
862  TRUE);
863 
864 /*
865  * Switch on the match type
866  */
867 
868  switch (st->type & 0xff)
869  {
870  case CHAR_MATCH_START | CHAR_MAGIC:/* longest match at begin */
871  mode = GM_LONGEST;
872 
873  case CHAR_MATCH_START: /* shortest at begin */
874  if (GeneralPatternMatch (str, (unsigned char *)pat, FALSE, &pos, mode))
875  return pos;
876 
877  break;
878 
879  case CHAR_MATCH_END | CHAR_MAGIC:/* longest match at end */
880  mode = GM_LONGEST;
881 
882  case CHAR_MATCH_END: /* shortest match at end */
883  if (SuffixPatternMatch (str, pat, &pos, mode))
884  {
885  tsp = StringCopy (str);
886  tsp[pos - str] = 0;
887  return tsp;
888  }
889 
890  break;
891 
892  }
893 
894  return str; /* no match, return string */
895 }
896 
897 /*
898  * glob
899  * Name derived from V6's /etc/glob, the program that expanded filenames.
900  */
901 
903 {
904  char path [FFNAME_MAX];
905  int oldsize = WordBlockSize (*WordList);
906  int newsize;
907 
908 #if (OS_TYPE != OS_UNIX)
909  char *NewPattern; /* Search file name */
910  int CurrentDrive; /* Current drive */
911  int MaxDrives; /* Max drive */
912  int SelectedDrive; /* Selected drive */
913  int y_drive; /* Dummies */
914  unsigned char *DriveCharacter; /* Multi-drive flag */
915  char SDriveString[2];
916  char *EndPattern;
917 
918 /* Search all drives ? */
919 
920  if ((DriveCharacter = CheckForMultipleDrives (Pattern))
921  != (unsigned char *)NULL)
922  {
923  CurrentDrive = GetCurrentDrive ();
924  MaxDrives = SetCurrentDrive (CurrentDrive);
925  SDriveString[1] = 0;
926  EndPattern = WordScan (Pattern, 0);
927  NewPattern = GetAllocatedSpace ((EndPattern - Pattern) + 1);
928 
929 /* Scan the available drives */
930 
931  for (SelectedDrive = 1; SelectedDrive <= MaxDrives; ++SelectedDrive)
932  {
933  if (SetCurrentDrive (SelectedDrive) != -1)
934  {
935  y_drive = GetCurrentDrive ();
936  SetCurrentDrive (CurrentDrive);
937  }
938 
939  else
940  y_drive = -1;
941 
942 /* Check to see if the second diskette drive is really there */
943 
944  if ((GetNumberofFloppyDrives () < 2) && (SelectedDrive == 2))
945  continue;
946 
947 /* If the drive exists and is in our list - process it */
948 
949  *DriveCharacter = 0;
950  *SDriveString = GetDriveLetter (SelectedDrive);
951  strlwr (Pattern);
952 
953  if ((y_drive == SelectedDrive) &&
954  GeneralPatternMatch (SDriveString, Pattern, TRUE, (char **)NULL,
955  GM_ALL))
956  {
957  *DriveCharacter = CHAR_DRIVE;
958  *NewPattern = *SDriveString;
959  memcpy (NewPattern + 1, DriveCharacter,
960  ((unsigned char *)EndPattern - DriveCharacter) + 1);
961 
962  GlobAWord (path, path, NewPattern, WordList, FALSE);
963  }
964 
965  *DriveCharacter = CHAR_DRIVE;
966  }
967 
968  ReleaseMemoryCell (NewPattern);
969  }
970 
971 /*
972  * No special processing for drives
973  */
974 
975  else
977 #else
978 
979 /* UNIX has not drives. Goodie! */
980 
982 #endif
983 
984 /*
985  * Sort or something
986  */
987 
988  if ((newsize = WordBlockSize (*WordList)) == oldsize)
989  *WordList = AddWordToBlock (RemoveMagicMarkers ((unsigned char *)Pattern),
990  *WordList);
991 
992  else
993  qsort (&(*WordList)->w_words[oldsize], (size_t)(newsize - oldsize),
994  sizeof (char *), SortCompare);
995 }
996 
997 /*
998  * Recursive bit
999  */
1000 
1001 static void F_LOCAL GlobAWord (char *ds, /* dest path */
1002  char *dp, /* dest end */
1003  char *sp, /* source path */
1004  Word_B **WordList,/* output list */
1005  bool check) /* check dest existence */
1006 {
1007  char *EndFileName; /* next source component */
1008  char EndChar;
1009  char *CFileName;
1010  char *tdp;
1011  DIR *dirp;
1012  struct dirent *d;
1013  bool IgnoreCase = TRUE;
1014 
1015 /* End of source path ? */
1016 
1017  if (sp == (char *)NULL)
1018  {
1019  if (check && (!S_access (ds, F_OK)))
1020  return;
1021 
1023  return;
1024  }
1025 
1026  if ((dp > ds) && (!IsDriveCharacter (*(dp - 1))))
1027  *dp++ = CHAR_UNIX_DIRECTORY;
1028 
1029  while (IsPathCharacter (*sp))
1030  *(dp++) = *(sp++);
1031 
1032 /* Find end of current file name */
1033 
1034  if ((EndFileName = FindPathCharacter (sp)) != (char *)NULL)
1035  {
1036  *(EndFileName++) = 0;
1038  }
1039 
1040 #if (OS_TYPE != OS_UNIX)
1041  if ((tdp = strchr (sp, CHAR_DRIVE)) != (char *)NULL)
1042  {
1043  if (EndFileName != (char *)NULL)
1044  *(--EndFileName) = CHAR_UNIX_DIRECTORY;
1045 
1046  EndFileName = tdp;
1047  *(EndFileName++) = 0;
1048  EndChar = CHAR_DRIVE;
1049  }
1050 #endif
1051 
1052  *dp = 0;
1053 
1054  /* contains no pattern? */
1055 
1056  if (strchr (sp, CHAR_MAGIC) == NULL)
1057  {
1058  tdp = dp;
1059  CFileName = sp;
1060 
1061  while ((*(tdp++) = *(CFileName++)) != 0)
1062  continue;
1063 
1064  if (IsDriveCharacter (EndChar))
1065  {
1066  *(tdp - 1) = CHAR_DRIVE;
1067  *tdp = 0;
1068  }
1069 
1070  else
1071  --tdp;
1072 
1073  GlobAWord (ds, tdp, EndFileName, WordList, check);
1074  }
1075 
1076  else
1077  {
1078 
1079 /* Check for drive letter and append a . to get the current directory */
1080 
1081  if ((strlen (ds) == 2) && IsDriveCharacter (*(ds + 1)))
1082  {
1083  *(ds + 2) = CHAR_PERIOD;
1084  *(ds + 3) = 0;
1085  }
1086 
1087 /* Scan the directory */
1088 
1089  if ((dirp = opendir ((*ds == 0) ? CurrentDirLiteral
1090  : ds)) != (DIR *)NULL)
1091  {
1092  if ((IsHPFSFileSystem ((*ds == 0) ? CurrentDirLiteral : ds)) &&
1094  IgnoreCase = FALSE;
1095 
1096  while ((d = readdir (dirp)) != (struct dirent *)NULL)
1097  {
1098  CFileName = d->d_name;
1099 
1100 /*
1101  * Ignore . * ..
1102  */
1103 
1104  if ((*CFileName == CHAR_PERIOD) &&
1105  ((*(CFileName + 1) == 0) ||
1106  ((*(CFileName + 1) == CHAR_PERIOD) &&
1107  (*(CFileName + 2) == 0))))
1108  continue;
1109 
1110 /*
1111  * Ignore . files unless match starts with a dot.
1112  */
1113 
1114  if ((*CFileName == CHAR_PERIOD && *sp != CHAR_PERIOD) ||
1115  !GeneralPatternMatch (CFileName, (unsigned char *)sp,
1116  IgnoreCase, (char **)NULL, GM_ALL))
1117  continue;
1118 
1119  tdp = dp;
1120  while ((*tdp++ = *CFileName++) != 0)
1121  continue;
1122 
1123  --tdp;
1124 
1125  GlobAWord (ds, tdp, EndFileName, WordList,
1126  C2bool (EndFileName != NULL));
1127  }
1128 
1129  closedir (dirp);
1130  }
1131  }
1132 
1133  if (EndFileName != NULL)
1134  *(--EndFileName) = EndChar;
1135 }
1136 
1137 /*
1138  * remove MAGIC from string
1139  */
1140 
1141 static char * F_LOCAL RemoveMagicMarkers (unsigned char *Word)
1142 {
1143  unsigned char *dp, *sp;
1144 
1145  for (dp = sp = Word; *sp != 0; sp++)
1146  {
1147  if (*sp != CHAR_MAGIC)
1148  *dp++ = *sp;
1149  }
1150 
1151  *dp = 0;
1152  return (char *)Word;
1153 }
1154 
1155 /*
1156  * tilde expansion
1157  *
1158  * based on a version by Arnold Robbins
1159  *
1160  * Think this needs Expanable strings!!
1161  */
1162 
1163 static char * F_LOCAL TildeSubstitution (unsigned char *acp)
1164 {
1165  unsigned c;
1166  unsigned char path[FFNAME_MAX];
1167  unsigned char *cp = acp;
1168  unsigned char *wp = path;
1169  unsigned char *dp;
1170 
1171  while (TRUE)
1172  {
1173  while (TRUE)
1174  {
1175  if ((c = *cp++) == 0)
1176  {
1177  *wp = 0;
1178  ReleaseMemoryCell ((void *)acp);
1179  return StringCopy ((char *)path);
1180  }
1181 
1182  else if ((c == CHAR_MAGIC) && (*cp == CHAR_TILDE))
1183  break;
1184 
1185  else
1186  *wp++ = (char)c;
1187  }
1188 
1189  dp = NULL; /* no output substitution */
1190 
1191  /*
1192  * ~ or ~/
1193  */
1194 
1195  if ((cp[1] == 0) || IsPathCharacter (cp[1]) || (IsDriveCharacter (cp[1])))
1196  {
1197  dp = (unsigned char *)GetVariableAsString (HomeVariableName, FALSE);
1198  cp += 1;
1199  }
1200 
1201  else if ((cp[1] == '+') && (IsPathCharacter (cp[2]) ||
1202  IsDriveCharacter (cp[2]) || (cp[2] == 0)))
1203  {
1204  dp = (unsigned char *)GetVariableAsString (PWDVariable, FALSE);
1205  cp += 2;
1206  }
1207 
1208  else if ((cp[1] == '-') && (IsPathCharacter (cp[2]) ||
1209  IsDriveCharacter (cp[2]) || (cp[2] == 0)))
1210  {
1211  dp = (unsigned char *)GetVariableAsString (OldPWDVariable, FALSE);
1212  cp += 2;
1213  }
1214 
1215 /* substitute */
1216 
1217  if (dp != NULL)
1218  {
1219  while (*dp != 0)
1220  *wp++ = *dp++;
1221 
1222 /* Remove double //'s on directories */
1223 
1224  if (IsPathCharacter (*(wp - 1)) && IsPathCharacter (*cp))
1225  cp++;
1226  }
1227  }
1228 }
1229 
1230 /*
1231  * Sort Compare
1232  */
1233 
1234 int SortCompare (const void *a1, const void *a2)
1235 {
1236  return strcmp (*((char **)a1), *((char **)a2));
1237 }
1238 
1239 /*
1240  * Return the position of Prefix StopWord in the quoted string
1241  */
1242 
1243 static char * F_LOCAL WordScan (char *QString, int StopWord)
1244 {
1245  int VarSubNest = 0;
1246 
1247  while (TRUE)
1248  {
1249  switch (*(QString++))
1250  {
1251  case WORD_EOS:
1252  return QString;
1253 
1254  case WORD_CHAR:
1255  case WORD_QCHAR:
1256  case WORD_QTCHAR:
1257  QString++;
1258  break;
1259 
1260  case WORD_OQUOTE:
1261  case WORD_ODQUOTE:
1262  case WORD_CQUOTE:
1263  case WORD_CDQUOTE:
1264  break;
1265 
1266  case WORD_OARRAY:
1267  VarSubNest++;
1268  break;
1269 
1270  case WORD_CARRAY:
1271  if ((StopWord == WORD_CARRAY) && (VarSubNest == 0))
1272  return QString;
1273 
1274  VarSubNest--;
1275  break;
1276 
1277  case WORD_OSUBST:
1278  VarSubNest++;
1279 
1280  while (*(QString++) != 0)
1281  continue;
1282 
1283  if (*QString != WORD_CSUBST)
1284  QString++;
1285 
1286  break;
1287 
1288  case WORD_CSUBST:
1289  if ((StopWord == WORD_CSUBST) && (VarSubNest == 0))
1290  return QString;
1291 
1292  VarSubNest--;
1293  break;
1294 
1295  case WORD_COMSUB:
1296  case WORD_OMATHS:
1297  while (*(QString++) != 0)
1298  continue;
1299 
1300  break;
1301  }
1302  }
1303 }
1304 
1305 /*
1306  * Maths substitute - convert $((....)) to a number.
1307  */
1308 
1309 static int F_LOCAL MathsSubstitute (Expand *xp, char *sp)
1310 {
1311  char DecimalString[12];
1312  char *esp;
1313 
1314  esp = substitute (sp, 0);
1315  sprintf (DecimalString, "%lu", EvaluateMathsExpression (esp));
1316  xp->str = StringCopy (DecimalString);
1317  return XSUB;
1318 }
1319 
1320 
1321 /*
1322  * Check for multi_drive prefix
1323  */
1324 
1325 #if (OS_TYPE != OS_UNIX)
1326 static unsigned char * F_LOCAL CheckForMultipleDrives (unsigned char *prefix)
1327 {
1328  if ((*(prefix++) != CHAR_MAGIC) || (!IS_WildCard (*prefix)))
1329  return (unsigned char *)NULL;
1330 
1331  if (*prefix != CHAR_OPEN_BRACKETS)
1332  return *(prefix + 1) == CHAR_DRIVE ? prefix + 1 : (unsigned char *)NULL;
1333 
1334  while (*prefix && (*prefix != CHAR_CLOSE_BRACKETS))
1335  {
1336  if ((*prefix == CHAR_MATCH_RANGE) && (*(prefix + 1)))
1337  ++prefix;
1338 
1339  ++prefix;
1340  }
1341 
1342  return (*prefix && (*(prefix + 1) == CHAR_DRIVE))
1343  ? prefix + 1 : (unsigned char *)NULL;
1344 }
1345 #endif
1346 
1347 /*
1348  * A command tree is to be expanded for stdin
1349  */
1350 
1351 static bool F_LOCAL ProcessCommandTree (C_Op *outtree, int localpipe)
1352 {
1353  long s_flags = flags;
1354  Break_C *S_RList = Return_List; /* Save loval links */
1355  Break_C *S_BList = Break_List;
1356  Break_C *S_SList = SShell_List;
1357  bool s_ProcessingEXECCommand = ProcessingEXECCommand;
1358  int Local_depth = Execute_stack_depth++;
1359  jmp_buf ReturnPoint;
1360  int ReturnValue;
1361  FunctionList *s_CurrentFunction = CurrentFunction;
1362  Break_C bc;
1363 
1364 /* Create the pipe to read the output from the command string */
1365 
1366  S_dup2 (localpipe, 1);
1367 
1371 
1372 /* Set up new environment */
1373 
1374  ReturnValue = CreateGlobalVariableList (FLAGS_NONE);
1375 
1376  if ((ReturnValue != -1) && (!SetErrorPoint (ReturnPoint)))
1377  {
1378  Return_List = (Break_C *)NULL;
1379  Break_List = (Break_C *)NULL;
1380 
1381 /* Clear execute flags. */
1382 
1385 
1386 /* Parse the line and execute it */
1387 
1388  if (setjmp (bc.CurrentReturnPoint) == 0)
1389  {
1390  bc.NextExitLevel = SShell_List;
1391  SShell_List = &bc;
1392  ReturnValue = ExecuteParseTree (outtree, NOPIPE, NOPIPE, 0);
1393  }
1394 
1395 /* Parse error */
1396 
1397  else
1398  ReturnValue = -1;
1399 
1400 /* Clean up any files around we nolonger need */
1401 
1403  }
1404 
1405  else
1406  ReturnValue = -1;
1407 
1408 /* Restore environment */
1409 
1410  RestoreEnvironment (ReturnValue, Local_depth);
1411 
1412 /* Free old space */
1413 
1415 
1416 /* Ok - completed processing - restore environment and read the pipe */
1417 
1418  ProcessingEXECCommand = s_ProcessingEXECCommand;
1419  flags = s_flags;
1420  Return_List = S_RList;
1421  Break_List = S_BList;
1422  SShell_List = S_SList;
1423  CurrentFunction = s_CurrentFunction;
1424 
1425 /* Move pipe to start so we can read it */
1426 
1427  lseek (localpipe, 0L, SEEK_SET);
1428  return C2bool (ReturnValue != -1);
1429 }
1430 
1431 /* (pc@hillside.co.uk)
1432  * I have decided to `fudge' alternations by picking up the compiled command
1433  * tree and working with it recursively to generate the set of arguments.
1434  * This has the advantage of making a single discrete change to the code
1435  *
1436  * This routine calls itself recursively
1437  *
1438  * a) Scan forward looking for { building the output string if none found
1439  * then call expand - and exit
1440  * b) When { found, scan forward finding the end }
1441  * c) Add first alternate to output string
1442  * d) Scan for the end of the string copying into output
1443  * e) Call routine with new string
1444  *
1445  * Major complication is quoting
1446  */
1447 
1448 static void F_LOCAL AlternationExpand (char *cp, /* input word */
1449  Word_B **WordList,/* output words */
1450  int ExpandMode)/* DO* flags */
1451 {
1452  char *srcp = cp;
1453  char *left; /* destination string of left hand side */
1454  char *leftend; /* end of left hand side */
1455  char *alt; /* start of alterate section */
1456  char *altend; /* end of alternate section */
1457  char *ap; /* working pointer */
1458  char *right; /* right hand side */
1459  char *rp; /* used to copy right-hand side */
1460  size_t maxlen; /* max string length */
1461 
1462  maxlen = WordScan (cp, 0) - cp;
1463  left = GetAllocatedSpace (maxlen);
1464  leftend = left;
1465 
1466  if (AlternationScan (&srcp, &leftend, CHAR_OPEN_BRACES, 0) == 0)
1467  {
1468  ExpandAWord (cp, WordList, ExpandMode & EXPAND_NOALTS);
1470  return;
1471  }
1472 
1473 /* We have a alternation section */
1474 
1475  alt = GetAllocatedSpace (maxlen);
1476  altend = alt;
1477  srcp += 2;
1478 
1479  if (AlternationScan (&srcp, &altend, CHAR_CLOSE_BRACES, 1) == 0)
1480  {
1483  PrintErrorMessage ("Mis-matched {}.");
1484  }
1485 
1486  *(altend++) = WORD_CHAR;
1487  *(altend++) = ',';
1488  *altend = WORD_EOS;
1489 
1490 /* finally we may have a right-hand side */
1491 
1492  right = srcp + 2;
1493 
1494 /* glue the bits together making a new string */
1495 
1496  for (srcp = alt; *srcp != WORD_EOS;)
1497  {
1498  ap = leftend;
1499 
1500  if (AlternationScan (&srcp, &ap, ',', -1) == 0)
1501  {
1504  PrintErrorMessage ("Missing comma.");
1505  }
1506 
1507  srcp += 2;
1508  rp = right;
1509  AlternationScan (&rp, &ap, WORD_EOS, 0);
1510  AlternationExpand (left, WordList, ExpandMode);
1511  }
1512 
1515  return;
1516 }
1517 
1518 /*
1519  * Scan the tree
1520  */
1521 
1522 static int F_LOCAL AlternationScan (char **cpp,/* source pointer */
1523  char **dpp,/* destination pointer */
1524  char endc, /* last character look for */
1525  int bal)
1526 {
1527  char *cp, *dp;
1528  bool QuoteStatus = FALSE;
1529  int balance = 0;
1530  bool UseBalance = FALSE;
1531  int VarSubNest = 0;
1532 
1533  if (bal)
1534  {
1535  UseBalance = TRUE;
1536  balance = (bal < 1) ? 0 : 1;
1537  }
1538 
1539  cp = *cpp;
1540  dp = *dpp;
1541 
1542  while (*cp != WORD_EOS)
1543  {
1544  switch (*cp)
1545  {
1546  case WORD_CHAR:
1547  if (QuoteStatus)
1548  {
1549  if (cp[1] == CHAR_CLOSE_BRACKETS)
1550  QuoteStatus = FALSE;
1551  }
1552 
1553  else if (!QuoteStatus)
1554  {
1555  if (cp[1] == CHAR_OPEN_BRACKETS)
1556  QuoteStatus = TRUE;
1557 
1558  else
1559  {
1560  if (UseBalance)
1561  {
1562  if (cp[1] == CHAR_OPEN_BRACES)
1563  balance++;
1564 
1565  if (cp[1] == CHAR_CLOSE_BRACES)
1566  balance--;
1567  }
1568 
1569  if ((cp[1] == endc) && (balance == 0))
1570  {
1571  *dp = WORD_EOS;
1572  *dpp = dp;
1573  *cpp = cp;
1574  return 1;
1575  }
1576  }
1577  }
1578 
1579  case WORD_QCHAR:
1580  case WORD_QTCHAR:
1581  *(dp++) = *(cp++);
1582  *(dp++) = *(cp++);
1583  break;
1584 
1585  case WORD_OQUOTE:
1586  case WORD_ODQUOTE:
1587  QuoteStatus = TRUE;
1588  *(dp++) = *(cp++);
1589  break;
1590 
1591  case WORD_CQUOTE:
1592  case WORD_CDQUOTE:
1593  QuoteStatus = FALSE;
1594  *(dp++) = *(cp++);
1595  break;
1596 
1597  case WORD_OARRAY:
1598  VarSubNest++;
1599  *(dp++) = *(cp++);
1600  break;
1601 
1602  case WORD_OSUBST:
1603  VarSubNest++;
1604 
1605  while ((*(dp++) = *(cp++)))
1606  continue;
1607 
1608  if (*cp != WORD_CSUBST)
1609  *(dp++) = *(cp++);
1610 
1611  break;
1612 
1613  case WORD_CSUBST:
1614  case WORD_CARRAY:
1615  *(dp++) = *(cp++);
1616  VarSubNest--;
1617  break;
1618 
1619  case WORD_COMSUB:
1620  case WORD_OMATHS:
1621  while ((*(dp++) = *(cp++)))
1622  continue;
1623 
1624  break;
1625  }
1626  }
1627 
1628  *dp = WORD_EOS;
1629  *cpp = cp;
1630  *dpp = dp;
1631 
1632  return 0;
1633 }
1634 
1635 /*
1636  * Handle Array Value between WORD_OARRAY & WORD_CARRAY
1637  * Return the array index (-1 == [*]).
1638  * (-2 == [@]).
1639  */
1640 
1641 static int F_LOCAL HandleArrayValue (char *name,
1642  char **InputString,
1643  int ExpandMode)
1644 {
1645  /* Start after the Open Array */
1646  char *End = WordScan ((*InputString) + 1, WORD_CARRAY);
1647  size_t Length = (End - *InputString) - 1;
1648  char *ExpWord;
1649  Word_B *WordList = (Word_B *)NULL;
1650  long value;
1651 
1652 /* Build a copy of the substring to expand */
1653 
1654  ExpWord = memcpy (GetAllocatedSpace (Length), *InputString + 1, Length);
1655  ExpWord[Length - 1] = WORD_EOS;
1656 
1657  ExpandMode &= ~(EXPAND_GLOBBING | EXPAND_CONVERT | EXPAND_NOALTS);
1658  ExpandAWord (ExpWord, &WordList, ExpandMode);
1659 
1660 /* Check for valid value */
1661 
1662  if (WordBlockSize (WordList) != 1)
1663  ShellErrorMessage (LIT_BadArray, "too many words");
1664 
1665 /*
1666  * There are a couple of special cases:
1667  *
1668  * ${#name[*]}
1669  * ${name[*]}
1670  * ${name[@]}
1671  */
1672 
1673  if (!strcmp (WordList->w_words[0], "*"))
1674  value = -1L;
1675 
1676  else if (!strcmp (WordList->w_words[0], "@") &&
1677  ((*name != '#') || (*(name + 1) == 0)))
1678  value = -2L;
1679 
1680 /*
1681  * Otherwise, get the array value
1682  */
1683 
1684  else
1685  {
1686  value = EvaluateMathsExpression (WordList->w_words[0]);
1687 
1688  if ((value < 0) || (value > INT_MAX))
1690  }
1691 
1692  *InputString = End;
1693  return (int)value;
1694 }
1695 
1696 /*
1697  * Check for Unset Variable
1698  */
1699 
1700 static void F_LOCAL CheckForUnset (char *name, int Index)
1701 {
1702  if ((FL_TEST (FLAG_UNSET_ERROR)) &&
1703  (GetVariableArrayAsString (name, Index, FALSE) == null))
1704  ShellErrorMessage ("%s: unset variable", name);
1705 }
1706 
1707 
1708 /*
1709  * TWALK - Build list of the values of an Environment Variable
1710  */
1711 
1712 static void BuildVariableEntryList (const void *key, VISIT visit, int level)
1713 {
1714  VariableList *vp = (*(VariableList **)key);
1715 
1716  if (((visit == postorder) || (visit == leaf)) &&
1717  (strcmp (GVAV_Name, vp->name) == 0))
1719  vp->index,
1720  TRUE),
1721  GVAV_WordList);
1722 }
1723 
1724 /*
1725  * Return the number of floppy disks
1726  */
1727 
1728 #if (OS_TYPE == OS_OS2)
1729 static int F_LOCAL GetNumberofFloppyDrives (void)
1730 {
1731  BYTE nflop = 1;
1732 
1733 # if (OS_SIZE == OS_16)
1734  DosDevConfig (&nflop, DEVINFO_FLOPPY, 0);
1735 # else
1736  DosDevConfig (&nflop, DEVINFO_FLOPPY);
1737 # endif
1738 
1739  return nflop;
1740 }
1741 #endif
1742 
1743 /* DOS Version */
1744 
1745 #if (OS_TYPE == OS_DOS)
1747 {
1748 # if defined (__TURBOC__)
1749 
1750  return ((biosequip () & 0x00c0) >> 6) + 1;
1751 
1752 # elif defined (__EMX__)
1753 
1754  union REGS r;
1755 
1756  SystemInterrupt (0x11, &r, &r);
1757  return ((r.x.REG_AX & 0x00c0) >> 6) + 1;
1758 
1759 # else
1760 
1761  return ((_bios_equiplist () & 0x00c0) >> 6) + 1;
1762 
1763 # endif
1764 }
1765 #endif
1766 
1767 /* NT Version */
1768 
1769 #if (OS_TYPE == OS_NT)
1770 static int F_LOCAL GetNumberofFloppyDrives (void)
1771 {
1772  char szNewDrive[4];
1773  DWORD dwLogicalDrives = GetLogicalDrives();
1774  int LastTest = 0;
1775  int i;
1776 
1777  strcpy (szNewDrive, "x:\\");
1778 
1779 /* Look at each drive until we find a non-floppy which exists */
1780 
1781  for (i = 0; i < 25; i++)
1782  {
1783  if (dwLogicalDrives & (1L << i))
1784  {
1785  szNewDrive[0] = i + 'A';
1786 
1787  if (GetDriveType (szNewDrive) != DRIVE_REMOVABLE)
1788  break;
1789 
1790  LastTest = i + 1;
1791  }
1792  }
1793 
1794  return LastTest;
1795 }
1796 #endif
#define strlwr
Definition: Utility.h:162
rp
Definition: action.c:992
cp
Definition: action.c:1035
int level
Definition: afm2pl.c:1694
int source[257]
Definition: afm2tfm.c:928
#define type(a)
Definition: aptex-macros.h:171
#define name
#define subtype(a)
Definition: aptex-macros.h:172
#define null
Definition: aptex-macros.h:127
#define mode
Definition: aptex-macros.h:510
#define check(T, S)
@ SSTRING
Definition: cmscgats.c:55
#define ap
@ FALSE
Definition: dd.h:101
@ TRUE
Definition: dd.h:102
#define F_OK
Definition: defs.h:34
int w
Definition: dviconv.c:26
int strcmp()
Definition: coll.cpp:143
char * strcpy()
#define yylval
#define xp
#define a1
#define a2
#define s
Definition: afcover.h:80
#define t
Definition: afcover.h:96
#define c(n)
Definition: gpos-common.c:150
#define d(n)
Definition: gpos-common.c:151
#define bc
Definition: gsftopk.c:501
#define strchr
Definition: gsftopk.c:59
#define memcpy(d, s, n)
Definition: gsftopk.c:64
#define SEEK_SET
Definition: jmemansi.c:26
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
sizeof(AF_ModuleRec)
#define EOF
Definition: afmparse.c:59
@ right
Definition: annotate.c:15
static unsigned char pat[8]
Definition: pkfont.c:194
unsigned char BYTE
Definition: sfnt.h:34
#define INT_MAX
Definition: c-minmax.h:53
struct dirent * readdir(DIR *dirp)
Definition: dirent.c:138
int closedir(DIR *dirp)
Definition: dirent.c:123
DIR * opendir(char *fname)
Definition: dirent.c:60
#define getc
Definition: line.c:39
#define lseek
Definition: win32lib.h:83
static void qst(char *base, char *max)
Definition: qsort.c:112
#define prefix
Definition: cwebboot.c:154
#define sprintf
Definition: snprintf.c:44
#define isdigit(c)
Definition: snprintf.c:177
#define qsort
Definition: includes.h:72
const int * pos
Definition: combiners.h:905
#define LINE_MAX
Definition: mkind.h:326
unsigned int DWORD
Definition: mktexlib.h:49
float x
Definition: cordic.py:15
cpp
Definition: cutout.py:14
constexpr auto visit(Visitor &&visitor, Vs &&... vs) -> decltype((detail::all(lib::array< bool, sizeof...(Vs)>{{!vs.valueless_by_exception()...}}) ?(void) 0 :throw_bad_variant_access()), detail::visitation::variant::visit_value(lib::forward< Visitor >(visitor), lib::forward< Vs >(vs)...))
Definition: variant.hpp:2697
union value value
Definition: obx.h:44
#define max(a, b)
Definition: pbmto4425.c:11
unsigned short word
Definition: picttoppm.c:64
#define res(length)
Definition: picttoppm.c:287
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst st
int r
Definition: ppmqvga.c:68
static void EndChar(void)
#define flags
static unsigned char * tsp
Definition: repack.c:40
lft_cell * left
Definition: routines.h:73
RETTYPE mp_ptr mp_size_t mp_srcptr dp
Definition: sec_div.c:70
static _ts_NODE_t * balance(_ts_NODE_t **, _ts_NODE_t *, int)
Definition: sh12.c:338
static void BuildVariableEntryList(const void *, VISIT, int)
Definition: sh4.c:1712
int SortCompare(const void *a1, const void *a2)
Definition: sh4.c:1234
static int near CommandSubstitute(Expand *, char *)
Definition: sh4.c:766
#define XARG
Definition: sh4.c:106
static unsigned char *near CheckForMultipleDrives(unsigned char *)
Definition: sh4.c:1326
static void near ExpandAWord(char *, Word_B **, int)
Definition: sh4.c:280
char * ExpandAString(char *cp, int ExpandMode)
Definition: sh4.c:244
static char * GVAV_Name
Definition: sh4.c:148
#define XBASE
Definition: sh4.c:103
#define QUOTE_NONE
Definition: sh4.c:113
static char *near TrimSubstitute(SubType *, char *)
Definition: sh4.c:856
static char *near WordScan(char *, int)
Definition: sh4.c:1243
struct Expand Expand
#define QUOTE_TEMP
Definition: sh4.c:115
static int near MathsSubstitute(Expand *, char *)
Definition: sh4.c:1309
#define XARGSEP
Definition: sh4.c:105
static void near AlternationExpand(char *, Word_B **, int)
Definition: sh4.c:1448
#define XCOM
Definition: sh4.c:107
static int near GetNumberofFloppyDrives(void)
Definition: sh4.c:1746
static char *near TildeSubstitution(unsigned char *)
Definition: sh4.c:1163
static void near ExpandGlobCharacters(char *, Word_B **)
Definition: sh4.c:902
static int near HandleArrayValue(char *, char **, int)
Definition: sh4.c:1641
static int near AlternationScan(char **, char **, char, int)
Definition: sh4.c:1522
#define XSUB
Definition: sh4.c:104
char ** ExpandWordList(char **ap, int ExpandMode, ExeMode *PMode)
Definition: sh4.c:178
#define QUOTE_INSIDE
Definition: sh4.c:114
static void near GlobAWord(char *, char *, char *, Word_B **, bool)
Definition: sh4.c:1001
char * substitute(char *cp, int ExpandMode)
Definition: sh4.c:158
static int near VariableSubstitute(Expand *, char *, int, int)
Definition: sh4.c:636
static char *near RemoveMagicMarkers(unsigned char *)
Definition: sh4.c:1141
struct SubType SubType
static char * PNullNSet
Definition: sh4.c:147
static Word_B * GVAV_WordList
Definition: sh4.c:151
static bool near ProcessCommandTree(C_Op *, int)
Definition: sh4.c:1351
char * ExpandOneStringFirstComponent(char *cp, int ExpandMode)
Definition: sh4.c:258
static void near CheckForUnset(char *, int)
Definition: sh4.c:1700
#define str(s)
Definition: sh6.c:399
Break_C * Break_List
Definition: sh6.c:144
char * GetVariableAsString(char *, bool)
Definition: sh1.c:3578
char CurrentDirLiteral[]
Definition: sh6.c:201
char * XClose(XString *, unsigned char *)
Definition: sh5.c:1337
#define FL_CLEAR(x)
Definition: sh.h:1707
char ** ParameterArray
Definition: sh6.c:117
#define F_LOCAL
Definition: sh.h:121
int MemoryAreaLevel
Definition: sh6.c:379
#define CHAR_TILDE
Definition: sh.h:1025
#define XResetOffset(xs, n)
Definition: sh.h:1215
#define FindPathCharacter(a)
Definition: sh.h:1142
char * GetVariableArrayAsString(char *, int, bool)
Definition: sh1.c:3587
#define CHAR_NEW_LINE
Definition: sh.h:1007
#define EXPAND_TILDE
Definition: sh.h:1485
#define PARSE_WORD
Definition: sh.h:1286
#define IS_WildCard(c)
Definition: sh.h:1092
#define EXPAND_SPLITIFS
Definition: sh.h:1482
#define CHAR_MATCH_RANGE
Definition: sh.h:1039
int S_close(int, bool)
Definition: sh8.c:448
#define FLAG_NO_EXECUTE
Definition: sh.h:1723
#define SWSTR
Definition: sh.h:1365
#define FL_TEST(x)
Definition: sh.h:1705
void * VariableTree
Definition: sh6.c:190
#define IsPathCharacter(a)
Definition: sh.h:1140
#define CHAR_PERIOD
Definition: sh.h:1042
void twalk(const void *, void(*)(const void *, VISIT, int))
#define GM_ALL
Definition: sh.h:1774
int Execute_stack_depth
Definition: sh6.c:188
char * IntegerToString(int)
Definition: sh1.c:1171
#define WORD_OQUOTE
Definition: sh.h:1270
void XCheck(XString *, unsigned char **)
Definition: sh5.c:1321
#define TCOM
Definition: sh.h:1241
#define IsDriveCharacter(a)
Definition: sh.h:1137
void * GetAllocatedSpace(size_t)
Definition: sh1.c:1241
unsigned int GetCurrentDrive(void)
Definition: sh8.c:1060
unsigned int ShellGlobalFlags
Definition: sh6.c:130
#define C2bool(c)
Definition: sh.h:1476
int ExecuteParseTree(C_Op *, int, int, int)
Definition: sh3.c:265
bool S_access(char *, int)
Definition: sh8.c:1730
#define WORD_OSUBST
Definition: sh.h:1274
int ScanNextToken(int)
Definition: sh5.c:153
void QuitCurrentEnvironment(void)
Definition: sh1.c:1126
int ParameterCount
Definition: sh6.c:118
#define FFNAME_MAX
Definition: sh.h:981
#define EP_CONVERT
Definition: sh.h:1977
#define O_RMASK
Definition: sh.h:1106
#define WORD_CQUOTE
Definition: sh.h:1271
char HomeVariableName[]
Definition: sh6.c:204
#define EP_NOEXPAND
Definition: sh.h:1973
#define CHAR_ASSIGN
Definition: sh.h:1054
#define WORD_OMATHS
Definition: sh.h:1276
void S_fclose(FILE *, bool)
Definition: sh8.c:544
void ClearExtendedLineFile(void)
Definition: system.c:946
#define CHAR_MATCH_END
Definition: sh.h:1034
#define FLAGS_NONE
Definition: sh.h:1738
#define WORD_QCHAR
Definition: sh.h:1267
bool ProcessingEXECCommand
Definition: sh6.c:123
#define EXPAND_GLOBBING
Definition: sh.h:1483
#define WORD_OARRAY
Definition: sh.h:1277
char * PWDVariable
Definition: sh6.c:222
void RestoreEnvironment(int, int)
Definition: sh3.c:1120
void PrintErrorMessage(char *,...)
Definition: sh1.c:1053
#define WORD_ODQUOTE
Definition: sh.h:1272
#define WORD_CHAR
Definition: sh.h:1266
void ReleaseMemoryArea(int)
Definition: sh1.c:2243
void SetVariableArrayFromString(char *, int, char *)
Definition: sh1.c:3424
#define FLAG_ECHO_INPUT
Definition: sh.h:1728
#define WORD_CSUBST
Definition: sh.h:1275
#define FLAGS_ALTERNATION
Definition: sh.h:1748
char * sOpenReadMode
Definition: sh6.c:290
#define EXPAND_PATTERN
Definition: sh.h:1484
#define CHAR_MATCH_ANY
Definition: sh.h:1056
C_Op * BuildParseTree(Source *)
Definition: sh2.c:886
long EvaluateMathsExpression(char *)
Definition: sh11.c:785
#define FLAG_EXIT_ON_ERROR
Definition: sh.h:1717
ShellFileEnvironment e
Definition: sh6.c:388
#define NOWORD
Definition: sh.h:1149
#define EP_NOWORDS
Definition: sh.h:1978
#define CHAR_OPEN_BRACES
Definition: sh.h:1021
#define CHAR_OPEN_BRACKETS
Definition: sh.h:1023
void ReleaseMemoryCell(void *)
Definition: sh1.c:2141
#define PATH_TO_DOS(x)
Definition: sh.h:1114
#define XStart(xs)
Definition: sh.h:1213
#define EXPAND_NOALTS
Definition: sh.h:1487
int WordBlockSize(Word_B *)
Definition: system.c:1779
int S_open(bool, char *, int)
Definition: sh8.c:253
#define IOTYPE
Definition: sh.h:1651
#define SetErrorPoint(a)
Definition: sh.h:1678
int SetCurrentDrive(unsigned int)
Definition: system.c:926
#define CHAR_MATCH_ALL
Definition: sh.h:1036
char * StringCopy(char *)
Definition: sh1.c:1325
void CreateNewEnvironment(void)
Definition: sh1.c:1100
Word_B * AddWordToBlock(char *, Word_B *)
Definition: system.c:1748
#define NOWORDS
Definition: sh.h:1150
#define GM_SHORTEST
Definition: sh.h:1775
#define IS_IFS(c)
Definition: sh.h:1088
#define ONEWORD
Definition: sh.h:1331
void CheckProgramMode(char *, ExeMode *)
Definition: sh3.c:2889
#define CHAR_SWITCH
Definition: sh.h:1041
char ** GetWordList(Word_B *)
Definition: sh8.c:1483
#define IsHPFSFileSystem(a)
Definition: sh.h:1127
FunctionList * CurrentFunction
Definition: sh6.c:152
void ShellErrorMessage(char *,...)
Definition: sh1.c:1032
char * LIT_ArrayRange
Definition: sh6.c:271
int S_dup2(int, int)
Definition: sh8.c:614
void FreeAllHereDocuments(int)
Definition: sh5.c:1438
#define CHAR_DRIVE
Definition: sh.h:1044
#define CHAR_MATCH_START
Definition: sh.h:1029
int CreateGlobalVariableList(unsigned int)
Definition: sh1.c:1671
Break_C * Return_List
Definition: sh6.c:145
#define CHAR_MAGIC
Definition: sh.h:1060
int ReMapIOHandler(int)
Definition: sh5.c:1216
#define CHAR_NOT
Definition: sh.h:1013
int CountVariableArraySize(char *)
Definition: sh1.c:1535
bool GeneralPatternMatch(char *, unsigned char *, bool, char **, int)
Definition: sh1.c:1879
#define NOPIPE
Definition: sh.h:1151
#define CHAR_CLOSE_BRACES
Definition: sh.h:1022
char * OldPWDVariable
Definition: sh6.c:221
#define XCurrentOffset(xs, xp)
Definition: sh.h:1214
#define SystemInterrupt(a, b, c)
Definition: sh.h:585
FILE * MyReOpenFile(int, char *)
Definition: sh8.c:1609
#define WORD_COMSUB
Definition: sh.h:1269
Source * pushs(int)
Definition: sh5.c:1018
#define WORD_EOS
Definition: sh.h:1265
#define CHAR_CLOSE_BRACKETS
Definition: sh.h:1024
char * LIT_BadArray
Definition: sh6.c:270
int OpenAPipe(void)
Definition: sh8.c:737
#define FLAG_DISABLE_GLOB
Definition: sh.h:1718
VISIT
Definition: sh.h:2439
@ postorder
Definition: sh.h:2439
@ leaf
Definition: sh.h:2439
#define IOREAD
Definition: sh.h:1652
char * XCreate(XString *, size_t)
Definition: sh5.c:1350
#define EXPAND_CONVERT
Definition: sh.h:1486
#define WORD_CARRAY
Definition: sh.h:1278
Break_C * SShell_List
Definition: sh6.c:146
bool SuffixPatternMatch(char *, char *, char **, int)
Definition: sh1.c:2033
#define FLAGS_NOCASE
Definition: sh.h:1751
char GetDriveLetter(unsigned int)
Definition: sh8.c:3405
#define WORD_CDQUOTE
Definition: sh.h:1273
char IFS[]
Definition: sh6.c:194
#define GM_LONGEST
Definition: sh.h:1776
#define WORD_QTCHAR
Definition: sh.h:1268
#define FLAG_UNSET_ERROR
Definition: sh.h:1727
#define CHAR_UNIX_DIRECTORY
Definition: sh.h:1006
Definition: dirent.h:44
unsigned int Flags
Definition: sh.h:1961
Definition: sh4.c:92
char * str
Definition: sh4.c:94
char ** strv
Definition: sh4.c:96
FILE * file
Definition: sh4.c:97
union Expand::@238 u
bool split
Definition: sh4.c:100
Definition: sh4.c:121
short base
Definition: sh4.c:123
char * name
Definition: sh4.c:124
short type
Definition: sh4.c:122
int index
Definition: sh4.c:125
Definition: sh.h:1206
Definition: sh.h:1540
Definition: dirent.h:34
char * line
Definition: sh.h:1693
Definition: psread.c:42
Definition: sh.h:1645
Definition: sh.h:1226
Definition: tpic.c:45
Definition: sh2.c:920
Definition: sh.h:1345
char * str
Definition: sh.h:1346
Definition: stemdb.c:56
Definition: dvips.h:235
Definition: sh.h:1782
char * name
Definition: sh.h:1783
int index
Definition: sh.h:1785
Definition: sh.h:1559
pointer path
Definition: t1imager.h:36
#define FILE
Definition: t1stdio.h:34
#define ungetc(c, f)
Definition: t1stdio.h:106
*job_name strlen((char *) job_name) - 4)
#define key
Definition: tex2xindy.c:753
#define sp
Definition: stack.c:11
@ L
Definition: ubidiimp.h:45
Definition: obx.h:51