📄 registry.c
字号:
/* * Copyright (c) 1999-2002 Caucho Technology. All rights reserved. * * Caucho Technology permits redistribution, modification and use * of this file in source and binary form ("the Software") under the * Caucho Developer Source License ("the License"). In particular, the * following conditions must be met: * * 1. Each copy or derived work of the Software must preserve the copyright * notice and this notice unmodified. * * 2. Redistributions of the Software in source or binary form must include * an unmodified copy of the License, normally in a plain ASCII text * * 3. The names "Resin" or "Caucho" are trademarks of Caucho Technology and * may not be used to endorse products derived from this software. * "Resin" or "Caucho" may not appear in the names of products derived * from this software. * * 4. Caucho Technology requests that attribution be given to Resin * in any manner possible. We suggest using the "Resin Powered" * button or creating a "powered by Resin(tm)" link to * http://www.caucho.com for each page served by Resin. * * This Software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * * Caucho Technology AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE OR ANY THIRD PARTY AS A RESULT OF USING OR * DISTRIBUTING SOFTWARE. IN NO EVENT WILL Caucho OR ITS LICENSORS BE LIABLE * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE SOFTWARE, EVEN IF HE HAS BEEN ADVISED OF THE POSSIBILITY * OF SUCH DAMAGES. */#include <stdio.h>#include <ctype.h>#include <string.h>#include <time.h>#ifdef WIN32#include <windows.h>#else#include <dirent.h>#endif#include "cse.h"/* * stream_t is a convenience class containing the parse state. */typedef struct rstream_t { void *pool; config_t *config; /* configuration we're reading into */ FILE *file; /* input stream to read */ char *path; /* file name */ int line; /* current line */ char *buf; /* expandable buffer for reading tokens */ int length; /* current length of the token in the buffer */ int capacity; /* total buffer capacity */} rstream_t;/* * Read a byte from the input stream, counting lines. */static intbuf_read(rstream_t *is){ int ch = fgetc(is->file); if (ch == '\n') is->line++; return ch;}/* * append a character to the token, expanding if necessary */static voidbuf_append(rstream_t *is, int ch){ if (is->length + 2 >= is->capacity) { is->capacity *= 2; is->buf = cse_alloc(is->pool, 2 * is->capacity); } is->buf[is->length++] = ch;}/* * Add a child to the current registry node. */static registry_t *registry_add(rstream_t *is, registry_t *node, char *key){ registry_t *child = (registry_t *) cse_alloc(is->pool, sizeof(registry_t)); memset(child, 0, sizeof(registry_t)); child->parent = node; child->key = key; child->prev = node->last; if (node->last) { node->last->next = child; node->last = child; } else { node->first = child; node->last = child; } return child;}/* * Parse an attribute. * * The 'id' attribute is equivalent to a value of the parent node. * * entity references are not handled, i.e. ', " and &. */static int parse_attribute(rstream_t *is, registry_t *node, int ch){ registry_t *attr; for (; isspace(ch); ch = buf_read(is)) { } is->length = 0; for (; ch >= 0 && ! isspace(ch) && ch != '=' && ch != '/' && ch != '>'; ch = buf_read(is)) { buf_append(is, ch); } if (is->length == 0) { ungetc(ch, is->file); return 0; } is->buf[is->length] = 0; if (! strcmp(is->buf, "id")) attr = node; else attr = registry_add(is, node, cse_strdup(is->pool, is->buf)); for (; isspace(ch); ch = buf_read(is)) { } if (ch != '=') { ungetc(ch, is->file); return ' '; } for (ch = buf_read(is); isspace(ch); ch = buf_read(is)) { } if (ch < 0 || ch == '/' || ch == '>') { cse_error(is->config, "%s:%d: expected attribute at '%c'\n", is->path, is->line, ch); return -1; } if (ch == '\'' || ch == '\"') { int end = ch; is->length = 0; for (ch = buf_read(is); ch >= 0 && ch != end; ch = buf_read(is)) buf_append(is, ch); if (ch != end) { cse_error(is->config, "%s:%d: expected '%c' at '%c'\n", is->path, is->line, end, ch); return -1; } is->buf[is->length] = 0; attr->value = cse_strdup(is->pool, is->buf); return ' '; } else { is->length = 0; for (; ch >= 0 && ! isspace(ch) && ch != '/' && ch != '>'; ch = buf_read(is)) { buf_append(is, ch); } is->buf[is->length] = 0; attr->value = cse_strdup(is->pool, is->buf); return ch; }}/* * parses an open tag, including the attributes. */static intparse_tag(rstream_t *is, registry_t **p_node, int ch){ registry_t *node = *p_node; registry_t *child = 0; is->length = 0; for (; ch >= 0 && ! isspace(ch) && ch != '/' && ch != '>'; ch = buf_read(is)) { buf_append(is, ch); } if (is->length == 0) { cse_error(is->config, "%s:%d: unexpected char at '%c'\n", is->path, is->line, ch); return -1; } is->buf[is->length] = 0; child = registry_add(is, node, cse_strdup(is->pool, is->buf)); while ((ch = parse_attribute(is, child, ch)) > 0) { } if (ch < 0) { cse_error(is->config, "%s:%d: unexpected end of file\n", is->path, is->line); return ch; } else if (ch == 0) ch = buf_read(is); for (; isspace(ch); ch = buf_read(is)) { } if (ch == '>') { *p_node = child; return 0; } else if (ch != '/') { cse_error(is->config, "%s:%d: expected '/' at '%c'\n", is->path, is->line, ch); return -1; } ch = buf_read(is); if (ch == '>') return 1; else { cse_error(is->config, "%s:%d: expected '>' at '%c'\n", is->path, is->line, ch); return -1; }}/* * parses a close tag */static intparse_end_tag(rstream_t *is, registry_t **p_node){ int ch; registry_t *node = *p_node; is->length = 0; for (ch = buf_read(is); ch >= 0 && ! isspace(ch) && ch != '/' && ch != '>'; ch = buf_read(is)) { buf_append(is, ch); } if (is->length == 0) { cse_error(is->config, "%s:%d: expected end tag at '%c'\n", is->path, is->line, ch); return -1; } for (; ch >= 0 && isspace(ch); ch = buf_read(is)) { } if (ch != '>') { cse_error(is->config, "%s:%d: expected '>' at '%c'\n", is->path, is->line, ch); return -1; } is->buf[is->length] = 0; if (strcmp(is->buf, node->key)) { cse_error(is->config, "%s:%d: end tag </%s> does not match open tag <%s>\n", is->path, is->line, is->buf, node->key); return -1; } /* XXX: need to check */ *p_node = node->parent; return 1;}/* * skips to the end of the comment */static voidskip_comment(rstream_t *is){ int ch; while ((ch = buf_read(is)) >= 0) { while (ch == '-') { ch = buf_read(is); while (ch == '-') { if ((ch = buf_read(is)) == '>') return; } } } cse_error(is->config, "%s:%d: expected comment end at end of file\n", is->path, is->line);}/* * skips to the end of the doctype declaration */static voidskip_doctype(rstream_t *is){ int ch; while ((ch = buf_read(is)) >= 0) { if (ch == '>') return; else if (ch == '"') { for (ch = buf_read(is); ch >= 0 && ch != '"'; ch = buf_read(is)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -