summaryrefslogtreecommitdiffstats
path: root/private/crt32/startup/wild.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/startup/wild.c')
-rw-r--r--private/crt32/startup/wild.c341
1 files changed, 341 insertions, 0 deletions
diff --git a/private/crt32/startup/wild.c b/private/crt32/startup/wild.c
new file mode 100644
index 000000000..a13c62d4e
--- /dev/null
+++ b/private/crt32/startup/wild.c
@@ -0,0 +1,341 @@
+/***
+*wild.c - wildcard expander
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* expands wildcards in argv
+*
+* handles '*' (none or more of any char) and '?' (exactly one char)
+*
+*Revision History:
+* 05-21-84 RN initial version
+* 06-07-85 TDC since dos accepts forward slash, added
+* code to accept forward slash in a manner consistent
+* with reverse slash.
+* 09-20-86 SKS Modified for OS/2
+* All argument strings to this function have a
+* leading flag character. If the flag is a quote,
+* that argument string was quoted on the command
+* line and should have not wildcard expansion. In all
+* cases the leading flag character is removed from
+* the string.
+* 11-11-86 JMB Added Kanji support under KANJI switch.
+* 09-21-88 WAJ initial 386 version
+* 04-09-90 GJF Added #include <cruntime.h> and removed #include
+* <register.h>. Made calling types explicit (_CALLTYPE1
+* or _CALLTYPE4). Also, fixed the copyright.
+* 04-10-90 GJF Added #include <internal.h> and fixed compiler warnings
+* (-W3).
+* 07-03-90 SBM Compiles cleanly with -W3 under KANJI, removed
+* redundant includes, removed #include <internal.h>
+* to keep wild.c free of private stuff, should we
+* decide to release it
+* 09-07-90 SBM put #include <internal.h> back in, reason for
+* removing it discovered to be horribly bogus
+* 10-08-90 GJF New-style function declarators.
+* 01-18-91 GJF ANSI naming.
+* 06-09-93 KRS Update _MBCS support.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <msdos.h>
+#include <internal.h>
+
+#ifdef _MBCS
+#include <mbdata.h>
+#include <mbstring.h>
+#define STRPBRK _mbspbrk
+#define STRCMP _mbscmp
+#define STRICMP _mbsicmp
+#else
+#define STRPBRK strpbrk
+#define STRCMP strcmp
+#define STRICMP _stricmp
+#endif
+
+/*
+** these are the data structures
+**
+** __argv
+** ------- ------
+** | |---->| |---->"arg0"
+** ------- ------
+** | |---->"arg1"
+** ------
+** ....
+** ------
+** | |---->"argn"
+** ------
+** |NULL|
+** ------
+** argend
+** -------
+** ------- | |
+** | | __argc -------
+** ------- |
+** |
+** arghead V
+** ------ --------- ----------
+** | |---->| | |----> .... ---->| |NULL|
+** ------ --------- ----------
+** | |
+** V V
+** "narg0" "nargn"
+*/
+
+#define SLASHCHAR '\\'
+#define FWDSLASHCHAR '/'
+#define SLASH "\\"
+#define FWDSLASH "/"
+#define STAR "*.*"
+
+#define WILDSTRING "*?"
+
+
+extern int __argc;
+extern char **__argv;
+
+struct argnode {
+ char *argptr;
+ struct argnode *nextnode;
+};
+
+static struct argnode *arghead;
+static struct argnode *argend;
+
+static int _CALLTYPE4 match(char *, char *);
+static int _CALLTYPE4 add(char *);
+static void _CALLTYPE4 sort(struct argnode *);
+
+/***
+*int _cwild() - wildcard expander
+*
+*Purpose:
+* expands wildcard in file specs in argv
+*
+* handles '*' (none or more of any char), '?' (exactly one char), and
+* '[string]' (chars which match string chars or between n1 and n2
+* if 'n1-n2' in string inclusive)
+*
+*Entry:
+*
+*Exit:
+* returns 0 if successful, -1 if any malloc() calls fail
+* if problems with malloc, the old argc and argv are not touched
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CALLTYPE1 _cwild (
+ void
+ )
+{
+ REG1 char **argv = __argv;
+ REG2 struct argnode *nodeptr;
+ REG3 int argc;
+ REG4 char **tmp;
+ char *wchar;
+
+ arghead = argend = NULL;
+
+ for (argv = __argv; *argv; argv++) /* for each arg... */
+ if ( *(*argv)++ == '"' )
+ /* strip leading quote from quoted arg */
+ {
+ if (add(*argv))
+ return(-1);
+ }
+ else if (wchar = STRPBRK( *argv, WILDSTRING )) {
+ /* attempt to expand arg with wildcard */
+ if (match( *argv, wchar ))
+ return(-1);
+ }
+ else if (add( *argv )) /* normal arg, just add */
+ return(-1);
+
+ /* count the args */
+ for (argc = 0, nodeptr = arghead; nodeptr;
+ nodeptr = nodeptr->nextnode, argc++)
+ ;
+
+ /* try to get new arg vector */
+ if (!(tmp = (char **)malloc(sizeof(char *)*(argc+1))))
+ return(-1);
+
+ /* the new arg vector... */
+ __argv = tmp;
+
+ /* the new arg count... */
+ __argc = argc;
+
+ /* install the new args */
+ for (nodeptr = arghead; nodeptr; nodeptr = nodeptr->nextnode)
+ *tmp++ = nodeptr->argptr;
+
+ /* the terminal NULL */
+ *tmp = NULL;
+
+ /* free up local data */
+ for (nodeptr = arghead; nodeptr; nodeptr = arghead) {
+ arghead = arghead->nextnode;
+ free(nodeptr);
+ }
+
+ /* return success */
+ return(0);
+}
+
+
+/***
+*match(arg, ptr) - [STATIC]
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 match (
+ REG4 char *arg,
+ REG1 char *ptr
+ )
+{
+ REG2 char *new;
+ REG3 int length = 0;
+ char *all;
+ REG5 struct argnode *first;
+ REG6 int gotone = 0;
+
+ while (ptr != arg && *ptr != SLASHCHAR && *ptr != FWDSLASHCHAR
+ && *ptr != ':') {
+ /* find first slash or ':' before wildcard */
+#ifdef _MBCS
+ if (--ptr > arg)
+ ptr = _mbsdec(arg,ptr+1);
+#else
+ ptr--;
+#endif
+ }
+
+ if (*ptr == ':' && ptr != arg+1) /* weird name, just add it as is */
+ return(add(arg));
+
+ if (*ptr == SLASHCHAR || *ptr == FWDSLASHCHAR
+ || *ptr == ':') /* pathname */
+ length = ptr - arg + 1; /* length of dir prefix */
+
+ if (new = _find(arg)) { /* get the first file name */
+ first = argend;
+
+ do { /* got a file name */
+ if (strcmp(new, ".") && strcmp(new, "..")) {
+ if (*ptr != SLASHCHAR && *ptr != ':'
+ && *ptr != FWDSLASHCHAR ) {
+ /* current directory; don't need path */
+ if (!(arg = _strdup(new)) || add(arg))
+ return(-1);
+ }
+ else /* add full pathname */
+ if (!(all=malloc(length+strlen(new)+1))
+ || add(strcpy(strncpy(all,arg,length)+length,new)
+ - length))
+ return(-1);
+
+ gotone++;
+ }
+
+ }
+ while (new = _find(NULL)); /* get following files */
+
+ if (gotone) {
+ sort(first ? first->nextnode : arghead);
+ return(0);
+ }
+ }
+
+ return(add(arg)); /* no match */
+}
+
+/***
+*add(arg) - [STATIC]
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static int _CALLTYPE4 add (
+ char *arg
+ )
+{
+ REG1 struct argnode *nodeptr;
+
+ if (!(nodeptr = (struct argnode *)malloc(sizeof(struct argnode))))
+ return(-1);
+
+ nodeptr->argptr = arg;
+ nodeptr->nextnode = NULL;
+
+ if (arghead)
+ argend->nextnode = nodeptr;
+ else
+ arghead = nodeptr;
+
+ argend = nodeptr;
+ return(0);
+}
+
+
+/***
+*sort(first) - [STATIC]
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CALLTYPE4 sort (
+ REG2 struct argnode *first
+ )
+{
+ REG1 struct argnode *nodeptr;
+ REG3 char *temp;
+
+ if (first) /* something to sort */
+ while (nodeptr = first->nextnode) {
+ do {
+#ifdef _POSIX
+ if (STRCMP(nodeptr->argptr, first->argptr) < 0) {
+#else
+ if (STRICMP(nodeptr->argptr, first->argptr) < 0) {
+#endif /* _POSIX_ */
+ temp = first->argptr;
+ first->argptr = nodeptr->argptr;
+ nodeptr->argptr = temp;
+ }
+ }
+ while (nodeptr = nodeptr->nextnode);
+
+ first = first->nextnode;
+ }
+}