static char * _tinycxml_parse(char *xml,XMLNode *parent, char *buffer){ char *c = NULL; char *n = NULL; char *p = NULL; XMLNode *node = NULL; if(xml == NULL) return NULL; if(*xml == 0) return xml; c = strstr(xml,"<"); if(c == NULL) return NULL; c++; if(*c == '/' ) return c; p = buffer; for(;*c && *c != '>' && *c != ' '; c++){ *(p++) = *c; } *p = 0; node = xmlnode_new(buffer); xmlnode_add(&parent->children,node); XMLNode *attrib; if(*c == ' '){ // Attributes p = buffer; n = c; c = strstr(c,">"); for(n++;n<c;n++){ if(*n == '='){ *p = 0; attrib = xmlnode_new(buffer); xmlnode_add(&node->attributes,attrib); p = buffer; // n+=2 // Get past the opening " char for(n+=2;n<c && *n!='"';n++){ *(p++) = *n; } *p = 0; attrib->content = strdup(buffer); p = buffer; }else if (*n != ' '){ *(p++) = *n; } } // Self closing tag? if( *(c-1) == '/' ) return c; } c++; /* There is a lot of XML out there that invalidates * XML spec by using '<' and friends inside a CDATA tag. * Although according to the spec we should just error * out, I prefer to mitigate errors in well known conditions. */ /* Raw copy in the CDATA tag */ /* Assume CDATA is the only content */ if(strncmp(c,"<![CDATA[",9) == 0){ n = strstr(c,"]]>"); n += 3; node->content = g_strndup(c, n-c); n = strstr(n,">"); return (n) ? n+1 : NULL; } while(1){ n = _tinycxml_parse(c,node,buffer); if (n == NULL ) break; if(*n == '/' ) { memcpy(buffer,c,n-c-1); buffer[n-c-1] = 0; if(!strisspace(buffer)){ node->content = strdup(buffer); } n = strstr(n,">"); return (n) ? n+1 : NULL; } if(*n == 0) break; c = n; } return NULL; }
char *get_next_token(char *line, size_t line_size, int *start_from) { enum parse_state state = NORMAL; int i = *start_from; static char word[BUFSIZE] = {'\0'}; int word_i = 0; /* No further tokens */ if (*start_from >= line_size) return NULL; if (strisspace(line)) return NULL; while (isspace(line[i])) ++i; /* Comment */ if (line[i] == '#') { return NULL; } if (line[i] == '$' && line[i+1] == '\'') { state = SINGLE_QUOTE; word[word_i++] = line[i++]; word[word_i++] = line[i++]; } else if (line[i] == '\'') { state = SINGLE_QUOTE; word[word_i++] = line[i++]; } if (state == SINGLE_QUOTE) { for (; i < line_size; ++i) { /* single quote makes entire value have single quote */ if (line[i] == '\'' && line[i+1] == '\'') { word[word_i++] = '\''; word[word_i] = '\''; ++i; /* this will increment a second time during loopover to skip the second quote */ } else if (line[i] == '\''){ /* terminate single-quoted string */ word[word_i++] = line[i]; word[word_i] = '\0'; break; } else { word[word_i] = line[i]; } ++word_i; } if (i >= line_size) { eprintf("Input ended unexpectedly\n"); return NULL; } ++i; /* Increment one last time to get to possible whitespace */ if (!isspace(line[i])) { eprintf("Input after quote is not whitespace.\n"); return NULL; } } else if (state == NORMAL) { for (; i < line_size; ++i) { if (isspace(line[i])) { word[word_i] = '\0'; break; } else { word[word_i] = line[i]; ++word_i; } } } /* Skip whitespace */ while (isspace(line[i])) ++i; *start_from = i; return word; }