--- /dev/null
+/*
+ * Copyright (C) 2015 Thadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "token.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char * token_unescape(char *start, char *end)
+{
+ int escape = 0;
+ char *s, *r, *n;
+ s = n = malloc(end - start);
+ if (!s)
+ return NULL;
+ for (r = start + 1; r < end; r++) {
+ if (escape) {
+ *s = *r;
+ s++;
+ escape = 0;
+ } else if (*r == '\\') {
+ escape = 1;
+ } else {
+ *s = *r;
+ s++;
+ }
+ }
+ *s = 0;
+ return n;
+}
+
+static char * token_next(char *line, char **end)
+{
+ char *start;
+ char *lend;
+ char cend;
+ int escape = 0;
+ start = line;
+ while (isspace(*start))
+ start++;
+ if (*start == '"') {
+ lend = start + 1;
+ while (*lend) {
+ cend = *lend;
+ lend++;
+ if (escape)
+ escape = 0;
+ else if (cend == '\\')
+ escape = 1;
+ else if (cend == '"')
+ break;
+ }
+ } else {
+ lend = start;
+ while (*lend && !isspace(*lend))
+ lend++;
+ }
+ *end = lend;
+ return start;
+}
+
+char ** tokens_new(char *line)
+{
+ char **args = NULL;
+ size_t alloc = 0;
+ size_t next = 0;
+ const int inc = 8;
+ int more = 0;
+ char *start;
+ char *end;
+ int i;
+ end = line;
+ do {
+ if (next <= alloc) {
+ char **nargs;
+ alloc += inc;
+ nargs = realloc(args, alloc * sizeof(char *));
+ if (!nargs) {
+ for (i = 0; i < alloc - inc; i++)
+ if (args[i])
+ free(args[i]);
+ free(args);
+ return NULL;
+ }
+ for (i = alloc - inc; i < alloc; i++)
+ nargs[i] = NULL;
+ args = nargs;
+ }
+ start = token_next(end, &end);
+ if (start == end)
+ break;
+ if (*start == '"') {
+ args[next] = token_unescape(start, end - 1);
+ } else {
+ args[next] = strndup(start, end - start);
+ }
+ if (!args[next]) {
+ for (i = 0; i < alloc; i++)
+ if (args[i])
+ free(args[i]);
+ free(args);
+ return NULL;
+ }
+ next++;
+ } while (1);
+ return args;
+}
+
+void tokens_free(char **args)
+{
+ char *arg;
+ for (arg = *args; *arg; arg++)
+ free(arg);
+ free(args);
+}
--- /dev/null
+/*
+ * Copyright (C) 2015 Thadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _TOKEN_H
+#define _TOKEN_H
+
+char ** tokens_new(char *line);
+void tokens_free(char **args);
+
+#endif