version 1.4.30b
[polyglot.git] / parse.c
diff --git a/parse.c b/parse.c
new file mode 100644 (file)
index 0000000..aaacae1
--- /dev/null
+++ b/parse.c
@@ -0,0 +1,264 @@
+\r
+// parse.c\r
+\r
+// includes\r
+\r
+#include <string.h>\r
+\r
+#include "parse.h"\r
+#include "util.h"\r
+\r
+// constants\r
+\r
+static const int StringSize = 256;\r
+\r
+// variables\r
+\r
+char * Star[STAR_NUMBER];\r
+\r
+// prototypes\r
+\r
+static bool match_rec (char string[], const char pattern[], char * star[]);\r
+\r
+// functions\r
+\r
+// match()\r
+\r
+bool match(char string[], const char pattern[]) {\r
+\r
+   ASSERT(string!=NULL);\r
+   ASSERT(pattern!=NULL);\r
+\r
+   ASSERT(strstr(pattern,"**")==NULL);\r
+\r
+   return match_rec(string,pattern,Star);\r
+}\r
+\r
+// match_rec()\r
+\r
+static bool match_rec(char string[], const char pattern[], char * star[]) {\r
+\r
+   int c;\r
+\r
+   ASSERT(string!=NULL);\r
+   ASSERT(pattern!=NULL);\r
+   ASSERT(star!=NULL);\r
+\r
+   // iterative matches\r
+\r
+   while ((c=*pattern++) != '*') {\r
+      if (FALSE) {\r
+      } else if (c == '\0') { // end of pattern\r
+         while (*string == ' ') string++; // skip trailing spaces\r
+         return *string == '\0';\r
+      } else if (c == ' ') { // spaces\r
+         if (*string++ != ' ') return FALSE; // mismatch\r
+         while (*string == ' ') string++; // skip trailing spaces\r
+      } else { // normal character\r
+         if (*string++ != c) return FALSE; // mismatch\r
+      }\r
+   }\r
+\r
+   // recursive wildcard match\r
+\r
+   ASSERT(c=='*');\r
+\r
+   while (*string == ' ') string++; // skip leading spaces\r
+   *star++ = string; // remember beginning of star\r
+\r
+   while ((c=*string++) != '\0') { // reject empty-string match\r
+      if (c != ' ' && match_rec(string,pattern,star)) { // shortest match\r
+         ASSERT(string>star[-1]);\r
+         *string = '\0'; // truncate star\r
+         return TRUE;\r
+      }\r
+   }\r
+\r
+   return FALSE;\r
+}\r
+\r
+// parse_is_ok()\r
+\r
+bool parse_is_ok(const parse_t * parse) {\r
+\r
+   if (parse == NULL) return FALSE;\r
+   if (parse->string == NULL) return FALSE;\r
+   if (parse->pos < 0 || parse->pos > (int) strlen(parse->string)) return FALSE;\r
+   if (parse->keyword_nb < 0 || parse->keyword_nb >= KEYWORD_NUMBER) return FALSE;\r
+\r
+   return TRUE;\r
+}\r
+\r
+// parse_open()\r
+\r
+void parse_open(parse_t * parse, const char string[]) {\r
+\r
+   ASSERT(parse!=NULL);\r
+   ASSERT(string!=NULL);\r
+\r
+   parse->string = string;\r
+   parse->pos = 0;\r
+   parse->keyword_nb = 0;\r
+}\r
+\r
+// parse_close()\r
+\r
+void parse_close(parse_t * parse) {\r
+\r
+   int i;\r
+\r
+   ASSERT(parse_is_ok(parse));\r
+\r
+   parse->string = NULL;\r
+   parse->pos = 0;\r
+\r
+   for (i = 0; i < parse->keyword_nb; i++) {\r
+      my_string_clear(&parse->keyword[i]);\r
+   }\r
+\r
+   parse->keyword_nb = 0;\r
+}\r
+\r
+// parse_add_keyword()\r
+\r
+void parse_add_keyword(parse_t * parse, const char keyword[]) {\r
+\r
+   const char * * string;\r
+\r
+   ASSERT(parse_is_ok(parse));\r
+   ASSERT(keyword!=NULL);\r
+\r
+   if (parse->keyword_nb < KEYWORD_NUMBER) {\r
+\r
+      string = &parse->keyword[parse->keyword_nb];\r
+      parse->keyword_nb++;\r
+\r
+      *string = NULL;\r
+      my_string_set(string,keyword);\r
+   }\r
+}\r
+\r
+// parse_get_word()\r
+\r
+bool parse_get_word(parse_t * parse, char string[], int size) {\r
+\r
+   int pos;\r
+   int c;\r
+\r
+   ASSERT(parse!=NULL);\r
+   ASSERT(string!=NULL);\r
+   ASSERT(size>=256);\r
+\r
+   // skip blanks\r
+\r
+   for (; parse->string[parse->pos] == ' '; parse->pos++)\r
+      ;\r
+\r
+   ASSERT(parse->string[parse->pos]!=' ');\r
+\r
+   // copy word\r
+\r
+   pos = 0;\r
+\r
+   while (TRUE) {\r
+\r
+      c = parse->string[parse->pos];\r
+      if (c == ' ' || pos >= size-1) c = '\0';\r
+\r
+      string[pos] = c;\r
+      if (c == '\0') break;\r
+\r
+      parse->pos++;\r
+      pos++;\r
+   }\r
+\r
+   ASSERT(strchr(string,' ')==NULL);\r
+\r
+   return pos > 0; // non-empty word?\r
+}\r
+\r
+// parse_get_string()\r
+\r
+bool parse_get_string(parse_t * parse, char string[], int size) {\r
+\r
+   int pos;\r
+   parse_t parse_2[1];\r
+   char word[StringSize];\r
+   int i;\r
+   int c;\r
+\r
+   ASSERT(parse!=NULL);\r
+   ASSERT(string!=NULL);\r
+   ASSERT(size>=256);\r
+\r
+   // skip blanks\r
+\r
+   for (; parse->string[parse->pos] == ' '; parse->pos++)\r
+      ;\r
+\r
+   ASSERT(parse->string[parse->pos]!=' ');\r
+\r
+   // copy string\r
+\r
+   pos = 0;\r
+\r
+   while (TRUE) {\r
+\r
+      parse_open(parse_2,&parse->string[parse->pos]);\r
+\r
+      if (!parse_get_word(parse_2,word,StringSize)) {\r
+         string[pos] = '\0';\r
+         parse_close(parse_2);\r
+         goto finished;\r
+      }\r
+\r
+      for (i = 0; i < parse->keyword_nb; i++) {\r
+         if (my_string_equal(parse->keyword[i],word)) {\r
+            string[pos] = '\0';\r
+            parse_close(parse_2);\r
+            goto finished;\r
+         }\r
+      }\r
+\r
+      parse_close(parse_2);\r
+\r
+      // copy spaces\r
+\r
+      while (TRUE) {\r
+\r
+         c = parse->string[parse->pos];\r
+         if (c != ' ') break;\r
+\r
+         if (pos >= size-1) c = '\0';\r
+\r
+         string[pos] = c;\r
+         if (c == '\0') break;\r
+\r
+         parse->pos++;\r
+         pos++;\r
+      }\r
+\r
+      // copy non spaces\r
+\r
+      while (TRUE) {\r
+\r
+         c = parse->string[parse->pos];\r
+         if (c == ' ' || pos >= size-1) c = '\0';\r
+\r
+         string[pos] = c;\r
+         if (c == '\0') break;\r
+\r
+         parse->pos++;\r
+         pos++;\r
+      }\r
+\r
+      string[pos] = '\0';\r
+   }\r
+\r
+finished: ;\r
+\r
+   return pos > 0; // non-empty string?\r
+}\r
+\r
+// end of parse.cpp\r
+\r