Mercurial > projects > ldc
view dmd2/root/response.c @ 1514:7a528017b4c6
Don't initialize arrays of (arrays of...) void-initialized typedefs.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Wed, 24 Jun 2009 17:14:50 +0200 |
parents | 638d16625da2 |
children | e4f7b5d9c68a |
line wrap: on
line source
// Copyright (C) 1990-1998 by Symantec // Copyright (C) 2000-2009 by Digital Mars // All Rights Reserved // http://www.digitalmars.com // Written by Walter Bright /* * This source file is made available for personal use * only. The license is in /dmd/src/dmd/backendlicense.txt * For any other uses, please contact Digital Mars. */ #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #if !__DMC__ #include <sys/stat.h> #endif #if _WIN32 #include <tchar.h> #include <io.h> #endif #if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 #include <sys/types.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <utime.h> #endif /********************************* * #include <stdlib.h> * int response_expand(int *pargc,char ***pargv); * * Expand any response files in command line. * Response files are arguments that look like: * @NAME * The name is first searched for in the environment. If it is not * there, it is searched for as a file name. * Arguments are separated by spaces, tabs, or newlines. These can be * imbedded within arguments by enclosing the argument in '' or "". * Recursively expands nested response files. * * To use, put the line: * response_expand(&argc,&argv); * as the first executable statement in main(int argc, char **argv). * argc and argv are adjusted to be the new command line arguments * after response file expansion. * * Digital Mars's MAKE program can be notified that a program can accept * long command lines via environment variables by preceding the rule * line for the program with a *. * * Returns: * 0 success * !=0 failure (argc, argv unchanged) */ struct Narg { int argc; /* arg count */ int argvmax; /* dimension of nargv[] */ char **argv; }; static int addargp(struct Narg *n, char *p) { /* The 2 is to always allow room for a NULL argp at the end */ if (n->argc + 2 >= n->argvmax) { n->argvmax = n->argc + 2; n->argv = (char **) realloc(n->argv,n->argvmax * sizeof(char *)); if (!n->argv) return 1; } n->argv[n->argc++] = p; return 0; } int response_expand(int *pargc, char ***pargv) { struct Narg n; int i; char *cp; int recurse = 0; n.argc = 0; n.argvmax = 0; /* dimension of n.argv[] */ n.argv = NULL; for(i=0; i<*pargc; ++i) { cp = (*pargv)[i]; if (*cp == '@') { char *buffer; char *bufend; char *p; cp++; p = getenv(cp); if (p) { buffer = strdup(p); if (!buffer) goto noexpand; bufend = buffer + strlen(buffer); } else { long length; int fd; int nread; size_t len; #if __DMC__ length = filesize(cp); #else struct stat statbuf; if (stat(cp, &statbuf)) goto noexpand; length = statbuf.st_size; #endif if (length & 0xF0000000) /* error or file too big */ goto noexpand; len = length; buffer = (char *)malloc(len + 1); if (!buffer) goto noexpand; bufend = &buffer[len]; /* Read file into buffer */ #if _WIN32 fd = open(cp,O_RDONLY|O_BINARY); #else fd = open(cp,O_RDONLY); #endif if (fd == -1) goto noexpand; nread = read(fd,buffer,len); close(fd); if (nread != len) goto noexpand; } // The logic of this should match that in setargv() for (p = buffer; p < bufend; p++) { char *d; char c,lastc; unsigned char instring; int num_slashes,non_slashes; switch (*p) { case 26: /* ^Z marks end of file */ goto L2; case 0xD: case 0: case ' ': case '\t': case '\n': continue; // scan to start of argument case '@': recurse = 1; default: /* start of new argument */ if (addargp(&n,p)) goto noexpand; instring = 0; c = 0; num_slashes = 0; for (d = p; 1; p++) { lastc = c; if (p >= bufend) goto Lend; c = *p; switch (c) { case '"': /* Yes this looks strange,but this is so that we are MS Compatible, tests have shown that: \\\\"foo bar" gets passed as \\foo bar \\\\foo gets passed as \\\\foo \\\"foo gets passed as \"foo and \"foo gets passed as "foo in VC! */ non_slashes = num_slashes % 2; num_slashes = num_slashes / 2; for (; num_slashes > 0; num_slashes--) { d--; *d = '\0'; } if (non_slashes) { *(d-1) = c; } else { instring ^= 1; } break; case 26: Lend: *d = 0; // terminate argument goto L2; case 0xD: // CR c = lastc; continue; // ignore case '@': recurse = 1; goto Ladd; case ' ': case '\t': if (!instring) { case '\n': case 0: *d = 0; // terminate argument goto Lnextarg; } default: Ladd: if (c == '\\') num_slashes++; else num_slashes = 0; *d++ = c; break; } #ifdef _MBCS if (_istlead (c)) { *d++ = *++p; if (*(d - 1) == '\0') { d--; goto Lnextarg; } } #endif } break; } Lnextarg: ; } L2: ; } else if (addargp(&n,(*pargv)[i])) goto noexpand; } n.argv[n.argc] = NULL; if (recurse) { /* Recursively expand @filename */ if (response_expand(&n.argc,&n.argv)) goto noexpand; } *pargc = n.argc; *pargv = n.argv; return 0; /* success */ noexpand: /* error */ free(n.argv); /* BUG: any file buffers are not free'd */ return 1; }