tts/str.c
2014-03-07 17:43:41 +00:00

107 lines
2 KiB
C

/*
* TTS - track your time.
* Copyright (c) 2012-2014 Felicity Tarnell.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely. This software is provided 'as-is', without any express or implied
* warranty.
*/
#include "str.h"
size_t
tokenise(str, res)
const WCHAR *str;
WCHAR ***res;
{
int ntoks = 0;
const WCHAR *p, *q;
*res = NULL;
p = str;
for (;;) {
ptrdiff_t sz;
int qskip = 0;
/* Skip leading whitespace */
while (ISSPACE(*p))
p++;
/* End of string - no more arguments */
if (!*p)
break;
q = p;
if (*q == '"') {
/* Quoted string - scan for end of string */
int isbsl = 0;
p++;
while (*++q) {
/* Handle escaping with backslash; currently works but the \ isn't
* removed from the string.
*/
if (*q == '\\') {
isbsl = 1;
continue;
}
if (!isbsl && (*q == '"'))
break;
isbsl = 0;
}
/* At this point, *q == '"'. If it's NUL instead, then the
* string was not terminated with a closing '"' before the end
* of the line. We could give an error here, but it seems
* more useful to just accept it.
*/
if (*q == '"')
qskip = 1;
} else {
/* Not quoted - just find the next whitespace */
while (!ISSPACE(*q) && *q)
q++;
}
/* Copy the argument (which is sz bytes long) into the result array */
sz = (q - p);
*res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1));
(*res)[ntoks] = malloc(sizeof(WCHAR) * (sz + 1));
MEMCPY((*res)[ntoks], p, sz);
(*res)[ntoks][sz] = 0;
ntoks++;
if (qskip)
q += qskip;
while (ISSPACE(*q))
q++;
/*
* q is the start of the next token (with leading whitespace); reset
* p to process the next argument.
*/
if (!*q)
break;
p = q;
}
*res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1));
(*res)[ntoks] = NULL;
return ntoks;
}
void
tokfree(vec)
WCHAR ***vec;
{
WCHAR **p;
for (p = (*vec); *p; p++)
free(*p);
free(*vec);
}