[misc] Add error code 'GENERIC_BADNESS'
[vsc-common.git] / cli / token.c
1 /*
2  * token.c: Library for interactive commandline interfaces
3  *
4  * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19  */
20
21 /*!
22  * @file
23  */
24
25 #include <libvscmisc/assert.h>
26 #include <libvscmisc/error.h>
27 #include <libvscmisc/memory.h>
28
29 #include "token.h"
30
31 // FIXME: remove char **token and return it instead
32 void
33 _vsc_cli_token_parse (struct VscError *error, const char *input, char **token,
34                       const char **input_tail)
35 {
36         const char *ptr = input;
37         int quote = FALSE;
38         const char *start = NULL;
39         int length = 0;
40
41         VSC__ASSERT (error != NULL);
42         VSC__ASSERT (! error->occured);
43         VSC__ASSERT (input != NULL);
44         VSC__ASSERT (token != NULL);
45         VSC__ASSERT (input_tail != NULL);
46
47         *token = NULL;
48
49         while (ptr != NULL && *ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
50                 ++ptr;
51         }
52
53         if (ptr == NULL || *ptr == '\0') {
54                 *input_tail = NULL;
55                 return;
56         }
57
58         if (*ptr == ',') {
59                 *input_tail = ++ptr;
60                 return;
61         }
62
63         while (*ptr != '\0') {
64                 if (quote == FALSE && (*ptr == ' ' || *ptr == '\t' || *ptr == ',')) {
65                         break;
66                 }
67
68                 if (*ptr == '"') {
69                         ++ptr;
70
71                         if (! quote) {
72                                 quote = TRUE;
73                         } else {
74                                 quote = FALSE;
75                                 break;
76                         }
77                 }
78
79                 if (start == NULL) {
80                         start = ptr;
81                 }
82
83                 ++ptr;
84                 ++length;
85         }
86
87         if (quote) {
88                 VSC__ERROR1 (error, VSC__ERROR_CODE__INTERNAL_ERROR,
89                              "Input is malformed, missing \"");
90                 return;
91         }
92
93         *input_tail = ptr;
94
95         if (start == NULL || *start == '\0' || length == 0) {
96                 return;
97         }
98
99         *token = vsc_alloc (error, length + 1);
100
101         if (error->occured) {
102                 VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
103                 return;
104         }
105
106         // FIXME: use strncpy?
107         memcpy (*token, start, length);
108         (*token)[length] = '\0';
109 }