#include <eggdrop/eggdrop.h>
#include <errno.h>
Go to the source code of this file.
Functions | |
int | xml_parse_children (xml_node_t *parent, char **bufptr) |
static int | skip_space (char **bufptr) |
static void | copy_text (char **ptr, int *ptrlen, int *ptrmax, char *str, int len) |
char * | xml_entity_lookup (const char *name) |
int | xml_decode_text (char *text, int len, char **outtext, int *outlen) |
static void | append_text (xml_node_t *node, char *text, int len, int decode) |
static char * | read_name (char **bufptr) |
static char * | read_value (char **bufptr) |
static void | read_attributes (xml_node_t *node, char **bufptr) |
int | xml_parse_node (xml_node_t *parent, char **bufptr) |
xml_node_t * | xml_parse_file (const char *fname) |
Variables | |
static const char * | name_terminators = "= \t\n\r?/>" |
static xml_entity_t | entities [] |
static int | nentities = 5 |
static void append_text | ( | xml_node_t * | node, | |
char * | text, | |||
int | len, | |||
int | decode | |||
) | [static] |
Definition at line 84 of file xmlread.c.
References xml_node::len, xml_node::text, and xml_decode_text().
Referenced by xml_parse_children(), and xml_parse_node().
00085 { 00086 char *finaltext; 00087 int finallen; 00088 00089 if (decode) xml_decode_text(text, len, &finaltext, &finallen); 00090 else { 00091 finaltext = text; 00092 finallen = len; 00093 } 00094 00095 node->text = realloc(node->text, node->len + finallen + 1); 00096 memcpy(node->text + node->len, finaltext, finallen); 00097 node->len += finallen; 00098 node->text[node->len] = 0; 00099 00100 if (finaltext != text) free(finaltext); 00101 }
static void copy_text | ( | char ** | ptr, | |
int * | ptrlen, | |||
int * | ptrmax, | |||
char * | str, | |||
int | len | |||
) | [static] |
Definition at line 27 of file xmlread.c.
Referenced by xml_decode_text().
00028 { 00029 if (*ptrlen + len + 1 > *ptrmax) { 00030 *ptrmax = *ptrlen + len + 64; 00031 *ptr = realloc(*ptr, *ptrmax); 00032 } 00033 memcpy(*ptr + *ptrlen, str, len); 00034 *ptrlen += len; 00035 }
static void read_attributes | ( | xml_node_t * | node, | |
char ** | bufptr | |||
) | [static] |
Definition at line 142 of file xmlread.c.
References read_name(), read_value(), skip_space(), xml_attr_new(), and xml_node_append_attr().
Referenced by xml_parse_node().
00143 { 00144 xml_attr_t *attr; 00145 char *name, *value; 00146 00147 while (1) { 00148 skip_space(bufptr); 00149 name = read_name(bufptr); 00150 if (!name || **bufptr != '=') { 00151 if (name) free(name); 00152 return; 00153 } 00154 (*bufptr)++; 00155 value = read_value(bufptr); 00156 attr = xml_attr_new(name, value); 00157 xml_node_append_attr(node, attr); 00158 } 00159 }
static char* read_name | ( | char ** | bufptr | ) | [static] |
Definition at line 103 of file xmlread.c.
References name_terminators, and NULL.
Referenced by read_attributes(), and xml_parse_node().
00104 { 00105 int n; 00106 char *name; 00107 00108 n = strcspn(*bufptr, name_terminators); 00109 if (!n) return NULL; 00110 name = malloc(n+1); 00111 memcpy(name, *bufptr, n); 00112 name[n] = 0; 00113 *bufptr += n; 00114 return(name); 00115 }
static char* read_value | ( | char ** | bufptr | ) | [static] |
Definition at line 117 of file xmlread.c.
References name_terminators.
Referenced by read_attributes().
00118 { 00119 const char *term; 00120 char *value; 00121 int n; 00122 00123 if (**bufptr == '\'') term = "'"; 00124 else if (**bufptr == '"') term = "\""; 00125 else { 00126 term = name_terminators; 00127 (*bufptr)--; 00128 } 00129 00130 /* Skip past first quote. */ 00131 (*bufptr)++; 00132 n = strcspn(*bufptr, term); 00133 value = malloc(n+1); 00134 memcpy(value, *bufptr, n); 00135 value[n] = 0; 00136 00137 if (term != name_terminators) n++; 00138 *bufptr += n; 00139 return(value); 00140 }
static int skip_space | ( | char ** | bufptr | ) | [static] |
Definition at line 17 of file xmlread.c.
References start.
Referenced by read_attributes(), xml_decode_text(), and xml_parse_node().
00018 { 00019 char *start, *ptr; 00020 00021 start = ptr = *bufptr; 00022 while (isspace(*ptr)) ptr++; 00023 *bufptr = ptr; 00024 return(ptr - start); 00025 }
int xml_decode_text | ( | char * | text, | |
int | len, | |||
char ** | outtext, | |||
int * | outlen | |||
) |
Definition at line 57 of file xmlread.c.
References copy_text(), skip_space(), and xml_entity_lookup().
Referenced by append_text().
00058 { 00059 char *amp, *colon, *entity; 00060 int outmax, amplen; 00061 00062 *outlen = 0; 00063 outmax = len+1; 00064 *outtext = malloc(outmax); 00065 00066 len -= skip_space(&text); 00067 00068 while ((amp = memchr(text, '&', len))) { 00069 amplen = amp - text; 00070 colon = memchr(amp, ';', len - amplen); 00071 if (!colon) break; 00072 copy_text(outtext, outlen, &outmax, text, amplen); 00073 len -= (colon+1 - text); 00074 text = colon+1; 00075 *colon = 0; 00076 entity = xml_entity_lookup(amp+1); 00077 if (entity) copy_text(outtext, outlen, &outmax, entity, strlen(entity)); 00078 } 00079 while (len > 0 && isspace(text[len-1])) len--; 00080 copy_text(outtext, outlen, &outmax, text, len); 00081 return(0); 00082 }
char* xml_entity_lookup | ( | const char * | name | ) |
Definition at line 37 of file xmlread.c.
References nentities, and NULL.
Referenced by xml_decode_text().
00038 { 00039 int i, num; 00040 static char numcode[2] = {0, 0}; 00041 00042 /* See if it's a hex code. */ 00043 if (*name == '#') { 00044 name++; 00045 if (*name == 'x') num = strtol(name+1, NULL, 16); 00046 else num = strtol(name, NULL, 10); 00047 numcode[0] = num; 00048 return(numcode); 00049 } 00050 00051 for (i = 0; i < nentities; i++) { 00052 if (!strcasecmp(entities[i].name, name)) return(entities[i].value); 00053 } 00054 return(NULL); 00055 }
int xml_parse_children | ( | xml_node_t * | parent, | |
char ** | bufptr | |||
) |
Definition at line 280 of file xmlread.c.
References append_text(), and xml_parse_node().
Referenced by xml_parse_file(), and xml_parse_node().
00281 { 00282 char *ptr, *buf = *bufptr; 00283 int ret; 00284 00285 do { 00286 ptr = strchr(buf, '<'); 00287 if (!ptr) { 00288 append_text(parent, buf, strlen(buf), 1); 00289 return(0); 00290 } 00291 00292 /* Append the intervening text to the parent. */ 00293 append_text(parent, buf, ptr - buf, 1); 00294 buf = ptr; 00295 00296 ret = xml_parse_node(parent, &buf); 00297 *bufptr = buf; 00298 } while (ret == 1); 00299 return(ret); 00300 }
xml_node_t* xml_parse_file | ( | const char * | fname | ) |
Definition at line 302 of file xmlread.c.
References NULL, xml_node::type, XML_DOCUMENT, xml_node_new(), xml_parse_children(), xml_root_element(), and xml_set_error().
Referenced by channel_load(), config_load(), help_lookup_entry(), help_parse_file(), and user_load().
00303 { 00304 FILE *fp; 00305 xml_node_t *root; 00306 char *buf, *ptr; 00307 int len; 00308 00309 fp = fopen(fname, "r"); 00310 if (!fp) { 00311 xml_set_error(strerror(errno)); 00312 return(NULL); 00313 } 00314 fseek(fp, 0l, SEEK_END); 00315 len = ftell(fp); 00316 fseek(fp, 0l, SEEK_SET); 00317 buf = malloc(len+1); 00318 if (!buf) { 00319 fclose(fp); 00320 xml_set_error("out of memory"); 00321 return(NULL); 00322 } 00323 len = fread(buf, 1, len, fp); 00324 buf[len] = '\0'; 00325 fclose(fp); 00326 root = xml_node_new(); 00327 root->type = XML_DOCUMENT; 00328 ptr = buf; 00329 xml_parse_children(root, &ptr); 00330 free(buf); 00331 return xml_root_element(root); 00332 }
int xml_parse_node | ( | xml_node_t * | parent, | |
char ** | bufptr | |||
) |
Definition at line 162 of file xmlread.c.
References append_text(), xml_node::name, read_attributes(), read_name(), skip_space(), xml_node::type, XML_COMMENT, XML_ELEMENT, xml_node_append(), xml_node_free(), xml_node_new(), xml_parse_children(), XML_PROCESSING_INSTRUCTION, and xml_set_error().
Referenced by xml_parse_children().
00163 { 00164 xml_node_t *node; 00165 char *ptr, *buf = *bufptr; 00166 00167 if (*buf++ != '<') return(-1); 00168 skip_space(&buf); 00169 00170 /* Is it a closing tag? (returns 0) */ 00171 if (*buf == '/') { 00172 char *name; 00173 00174 if (!parent->name) return(-1); 00175 00176 buf++; 00177 name = read_name(&buf); 00178 if (strcasecmp(name, parent->name)) { 00179 free(name); 00180 xml_set_error("closing tag doesn't match opening tag"); 00181 return(-1); 00182 } 00183 free(name); 00184 00185 ptr = strchr(buf, '>'); 00186 if (!ptr) return(-1); 00187 *bufptr = ptr+1; 00188 return(0); 00189 } 00190 00191 /* Figure out what type of node this is. */ 00192 if (!strncmp(buf, "!--", 3)) { 00193 /* A comment. */ 00194 buf += 3; 00195 ptr = strstr(buf, "-->"); 00196 if (!ptr) { 00197 xml_set_error("comment has no end"); 00198 return(-1); 00199 } 00200 00201 node = xml_node_new(); 00202 node->type = XML_COMMENT; 00203 append_text(node, buf, ptr-buf, 1); 00204 xml_node_append(parent, node); 00205 *bufptr = ptr+3; 00206 return(1); 00207 } 00208 else if (!strncasecmp(buf, "![CDATA[", 8)) { 00209 /* CDATA section. */ 00210 buf += 7; 00211 ptr = strstr(buf, "]]>"); 00212 if (!ptr) { 00213 xml_set_error("CDATA has no end"); 00214 return(-1); 00215 } 00216 00217 append_text(parent, buf, ptr-buf, 0); 00218 *bufptr = ptr+3; 00219 return(1); 00220 } 00221 else if (!strncasecmp(buf, "!DOCTYPE", 8)) { 00222 /* XXX Incorrect doctype parsing, fix later. */ 00223 buf += 8; 00224 ptr = strchr(buf, '>'); 00225 if (!ptr) return(-1); 00226 *bufptr = ptr+1; 00227 return(1); 00228 } 00229 else if (*buf == '?') { 00230 /* Processing instruction. */ 00231 buf++; 00232 skip_space(&buf); 00233 node = xml_node_new(); 00234 node->type = XML_PROCESSING_INSTRUCTION; 00235 } 00236 else { 00237 /* Otherwise, try it as a normal node. */ 00238 node = xml_node_new(); 00239 node->type = XML_ELEMENT; 00240 } 00241 00242 node->name = read_name(&buf); 00243 read_attributes(node, &buf); 00244 if (node->type == XML_PROCESSING_INSTRUCTION) { 00245 if (strncmp(buf, "?>", 2)) { 00246 xml_node_free(node); 00247 xml_set_error("invalid processing instruction"); 00248 return(-1); 00249 } 00250 xml_node_append(parent, node); 00251 *bufptr = buf+2; 00252 return(1); 00253 } 00254 00255 /* Is it an empty tag? */ 00256 if (!strncmp(buf, "/>", 2)) { 00257 xml_node_append(parent, node); 00258 *bufptr = buf+2; 00259 return(1); 00260 } 00261 else if (*buf != '>') { 00262 xml_set_error("invalid tag"); 00263 return(-1); 00264 } 00265 00266 /* Move past the '>'. */ 00267 buf++; 00268 if (xml_parse_children(node, &buf) != -1) { 00269 *bufptr = buf; 00270 xml_node_append(parent, node); 00271 return(1); 00272 } 00273 00274 /* Error reading children. */ 00275 xml_node_free(node); 00276 return(-1); 00277 }
xml_entity_t entities[] [static] |
const char* name_terminators = "= \t\n\r?/>" [static] |
int nentities = 5 [static] |