1b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project#include <string.h>
2b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project#include "xmlmime.h"
3b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project
4b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Projectstatic const char *
5b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source ProjectgetTok(const char **pp)
6b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project{
7b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  /* inComment means one level of nesting; inComment+1 means two levels etc */
8b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  enum { inAtom, inString, init, inComment };
9b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  int state = init;
10b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  const char *tokStart = 0;
11b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  for (;;) {
12b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    switch (**pp) {
13b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case '\0':
14b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (state == inAtom)
15b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        return tokStart;
16b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      return 0;
17b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case ' ':
18b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case '\r':
19b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case '\t':
20b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case '\n':
21b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (state == inAtom)
22b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        return tokStart;
23b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      break;
24b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case '(':
25b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (state == inAtom)
26b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        return tokStart;
27b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (state != inString)
28b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        state++;
29b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      break;
30b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case ')':
31b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (state > init)
32b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        --state;
33b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      else if (state != inString)
34b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        return 0;
35b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      break;
36b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case ';':
37b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case '/':
38b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case '=':
39b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (state == inAtom)
40b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        return tokStart;
41b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (state == init)
42b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        return (*pp)++;
43b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      break;
44b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case '\\':
45b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      ++*pp;
46b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (**pp == '\0')
47b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        return 0;
48b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      break;
49b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    case '"':
50b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      switch (state) {
51b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      case inString:
52b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        ++*pp;
53b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        return tokStart;
54b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      case inAtom:
55b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        return tokStart;
56b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      case init:
57b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        tokStart = *pp;
58b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        state = inString;
59b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        break;
60b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      }
61b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      break;
62b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    default:
63b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (state == init) {
64b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        tokStart = *pp;
65b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        state = inAtom;
66b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      }
67b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      break;
68b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    }
69b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    ++*pp;
70b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  }
71b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  /* not reached */
72b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project}
73b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project
74b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project/* key must be lowercase ASCII */
75b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project
76b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Projectstatic int
77b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Projectmatchkey(const char *start, const char *end, const char *key)
78b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project{
79b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  if (!start)
80b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    return 0;
81b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  for (; start != end; start++, key++)
82b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    if (*start != *key && *start != 'A' + (*key - 'a'))
83b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      return 0;
84b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  return *key == '\0';
85b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project}
86b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project
87b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Projectvoid
88b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source ProjectgetXMLCharset(const char *buf, char *charset)
89b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project{
90b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  const char *next, *p;
91b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project
92b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  charset[0] = '\0';
93b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  next = buf;
94b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  p = getTok(&next);
95b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  if (matchkey(p, next, "text"))
96b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    strcpy(charset, "us-ascii");
97b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  else if (!matchkey(p, next, "application"))
98b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    return;
99b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  p = getTok(&next);
100b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  if (!p || *p != '/')
101b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    return;
102b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  p = getTok(&next);
103b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project#if 0
104b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  if (!matchkey(p, next, "xml") && charset[0] == '\0')
105b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    return;
106b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project#endif
107b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  p = getTok(&next);
108b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  while (p) {
109b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    if (*p == ';') {
110b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      p = getTok(&next);
111b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      if (matchkey(p, next, "charset")) {
112b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        p = getTok(&next);
113b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        if (p && *p == '=') {
114b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project          p = getTok(&next);
115b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project          if (p) {
116b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project            char *s = charset;
117b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project            if (*p == '"') {
118b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project              while (++p != next - 1) {
119b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project                if (*p == '\\')
120b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project                  ++p;
121b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project                if (s == charset + CHARSET_MAX - 1) {
122b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project                  charset[0] = '\0';
123b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project                  break;
124b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project                }
125b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project                *s++ = *p;
126b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project              }
127b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project              *s++ = '\0';
128b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project            }
129b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project            else {
130b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project              if (next - p > CHARSET_MAX - 1)
131b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project                break;
132b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project              while (p != next)
133b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project                *s++ = *p++;
134b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project              *s = 0;
135b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project              break;
136b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project            }
137b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project          }
138b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        }
139b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project        break;
140b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project      }
141b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    }
142b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  else
143b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    p = getTok(&next);
144b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  }
145b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project}
146b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project
147b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project#ifdef TEST
148b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project
149b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project#include <stdio.h>
150b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project
151b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Projectint
152b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Projectmain(int argc, char *argv[])
153b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project{
154b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  char buf[CHARSET_MAX];
155b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  if (argc <= 1)
156b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project    return 1;
157b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  printf("%s\n", argv[1]);
158b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  getXMLCharset(argv[1], buf);
159b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  printf("charset=\"%s\"\n", buf);
160b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project  return 0;
161b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project}
162b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project
163b80e287d54a028e744f9fe412840a89ec7f8084bThe Android Open Source Project#endif /* TEST */
164