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