1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
/*
* Copyright (c) 1998 by Christopher Nebel. All Rights Reserved.
*
* Please see the accompanying license file, LICENSE.TXT, for information
* on using and copying this software.
*/
/*
Name:
argize.c
Function:
Break a string into argc/argv-style arguments.
Notes:
none
Modified:
<2>07/04/98 CNebel - Fixed so that args wouldn't pick up trailing
whitespace.
<1>07/04/98 CNebel - Created based on older Mac-specific argize source
*/
#include "argize.h"
#include <stddef.h>
#include <ctype.h>
/*
* Return what argc would be if this string were fed to argize.
*/
int countargs(const char *cmdline)
{
const char *p = cmdline;
int state = 0;
int argc = 0;
while (*p) {
switch (state) {
case 0: /* skip leading white space */
while (isspace((unsigned char)*p)) p++;
if (!*p) break; /* If there's nothing left, get out. */
state = 1;
/* fall through */;
case 1: /* begin arg */
argc++;
state = 2;
/* fall through */
case 2: /* collect chars for current arg */
if (isspace((unsigned char)*p))
p++, state = 0; /* Terminate this arg */
else if (*p == '"')
p++, state = 3; /* Open quote. */
else if (*p == '\\')
p++, state = 4; /* Escape sequence. */
else
p++; /* Just keep going. */
break;
case 3: /* collect chars inside quotes. */
switch (*p) {
case '"' : p++; state = 2; break; /* Close quote */
case '\\': p++; state = 5; break; /* Escape sequence. */
default: p++; break;
}
break;
case 4: /* escaped character outside quotes. */
p++; state = 2;
break;
case 5: /* escaped character inside quotes. */
p++; state = 3;
break;
}
}
return argc;
}
/*
* Break a string <cmdline> into argc/argv arguments, removing quotes in
* the process. Returns 0 on success, 1 if there were too many
* arguments.
*/
int argize(char *cmdline, int *const argc, char *argv[], const size_t argvlen)
{
char *p, *q;
int state;
p = q = cmdline;
*argc = 0;
state = 0;
while (*p) {
switch (state) {
case 0: /* skip leading white space */
while (isspace((unsigned char)*p)) p++, q++;
if (!*p) break; /* If there's nothing left, get out. */
state = 1;
/* fall through */;
case 1: /* begin arg */
if ((size_t)*argc < argvlen)
argv[(*argc)++] = q;
else
return 1;
state = 2;
/* fall through */
case 2: /* collect chars for current arg */
if (isspace((unsigned char)*p))
*q++ = *p++ = '\0', state = 0; /* Terminate this arg */
else if (*p == '"')
p++, state = 3; /* Open quote. */
else if (*p == '\\')
p++, state = 4; /* Escape sequence. */
else
*q++ = *p++; /* Just keep going. */
break;
case 3: /* collect chars inside quotes. */
switch (*p) {
case '"' : p++; state = 2; break; /* Close quote.*/
case '\\': p++; state = 5; break; /* Escape sequence. */
default: *q++ = *p++; break;
}
break;
case 4: /* escaped character outside quotes. */
*q++ = *p++; state = 2;
break;
case 5: /* escaped character inside quotes. */
*q++ = *p++; state = 3;
break;
}
}
*q = '\0';
return 0;
}
|