You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
5.3 KiB
218 lines
5.3 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Utility Library
|
|
* ----------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Command line parser.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "deCommandLine.h"
|
|
#include "deMemPool.h"
|
|
#include "dePoolArray.h"
|
|
#include "deMemory.h"
|
|
#include "deString.h"
|
|
|
|
#include <string.h>
|
|
|
|
DE_DECLARE_POOL_ARRAY(CharPtrArray, char*);
|
|
|
|
enum
|
|
{
|
|
MAX_ARGS = 64
|
|
};
|
|
|
|
deCommandLine* deCommandLine_parse (const char* commandLine)
|
|
{
|
|
deMemPool* tmpPool = deMemPool_createRoot(DE_NULL, 0);
|
|
CharPtrArray* args = tmpPool ? CharPtrArray_create(tmpPool) : DE_NULL;
|
|
char* buf = DE_NULL;
|
|
char* outPtr;
|
|
int pos;
|
|
int argNdx;
|
|
char strChr;
|
|
|
|
if (!args)
|
|
{
|
|
if (tmpPool)
|
|
deMemPool_destroy(tmpPool);
|
|
return DE_NULL;
|
|
}
|
|
|
|
DE_ASSERT(commandLine);
|
|
|
|
/* Create buffer for args (no expansion can happen). */
|
|
buf = (char*)deCalloc(strlen(commandLine)+1);
|
|
pos = 0;
|
|
argNdx = 0;
|
|
outPtr = buf;
|
|
strChr = 0;
|
|
|
|
if (!buf || !CharPtrArray_pushBack(args, buf))
|
|
{
|
|
deMemPool_destroy(tmpPool);
|
|
return DE_NULL;
|
|
}
|
|
|
|
while (commandLine[pos] != 0)
|
|
{
|
|
char c = commandLine[pos++];
|
|
|
|
if (strChr != 0 && c == '\\')
|
|
{
|
|
/* Escape. */
|
|
c = commandLine[pos++];
|
|
switch (c)
|
|
{
|
|
case 'n': *outPtr++ = '\n'; break;
|
|
case 't': *outPtr++ = '\t'; break;
|
|
default: *outPtr++ = c; break;
|
|
}
|
|
}
|
|
else if (strChr != 0 && c == strChr)
|
|
{
|
|
/* String end. */
|
|
strChr = 0;
|
|
}
|
|
else if (strChr == 0 && (c == '"' || c == '\''))
|
|
{
|
|
/* String start. */
|
|
strChr = c;
|
|
}
|
|
else if (c == ' ' && strChr == 0)
|
|
{
|
|
/* Arg end. */
|
|
*outPtr++ = 0;
|
|
argNdx += 1;
|
|
if (!CharPtrArray_pushBack(args, outPtr))
|
|
{
|
|
deFree(buf);
|
|
deMemPool_destroy(tmpPool);
|
|
return DE_NULL;
|
|
}
|
|
}
|
|
else
|
|
*outPtr++ = c;
|
|
}
|
|
|
|
DE_ASSERT(commandLine[pos] == 0);
|
|
|
|
/* Terminate last arg. */
|
|
*outPtr = 0;
|
|
|
|
/* Create deCommandLine. */
|
|
{
|
|
deCommandLine* cmdLine = (deCommandLine*)deCalloc(sizeof(deCommandLine));
|
|
|
|
if (!cmdLine || !(cmdLine->args = (char**)deCalloc(sizeof(char*)*(size_t)CharPtrArray_getNumElements(args))))
|
|
{
|
|
deFree(cmdLine);
|
|
deFree(buf);
|
|
deMemPool_destroy(tmpPool);
|
|
return DE_NULL;
|
|
}
|
|
|
|
cmdLine->numArgs = CharPtrArray_getNumElements(args);
|
|
cmdLine->argBuf = buf;
|
|
|
|
for (argNdx = 0; argNdx < cmdLine->numArgs; argNdx++)
|
|
cmdLine->args[argNdx] = CharPtrArray_get(args, argNdx);
|
|
|
|
deMemPool_destroy(tmpPool);
|
|
return cmdLine;
|
|
}
|
|
}
|
|
|
|
void deCommandLine_destroy (deCommandLine* cmdLine)
|
|
{
|
|
deFree(cmdLine->argBuf);
|
|
deFree(cmdLine);
|
|
}
|
|
|
|
static void testParse (const char* cmdLine, const char* const* refArgs, int numArgs)
|
|
{
|
|
deCommandLine* parsedCmdLine = deCommandLine_parse(cmdLine);
|
|
int argNdx;
|
|
|
|
DE_TEST_ASSERT(parsedCmdLine);
|
|
DE_TEST_ASSERT(parsedCmdLine->numArgs == numArgs);
|
|
|
|
for (argNdx = 0; argNdx < numArgs; argNdx++)
|
|
DE_TEST_ASSERT(deStringEqual(parsedCmdLine->args[argNdx], refArgs[argNdx]));
|
|
|
|
deCommandLine_destroy(parsedCmdLine);
|
|
}
|
|
|
|
void deCommandLine_selfTest (void)
|
|
{
|
|
{
|
|
const char* cmdLine = "hello";
|
|
const char* ref[] = { "hello" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "hello world";
|
|
const char* ref[] = { "hello", "world" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "hello/world";
|
|
const char* ref[] = { "hello/world" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "hello/world --help";
|
|
const char* ref[] = { "hello/world", "--help" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "hello/world --help foo";
|
|
const char* ref[] = { "hello/world", "--help", "foo" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "hello\\world --help foo";
|
|
const char* ref[] = { "hello\\world", "--help", "foo" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "\"hello/worl d\" --help --foo=\"bar\" \"ba z\\\"\"";
|
|
const char* ref[] = { "hello/worl d", "--help", "--foo=bar", "ba z\"" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "'hello/worl d' --help --foo='bar' 'ba z\\\''";
|
|
const char* ref[] = { "hello/worl d", "--help", "--foo=bar", "ba z'" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "hello \"'world'\"";
|
|
const char* ref[] = { "hello", "'world'" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "hello '\"world\"'";
|
|
const char* ref[] = { "hello", "\"world\"" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
{
|
|
const char* cmdLine = "hello \"world\\n\"";
|
|
const char* ref[] = { "hello", "world\n" };
|
|
testParse(cmdLine, ref, DE_LENGTH_OF_ARRAY(ref));
|
|
}
|
|
}
|