Adiciona tokenizer.
authorThadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
Sun, 26 Apr 2015 15:51:11 +0000 (15:51 +0000)
committerThadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
Mon, 11 May 2015 00:35:50 +0000 (00:35 +0000)
token.c [new file with mode: 0644]
token.h [new file with mode: 0644]

diff --git a/token.c b/token.c
new file mode 100644 (file)
index 0000000..6591ff9
--- /dev/null
+++ b/token.c
@@ -0,0 +1,130 @@
+/*
+ *  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);
+}
diff --git a/token.h b/token.h
new file mode 100644 (file)
index 0000000..5050c26
--- /dev/null
+++ b/token.h
@@ -0,0 +1,25 @@
+/*
+ *  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