Skip to content

Instantly share code, notes, and snippets.

@hamsham
Created August 5, 2017 02:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hamsham/cff3f62873888e6c68f8a472399cd133 to your computer and use it in GitHub Desktop.
Save hamsham/cff3f62873888e6c68f8a472399cd133 to your computer and use it in GitHub Desktop.
Simple example of how to parse arguments from a single string, with quote-handling.
/*
* Test for parsing command-line arguments from a single string
*
* gcc -std=c11 -Wall -Werror -Wextra -pedantic -pedantic-errors parse_args.c -o parse_args
*/
#include <stdio.h> // printf(), fprintf()
#include <string.h> // strlen()
#include <stdbool.h> // bool, true, false
#include <ctype.h> // isspace()
/*-------------------------------------
* Count the number of arguments in an argument string
-------------------------------------*/
bool _args_from_string(char* const pArgString)
{
if (!pArgString || pArgString[0] == '\0')
{
fprintf(stderr, "Invalid input: %s\n", pArgString);
return false;
}
unsigned argc = 0;
bool isQuotedS = false;
bool isQuotedD = false;
bool isEscaped = false;
bool wasQuotedD = false;
bool wasQuotedS = false;
unsigned lastArg = 0;
unsigned i = 0;
// count all arguments in the string
do
{
const char c = pArgString[i];
// single quotes embedded in double quotes aren't counted
// and vice-versa
if ((c == '\"') && !isEscaped && !isQuotedS)
{
isQuotedD = !isQuotedD;
wasQuotedD = true;
++lastArg;
}
if ((c == '\'') && !isEscaped && !isQuotedD)
{
isQuotedS = !isQuotedS;
wasQuotedS = true;
++lastArg;
}
const bool wasQuoted = wasQuotedS || wasQuotedD;
const bool isQuoted = isQuotedS || isQuotedD;
const bool isDelimiter = (!isEscaped && isspace(c)) || c == '\0';
// count arguments which are not separated by an escaped space
if (isDelimiter && !isQuoted)
{
const unsigned length = i - wasQuoted;
const char* subStr = pArgString + lastArg;
const char temp = pArgString[length];
pArgString[length] = '\0';
printf("Argument found: %s\n", subStr);
// printf("\tQuoted: %d\n", wasQuoted);
// printf("\tOffset: %u - %u\n", lastArg, length);
// printf("\tlength: %zu\n", strlen(subStr));
pArgString[length] = temp;
lastArg = i;
isQuotedS = isQuotedD = false;
wasQuotedS = wasQuotedD = false;
++argc;
}
// Flip the check for character escapes
isEscaped = (c == '\\');
}
while (pArgString[i++] != '\0');
// printf("%d arguments found in the input string: %s\n\n", argc, pArgString);
return !isQuotedS && !isQuotedD;
}
int main(int argc, char* argv[])
{
int ret = 0;
printf("%d Arguments available to parse.\n", argc);
for (int i = 0; i < argc; ++i)
{
ret += _args_from_string(argv[i]);
}
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment