about summary refs log tree commit diff
path: root/lib/util/token.c
blob: a68a4821f1562918c034c8d707548fc83244a7e9 (plain) (blame)
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
#include <stdlib.h>
#include <assert.h>

#include "nstring.h"

#include "token.h"


void
pm_gettoken(const char *  const tokenStart,
            char          const delimiter,
            const char ** const tokenP,
            const char ** const nextP,
            const char ** const errorP) {
/*----------------------------------------------------------------------------
   Find the token starting at 'tokenStart' up to but not including
   the first 'delimiter' character or end of string.  Return it in newly
   malloced memory as *tokenP, NUL-terminated.

   Make *nextP point just past the token, i.e. to the delimiter or
   end of string NUL character.

   Note that if the string is empty, or starts with the delimiter,
   we return an empty string and *nextP == tokenStart, i.e. *nextP
   doesn't necessarily advance.
-----------------------------------------------------------------------------*/
    char * token;
    const char * cursor;
    unsigned int charCount;

    /* Run through the token, counting characters */

    charCount = 0;        /* initial value */
    cursor = tokenStart;  /* initial value */
    *errorP = NULL;       /* initial value */

    while (*cursor != delimiter && *cursor != '\0' && !*errorP) {
        if (*cursor == '\\') {
            ++cursor;
            if (*cursor == '\0')
                pm_asprintf(errorP,
                            "string ends with an escape character (\\)");
        } else {
            ++cursor;
            ++charCount;
        }
    }
    if (!*errorP) {
        token = malloc(charCount + 1);
        if (token == NULL)
            pm_asprintf(errorP, "Could not allocate %u bytes of memory "
                        "to parse a string",
                        charCount + 1);
        else {
            /* Go back and do it again, this time copying the characters */
            charCount = 0;
            cursor = tokenStart;

            while (*cursor != delimiter && *cursor != '\0') {
                if (*cursor == '\\')
                    ++cursor;

                assert(*cursor != '\0');

                token[charCount++] = *cursor++;
            }
            token[charCount] = '\0';
            
            *tokenP = token;
            *nextP = cursor;
        }
    }
}