netsurf-2.9/0000775000175000017500000000000011734430315012047 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/0000775000175000017500000000000011734430254013754 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/include/0000775000175000017500000000000011734430254015377 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/include/hubbub/0000775000175000017500000000000011734430254016646 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/include/hubbub/functypes.h0000664000175000017500000000272111460664405021044 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007-8 John-Mark Bell */ #ifndef hubbub_functypes_h_ #define hubbub_functypes_h_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include /** * Type of allocation function for hubbub * * The semantics of this function are the same as for realloc(). * * \param ptr Pointer to object to reallocate, or NULL for a new allocation * \param size Required length in bytes, or zero to free ::ptr * \param pw Pointer to client data * \return Pointer to allocated object, or NULL on failure */ typedef void *(*hubbub_allocator_fn)(void *ptr, size_t size, void *pw); /** * Type of token handling function * * \param token Pointer to token to handle * \param pw Pointer to client data * \return HUBBUB_OK on success, appropriate error otherwise. */ typedef hubbub_error (*hubbub_token_handler)( const hubbub_token *token, void *pw); /** * Type of parse error handling function * * \param line Source line on which error occurred * \param col Column in ::line of start of erroneous input * \param message Error message * \param pw Pointer to client data */ typedef void (*hubbub_error_handler)(uint32_t line, uint32_t col, const char *message, void *pw); #ifdef __cplusplus } #endif #endif netsurf-2.9/hubbub-0.1.2/include/hubbub/hubbub.h0000664000175000017500000000062111476510167020272 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef hubbub_h_ #define hubbub_h_ #ifdef __cplusplus extern "C" { #endif #include #include #include #ifdef __cplusplus } #endif #endif netsurf-2.9/hubbub-0.1.2/include/hubbub/parser.h0000664000175000017500000000433511460664405020323 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007-8 John-Mark Bell */ #ifndef hubbub_parser_h_ #define hubbub_parser_h_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include typedef struct hubbub_parser hubbub_parser; /** * Hubbub parser option types */ typedef enum hubbub_parser_opttype { HUBBUB_PARSER_TOKEN_HANDLER, HUBBUB_PARSER_ERROR_HANDLER, HUBBUB_PARSER_CONTENT_MODEL, HUBBUB_PARSER_TREE_HANDLER, HUBBUB_PARSER_DOCUMENT_NODE, HUBBUB_PARSER_ENABLE_SCRIPTING } hubbub_parser_opttype; /** * Hubbub parser option parameters */ typedef union hubbub_parser_optparams { struct { hubbub_token_handler handler; void *pw; } token_handler; /**< Token handling callback */ struct { hubbub_error_handler handler; void *pw; } error_handler; /**< Error handling callback */ struct { hubbub_content_model model; } content_model; /**< Current content model */ hubbub_tree_handler *tree_handler; /**< Tree handling callbacks */ void *document_node; /**< Document node */ bool enable_scripting; /**< Whether to enable scripting */ } hubbub_parser_optparams; /* Create a hubbub parser */ hubbub_error hubbub_parser_create(const char *enc, bool fix_enc, hubbub_allocator_fn alloc, void *pw, hubbub_parser **parser); /* Destroy a hubbub parser */ hubbub_error hubbub_parser_destroy(hubbub_parser *parser); /* Configure a hubbub parser */ hubbub_error hubbub_parser_setopt(hubbub_parser *parser, hubbub_parser_opttype type, hubbub_parser_optparams *params); /* Pass a chunk of data to a hubbub parser for parsing */ /* This data is encoded in the input charset */ hubbub_error hubbub_parser_parse_chunk(hubbub_parser *parser, const uint8_t *data, size_t len); /* Inform the parser that the last chunk of data has been parsed */ hubbub_error hubbub_parser_completed(hubbub_parser *parser); /* Read the document charset */ const char *hubbub_parser_read_charset(hubbub_parser *parser, hubbub_charset_source *source); #ifdef __cplusplus } #endif #endif netsurf-2.9/hubbub-0.1.2/include/hubbub/errors.h0000664000175000017500000000142311460664405020336 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef hubbub_errors_h_ #define hubbub_errors_h_ #ifdef __cplusplus extern "C" { #endif #include typedef enum hubbub_error { HUBBUB_OK = 0, HUBBUB_REPROCESS = 1, HUBBUB_ENCODINGCHANGE = 2, HUBBUB_NOMEM = 5, HUBBUB_BADPARM = 6, HUBBUB_INVALID = 7, HUBBUB_FILENOTFOUND = 8, HUBBUB_NEEDDATA = 9, HUBBUB_BADENCODING = 10, HUBBUB_UNKNOWN = 11 } hubbub_error; /* Convert a hubbub error value to a string */ const char *hubbub_error_to_string(hubbub_error error); #ifdef __cplusplus } #endif #endif netsurf-2.9/hubbub-0.1.2/include/hubbub/types.h0000664000175000017500000000573011460664405020173 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef hubbub_types_h_ #define hubbub_types_h_ #ifdef __cplusplus extern "C" { #endif #include #include /** Source of charset information, in order of importance * A client-dictated charset will override all others. * A document-specified charset will override autodetection or the default */ typedef enum hubbub_charset_source { HUBBUB_CHARSET_UNKNOWN = 0, /**< Unknown */ HUBBUB_CHARSET_TENTATIVE = 1, /**< Charset may be changed * with further data */ HUBBUB_CHARSET_CONFIDENT = 2 /**< Charset definite */ } hubbub_charset_source; /** * Content model flag */ typedef enum hubbub_content_model { HUBBUB_CONTENT_MODEL_PCDATA, HUBBUB_CONTENT_MODEL_RCDATA, HUBBUB_CONTENT_MODEL_CDATA, HUBBUB_CONTENT_MODEL_PLAINTEXT } hubbub_content_model; /** * Quirks mode flag */ typedef enum hubbub_quirks_mode { HUBBUB_QUIRKS_MODE_NONE, HUBBUB_QUIRKS_MODE_LIMITED, HUBBUB_QUIRKS_MODE_FULL } hubbub_quirks_mode; /** * Type of an emitted token */ typedef enum hubbub_token_type { HUBBUB_TOKEN_DOCTYPE, HUBBUB_TOKEN_START_TAG, HUBBUB_TOKEN_END_TAG, HUBBUB_TOKEN_COMMENT, HUBBUB_TOKEN_CHARACTER, HUBBUB_TOKEN_EOF } hubbub_token_type; /** * Possible namespaces */ typedef enum hubbub_ns { HUBBUB_NS_NULL, HUBBUB_NS_HTML, HUBBUB_NS_MATHML, HUBBUB_NS_SVG, HUBBUB_NS_XLINK, HUBBUB_NS_XML, HUBBUB_NS_XMLNS } hubbub_ns; /** * Tokeniser string type */ typedef struct hubbub_string { const uint8_t *ptr; /**< Pointer to data */ size_t len; /**< Byte length of string */ } hubbub_string; /** * Tag attribute data */ typedef struct hubbub_attribute { hubbub_ns ns; /**< Attribute namespace */ hubbub_string name; /**< Attribute name */ hubbub_string value; /**< Attribute value */ } hubbub_attribute; /** * Data for doctype token */ typedef struct hubbub_doctype { hubbub_string name; /**< Doctype name */ bool public_missing; /**< Whether the public id is missing */ hubbub_string public_id; /**< Doctype public identifier */ bool system_missing; /**< Whether the system id is missing */ hubbub_string system_id; /**< Doctype system identifier */ bool force_quirks; /**< Doctype force-quirks flag */ } hubbub_doctype; /** * Data for a tag */ typedef struct hubbub_tag { hubbub_ns ns; /**< Tag namespace */ hubbub_string name; /**< Tag name */ uint32_t n_attributes; /**< Count of attributes */ hubbub_attribute *attributes; /**< Array of attribute data */ bool self_closing; /**< Whether the tag can have children */ } hubbub_tag; /** * Token data */ typedef struct hubbub_token { hubbub_token_type type; /**< The token type */ union { hubbub_doctype doctype; hubbub_tag tag; hubbub_string comment; hubbub_string character; } data; /**< Type-specific data */ } hubbub_token; #ifdef __cplusplus } #endif #endif netsurf-2.9/hubbub-0.1.2/include/hubbub/tree.h0000664000175000017500000002162711460664405017771 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef hubbub_tree_h_ #define hubbub_tree_h_ #ifdef __cplusplus extern "C" { #endif #include /** * Create a comment node * * \param ctx Client's context * \param data String content of node * \param result Pointer to location to receive created node * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: if successful, result's reference count must be 1. */ typedef hubbub_error (*hubbub_tree_create_comment)(void *ctx, const hubbub_string *data, void **result); /** * Create a doctype node * * \param ctx Client's context * \param doctype Data for doctype node (name, public id, system id) * \param result Pointer to location to receive created node * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: if successful, result's reference count must be 1. */ typedef hubbub_error (*hubbub_tree_create_doctype)(void *ctx, const hubbub_doctype *doctype, void **result); /** * Create an element node * * \param ctx Client's context * \param tag Data for element node (namespace, name, attributes) * \param result Pointer to location to receive created node * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: if successful, result's reference count must be 1. */ typedef hubbub_error (*hubbub_tree_create_element)(void *ctx, const hubbub_tag *tag, void **result); /** * Create a text node * * \param ctx Client's context * \param data String content of node * \param result Pointer to location to receive created node * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: if successful, result's reference count must be 1. */ typedef hubbub_error (*hubbub_tree_create_text)(void *ctx, const hubbub_string *data, void **result); /** * Increase a node's reference count * * \param ctx Client's context * \param node Node to reference * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: node's reference count is one larger than before */ typedef hubbub_error (*hubbub_tree_ref_node)(void *ctx, void *node); /** * Decrease a node's reference count * * \param ctx Client's context * \param node Node to reference * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: If the node's reference count becomes zero, and it has no * parent, and it is not the document node, then it is destroyed. Otherwise, * the reference count is one less than before. */ typedef hubbub_error (*hubbub_tree_unref_node)(void *ctx, void *node); /** * Append a node to the end of another's child list * * \param ctx Client's context * \param parent The node to append to * \param child The node to append * \param result Pointer to location to receive appended node * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: if successful, result's reference count is increased by 1 * * Important: *result may not == child (e.g. if text nodes got coalesced) */ typedef hubbub_error (*hubbub_tree_append_child)(void *ctx, void *parent, void *child, void **result); /** * Insert a node into another's child list * * \param ctx Client's context * \param parent The node to insert into * \param child The node to insert * \param ref_child The node to insert before * \param result Pointer to location to receive inserted node * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: if successful, result's reference count is increased by 1 * * Important: *result may not == child (e.g. if text nodes got coalesced) */ typedef hubbub_error (*hubbub_tree_insert_before)(void *ctx, void *parent, void *child, void *ref_child, void **result); /** * Remove a node from another's child list * * \param ctx Client context * \param parent The node to remove from * \param child The node to remove * \param result Pointer to location to receive removed node * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: if successful, result's reference count is increased by 1 */ typedef hubbub_error (*hubbub_tree_remove_child)(void *ctx, void *parent, void *child, void **result); /** * Clone a node * * \param ctx Client's context * \param node The node to clone * \param deep True to clone entire subtree, false to clone only the node * \param result Pointer to location to receive clone * \return HUBBUB_OK on success, appropriate error otherwise. * * Postcondition: if successful, result's reference count must be 1. */ typedef hubbub_error (*hubbub_tree_clone_node)(void *ctx, void *node, bool deep, void **result); /** * Move all the children of one node to another * * \param ctx Client's context * \param node The initial parent node * \param new_parent The new parent node * \return HUBBUB_OK on success, appropriate error otherwise. */ typedef hubbub_error (*hubbub_tree_reparent_children)(void *ctx, void *node, void *new_parent); /** * Retrieve the parent of a node * * \param ctx Client context * \param node Node to retrieve the parent of * \param element_only True if the parent must be an element, false otherwise * \param result Pointer to location to receive parent node * \return HUBBUB_OK on success, appropriate error otherwise. * * If there is a parent node, but it is not an element node and element_only * is true, then act as if no parent existed. * * Postcondition: if there is a parent, then result's reference count must be * increased. */ typedef hubbub_error (*hubbub_tree_get_parent)(void *ctx, void *node, bool element_only, void **result); /** * Determine if a node has children * * \param ctx Client's context * \param node The node to inspect * \param result Location to receive result * \return HUBBUB_OK on success, appropriate error otherwise. */ typedef hubbub_error (*hubbub_tree_has_children)(void *ctx, void *node, bool *result); /** * Associate a node with a form * * \param ctx Client's context * \param form The form to associate with * \param node The node to associate * \return HUBBUB_OK on success, appropriate error otherwise. */ typedef hubbub_error (*hubbub_tree_form_associate)(void *ctx, void *form, void *node); /** * Add attributes to a node * * \param ctx Client's context * \param node The node to add to * \param attributes Array of attributes to add * \param n_attributes Number of entries in array * \return HUBBUB_OK on success, appropriate error otherwise. */ typedef hubbub_error (*hubbub_tree_add_attributes)(void *ctx, void *node, const hubbub_attribute *attributes, uint32_t n_attributes); /** * Notification of the quirks mode of a document * * \param ctx Client's context * \param mode The quirks mode * \return HUBBUB_OK on success, appropriate error otherwise. */ typedef hubbub_error (*hubbub_tree_set_quirks_mode)(void *ctx, hubbub_quirks_mode mode); /** * Notification that a potential encoding change is required * * \param ctx Client's context * \param charset The new charset for the source data * \return HUBBUB_OK to continue using the current input handler, * HUBBUB_ENCODINGCHANGE to stop processing immediately and * return control to the client, * appropriate error otherwise. */ typedef hubbub_error (*hubbub_tree_encoding_change)(void *ctx, const char *encname); /** * Hubbub tree handler */ typedef struct hubbub_tree_handler { hubbub_tree_create_comment create_comment; /**< Create comment */ hubbub_tree_create_doctype create_doctype; /**< Create doctype */ hubbub_tree_create_element create_element; /**< Create element */ hubbub_tree_create_text create_text; /**< Create text */ hubbub_tree_ref_node ref_node; /**< Reference node */ hubbub_tree_unref_node unref_node; /**< Unreference node */ hubbub_tree_append_child append_child; /**< Append child */ hubbub_tree_insert_before insert_before; /**< Insert before */ hubbub_tree_remove_child remove_child; /**< Remove child */ hubbub_tree_clone_node clone_node; /**< Clone node */ hubbub_tree_reparent_children reparent_children;/**< Reparent children*/ hubbub_tree_get_parent get_parent; /**< Get parent */ hubbub_tree_has_children has_children; /**< Has children? */ hubbub_tree_form_associate form_associate; /**< Form associate */ hubbub_tree_add_attributes add_attributes; /**< Add attributes */ hubbub_tree_set_quirks_mode set_quirks_mode; /**< Set quirks mode */ hubbub_tree_encoding_change encoding_change; /**< Change encoding */ void *ctx; /**< Context pointer */ } hubbub_tree_handler; #ifdef __cplusplus } #endif #endif netsurf-2.9/hubbub-0.1.2/examples/0000775000175000017500000000000011734430254015572 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/examples/makefile0000664000175000017500000000046111470325110017262 0ustar vincevinceCC := gcc LD := gcc CFLAGS := `pkg-config --cflags libhubbub` `xml2-config --cflags` LDFLAGS := `pkg-config --libs libhubbub` `xml2-config --libs` SRC := libxml.c libxml: $(SRC:.c=.o) @$(LD) -o $@ $^ $(LDFLAGS) .PHONY: clean clean: $(RM) libxml $(SRC:.c=.o) %.o: %.c @$(CC) -c $(CFLAGS) -o $@ $< netsurf-2.9/hubbub-0.1.2/examples/libxml.c0000664000175000017500000006516211507106652017237 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * * Copyright 2008 Andrew Sidwell * Copyright 2008 John-Mark Bell */ #define _GNU_SOURCE /* for strndup */ #include #include #include #include #include #include #include #define UNUSED(x) ((x)=(x)) /** * Error codes */ typedef enum error_code { OK, NOMEM, BADENCODING, ENCODINGCHANGE } error_code; /** * Source of encoding information */ typedef enum encoding_source { ENCODING_SOURCE_HEADER, ENCODING_SOURCE_DETECTED, ENCODING_SOURCE_META } encoding_source; /** * Our context */ typedef struct context { hubbub_parser *parser; /**< Underlying parser */ htmlDocPtr document; /**< Document we're building */ const char *encoding; /**< The charset of the input */ encoding_source enc_source; /**< The encoding source */ #define NUM_NAMESPACES (6) xmlNsPtr namespaces[NUM_NAMESPACES]; /**< XML namespaces */ #undef NUM_NAMESPACES hubbub_tree_handler tree_handler; /**< Hubbub tree callbacks */ } context; /** * Mapping of namespace prefixes to URIs, indexed by hubbub_ns. */ static struct { const char *prefix; const char *url; } namespaces[] = { { NULL, NULL }, { NULL, "http://www.w3.org/1999/xhtml" }, { "math", "http://www.w3.org/1998/Math/MathML" }, { "svg", "http://www.w3.org/2000/svg" }, { "xlink", "http://www.w3.org/1999/xlink" }, /** \todo Oh dear. LibXML2 refuses to create any namespace with a * prefix of "xml". That sucks, royally. */ { "xml", "http://www.w3.org/XML/1998/namespace" }, { "xmlns", "http://www.w3.org/2000/xmlns/" } }; static inline char *c_string_from_hubbub_string(context *ctx, const hubbub_string *str); static void create_namespaces(context *ctx, xmlNode *root); static hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result); static hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, void **result); static hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result); static hubbub_error create_text(void *ctx, const hubbub_string *data, void **result); static hubbub_error ref_node(void *ctx, void *node); static hubbub_error unref_node(void *ctx, void *node); static hubbub_error append_child(void *ctx, void *parent, void *child, void **result); static hubbub_error insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result); static hubbub_error remove_child(void *ctx, void *parent, void *child, void **result); static hubbub_error clone_node(void *ctx, void *node, bool deep, void **result); static hubbub_error reparent_children(void *ctx, void *node, void *new_parent); static hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result); static hubbub_error has_children(void *ctx, void *node, bool *result); static hubbub_error form_associate(void *ctx, void *form, void *node); static hubbub_error add_attributes(void *ctx, void *node, const hubbub_attribute *attributes, uint32_t n_attributes); static hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode); static hubbub_error change_encoding(void *ctx, const char *charset); /* Prototype tree handler struct */ static hubbub_tree_handler tree_handler = { create_comment, create_doctype, create_element, create_text, ref_node, unref_node, append_child, insert_before, remove_child, clone_node, reparent_children, get_parent, has_children, form_associate, add_attributes, set_quirks_mode, change_encoding, NULL }; /** * Memory allocation callback. * * \param ptr Pointer to block to reallocate, or NULL for a new allocation * \param len Required length, in bytes. If zero, then free the block * \param pw Pointer to our private data * \return Pointer to resized block */ static void *myrealloc(void *ptr, size_t len, void *pw) { /* In this implementation, we just call realloc. * If we have more complex allocation requirements (e.g. multiple * allocation arenas, then we could use pw to point to the arena to use) */ UNUSED(pw); return realloc(ptr, len); } /****************************************************************************** * Main hubbub driver code * ******************************************************************************/ static error_code create_context(const char *charset, context **ctx); static void destroy_context(context *c); static error_code parse_chunk(context *c, const uint8_t *data, size_t len); static error_code parse_completed(context *c); int main(int argc, char **argv) { error_code error; context *c; hubbub_parser_optparams params; FILE *input; uint8_t *buf; size_t len; if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } /* Read input file into memory. If we wanted to, we could read into * a fixed-size buffer and pass each chunk to the parser sequentially. */ input = fopen(argv[1], "r"); if (input == NULL) { fprintf(stderr, "Failed opening %s\n", argv[1]); return 1; } fseek(input, 0, SEEK_END); len = ftell(input); fseek(input, 0, SEEK_SET); buf = malloc(len); if (buf == NULL) { fclose(input); fprintf(stderr, "No memory for buf\n"); return 1; } fread(buf, 1, len, input); /* Create our parsing context */ error = create_context(NULL, &c); if (error != OK) { free(buf); fclose(input); fprintf(stderr, "Failed creating parsing context\n"); return 1; } /* Attempt to parse the document */ error = parse_chunk(c, buf, len); assert(error == OK || error == ENCODINGCHANGE); if (error == ENCODINGCHANGE) { /* During parsing, we detected that the charset of the * input data was different from what was auto-detected * (see the change_encoding callback for more details). * Therefore, we must destroy the current parser and create * a new one using the newly-detected charset. Then we * reparse the data using the new parser. * * change_encoding() will have put the new charset into * c->encoding. */ hubbub_parser *temp; if (hubbub_parser_create(c->encoding, true, myrealloc, NULL, &temp) != HUBBUB_OK) { destroy_context(c); free(buf); fclose(input); fprintf(stderr, "Failed recreating parser\n"); return 1; } hubbub_parser_destroy(c->parser); c->parser = temp; /* Retry the parse */ error = parse_chunk(c, buf, len); } if (error != OK) { destroy_context(c); free(buf); fclose(input); fprintf(stderr, "Failed parsing document\n"); return 1; } /* Tell hubbub that we've finished */ error = parse_completed(c); if (error != OK) { destroy_context(c); free(buf); fclose(input); fprintf(stderr, "Failed parsing document\n"); return 1; } /* We're done with this */ free(buf); /* At this point, the DOM tree can be accessed through c->document */ /* Let's dump it to stdout */ /* In a real application, we'd probably want to grab the document * from the parsing context, then destroy the context as it's no * longer of any use */ xmlDebugDumpDocument(stdout, c->document); /* Clean up */ destroy_context(c); fclose(input); return 0; } /** * Create a parsing context * * \param charset The charset the input data is in, or NULL to autodetect * \param ctx Location to receive context * \return OK on success, * NOMEM on memory exhaustion, * BADENCODING if charset isn't supported */ error_code create_context(const char *charset, context **ctx) { context *c; hubbub_parser_optparams params; uint32_t i; hubbub_error error; c = malloc(sizeof(context)); if (c == NULL) return NOMEM; c->parser = NULL; c->encoding = charset; c->enc_source = ENCODING_SOURCE_HEADER; c->document = NULL; /* Create the parser */ error = hubbub_parser_create(c->encoding, true, myrealloc, NULL, &c->parser); if (error != HUBBUB_OK) { free(c); if (error == HUBBUB_BADENCODING) return BADENCODING; else return NOMEM; /* Assume OOM */ } /* Create the root node of the document */ c->document = htmlNewDocNoDtD(NULL, NULL); if (c->document == NULL) { hubbub_parser_destroy(c->parser); free(c); return NOMEM; } /* Reference count of zero */ c->document->_private = (void *) 0; for (i = 0; i < sizeof(c->namespaces) / sizeof(c->namespaces[0]); i++) { c->namespaces[i] = NULL; } /* The following are both needed to make hubbub do anything. If it has * no tree handler or document node registered, it won't attempt to * build a tree. */ /* Register tree handler with hubbub */ c->tree_handler = tree_handler; c->tree_handler.ctx = (void *) c; params.tree_handler = &c->tree_handler; hubbub_parser_setopt(c->parser, HUBBUB_PARSER_TREE_HANDLER, ¶ms); /* Also tell it about the document node (referencing it first) */ ref_node(c, c->document); params.document_node = c->document; hubbub_parser_setopt(c->parser, HUBBUB_PARSER_DOCUMENT_NODE, ¶ms); *ctx = c; return OK; } /** * Destroy a parsing context * * \param c Context to destroy */ void destroy_context(context *c) { if (c == NULL) return; if (c->parser != NULL) hubbub_parser_destroy(c->parser); xmlFreeDoc(c->document); c->parser = NULL; c->encoding = NULL; c->document = NULL; free(c); return; } /** * Parse a chunk of the input document * * \param c Parsing context * \param data Data buffer * \param len Length, in bytes, of data in buffer * \return OK on success, * ENCODINGCHANGE if the encoding needs changing */ error_code parse_chunk(context *c, const uint8_t *data, size_t len) { hubbub_error err; err = hubbub_parser_parse_chunk(c->parser, (uint8_t *) data, len); if (err == HUBBUB_ENCODINGCHANGE) return ENCODINGCHANGE; return OK; } /** * Inform that we've run out of input to parse * * \param c Parsing context * \return OK. */ error_code parse_completed(context *c) { hubbub_error error; error = hubbub_parser_completed(c->parser); /** \todo error handling */ return OK; } /****************************************************************************** * Helper functions for tree building * ******************************************************************************/ /** * Convert a hubbub string to a C string * * \param ctx Our context * \param str The string to convert * \return Pointer to C string, must be freed * * This is a simple utility routine, as libXML expects data to be C strings. * If we were implementing our own tree, we might store hubbub-style strings * instead (with the associated memory saving) */ char *c_string_from_hubbub_string(context *ctx, const hubbub_string *str) { return strndup((const char *) str->ptr, (int) str->len); } /** * Initialise a context's XML namespaces * * \param ctx Our context * \param root The root node of the XML tree * * Again, this is specific to the needs of libXML. */ void create_namespaces(context *ctx, xmlNode *root) { uint32_t i; /* Index 0 is the NULL namespace, so skip over it */ for (i = 1; i < sizeof(namespaces) / sizeof(namespaces[0]); i++) { ctx->namespaces[i - 1] = xmlNewNs(root, BAD_CAST namespaces[i].url, BAD_CAST namespaces[i].prefix); /* Expect "xml" to fail here */ if (ctx->namespaces[i - 1] == NULL) { fprintf(stderr, "WARNING: Failed creating namespace %s\n", namespaces[i].prefix); } } } /****************************************************************************** * Tree callbacks for hubbub * ******************************************************************************/ /** * Create a comment node * * \param ctx Our context * \param data The comment body * \param result Location to receive manufactured node * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: if successful, result's reference count must be 1. */ hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result) { context *c = (context *) ctx; char *content; xmlNodePtr n; content = c_string_from_hubbub_string(c, data); if (content == NULL) return HUBBUB_NOMEM; n = xmlNewDocComment(c->document, BAD_CAST content); if (n == NULL) { free(content); return HUBBUB_NOMEM; } /* We use the _private field of libXML's xmlNode struct for the * reference count. */ n->_private = (void *) (uintptr_t) 1; free(content); *result = (void *) n; return HUBBUB_OK; } /** * Create a doctype node * * \param ctx Our context * \param doctype Data for doctype node (name, public ID and system ID) * \param result Location to receive manufactured node * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: if successful, result's reference count must be 1. */ hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, void **result) { context *c = (context *) ctx; char *name, *public = NULL, *system = NULL; xmlDtdPtr n; name = c_string_from_hubbub_string(c, &doctype->name); if (name == NULL) return HUBBUB_NOMEM; /* May not have public ID */ if (!doctype->public_missing) { public = c_string_from_hubbub_string(c, &doctype->public_id); if (public == NULL) { free(name); return HUBBUB_NOMEM; } } /* May not have system ID */ if (!doctype->system_missing) { system = c_string_from_hubbub_string(c, &doctype->system_id); if (system == NULL) { free(public); free(name); return HUBBUB_NOMEM; } } n = xmlNewDtd(c->document, BAD_CAST name, BAD_CAST (public ? public : ""), BAD_CAST (system ? system : "")); if (n == NULL) { free(system); free(public); free(name); return HUBBUB_NOMEM; } /* Again, reference count must be 1 */ n->_private = (void *) (uintptr_t) 1; *result = (void *) n; free(system); free(public); free(name); return HUBBUB_OK; } /** * Create an element node * * \param ctx Our context * \param tag Data for node * \param result Location to receive manufactured node * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: if successful, result's reference count must be 1. */ hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result) { context *c = (context *) ctx; char *name; xmlNodePtr n; name = c_string_from_hubbub_string(c, &tag->name); if (name == NULL) return HUBBUB_NOMEM; if (c->namespaces[0] != NULL) { n = xmlNewDocNode(c->document, c->namespaces[tag->ns - 1], BAD_CAST name, NULL); } else { n = xmlNewDocNode(c->document, NULL, BAD_CAST name, NULL); /* We're creating the root node of the document. Therefore, * create the namespaces and set this node's namespace */ if (n != NULL && c->namespaces[0] == NULL) { create_namespaces(c, (void *) n); xmlSetNs(n, c->namespaces[tag->ns - 1]); } } if (n == NULL) { free(name); return HUBBUB_NOMEM; } /* Reference count must be 1 */ n->_private = (void *) (uintptr_t) 1; /* Attempt to add attributes to node */ if (tag->n_attributes > 0 && add_attributes(ctx, (void *) n, tag->attributes, tag->n_attributes) != 0) { xmlFreeNode(n); free(name); return HUBBUB_NOMEM; } *result = (void *) n; free(name); return HUBBUB_OK; } /** * Create a text node * * \param ctx Our context * \param data Node data * \param result Location to receive manufactured node * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: if successfult, result's reference count must be 1. */ hubbub_error create_text(void *ctx, const hubbub_string *data, void **result) { context *c = (context *) ctx; xmlNodePtr n; n = xmlNewDocTextLen(c->document, BAD_CAST data->ptr, (int) data->len); if (n == NULL) { return HUBBUB_NOMEM; } /* Reference count must be 1 */ n->_private = (void *) (uintptr_t) 1; *result = (void *) n; return HUBBUB_OK; } /** * Increase a node's reference count * * \param ctx Our context * \param node The node to reference * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error ref_node(void *ctx, void *node) { context *c = (context *) ctx; if (node == c->document) { xmlDoc *n = (xmlDoc *) node; uintptr_t count = (uintptr_t) n->_private; n->_private = (void *) ++count; } else { xmlNode *n = (xmlNode *) node; uintptr_t count = (uintptr_t) n->_private; n->_private = (void *) ++count; } return HUBBUB_OK; } /** * Decrease a node's reference count * * \param ctx Our context * \param node The node to unreference * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: If the node's reference count becomes zero, and it has no * parent, and it is not the document node, then it is destroyed. */ hubbub_error unref_node(void *ctx, void *node) { context *c = (context *) ctx; if (node == c->document) { xmlDoc *n = (xmlDoc *) node; uintptr_t count = (uintptr_t) n->_private; /* Trap any attempt to unref a non-referenced node */ assert(count != 0 && "Node has refcount of zero"); /* Never destroy document node */ n->_private = (void *) --count; } else { xmlNode *n = (xmlNode *) node; uintptr_t count = (uintptr_t) n->_private; /* Trap any attempt to unref a non-referenced node */ assert(count != 0 && "Node has refcount of zero"); n->_private = (void *) --count; /* Destroy node, if it has no parent */ if (count == 0 && n->parent == NULL) { xmlFreeNode(n); } } return HUBBUB_OK; } /** * Append a node to the end of another's child list * * \param ctx Our context * \param parent The node to append to * \param child The node to append * \param result Location to receive appended node * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: if successful, result's reference count is increased by 1 * * Important: *result may not == child (e.g. if text nodes got coalesced) */ hubbub_error append_child(void *ctx, void *parent, void *child, void **result) { xmlNode *chld = (xmlNode *) child; xmlNode *p = (xmlNode *) parent; /* Note: this does not exactly follow the current specification. * See http://www.whatwg.org/specs/web-apps/current-work/ \ * multipage/tree-construction.html#insert-a-character * for the exact behaviour required. */ if (chld->type == XML_TEXT_NODE && p->last != NULL && p->last->type == XML_TEXT_NODE) { /* Need to clone the child, as libxml will free it if it * merges the content with a pre-existing text node. */ chld = xmlCopyNode(chld, 0); if (chld == NULL) return HUBBUB_NOMEM; *result = xmlAddChild(p, chld); assert(*result != (void *) chld); } else { *result = xmlAddChild(p, chld); } if (*result == NULL) return HUBBUB_NOMEM; ref_node(ctx, *result); return HUBBUB_OK; } /** * Insert a node into another's child list * * \param ctx Our context * \param parent The node to insert into * \param child The node to insert * \param ref_child The node to insert before * \param result Location to receive inserted node * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: if successful, result's reference count is increased by 1 * * Important: *result may not == child (e.g. if text nodes got coalesced) */ hubbub_error insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result) { xmlNode *chld = (xmlNode *) child; xmlNode *ref = (xmlNode *) ref_child; if (chld->type == XML_TEXT_NODE && ref->prev != NULL && ref->prev->type == XML_TEXT_NODE) { /* Clone text node, as it'll be freed by libxml */ chld = xmlCopyNode(chld, 0); if (chld == NULL) return HUBBUB_NOMEM; *result = xmlAddNextSibling(ref->prev, chld); assert(*result != (void *) chld); } else { *result = xmlAddPrevSibling(ref, chld); } if (*result == NULL) return HUBBUB_NOMEM; ref_node(ctx, *result); return HUBBUB_OK; } /** * Remove a node from another's child list * * \param ctx Our context * \param parent The node to remove from * \param child The node to remove * \param result Location to receive removed node * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: if successful, result's reference count is increased by 1 */ hubbub_error remove_child(void *ctx, void *parent, void *child, void **result) { xmlNode *chld = (xmlNode *) child; xmlUnlinkNode(chld); *result = child; ref_node(ctx, *result); return HUBBUB_OK; } /** * Clone a node * * \param ctx Our context * \param node The node to clone * \param deep True to clone entire subtree, false to clone only the node * \param result Location to receive clone * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: if successful, result's reference count must be 1. */ hubbub_error clone_node(void *ctx, void *node, bool deep, void **result) { xmlNode *n = (xmlNode *) node; *result = xmlCopyNode(n, deep ? 1 : 2); if (*result == NULL) return HUBBUB_NOMEM; ((xmlNode *)(*result))->_private = (void *) (uintptr_t) 1; return HUBBUB_OK; } /** * Move all the children of one node to another * * \param ctx Our context * \param node The initial parent node * \param new_parent The new parent node * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error reparent_children(void *ctx, void *node, void *new_parent) { xmlNode *n = (xmlNode *) node; xmlNode *p = (xmlNode *) new_parent; xmlNode *child; for (child = n->children; child != NULL; ) { xmlNode *next = child->next; xmlUnlinkNode(child); if (xmlAddChild(p, child) == NULL) return HUBBUB_NOMEM; child = next; } return HUBBUB_OK; } /** * Retrieve the parent of a node * * \param ctx Our context * \param node Node to retrieve the parent of * \param element_only True if the parent must be an element, false otherwise * \param result Location to receive parent node * \return HUBBUB_OK on success, appropriate error otherwise * * Postcondition: if there is a parent, then result's reference count must be * increased. */ hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result) { xmlNode *n = (xmlNode *) node; *result = (void *) n->parent; if (*result != NULL && element_only && ((xmlNode *) *result)->type != XML_ELEMENT_NODE) { *result = NULL; } if (*result != NULL) ref_node(ctx, *result); return HUBBUB_OK; } /** * Determine if a node has children * * \param ctx Our context * \param node The node to inspect * \param result Location to receive result * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error has_children(void *ctx, void *node, bool *result) { xmlNode *n = (xmlNode *) node; *result = n->children != NULL; return HUBBUB_OK; } /** * Associate a node with a form * * \param ctx Our context * \param form The form to associate with * \param node The node to associate * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error form_associate(void *ctx, void *form, void *node) { /* In this implementation, we do nothing here. * * If we wish to process forms afterwards, then we would want to use * this entry point to associate inputs with form elements. This is * useful because forms may be misnested in the source data and thus * it is not necessarily sufficient to search the resultant DOM to * perform the association. * * Note that this callback will be called even if the node has * an @form. In that case, the association should be between the node * and the form identified by the ID in @form. This may not be the same * as the form passed in. */ return HUBBUB_OK; } /** * Add attributes to a node * * \param ctx Our context * \param node The node to add to * \param attributes Array of attributes to add * \param n_attributes Number of entries in array * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error add_attributes(void *ctx, void *node, const hubbub_attribute *attributes, uint32_t n_attributes) { context *c = (context *) ctx; xmlNode *n = (xmlNode *) node; uint32_t attr; for (attr = 0; attr < n_attributes; attr++) { xmlAttr *prop; char *name, *value; name = c_string_from_hubbub_string(c, &attributes[attr].name); if (name == NULL) return HUBBUB_NOMEM; value = c_string_from_hubbub_string(c, &attributes[attr].value); if (value == NULL) { free(name); return HUBBUB_NOMEM; } if (attributes[attr].ns != HUBBUB_NS_NULL && c->namespaces[0] != NULL) { prop = xmlNewNsProp(n, c->namespaces[attributes[attr].ns - 1], BAD_CAST name, BAD_CAST value); } else { prop = xmlNewProp(n, BAD_CAST name, BAD_CAST value); } if (prop == NULL) { free(value); free(name); return HUBBUB_NOMEM; } free(value); free(name); } return HUBBUB_OK; } /** * Notification of the quirks mode of a document * * \param ctx Our context * \param mode The quirks mode * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode) { /* In this implementation, we do nothing. * * The quirks mode is really only of any use when applying CSS * to the resulting DOM tree. */ return HUBBUB_OK; } /** * Notification that a potential encoding change is required * * \param ctx Our context * \param charset The new charset for the source data * \return HUBBUB_OK to continue using the current input handler, * HUBBUB_ENCODINGCHANGE to stop processing immediately and * return control to the client, * appropriate error otherwise. */ hubbub_error change_encoding(void *ctx, const char *charset) { context *c = (context *) ctx; uint32_t source; const char *name; /* If we have an encoding here, it means we are *certain* */ if (c->encoding != NULL) { return HUBBUB_OK; } /* Find the confidence otherwise (can only be from a BOM) */ name = hubbub_parser_read_charset(c->parser, &source); if (source == HUBBUB_CHARSET_CONFIDENT) { c->enc_source = ENCODING_SOURCE_DETECTED; c->encoding = (char *) charset; return HUBBUB_OK; } /* So here we have something of confidence tentative... */ /* http://www.whatwg.org/specs/web-apps/current-work/#change */ /* 2. "If the new encoding is identical or equivalent to the encoding * that is already being used to interpret the input stream, then set * the confidence to confident and abort these steps." */ /* Whatever happens, the encoding should be set here; either for * reprocessing with a different charset, or for confirming that the * charset is in fact correct */ c->encoding = charset; c->enc_source = ENCODING_SOURCE_META; /* Equal encodings will have the same string pointers */ return (charset == name) ? HUBBUB_OK : HUBBUB_ENCODINGCHANGE; } netsurf-2.9/hubbub-0.1.2/src/0000775000175000017500000000000011734430254014543 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/src/treebuilder/0000775000175000017500000000000011734430254017051 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/src/treebuilder/after_body.c0000664000175000017500000000505111171337335021335 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle token in "after body" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_after_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: { /* mostly cribbed from process_characters_expect_whitespace */ const uint8_t *data = token->data.character.ptr; size_t len = token->data.character.len; size_t c; /* Scan for whitespace */ for (c = 0; c < len; c++) { if (data[c] != 0x09 && data[c] != 0x0A && data[c] != 0x0C && data[c] != 0x20) break; } /* Whitespace characters in token, so handle as in body */ if (c > 0) { hubbub_token temp = *token; temp.data.character.len = c; err = handle_in_body(treebuilder, &temp); if (err != HUBBUB_OK) return err; } /* Anything else, switch to in body */ if (c != len) { /* Update token data to strip leading whitespace */ ((hubbub_token *) token)->data.character.ptr += c; ((hubbub_token *) token)->data.character.len -= c; treebuilder->context.mode = IN_BODY; err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ 0].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } else { /** \todo parse error */ treebuilder->context.mode = IN_BODY; err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /** \todo fragment case */ /** \todo parse error */ treebuilder->context.mode = AFTER_AFTER_BODY; } else { /** \todo parse error */ treebuilder->context.mode = IN_BODY; err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_EOF: break; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_table_body.c0000664000175000017500000001052611613627634022021 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Clear the stack back to a table body context. * * \param treebuilder The treebuilder instance */ static void table_clear_stack(hubbub_treebuilder *treebuilder) { element_type cur_node = current_node(treebuilder); while (cur_node != TBODY && cur_node != TFOOT && cur_node != THEAD && cur_node != HTML) { hubbub_ns ns; element_type type; void *node; element_stack_pop(treebuilder, &ns, &type, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); cur_node = current_node(treebuilder); } return; } /** * Handle the case common to some start tag and the table end tag cases. * * \param treebuilder The treebuilder instance * \return Whether to reprocess the current token */ static hubbub_error table_sub_start_or_table_end(hubbub_treebuilder *treebuilder) { if (element_in_scope(treebuilder, TBODY, true) || element_in_scope(treebuilder, THEAD, true) || element_in_scope(treebuilder, TFOOT, true)) { hubbub_ns ns; element_type otype; void *node; table_clear_stack(treebuilder); /* "Act as if an end tag with the same name as the current * node had been seen" -- this behaviour should be identical * to handling for (tbody/tfoot/thead) end tags in this mode */ element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->context.mode = IN_TABLE; return HUBBUB_REPROCESS; } else { /** \todo parse error */ } return HUBBUB_OK; } /** * Handle tokens in "in table body" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_in_table_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == TR) { table_clear_stack(treebuilder); err = insert_element(treebuilder, &token->data.tag, true); if (err == HUBBUB_OK) treebuilder->context.mode = IN_ROW; } else if (type == TH || type == TD) { hubbub_tag tag; /** \todo parse error */ /* Manufacture tr tag */ tag.ns = HUBBUB_NS_HTML; tag.name.ptr = (const uint8_t *) "tr"; tag.name.len = SLEN("tr"); tag.n_attributes = 0; tag.attributes = NULL; table_clear_stack(treebuilder); err = insert_element(treebuilder, &tag, true); if (err == HUBBUB_OK) { treebuilder->context.mode = IN_ROW; err = HUBBUB_REPROCESS; } } else if (type == CAPTION || type == COL || type == COLGROUP || type == TBODY || type == TFOOT || type == THEAD) { err = table_sub_start_or_table_end(treebuilder); } else { err = handle_in_table(treebuilder, token); } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == TBODY || type == TFOOT || type == THEAD) { if (!element_in_scope(treebuilder, type, true)) { /** \todo parse error */ /* Ignore the token */ } else { hubbub_ns ns; element_type otype; void *node; table_clear_stack(treebuilder); element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->context.mode = IN_TABLE; } } else if (type == TABLE) { err = table_sub_start_or_table_end(treebuilder); } else if (type == BODY || type == CAPTION || type == COL || type == COLGROUP || type == HTML || type == TD || type == TH || type == TR) { /** \todo parse error */ /* Ignore the token */ } else { err = handle_in_table(treebuilder, token); } } break; case HUBBUB_TOKEN_CHARACTER: case HUBBUB_TOKEN_COMMENT: case HUBBUB_TOKEN_DOCTYPE: case HUBBUB_TOKEN_EOF: err = handle_in_table(treebuilder, token); break; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_head.c0000664000175000017500000001233311613627634020614 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "charset/detect.h" #include "utils/utils.h" #include "utils/string.h" /** * Process a meta tag as if "in head". * * \param treebuilder The treebuilder instance * \param token The token to process */ static hubbub_error process_meta_in_head(hubbub_treebuilder *treebuilder, const hubbub_token *token) { static uint16_t utf16, utf16be, utf16le; uint16_t charset_enc = 0; uint16_t content_type_enc = 0; size_t i; hubbub_error err = HUBBUB_OK; err = insert_element(treebuilder, &token->data.tag, false); if (err != HUBBUB_OK) return err; /** \todo ack sc flag */ if (treebuilder->tree_handler->encoding_change == NULL) return err; /* Grab UTF-16 MIBenums */ if (utf16 == 0) { utf16 = parserutils_charset_mibenum_from_name( "utf-16", SLEN("utf-16")); utf16be = parserutils_charset_mibenum_from_name( "utf-16be", SLEN("utf-16be")); utf16le = parserutils_charset_mibenum_from_name( "utf-16le", SLEN("utf-16le")); assert(utf16 != 0 && utf16be != 0 && utf16le != 0); } for (i = 0; i < token->data.tag.n_attributes; i++) { hubbub_attribute *attr = &token->data.tag.attributes[i]; if (hubbub_string_match(attr->name.ptr, attr->name.len, (const uint8_t *) "charset", SLEN("charset")) == true) { /* Extract charset */ charset_enc = parserutils_charset_mibenum_from_name( (const char *) attr->value.ptr, attr->value.len); } else if (hubbub_string_match(attr->name.ptr, attr->name.len, (const uint8_t *) "content", SLEN("content")) == true) { /* Extract charset from Content-Type */ content_type_enc = hubbub_charset_parse_content( attr->value.ptr, attr->value.len); } } /* Fall back, if necessary */ if (charset_enc == 0 && content_type_enc != 0) charset_enc = content_type_enc; if (charset_enc != 0) { const char *name; hubbub_charset_fix_charset(&charset_enc); /* Change UTF-16 to UTF-8 */ if (charset_enc == utf16le || charset_enc == utf16be || charset_enc == utf16) { charset_enc = parserutils_charset_mibenum_from_name( "UTF-8", SLEN("UTF-8")); } name = parserutils_charset_mibenum_to_name(charset_enc); err = treebuilder->tree_handler->encoding_change( treebuilder->tree_handler->ctx, name); } return err; } /** * Handle token in "in head" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_in_head(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool handled = false; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, true); break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } else if (type == BASE || type == COMMAND || type == LINK) { err = insert_element(treebuilder, &token->data.tag, false); /** \todo ack sc flag */ } else if (type == META) { err = process_meta_in_head(treebuilder, token); } else if (type == TITLE) { err = parse_generic_rcdata(treebuilder, token, true); } else if (type == NOFRAMES || type == STYLE) { err = parse_generic_rcdata(treebuilder, token, false); } else if (type == NOSCRIPT) { if (treebuilder->context.enable_scripting) { err = parse_generic_rcdata(treebuilder, token, false); } else { err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) return err; treebuilder->context.mode = IN_HEAD_NOSCRIPT; } } else if (type == SCRIPT) { /** \todo need to ensure that the client callback * sets the parser-inserted/already-executed script * flags. */ err = parse_generic_rcdata(treebuilder, token, false); } else if (type == HEAD) { /** \todo parse error */ } else { err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HEAD) { handled = true; } else if (type == HTML || type == BODY || type == BR) { err = HUBBUB_REPROCESS; } /** \todo parse error */ } break; case HUBBUB_TOKEN_EOF: err = HUBBUB_REPROCESS; break; } if (handled || err == HUBBUB_REPROCESS) { hubbub_ns ns; element_type otype; void *node; element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->context.mode = AFTER_HEAD; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_head_noscript.c0000664000175000017500000000440011613627634022531 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle tokens in "in head noscript" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_in_head_noscript(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool handled = false; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, true); break; case HUBBUB_TOKEN_COMMENT: err = handle_in_head(treebuilder, token); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /* Process as "in body" */ err = handle_in_body(treebuilder, token); } else if (type == NOSCRIPT) { handled = true; } else if (type == LINK || type == META || type == NOFRAMES || type == STYLE) { /* Process as "in head" */ err = handle_in_head(treebuilder, token); } else if (type == HEAD || type == NOSCRIPT) { /** \todo parse error */ } else { /** \todo parse error */ err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == NOSCRIPT) { handled = true; } else if (type == BR) { /** \todo parse error */ err = HUBBUB_REPROCESS; } else { /** \todo parse error */ } } break; case HUBBUB_TOKEN_EOF: /** \todo parse error */ err = HUBBUB_REPROCESS; break; } if (handled || err == HUBBUB_REPROCESS) { hubbub_ns ns; element_type otype; void *node; element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->context.mode = IN_HEAD; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/after_after_body.c0000664000175000017500000000330411171337335022515 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle token in "after after body" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return HUBBUB_OK on completion, * HUBBUB_REPROCESS to reprocess the token, * appropriate error otherwise */ hubbub_error handle_after_after_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, true); if (err == HUBBUB_REPROCESS) treebuilder->context.mode = IN_BODY; break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.document); break; case HUBBUB_TOKEN_DOCTYPE: err = handle_in_body(treebuilder, token); break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } else { /** \todo parse error */ treebuilder->context.mode = IN_BODY; err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_END_TAG: /** \todo parse error */ treebuilder->context.mode = IN_BODY; err = HUBBUB_REPROCESS; break; case HUBBUB_TOKEN_EOF: break; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/internal.h0000664000175000017500000001660411171401566021044 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef hubbub_treebuilder_internal_h_ #define hubbub_treebuilder_internal_h_ #include "treebuilder/treebuilder.h" typedef enum { /* Special */ ADDRESS, AREA, ARTICLE, ASIDE, BASE, BASEFONT, BGSOUND, BLOCKQUOTE, BODY, BR, CENTER, COL, COLGROUP, COMMAND, DATAGRID, DD, DETAILS, DIALOG, DIR, DIV, DL, DT, EMBED, FIELDSET, FIGURE, FOOTER, FORM, FRAME, FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HEADER, HR, IFRAME, IMAGE, IMG, INPUT, ISINDEX, LI, LINK, LISTING, MENU, META, NAV, NOEMBED, NOFRAMES, NOSCRIPT, OL, OPTGROUP, OPTION, P, PARAM, PLAINTEXT, PRE, SCRIPT, SECTION, SELECT, SPACER, STYLE, TBODY, TEXTAREA, TFOOT, THEAD, TITLE, TR, UL, WBR, /* Scoping */ APPLET, BUTTON, CAPTION, HTML, MARQUEE, OBJECT, TABLE, TD, TH, /* Formatting */ A, B, BIG, CODE, EM, FONT, I, NOBR, S, SMALL, STRIKE, STRONG, TT, U, /* Phrasing */ /**< \todo Enumerate phrasing elements */ LABEL, OUTPUT, RP, RT, RUBY, SPAN, SUB, SUP, VAR, XMP, /* MathML */ MATH, MGLYPH, MALIGNMARK, MI, MO, MN, MS, MTEXT, ANNOTATION_XML, /* SVG */ SVG, FOREIGNOBJECT, /* foreignobject is scoping, but only in SVG ns */ DESC, UNKNOWN } element_type; /** * Item on the element stack */ typedef struct element_context { hubbub_ns ns; /**< Element namespace */ element_type type; /**< Element type */ uint8_t *name; /**< Element name (interned) */ bool tainted; /**< Only for tables. "Once the * current table has been tainted, * whitespace characters are inserted * into the foster parent element * instead of the current node." */ void *node; /**< Node pointer */ } element_context; /** * Entry in a formatting list */ typedef struct formatting_list_entry { element_context details; /**< Entry details */ uint32_t stack_index; /**< Index into element stack */ struct formatting_list_entry *prev; /**< Previous in list */ struct formatting_list_entry *next; /**< Next in list */ } formatting_list_entry; /** * Context for a tree builder */ typedef struct hubbub_treebuilder_context { insertion_mode mode; /**< The current insertion mode */ insertion_mode second_mode; /**< The secondary insertion mode */ #define ELEMENT_STACK_CHUNK 128 element_context *element_stack; /**< Stack of open elements */ uint32_t stack_alloc; /**< Number of stack slots allocated */ uint32_t current_node; /**< Index of current node in stack */ formatting_list_entry *formatting_list; /**< List of active formatting * elements */ formatting_list_entry *formatting_list_end; /**< End of active * formatting list */ void *head_element; /**< Pointer to HEAD element */ void *form_element; /**< Pointer to most recently * opened FORM element */ void *document; /**< Pointer to the document node */ bool enable_scripting; /**< Whether scripting is enabled */ struct { insertion_mode mode; /**< Insertion mode to return to */ element_type type; /**< Type of node */ } collect; /**< Context for character collecting */ bool strip_leading_lr; /**< Whether to strip a LR from the * start of the next character sequence * received */ bool in_table_foster; /**< Whether nodes that would be * inserted into the current node should * be foster parented */ bool frameset_ok; /**< Whether to process a frameset */ } hubbub_treebuilder_context; /** * Treebuilder object */ struct hubbub_treebuilder { hubbub_tokeniser *tokeniser; /**< Underlying tokeniser */ hubbub_treebuilder_context context; /**< Our context */ hubbub_tree_handler *tree_handler; /**< Callback table */ hubbub_error_handler error_handler; /**< Error handler */ void *error_pw; /**< Error handler data */ hubbub_allocator_fn alloc; /**< Memory (de)allocation function */ void *alloc_pw; /**< Client private data */ }; hubbub_error hubbub_treebuilder_token_handler( const hubbub_token *token, void *pw); hubbub_error process_characters_expect_whitespace( hubbub_treebuilder *treebuilder, const hubbub_token *token, bool insert_into_current_node); hubbub_error process_comment_append(hubbub_treebuilder *treebuilder, const hubbub_token *token, void *parent); hubbub_error parse_generic_rcdata(hubbub_treebuilder *treebuilder, const hubbub_token *token, bool rcdata); uint32_t element_in_scope(hubbub_treebuilder *treebuilder, element_type type, bool in_table); hubbub_error reconstruct_active_formatting_list( hubbub_treebuilder *treebuilder); void clear_active_formatting_list_to_marker( hubbub_treebuilder *treebuilder); hubbub_error remove_node_from_dom(hubbub_treebuilder *treebuilder, void *node); hubbub_error insert_element(hubbub_treebuilder *treebuilder, const hubbub_tag *tag_name, bool push); void close_implied_end_tags(hubbub_treebuilder *treebuilder, element_type except); void reset_insertion_mode(hubbub_treebuilder *treebuilder); hubbub_error append_text(hubbub_treebuilder *treebuilder, const hubbub_string *string); element_type element_type_from_name(hubbub_treebuilder *treebuilder, const hubbub_string *tag_name); bool is_special_element(element_type type); bool is_scoping_element(element_type type); bool is_formatting_element(element_type type); bool is_phrasing_element(element_type type); hubbub_error element_stack_push(hubbub_treebuilder *treebuilder, hubbub_ns ns, element_type type, void *node); hubbub_error element_stack_pop(hubbub_treebuilder *treebuilder, hubbub_ns *ns, element_type *type, void **node); hubbub_error element_stack_pop_until(hubbub_treebuilder *treebuilder, element_type type); hubbub_error element_stack_remove(hubbub_treebuilder *treebuilder, uint32_t index, hubbub_ns *ns, element_type *type, void **removed); uint32_t current_table(hubbub_treebuilder *treebuilder); element_type current_node(hubbub_treebuilder *treebuilder); element_type prev_node(hubbub_treebuilder *treebuilder); hubbub_error formatting_list_append(hubbub_treebuilder *treebuilder, hubbub_ns ns, element_type type, void *node, uint32_t stack_index); hubbub_error formatting_list_insert(hubbub_treebuilder *treebuilder, formatting_list_entry *prev, formatting_list_entry *next, hubbub_ns ns, element_type type, void *node, uint32_t stack_index); hubbub_error formatting_list_remove(hubbub_treebuilder *treebuilder, formatting_list_entry *entry, hubbub_ns *ns, element_type *type, void **node, uint32_t *stack_index); hubbub_error formatting_list_replace(hubbub_treebuilder *treebuilder, formatting_list_entry *entry, hubbub_ns ns, element_type type, void *node, uint32_t stack_index, hubbub_ns *ons, element_type *otype, void **onode, uint32_t *ostack_index); /* in_foreign_content.c */ void adjust_mathml_attributes(hubbub_treebuilder *treebuilder, hubbub_tag *tag); void adjust_svg_attributes(hubbub_treebuilder *treebuilder, hubbub_tag *tag); void adjust_svg_tagname(hubbub_treebuilder *treebuilder, hubbub_tag *tag); void adjust_foreign_attributes(hubbub_treebuilder *treebuilder, hubbub_tag *tag); /* in_body.c */ hubbub_error aa_insert_into_foster_parent(hubbub_treebuilder *treebuilder, void *node, void **inserted); #ifndef NDEBUG #include void element_stack_dump(hubbub_treebuilder *treebuilder, FILE *fp); void formatting_list_dump(hubbub_treebuilder *treebuilder, FILE *fp); const char *element_type_to_name(element_type type); #endif #endif netsurf-2.9/hubbub-0.1.2/src/treebuilder/after_head.c0000664000175000017500000000612111613627634021305 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle tokens in "after head" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_after_head(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool handled = false; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, true); break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } else if (type == BODY) { handled = true; } else if (type == FRAMESET) { err = insert_element(treebuilder, &token->data.tag, true); if (err == HUBBUB_OK) treebuilder->context.mode = IN_FRAMESET; } else if (type == BASE || type == LINK || type == META || type == NOFRAMES || type == SCRIPT || type == STYLE || type == TITLE) { hubbub_ns ns; element_type otype; void *node; uint32_t index; /** \todo parse error */ err = element_stack_push(treebuilder, HUBBUB_NS_HTML, HEAD, treebuilder->context.head_element); if (err != HUBBUB_OK) return err; index = treebuilder->context.current_node; /* Process as "in head" */ err = handle_in_head(treebuilder, token); element_stack_remove(treebuilder, index, &ns, &otype, &node); /* No need to unref node as we never increased * its reference count when pushing it on the stack */ } else if (type == HEAD) { /** \todo parse error */ } else { err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML || type == BODY || type == BR) { err = HUBBUB_REPROCESS; } else { /** \todo parse error */ } } break; case HUBBUB_TOKEN_EOF: err = HUBBUB_REPROCESS; break; } if (handled || err == HUBBUB_REPROCESS) { hubbub_error e; hubbub_tag tag; if (err == HUBBUB_REPROCESS) { /* Manufacture body */ tag.ns = HUBBUB_NS_HTML; tag.name.ptr = (const uint8_t *) "body"; tag.name.len = SLEN("body"); tag.n_attributes = 0; tag.attributes = NULL; } else { tag = token->data.tag; } e = insert_element(treebuilder, &tag, true); if (e != HUBBUB_OK) return e; treebuilder->context.mode = IN_BODY; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/initial.c0000664000175000017500000002040111226356152020643 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" #include "utils/string.h" #define S(s) { s, sizeof s - 1 } struct { const char *name; size_t len; } public_doctypes[] = { S("+//Silmaril//dtd html Pro v0r11 19970101//"), S("-//AdvaSoft Ltd//DTD HTML 3.0 asWedit + extensions//"), S("-//AS//DTD HTML 3.0 asWedit + extensions//"), S("-//IETF//DTD HTML 2.0 Level 1//"), S("-//IETF//DTD HTML 2.0 Level 2//"), S("-//IETF//DTD HTML 2.0 Strict Level 1//"), S("-//IETF//DTD HTML 2.0 Strict Level 2//"), S("-//IETF//DTD HTML 2.0 Strict//"), S("-//IETF//DTD HTML 2.0//"), S("-//IETF//DTD HTML 2.1E//"), S("-//IETF//DTD HTML 3.0//"), S("-//IETF//DTD HTML 3.2 Final//"), S("-//IETF//DTD HTML 3.2//"), S("-//IETF//DTD HTML 3//"), S("-//IETF//DTD HTML Level 0//"), S("-//IETF//DTD HTML Level 1//"), S("-//IETF//DTD HTML Level 2//"), S("-//IETF//DTD HTML Level 3//"), S("-//IETF//DTD HTML Strict Level 0//"), S("-//IETF//DTD HTML Strict Level 1//"), S("-//IETF//DTD HTML Strict Level 2//"), S("-//IETF//DTD HTML Strict Level 3//"), S("-//IETF//DTD HTML Strict//"), S("-//IETF//DTD HTML//"), S("-//Metrius//DTD Metrius Presentational//"), S("-//Microsoft//DTD Internet Explorer 2.0 HTML Strict//"), S("-//Microsoft//DTD Internet Explorer 2.0 HTML//"), S("-//Microsoft//DTD Internet Explorer 2.0 Tables//"), S("-//Microsoft//DTD Internet Explorer 3.0 HTML Strict//"), S("-//Microsoft//DTD Internet Explorer 3.0 HTML//"), S("-//Microsoft//DTD Internet Explorer 3.0 Tables//"), S("-//Netscape Comm. Corp.//DTD HTML//"), S("-//Netscape Comm. Corp.//DTD Strict HTML//"), S("-//O'Reilly and Associates//DTD HTML 2.0//"), S("-//O'Reilly and Associates//DTD HTML Extended 1.0//"), S("-//O'Reilly and Associates//DTD HTML Extended Relaxed 1.0//"), S("-//SoftQuad Software//DTD HoTMetaL PRO 6.0::19990601::extensions to HTML 4.0//"), S("-//SoftQuad//DTD HoTMetaL PRO 4.0::19971010::extensions to HTML 4.0//"), S("-//Spyglass//DTD HTML 2.0 Extended//"), S("-//SQ//DTD HTML 2.0 HoTMetaL + extensions//"), S("-//Sun Microsystems Corp.//DTD HotJava HTML//"), S("-//Sun Microsystems Corp.//DTD HotJava Strict HTML//"), S("-//W3C//DTD HTML 3 1995-03-24//"), S("-//W3C//DTD HTML 3.2 Draft//"), S("-//W3C//DTD HTML 3.2 Final//"), S("-//W3C//DTD HTML 3.2//"), S("-//W3C//DTD HTML 3.2S Draft//"), S("-//W3C//DTD HTML 4.0 Frameset//"), S("-//W3C//DTD HTML 4.0 Transitional//"), S("-//W3C//DTD HTML Experimental 19960712//"), S("-//W3C//DTD HTML Experimental 970421//"), S("-//W3C//DTD W3 HTML//"), S("-//W3O//DTD W3 HTML 3.0//"), }; #undef S /** * Check if one string starts with another. * * \param a String to compare * \param a_len Length of first string * \param b String to compare * \param b_len Length of second string */ static bool starts_with(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len) { if (a_len < b_len) return false; /* Now perform an insensitive comparison on the prefix */ return hubbub_string_match_ci(a, b_len, b, b_len); } /** * Determine whether this doctype triggers full quirks mode * * \param treebuilder Treebuilder instance * \param cdoc The doctype to examine * \return True to trigger quirks, false otherwise */ static bool lookup_full_quirks(hubbub_treebuilder *treebuilder, const hubbub_doctype *cdoc) { size_t i; const uint8_t *name = cdoc->name.ptr; size_t name_len = cdoc->name.len; const uint8_t *public_id = cdoc->public_id.ptr; size_t public_id_len = cdoc->public_id.len; const uint8_t *system_id = cdoc->system_id.ptr; size_t system_id_len = cdoc->system_id.len; UNUSED(treebuilder); #define S(s) (uint8_t *) s, sizeof s - 1 /* Check the name is "HTML" (case-insensitively) */ if (!hubbub_string_match_ci(name, name_len, S("HTML"))) return true; /* No public id means not-quirks */ if (cdoc->public_missing) return false; for (i = 0; i < sizeof public_doctypes / sizeof public_doctypes[0]; i++) { if (starts_with(public_id, public_id_len, (uint8_t *) public_doctypes[i].name, public_doctypes[i].len)) { return true; } } if (hubbub_string_match_ci(public_id, public_id_len, S("-//W3O//DTD W3 HTML Strict 3.0//EN//")) || hubbub_string_match_ci(public_id, public_id_len, S("-/W3C/DTD HTML 4.0 Transitional/EN")) || hubbub_string_match_ci(public_id, public_id_len, S("HTML")) || hubbub_string_match_ci(system_id, system_id_len, S("http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"))) { return true; } if (cdoc->system_missing == true && (starts_with(public_id, public_id_len, S("-//W3C//DTD HTML 4.01 Frameset//")) || starts_with(public_id, public_id_len, S("-//W3C//DTD HTML 4.01 Transitional//")))) { return true; } #undef S return false; } /** * Determine whether this doctype triggers limited quirks mode * * \param treebuilder Treebuilder instance * \param cdoc The doctype to examine * \return True to trigger quirks, false otherwise */ static bool lookup_limited_quirks(hubbub_treebuilder *treebuilder, const hubbub_doctype *cdoc) { const uint8_t *public_id = cdoc->public_id.ptr; size_t public_id_len = cdoc->public_id.len; UNUSED(treebuilder); #define S(s) (uint8_t *) s, sizeof s - 1 if (starts_with(public_id, public_id_len, S("-//W3C//DTD XHTML 1.0 Frameset//")) || starts_with(public_id, public_id_len, S("-//W3C//DTD XHTML 1.0 Transitional//"))) { return true; } if (cdoc->system_missing == false && (starts_with(public_id, public_id_len, S("-//W3C//DTD HTML 4.01 Frameset//")) || starts_with(public_id, public_id_len, S("-//W3C//DTD HTML 4.01 Transitional//")))) { return true; } #undef S return false; } /** * Handle token in initial insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_initial(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, false); if (err == HUBBUB_REPROCESS) { /** \todo parse error */ treebuilder->tree_handler->set_quirks_mode( treebuilder->tree_handler->ctx, HUBBUB_QUIRKS_MODE_FULL); treebuilder->context.mode = BEFORE_HTML; } break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.document); break; case HUBBUB_TOKEN_DOCTYPE: { void *doctype, *appended; const hubbub_doctype *cdoc; /** \todo parse error */ err = treebuilder->tree_handler->create_doctype( treebuilder->tree_handler->ctx, &token->data.doctype, &doctype); if (err != HUBBUB_OK) return err; /* Append to Document node */ err = treebuilder->tree_handler->append_child( treebuilder->tree_handler->ctx, treebuilder->context.document, doctype, &appended); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, doctype); if (err != HUBBUB_OK) return err; treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, appended); cdoc = &token->data.doctype; /* Work out whether we need quirks mode or not */ if (cdoc->force_quirks == true || lookup_full_quirks(treebuilder, cdoc)) { treebuilder->tree_handler->set_quirks_mode( treebuilder->tree_handler->ctx, HUBBUB_QUIRKS_MODE_FULL); } else if (lookup_limited_quirks(treebuilder, cdoc)) { treebuilder->tree_handler->set_quirks_mode( treebuilder->tree_handler->ctx, HUBBUB_QUIRKS_MODE_LIMITED); } treebuilder->context.mode = BEFORE_HTML; } break; case HUBBUB_TOKEN_START_TAG: case HUBBUB_TOKEN_END_TAG: case HUBBUB_TOKEN_EOF: /** \todo parse error */ treebuilder->tree_handler->set_quirks_mode( treebuilder->tree_handler->ctx, HUBBUB_QUIRKS_MODE_FULL); err = HUBBUB_REPROCESS; break; } if (err == HUBBUB_REPROCESS) { treebuilder->context.mode = BEFORE_HTML; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_caption.c0000664000175000017500000000467511613627634021362 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle tokens in "in caption" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_in_caption(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool handled = false; switch (token->type) { case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == CAPTION || type == COL || type == COLGROUP || type == TBODY || type == TD || type == TFOOT || type == TH || type == THEAD || type == TR) { /** \todo parse error */ err = HUBBUB_REPROCESS; } else { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == CAPTION) { handled = true; } else if (type == TABLE) { /** \todo parse error if type == TABLE */ err = HUBBUB_REPROCESS; } else if (type == BODY || type == COL || type == COLGROUP || type == HTML || type == TBODY || type == TD || type == TFOOT || type == TH || type == THEAD || type == TR) { /** \todo parse error */ } else { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } } break; case HUBBUB_TOKEN_CHARACTER: case HUBBUB_TOKEN_COMMENT: case HUBBUB_TOKEN_DOCTYPE: case HUBBUB_TOKEN_EOF: /* Process as if "in body" */ err = handle_in_body(treebuilder, token); break; } if (handled || err == HUBBUB_REPROCESS) { hubbub_ns ns; element_type otype = UNKNOWN; void *node; /** \todo fragment case */ close_implied_end_tags(treebuilder, UNKNOWN); while (otype != CAPTION) { /** \todo parse error */ element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } clear_active_formatting_list_to_marker(treebuilder); treebuilder->context.mode = IN_TABLE; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/treebuilder.c0000664000175000017500000011623111613627634021535 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" #include "utils/string.h" #define S(x) x, SLEN(x) static const struct { const char *name; size_t len; element_type type; } name_type_map[] = { { S("address"), ADDRESS }, { S("area"), AREA }, { S("base"), BASE }, { S("basefont"), BASEFONT }, { S("bgsound"), BGSOUND }, { S("blockquote"), BLOCKQUOTE }, { S("body"), BODY }, { S("br"), BR }, { S("center"), CENTER }, { S("col"), COL }, { S("colgroup"), COLGROUP }, { S("dd"), DD }, { S("dir"), DIR }, { S("div"), DIV }, { S("dl"), DL }, { S("dt"), DT }, { S("embed"), EMBED }, { S("fieldset"), FIELDSET }, { S("form"), FORM }, { S("frame"), FRAME }, { S("frameset"), FRAMESET }, { S("h1"), H1 }, { S("h2"), H2 }, { S("h3"), H3 }, { S("h4"), H4 }, { S("h5"), H5 }, { S("h6"), H6 }, { S("head"), HEAD }, { S("hr"), HR }, { S("iframe"), IFRAME }, { S("image"), IMAGE }, { S("img"), IMG }, { S("input"), INPUT }, { S("isindex"), ISINDEX }, { S("li"), LI }, { S("link"), LINK }, { S("listing"), LISTING }, { S("menu"), MENU }, { S("meta"), META }, { S("noembed"), NOEMBED }, { S("noframes"), NOFRAMES }, { S("noscript"), NOSCRIPT }, { S("ol"), OL }, { S("optgroup"), OPTGROUP }, { S("option"), OPTION }, { S("output"), OUTPUT }, { S("p"), P }, { S("param"), PARAM }, { S("plaintext"), PLAINTEXT }, { S("pre"), PRE }, { S("script"), SCRIPT }, { S("select"), SELECT }, { S("spacer"), SPACER }, { S("style"), STYLE }, { S("tbody"), TBODY }, { S("textarea"), TEXTAREA }, { S("tfoot"), TFOOT }, { S("thead"), THEAD }, { S("title"), TITLE }, { S("tr"), TR }, { S("ul"), UL }, { S("wbr"), WBR }, { S("applet"), APPLET }, { S("button"), BUTTON }, { S("caption"), CAPTION }, { S("html"), HTML }, { S("marquee"), MARQUEE }, { S("object"), OBJECT }, { S("table"), TABLE }, { S("td"), TD }, { S("th"), TH }, { S("a"), A }, { S("b"), B }, { S("big"), BIG }, { S("em"), EM }, { S("font"), FONT }, { S("i"), I }, { S("nobr"), NOBR }, { S("s"), S }, { S("small"), SMALL }, { S("strike"), STRIKE }, { S("strong"), STRONG }, { S("tt"), TT }, { S("u"), U }, { S("xmp"), XMP }, { S("math"), MATH }, { S("mglyph"), MGLYPH }, { S("malignmark"), MALIGNMARK }, { S("mi"), MI }, { S("mo"), MO }, { S("mn"), MN }, { S("ms"), MS }, { S("mtext"), MTEXT }, { S("annotation-xml"), ANNOTATION_XML }, { S("svg"), SVG }, { S("desc"), DESC }, { S("foreignobject"), FOREIGNOBJECT }, }; static bool is_form_associated(element_type type); /** * Create a hubbub treebuilder * * \param tokeniser Underlying tokeniser instance * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data * \param treebuilder Pointer to location to receive treebuilder instance * \return HUBBUB_OK on success, * HUBBUB_BADPARM on bad parameters * HUBBUB_NOMEM on memory exhaustion */ hubbub_error hubbub_treebuilder_create(hubbub_tokeniser *tokeniser, hubbub_allocator_fn alloc, void *pw, hubbub_treebuilder **treebuilder) { hubbub_error error; hubbub_treebuilder *tb; hubbub_tokeniser_optparams tokparams; if (tokeniser == NULL || alloc == NULL || treebuilder == NULL) return HUBBUB_BADPARM; tb = alloc(NULL, sizeof(hubbub_treebuilder), pw); if (tb == NULL) return HUBBUB_NOMEM; tb->tokeniser = tokeniser; tb->tree_handler = NULL; memset(&tb->context, 0, sizeof(hubbub_treebuilder_context)); tb->context.mode = INITIAL; tb->context.element_stack = alloc(NULL, ELEMENT_STACK_CHUNK * sizeof(element_context), pw); if (tb->context.element_stack == NULL) { alloc(tb, 0, pw); return HUBBUB_NOMEM; } tb->context.stack_alloc = ELEMENT_STACK_CHUNK; /* We rely on HTML not being equal to zero to determine * if the first item in the stack is in use. Assert this here. */ assert(HTML != 0); tb->context.element_stack[0].type = (element_type) 0; tb->context.strip_leading_lr = false; tb->context.frameset_ok = true; tb->error_handler = NULL; tb->error_pw = NULL; tb->alloc = alloc; tb->alloc_pw = pw; tokparams.token_handler.handler = hubbub_treebuilder_token_handler; tokparams.token_handler.pw = tb; error = hubbub_tokeniser_setopt(tokeniser, HUBBUB_TOKENISER_TOKEN_HANDLER, &tokparams); if (error != HUBBUB_OK) { alloc(tb->context.element_stack, 0, pw); alloc(tb, 0, pw); return error; } *treebuilder = tb; return HUBBUB_OK; } /** * Destroy a hubbub treebuilder * * \param treebuilder The treebuilder instance to destroy * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error hubbub_treebuilder_destroy(hubbub_treebuilder *treebuilder) { formatting_list_entry *entry, *next; hubbub_tokeniser_optparams tokparams; if (treebuilder == NULL) return HUBBUB_BADPARM; tokparams.token_handler.handler = NULL; tokparams.token_handler.pw = NULL; hubbub_tokeniser_setopt(treebuilder->tokeniser, HUBBUB_TOKENISER_TOKEN_HANDLER, &tokparams); /* Clean up context */ if (treebuilder->tree_handler != NULL) { uint32_t n; if (treebuilder->context.head_element != NULL) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, treebuilder->context.head_element); } if (treebuilder->context.form_element != NULL) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, treebuilder->context.form_element); } if (treebuilder->context.document != NULL) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, treebuilder->context.document); } for (n = treebuilder->context.current_node; n > 0; n--) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[n].node); } if (treebuilder->context.element_stack[0].type == HTML) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[0].node); } } treebuilder->alloc(treebuilder->context.element_stack, 0, treebuilder->alloc_pw); treebuilder->context.element_stack = NULL; for (entry = treebuilder->context.formatting_list; entry != NULL; entry = next) { next = entry->next; if (treebuilder->tree_handler != NULL) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, entry->details.node); } treebuilder->alloc(entry, 0, treebuilder->alloc_pw); } treebuilder->alloc(treebuilder, 0, treebuilder->alloc_pw); return HUBBUB_OK; } /** * Configure a hubbub treebuilder * * \param treebuilder The treebuilder instance to configure * \param type The option type to configure * \param params Pointer to option-specific parameters * \return HUBBUB_OK on success, appropriate error otherwise. */ hubbub_error hubbub_treebuilder_setopt(hubbub_treebuilder *treebuilder, hubbub_treebuilder_opttype type, hubbub_treebuilder_optparams *params) { if (treebuilder == NULL || params == NULL) return HUBBUB_BADPARM; switch (type) { case HUBBUB_TREEBUILDER_ERROR_HANDLER: treebuilder->error_handler = params->error_handler.handler; treebuilder->error_pw = params->error_handler.pw; break; case HUBBUB_TREEBUILDER_TREE_HANDLER: treebuilder->tree_handler = params->tree_handler; break; case HUBBUB_TREEBUILDER_DOCUMENT_NODE: treebuilder->context.document = params->document_node; break; case HUBBUB_TREEBUILDER_ENABLE_SCRIPTING: treebuilder->context.enable_scripting = params->enable_scripting; break; } return HUBBUB_OK; } /** * Handle tokeniser emitting a token * * \param token The emitted token * \param pw Pointer to treebuilder instance */ hubbub_error hubbub_treebuilder_token_handler(const hubbub_token *token, void *pw) { hubbub_treebuilder *treebuilder = (hubbub_treebuilder *) pw; hubbub_error err = HUBBUB_REPROCESS; /* Do nothing if we have no document node or there's no tree handler */ if (treebuilder->context.document == NULL || treebuilder->tree_handler == NULL) return HUBBUB_OK; assert((signed) treebuilder->context.current_node >= 0); /* A slightly nasty debugging hook, but very useful */ #ifdef NDEBUG # define mode(x) \ case x: #else # define mode(x) \ case x: \ printf( #x "\n"); #endif while (err == HUBBUB_REPROCESS) { switch (treebuilder->context.mode) { mode(INITIAL) err = handle_initial(treebuilder, token); break; mode(BEFORE_HTML) err = handle_before_html(treebuilder, token); break; mode(BEFORE_HEAD) err = handle_before_head(treebuilder, token); break; mode(IN_HEAD) err = handle_in_head(treebuilder, token); break; mode(IN_HEAD_NOSCRIPT) err = handle_in_head_noscript(treebuilder, token); break; mode(AFTER_HEAD) err = handle_after_head(treebuilder, token); break; mode(IN_BODY) err = handle_in_body(treebuilder, token); break; mode(IN_TABLE) err = handle_in_table(treebuilder, token); break; mode(IN_CAPTION) err = handle_in_caption(treebuilder, token); break; mode(IN_COLUMN_GROUP) err = handle_in_column_group(treebuilder, token); break; mode(IN_TABLE_BODY) err = handle_in_table_body(treebuilder, token); break; mode(IN_ROW) err = handle_in_row(treebuilder, token); break; mode(IN_CELL) err = handle_in_cell(treebuilder, token); break; mode(IN_SELECT) err = handle_in_select(treebuilder, token); break; mode(IN_SELECT_IN_TABLE) err = handle_in_select_in_table(treebuilder, token); break; mode(IN_FOREIGN_CONTENT) err = handle_in_foreign_content(treebuilder, token); break; mode(AFTER_BODY) err = handle_after_body(treebuilder, token); break; mode(IN_FRAMESET) err = handle_in_frameset(treebuilder, token); break; mode(AFTER_FRAMESET) err = handle_after_frameset(treebuilder, token); break; mode(AFTER_AFTER_BODY) err = handle_after_after_body(treebuilder, token); break; mode(AFTER_AFTER_FRAMESET) err = handle_after_after_frameset(treebuilder, token); break; mode(GENERIC_RCDATA) err = handle_generic_rcdata(treebuilder, token); break; } } return err; } /** * Process a character token in cases where we expect only whitespace * * \param treebuilder The treebuilder instance * \param token The character token * \param insert_into_current_node Whether to insert whitespace into * current node * \return HUBBUB_REPROCESS if the token needs reprocessing * (token data updated to skip any leading whitespace), * HUBBUB_OK if it contained only whitespace, * appropriate error otherwise */ hubbub_error process_characters_expect_whitespace( hubbub_treebuilder *treebuilder, const hubbub_token *token, bool insert_into_current_node) { const uint8_t *data = token->data.character.ptr; size_t len = token->data.character.len; size_t c; for (c = 0; c < len; c++) { if (data[c] != 0x09 && data[c] != 0x0A && data[c] != 0x0C && data[c] != 0x20) break; } if (c > 0 && insert_into_current_node) { hubbub_error error; hubbub_string temp; temp.ptr = data; temp.len = c; error = append_text(treebuilder, &temp); if (error != HUBBUB_OK) return error; } /* Non-whitespace characters in token, so reprocess */ if (c != len) { /* Update token data to strip leading whitespace */ ((hubbub_token *) token)->data.character.ptr += c; ((hubbub_token *) token)->data.character.len -= c; return HUBBUB_REPROCESS; } return HUBBUB_OK; } /** * Process a comment token, appending it to the given parent * * \param treebuilder The treebuilder instance * \param token The comment token * \param parent The node to append to * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error process_comment_append(hubbub_treebuilder *treebuilder, const hubbub_token *token, void *parent) { hubbub_error error = HUBBUB_OK; element_type type = current_node(treebuilder); void *comment, *appended; error = treebuilder->tree_handler->create_comment( treebuilder->tree_handler->ctx, &token->data.comment, &comment); if (error != HUBBUB_OK) return error; if (treebuilder->context.in_table_foster && (type == TABLE || type == TBODY || type == TFOOT || type == THEAD || type == TR)) { error = aa_insert_into_foster_parent(treebuilder, comment, &appended); } else { error = treebuilder->tree_handler->append_child( treebuilder->tree_handler->ctx, parent, comment, &appended); } if (error == HUBBUB_OK) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, appended); } treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, comment); return error; } /** * Trigger parsing of generic (R)CDATA * * \param treebuilder The treebuilder instance * \param token The current token * \param rcdata True for RCDATA, false for CDATA * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error parse_generic_rcdata(hubbub_treebuilder *treebuilder, const hubbub_token *token, bool rcdata) { hubbub_error error; element_type type; hubbub_tokeniser_optparams params; type = element_type_from_name(treebuilder, &token->data.tag.name); error = insert_element(treebuilder, &token->data.tag, true); if (error != HUBBUB_OK) return error; params.content_model.model = rcdata ? HUBBUB_CONTENT_MODEL_RCDATA : HUBBUB_CONTENT_MODEL_CDATA; error = hubbub_tokeniser_setopt(treebuilder->tokeniser, HUBBUB_TOKENISER_CONTENT_MODEL, ¶ms); /* There is no way that setopt can fail. Ensure this. */ assert(error == HUBBUB_OK); treebuilder->context.collect.mode = treebuilder->context.mode; treebuilder->context.collect.type = type; treebuilder->context.mode = GENERIC_RCDATA; return HUBBUB_OK; } /** * Determine if an element is in (table) scope * * \param treebuilder Treebuilder to look in * \param type Element type to find * \param in_table Whether we're looking in table scope * \return Element stack index, or 0 if not in scope */ uint32_t element_in_scope(hubbub_treebuilder *treebuilder, element_type type, bool in_table) { uint32_t node; if (treebuilder->context.element_stack == NULL) return 0; assert((signed) treebuilder->context.current_node >= 0); for (node = treebuilder->context.current_node; node > 0; node--) { hubbub_ns node_ns = treebuilder->context.element_stack[node].ns; element_type node_type = treebuilder->context.element_stack[node].type; if (node_type == type) return node; if (node_type == TABLE) break; /* The list of element types given in the spec here are the * scoping elements excluding TABLE and HTML. TABLE is handled * in the previous conditional and HTML should only occur * as the first node in the stack, which is never processed * in this loop. */ if (!in_table && (is_scoping_element(node_type) || (node_type == FOREIGNOBJECT && node_ns == HUBBUB_NS_SVG))) { break; } } return 0; } /** * Reconstruct the list of active formatting elements * * \param treebuilder Treebuilder instance containing list * \return HUBBUB_OK on success, appropriate error otherwise. */ hubbub_error reconstruct_active_formatting_list(hubbub_treebuilder *treebuilder) { hubbub_error error = HUBBUB_OK; formatting_list_entry *entry, *initial_entry; uint32_t sp = treebuilder->context.current_node; if (treebuilder->context.formatting_list == NULL) return HUBBUB_OK; entry = treebuilder->context.formatting_list_end; /* Assumption: HTML and TABLE elements are not inserted into the list */ if (is_scoping_element(entry->details.type) || entry->stack_index != 0) return HUBBUB_OK; while (entry->prev != NULL) { entry = entry->prev; if (is_scoping_element(entry->details.type) || entry->stack_index != 0) { entry = entry->next; break; } } /* Save initial entry for later */ initial_entry = entry; /* Process formatting list entries, cloning nodes and * inserting them into the DOM and element stack */ while (entry != NULL) { void *clone, *appended; bool foster; element_type type = current_node(treebuilder); error = treebuilder->tree_handler->clone_node( treebuilder->tree_handler->ctx, entry->details.node, false, &clone); if (error != HUBBUB_OK) goto cleanup; foster = treebuilder->context.in_table_foster && (type == TABLE || type == TBODY || type == TFOOT || type == THEAD || type == TR); if (foster) { error = aa_insert_into_foster_parent(treebuilder, clone, &appended); } else { error = treebuilder->tree_handler->append_child( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node, clone, &appended); } /* No longer interested in clone */ treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, clone); if (error != HUBBUB_OK) goto cleanup; error = element_stack_push(treebuilder, entry->details.ns, entry->details.type, appended); if (error != HUBBUB_OK) { remove_node_from_dom(treebuilder, appended); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, appended); goto cleanup; } entry = entry->next; } /* Now, replace the formatting list entries */ for (entry = initial_entry; entry != NULL; entry = entry->next) { void *node; hubbub_ns prev_ns; element_type prev_type; void *prev_node; uint32_t prev_stack_index; node = treebuilder->context.element_stack[++sp].node; treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, node); error = formatting_list_replace(treebuilder, entry, entry->details.ns, entry->details.type, node, sp, &prev_ns, &prev_type, &prev_node, &prev_stack_index); /* Cannot fail. Ensure this. */ assert(error == HUBBUB_OK); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, prev_node); } return HUBBUB_OK; cleanup: /* An error occurred while cloning nodes and inserting them. * We must restore the state on entry here. */ while (treebuilder->context.current_node > sp) { hubbub_ns ns; element_type type; void *node; element_stack_pop(treebuilder, &ns, &type, &node); remove_node_from_dom(treebuilder, node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } return error; } /** * Remove a node from the DOM * * \param treebuilder Treebuilder instance * \param node Node to remove * \return HUBBUB_OK on success, appropriate error otherwise. */ hubbub_error remove_node_from_dom(hubbub_treebuilder *treebuilder, void *node) { hubbub_error err; void *parent = NULL; void *removed; err = treebuilder->tree_handler->get_parent( treebuilder->tree_handler->ctx, node, false, &parent); if (err != HUBBUB_OK) return err; if (parent != NULL) { err = treebuilder->tree_handler->remove_child( treebuilder->tree_handler->ctx, parent, node, &removed); if (err != HUBBUB_OK) return err; treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, parent); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, removed); } return HUBBUB_OK; } /** * Clear the list of active formatting elements up to the last marker * * \param treebuilder The treebuilder instance containing the list */ void clear_active_formatting_list_to_marker(hubbub_treebuilder *treebuilder) { formatting_list_entry *entry; bool done = false; while ((entry = treebuilder->context.formatting_list_end) != NULL) { hubbub_ns ns; element_type type; void *node; uint32_t stack_index; if (is_scoping_element(entry->details.type)) done = true; formatting_list_remove(treebuilder, entry, &ns, &type, &node, &stack_index); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); if (done) break; } } /** * Create element and insert it into the DOM, * potentially pushing it on the stack * * \param treebuilder The treebuilder instance * \param tag The element to insert * \param push Whether to push the element onto the stack * \return HUBBUB_OK on success, appropriate error otherwise. */ hubbub_error insert_element(hubbub_treebuilder *treebuilder, const hubbub_tag *tag, bool push) { element_type type = current_node(treebuilder); hubbub_error error; void *node, *appended; error = treebuilder->tree_handler->create_element( treebuilder->tree_handler->ctx, tag, &node); if (error != HUBBUB_OK) return error; if (treebuilder->context.in_table_foster && (type == TABLE || type == TBODY || type == TFOOT || type == THEAD || type == TR)) { error = aa_insert_into_foster_parent(treebuilder, node, &appended); } else { error = treebuilder->tree_handler->append_child( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node, node, &appended); } /* No longer interested in node */ treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); if (error != HUBBUB_OK) return error; type = element_type_from_name(treebuilder, &tag->name); if (treebuilder->context.form_element != NULL && is_form_associated(type)) { /* Consideration of @form is left to the client */ error = treebuilder->tree_handler->form_associate( treebuilder->tree_handler->ctx, treebuilder->context.form_element, appended); if (error != HUBBUB_OK) { remove_node_from_dom(treebuilder, appended); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, appended); return error; } } if (push) { error = element_stack_push(treebuilder, tag->ns, type, appended); if (error != HUBBUB_OK) { remove_node_from_dom(treebuilder, appended); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, appended); return error; } } else { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, appended); } return HUBBUB_OK; } /** * Close implied end tags * * \param treebuilder The treebuilder instance * \param except Tag type to exclude from processing [DD,DT,LI,OPTION, * OPTGROUP,P,RP,RT], UNKNOWN to exclude nothing */ void close_implied_end_tags(hubbub_treebuilder *treebuilder, element_type except) { element_type type; type = treebuilder->context.element_stack[ treebuilder->context.current_node].type; while (type == DD || type == DT || type == LI || type == OPTION || type == OPTGROUP || type == P || type == RP || type == RT) { hubbub_ns ns; element_type otype; void *node; if (except != UNKNOWN && type == except) break; element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); type = treebuilder->context.element_stack[ treebuilder->context.current_node].type; } } /** * Reset the insertion mode * * \param treebuilder The treebuilder to reset */ void reset_insertion_mode(hubbub_treebuilder *treebuilder) { uint32_t node; element_context *stack = treebuilder->context.element_stack; /** \todo fragment parsing algorithm */ for (node = treebuilder->context.current_node; node > 0; node--) { if (stack[node].ns != HUBBUB_NS_HTML) { treebuilder->context.mode = IN_FOREIGN_CONTENT; treebuilder->context.second_mode = IN_BODY; break; } switch (stack[node].type) { case SELECT: /* fragment case */ break; case TD: case TH: treebuilder->context.mode = IN_CELL; return; case TR: treebuilder->context.mode = IN_ROW; return; case TBODY: case TFOOT: case THEAD: treebuilder->context.mode = IN_TABLE_BODY; return; case CAPTION: treebuilder->context.mode = IN_CAPTION; return; case COLGROUP: /* fragment case */ break; case TABLE: treebuilder->context.mode = IN_TABLE; return; case HEAD: /* fragment case */ break; case BODY: treebuilder->context.mode = IN_BODY; return; case FRAMESET: /* fragment case */ break; case HTML: /* fragment case */ break; default: break; } } } /** * Append text to the current node, inserting into the last child of the * current node, iff it's a Text node. * * \param treebuilder The treebuilder instance * \param string The string to append * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error append_text(hubbub_treebuilder *treebuilder, const hubbub_string *string) { element_type type = current_node(treebuilder); hubbub_error error = HUBBUB_OK; void *text, *appended; error = treebuilder->tree_handler->create_text( treebuilder->tree_handler->ctx, string, &text); if (error != HUBBUB_OK) return error; if (treebuilder->context.in_table_foster && (type == TABLE || type == TBODY || type == TFOOT || type == THEAD || type == TR)) { error = aa_insert_into_foster_parent(treebuilder, text, &appended); } else { error = treebuilder->tree_handler->append_child( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node, text, &appended); } if (error == HUBBUB_OK) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, appended); } treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, text); return error; } /** * Convert an element name into an element type * * \param treebuilder The treebuilder instance * \param tag_name The tag name to consider * \return The corresponding element type */ element_type element_type_from_name(hubbub_treebuilder *treebuilder, const hubbub_string *tag_name) { const uint8_t *name = tag_name->ptr; size_t len = tag_name->len; uint32_t i; UNUSED(treebuilder); /** \todo optimise this */ for (i = 0; i < N_ELEMENTS(name_type_map); i++) { if (name_type_map[i].len != len) continue; if (strncasecmp(name_type_map[i].name, (const char *) name, len) == 0) return name_type_map[i].type; } return UNKNOWN; } /** * Determine if a node is a special element * * \param type Node type to consider * \return True iff node is a special element */ bool is_special_element(element_type type) { return (type <= WBR); } /** * Determine if a node is a scoping element * * \param type Node type to consider * \return True iff node is a scoping element */ bool is_scoping_element(element_type type) { return (type >= APPLET && type <= TH); } /** * Determine if a node is a formatting element * * \param type Node type to consider * \return True iff node is a formatting element */ bool is_formatting_element(element_type type) { return (type >= A && type <= U); } /** * Determine if a node is a phrasing element * * \param type Node type to consider * \return True iff node is a phrasing element */ bool is_phrasing_element(element_type type) { return (type > U); } /** * Determine if a node is form associated * * \param type Node type to consider * \return True iff node is form associated */ bool is_form_associated(element_type type) { return type == FIELDSET || type == LABEL || type == INPUT || type == BUTTON || type == SELECT || type == TEXTAREA || type == OUTPUT; } /** * Push an element onto the stack of open elements * * \param treebuilder The treebuilder instance containing the stack * \param ns The namespace of element being pushed * \param type The type of element being pushed * \param node The node to push * \return HUBBUB_OK on success, appropriate error otherwise. */ hubbub_error element_stack_push(hubbub_treebuilder *treebuilder, hubbub_ns ns, element_type type, void *node) { uint32_t slot = treebuilder->context.current_node + 1; if (slot >= treebuilder->context.stack_alloc) { element_context *temp = treebuilder->alloc( treebuilder->context.element_stack, (treebuilder->context.stack_alloc + ELEMENT_STACK_CHUNK) * sizeof(element_context), treebuilder->alloc_pw); if (temp == NULL) return HUBBUB_NOMEM; treebuilder->context.element_stack = temp; treebuilder->context.stack_alloc += ELEMENT_STACK_CHUNK; } treebuilder->context.element_stack[slot].ns = ns; treebuilder->context.element_stack[slot].type = type; treebuilder->context.element_stack[slot].node = node; treebuilder->context.current_node = slot; return HUBBUB_OK; } /** * Pop an element off the stack of open elements * * \param treebuilder The treebuilder instance containing the stack * \param ns Pointer to location to receive element namespace * \param type Pointer to location to receive element type * \param node Pointer to location to receive node * \return HUBBUB_OK on success, appropriate error otherwise. */ hubbub_error element_stack_pop(hubbub_treebuilder *treebuilder, hubbub_ns *ns, element_type *type, void **node) { element_context *stack = treebuilder->context.element_stack; uint32_t slot = treebuilder->context.current_node; formatting_list_entry *entry; /* We're popping a table, find previous */ if (stack[slot].type == TABLE) { uint32_t t; for (t = slot - 1; t > 0; t--) { if (stack[t].type == TABLE) break; } } if (is_formatting_element(stack[slot].type) || (is_scoping_element(stack[slot].type) && stack[slot].type != HTML && stack[slot].type != TABLE)) { /* Find occurrences of the node we're about to pop in the list * of active formatting elements. We need to invalidate their * stack index information. */ for (entry = treebuilder->context.formatting_list_end; entry != NULL; entry = entry->prev) { /** \todo Can we optimise this? * (i.e. by not traversing the entire list) */ if (entry->stack_index == slot) entry->stack_index = 0; } } *ns = stack[slot].ns; *type = stack[slot].type; *node = stack[slot].node; /** \todo reduce allocated stack size once there's enough free */ treebuilder->context.current_node = slot - 1; assert((signed) treebuilder->context.current_node >= 0); return HUBBUB_OK; } /** * Pop elements until an element of type "element" has been popped. * * \return HUBBUB_OK on success, appropriate error otherwise. */ hubbub_error element_stack_pop_until(hubbub_treebuilder *treebuilder, element_type type) { element_type otype = UNKNOWN; void *node; hubbub_ns ns; while (otype != type) { element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); assert((signed) treebuilder->context.current_node >= 0); } return HUBBUB_OK; } /** * Remove a node from the stack of open elements * * \param treebuilder The treebuilder instance * \param index The index of the node to remove * \param ns Pointer to location to receive namespace * \param type Pointer to location to receive type * \param removed Pointer to location to receive removed node * \return HUBBUB_OK on success, appropriate error otherwise. */ hubbub_error element_stack_remove(hubbub_treebuilder *treebuilder, uint32_t index, hubbub_ns *ns, element_type *type, void **removed) { element_context *stack = treebuilder->context.element_stack; uint32_t n; assert(index <= treebuilder->context.current_node); /* Scan over subsequent entries in the stack, * searching for them in the list of active formatting * entries. If found, update the corresponding * formatting list entry's stack index to match the * new stack location */ for (n = index + 1; n <= treebuilder->context.current_node; n++) { if (is_formatting_element(stack[n].type) || (is_scoping_element(stack[n].type) && stack[n].type != HTML && stack[n].type != TABLE)) { formatting_list_entry *e; for (e = treebuilder->context.formatting_list_end; e != NULL; e = e->prev) { if (e->stack_index == n) e->stack_index--; } } } *ns = stack[index].ns; *type = stack[index].type; *removed = stack[index].node; /* Now, shuffle the stack up one, removing node in the process */ if (index < treebuilder->context.current_node) { memmove(&stack[index], &stack[index + 1], (treebuilder->context.current_node - index) * sizeof(element_context)); } treebuilder->context.current_node--; return HUBBUB_OK; } /** * Find the stack index of the current table. */ uint32_t current_table(hubbub_treebuilder *treebuilder) { element_context *stack = treebuilder->context.element_stack; size_t t; for (t = treebuilder->context.current_node; t != 0; t--) { if (stack[t].type == TABLE) return t; } /* fragment case */ return 0; } /** * Peek at the top element of the element stack. * * \param treebuilder Treebuilder instance * \return Element type on the top of the stack */ element_type current_node(hubbub_treebuilder *treebuilder) { return treebuilder->context.element_stack [treebuilder->context.current_node].type; } /** * Peek at the element below the top of the element stack. * * \param treebuilder Treebuilder instance * \return Element type of the element one below the top of the stack */ element_type prev_node(hubbub_treebuilder *treebuilder) { if (treebuilder->context.current_node == 0) return UNKNOWN; return treebuilder->context.element_stack [treebuilder->context.current_node - 1].type; } /** * Append an element to the end of the list of active formatting elements * * \param treebuilder Treebuilder instance containing list * \param ns Namespace of node being inserted * \param type Type of node being inserted * \param node Node being inserted * \param stack_index Index into stack of open elements * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error formatting_list_append(hubbub_treebuilder *treebuilder, hubbub_ns ns, element_type type, void *node, uint32_t stack_index) { formatting_list_entry *entry; entry = treebuilder->alloc(NULL, sizeof(formatting_list_entry), treebuilder->alloc_pw); if (entry == NULL) return HUBBUB_NOMEM; entry->details.ns = ns; entry->details.type = type; entry->details.node = node; entry->stack_index = stack_index; entry->prev = treebuilder->context.formatting_list_end; entry->next = NULL; if (entry->prev != NULL) entry->prev->next = entry; else treebuilder->context.formatting_list = entry; treebuilder->context.formatting_list_end = entry; return HUBBUB_OK; } /** * Insert an element into the list of active formatting elements * * \param treebuilder Treebuilder instance containing list * \param prev Previous entry * \param next Next entry * \param ns Namespace of node being inserted * \param type Type of node being inserted * \param node Node being inserted * \param stack_index Index into stack of open elements * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error formatting_list_insert(hubbub_treebuilder *treebuilder, formatting_list_entry *prev, formatting_list_entry *next, hubbub_ns ns, element_type type, void *node, uint32_t stack_index) { formatting_list_entry *entry; if (prev != NULL) { assert(prev->next == next); } if (next != NULL) { assert(next->prev == prev); } entry = treebuilder->alloc(NULL, sizeof(formatting_list_entry), treebuilder->alloc_pw); if (entry == NULL) return HUBBUB_NOMEM; entry->details.ns = ns; entry->details.type = type; entry->details.node = node; entry->stack_index = stack_index; entry->prev = prev; entry->next = next; if (entry->prev != NULL) entry->prev->next = entry; else treebuilder->context.formatting_list = entry; if (entry->next != NULL) entry->next->prev = entry; else treebuilder->context.formatting_list_end = entry; return HUBBUB_OK; } /** * Remove an element from the list of active formatting elements * * \param treebuilder Treebuilder instance containing list * \param entry The item to remove * \param ns Pointer to location to receive namespace of node * \param type Pointer to location to receive type of node * \param node Pointer to location to receive node * \param stack_index Pointer to location to receive stack index * \return HUBBUB_OK on success, appropriate error otherwise. */ hubbub_error formatting_list_remove(hubbub_treebuilder *treebuilder, formatting_list_entry *entry, hubbub_ns *ns, element_type *type, void **node, uint32_t *stack_index) { *ns = entry->details.ns; *type = entry->details.type; *node = entry->details.node; *stack_index = entry->stack_index; if (entry->prev == NULL) treebuilder->context.formatting_list = entry->next; else entry->prev->next = entry->next; if (entry->next == NULL) treebuilder->context.formatting_list_end = entry->prev; else entry->next->prev = entry->prev; treebuilder->alloc(entry, 0, treebuilder->alloc_pw); return HUBBUB_OK; } /** * Remove an element from the list of active formatting elements * * \param treebuilder Treebuilder instance containing list * \param entry The item to replace * \param ns Replacement node namespace * \param type Replacement node type * \param node Replacement node * \param stack_index Replacement stack index * \param ons Pointer to location to receive old namespace * \param otype Pointer to location to receive old type * \param onode Pointer to location to receive old node * \param ostack_index Pointer to location to receive old stack index * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error formatting_list_replace(hubbub_treebuilder *treebuilder, formatting_list_entry *entry, hubbub_ns ns, element_type type, void *node, uint32_t stack_index, hubbub_ns *ons, element_type *otype, void **onode, uint32_t *ostack_index) { UNUSED(treebuilder); *ons = entry->details.ns; *otype = entry->details.type; *onode = entry->details.node; *ostack_index = entry->stack_index; entry->details.ns = ns; entry->details.type = type; entry->details.node = node; entry->stack_index = stack_index; return HUBBUB_OK; } #ifndef NDEBUG /** * Dump an element stack to the given file pointer * * \param treebuilder The treebuilder instance * \param fp The file to dump to */ void element_stack_dump(hubbub_treebuilder *treebuilder, FILE *fp) { element_context *stack = treebuilder->context.element_stack; uint32_t i; for (i = 0; i <= treebuilder->context.current_node; i++) { fprintf(fp, "%u: %s %p\n", i, element_type_to_name(stack[i].type), stack[i].node); } } /** * Dump a formatting list to the given file pointer * * \param treebuilder The treebuilder instance * \param fp The file to dump to */ void formatting_list_dump(hubbub_treebuilder *treebuilder, FILE *fp) { formatting_list_entry *entry; for (entry = treebuilder->context.formatting_list; entry != NULL; entry = entry->next) { fprintf(fp, "%s %p %u\n", element_type_to_name(entry->details.type), entry->details.node, entry->stack_index); } } /** * Convert an element type to a name * * \param type The element type * \return Pointer to name */ const char *element_type_to_name(element_type type) { size_t i; for (i = 0; i < sizeof(name_type_map) / sizeof(name_type_map[0]); i++) { if (name_type_map[i].type == type) return name_type_map[i].name; } return "UNKNOWN"; } #endif netsurf-2.9/hubbub-0.1.2/src/treebuilder/before_head.c0000664000175000017500000000474511171337335021453 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle token in "before head" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_before_head(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool handled = false; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, false); break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } else if (type == HEAD) { handled = true; } else { err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML || type == BODY || type == HEAD || type == BR) { err = HUBBUB_REPROCESS; } else { /** \todo parse error */ } } break; case HUBBUB_TOKEN_EOF: err = HUBBUB_REPROCESS; break; } if (handled || err == HUBBUB_REPROCESS) { hubbub_error e; hubbub_tag tag; if (err == HUBBUB_REPROCESS) { /* Manufacture head tag */ tag.ns = HUBBUB_NS_HTML; tag.name.ptr = (const uint8_t *) "head"; tag.name.len = SLEN("head"); tag.n_attributes = 0; tag.attributes = NULL; } else { tag = token->data.tag; } e = insert_element(treebuilder, &tag, true); if (e != HUBBUB_OK) return e; treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); treebuilder->context.head_element = treebuilder->context.element_stack[ treebuilder->context.current_node].node; treebuilder->context.mode = IN_HEAD; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/after_after_frameset.c0000664000175000017500000000316611171337335023374 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle token in "after after frameset" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_after_after_frameset(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, true); if (err == HUBBUB_REPROCESS) treebuilder->context.mode = IN_FRAMESET; break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.document); break; case HUBBUB_TOKEN_END_TAG: case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ /* ignore token */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } else if (type == NOFRAMES) { err = handle_in_head(treebuilder, token); } else { /** \todo parse error */ treebuilder->context.mode = IN_FRAMESET; err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_EOF: break; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/treebuilder.h0000664000175000017500000000321311171401566021526 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef hubbub_treebuilder_treebuilder_h_ #define hubbub_treebuilder_treebuilder_h_ #include #include #include #include #include #include #include "tokeniser/tokeniser.h" typedef struct hubbub_treebuilder hubbub_treebuilder; /** * Hubbub treebuilder option types */ typedef enum hubbub_treebuilder_opttype { HUBBUB_TREEBUILDER_ERROR_HANDLER, HUBBUB_TREEBUILDER_TREE_HANDLER, HUBBUB_TREEBUILDER_DOCUMENT_NODE, HUBBUB_TREEBUILDER_ENABLE_SCRIPTING } hubbub_treebuilder_opttype; /** * Hubbub treebuilder option parameters */ typedef union hubbub_treebuilder_optparams { struct { hubbub_error_handler handler; void *pw; } error_handler; /**< Error handling callback */ hubbub_tree_handler *tree_handler; /**< Tree handling callbacks */ void *document_node; /**< The document node */ bool enable_scripting; /**< Enable scripting */ } hubbub_treebuilder_optparams; /* Create a hubbub treebuilder */ hubbub_error hubbub_treebuilder_create(hubbub_tokeniser *tokeniser, hubbub_allocator_fn alloc, void *pw, hubbub_treebuilder **treebuilder); /* Destroy a hubbub treebuilder */ hubbub_error hubbub_treebuilder_destroy(hubbub_treebuilder *treebuilder); /* Configure a hubbub treebuilder */ hubbub_error hubbub_treebuilder_setopt(hubbub_treebuilder *treebuilder, hubbub_treebuilder_opttype type, hubbub_treebuilder_optparams *params); #endif netsurf-2.9/hubbub-0.1.2/src/treebuilder/generic_rcdata.c0000664000175000017500000000436011613627634022160 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle tokens in "generic rcdata" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_generic_rcdata(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool done = false; if (treebuilder->context.strip_leading_lr && token->type != HUBBUB_TOKEN_CHARACTER) { /* Reset the LR stripping flag */ treebuilder->context.strip_leading_lr = false; } switch (token->type) { case HUBBUB_TOKEN_CHARACTER: { hubbub_string chars = token->data.character; if (treebuilder->context.strip_leading_lr) { if (chars.ptr[0] == '\n') { chars.ptr++; chars.len--; } treebuilder->context.strip_leading_lr = false; } if (chars.len == 0) break; err = append_text(treebuilder, &chars); } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type != treebuilder->context.collect.type) { /** \todo parse error */ } if (type == SCRIPT) { /** \todo script processing and execution */ } done = true; } break; case HUBBUB_TOKEN_EOF: /** \todo if the current node's a script, * mark it as already executed */ /** \todo parse error */ done = true; err = HUBBUB_REPROCESS; break; case HUBBUB_TOKEN_COMMENT: case HUBBUB_TOKEN_DOCTYPE: case HUBBUB_TOKEN_START_TAG: /* Should never happen */ assert(0); break; } if (done) { hubbub_ns ns; element_type otype; void *node; /* Pop the current node from the stack */ element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); /* Return to previous insertion mode */ treebuilder->context.mode = treebuilder->context.collect.mode; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/Makefile0000664000175000017500000000066011162164230020504 0ustar vincevince# Sources DIR_SOURCES := treebuilder.c \ initial.c before_html.c before_head.c in_head.c \ in_head_noscript.c after_head.c in_body.c in_table.c \ in_caption.c in_column_group.c in_table_body.c in_row.c \ in_cell.c in_select.c in_select_in_table.c \ in_foreign_content.c after_body.c in_frameset.c \ after_frameset.c after_after_body.c after_after_frameset.c \ generic_rcdata.c include build/makefiles/Makefile.subdir netsurf-2.9/hubbub-0.1.2/src/treebuilder/modes.h0000664000175000017500000000560011171401566020331 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef hubbub_treebuilder_modes_h_ #define hubbub_treebuilder_modes_h_ #include "treebuilder/treebuilder.h" /** The various treebuilder insertion modes */ typedef enum { INITIAL, BEFORE_HTML, BEFORE_HEAD, IN_HEAD, IN_HEAD_NOSCRIPT, AFTER_HEAD, IN_BODY, IN_TABLE, IN_CAPTION, IN_COLUMN_GROUP, IN_TABLE_BODY, IN_ROW, IN_CELL, IN_SELECT, IN_SELECT_IN_TABLE, IN_FOREIGN_CONTENT, AFTER_BODY, IN_FRAMESET, AFTER_FRAMESET, AFTER_AFTER_BODY, AFTER_AFTER_FRAMESET, GENERIC_RCDATA } insertion_mode; hubbub_error handle_initial(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_before_html(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_before_head(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_head(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_head_noscript(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_after_head(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_table(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_caption(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_column_group(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_table_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_row(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_cell(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_select(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_select_in_table(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_generic_rcdata(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_script_collect_characters(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_foreign_content(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_after_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_in_frameset(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_after_frameset(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_after_after_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); hubbub_error handle_after_after_frameset(hubbub_treebuilder *treebuilder, const hubbub_token *token); #endif netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_body.c0000664000175000017500000020004611613627634020650 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" #undef DEBUG_IN_BODY /** * Bookmark for formatting list. Used in adoption agency */ typedef struct bookmark { formatting_list_entry *prev; /**< Previous entry */ formatting_list_entry *next; /**< Next entry */ } bookmark; static hubbub_error process_character(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_start_tag(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_end_tag(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_html_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_body_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_frameset_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_container_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_hN_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_form_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_dd_dt_li_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token, element_type type); static hubbub_error process_plaintext_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_a_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_presentational_in_body( hubbub_treebuilder *treebuilder, const hubbub_token *token, element_type type); static hubbub_error process_nobr_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_button_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_applet_marquee_object_in_body( hubbub_treebuilder *treebuilder, const hubbub_token *token, element_type type); static hubbub_error process_hr_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_image_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_isindex_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_textarea_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_select_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_opt_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_phrasing_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token); static hubbub_error process_0body_in_body(hubbub_treebuilder *treebuilder); static hubbub_error process_0container_in_body(hubbub_treebuilder *treebuilder, element_type type); static hubbub_error process_0form_in_body(hubbub_treebuilder *treebuilder); static hubbub_error process_0p_in_body(hubbub_treebuilder *treebuilder); static hubbub_error process_0dd_dt_li_in_body(hubbub_treebuilder *treebuilder, element_type type); static hubbub_error process_0h_in_body(hubbub_treebuilder *treebuilder, element_type type); static hubbub_error process_0presentational_in_body( hubbub_treebuilder *treebuilder, element_type type); static hubbub_error process_0applet_button_marquee_object_in_body( hubbub_treebuilder *treebuilder, element_type type); static hubbub_error process_0br_in_body(hubbub_treebuilder *treebuilder); static hubbub_error process_0generic_in_body(hubbub_treebuilder *treebuilder, element_type type); static hubbub_error aa_find_and_validate_formatting_element( hubbub_treebuilder *treebuilder, element_type type, formatting_list_entry **element); static formatting_list_entry *aa_find_formatting_element( hubbub_treebuilder *treebuilder, element_type type); static hubbub_error aa_find_furthest_block(hubbub_treebuilder *treebuilder, formatting_list_entry *formatting_element, uint32_t *furthest_block); static hubbub_error aa_reparent_node(hubbub_treebuilder *treebuilder, void *node, void *new_parent, void **reparented); static hubbub_error aa_find_bookmark_location_reparenting_misnested( hubbub_treebuilder *treebuilder, uint32_t formatting_element, uint32_t *furthest_block, bookmark *bookmark, uint32_t *last_node); static hubbub_error aa_remove_element_stack_item( hubbub_treebuilder *treebuilder, uint32_t index, uint32_t limit); static hubbub_error aa_clone_and_replace_entries( hubbub_treebuilder *treebuilder, formatting_list_entry *element); /** * Handle tokens in "in body" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; uint32_t i; #if !defined(NDEBUG) && defined(DEBUG_IN_BODY) fprintf(stdout, "Processing token %d\n", token->type); element_stack_dump(treebuilder, stdout); formatting_list_dump(treebuilder, stdout); #endif if (treebuilder->context.strip_leading_lr && token->type != HUBBUB_TOKEN_CHARACTER) { /* Reset the LR stripping flag */ treebuilder->context.strip_leading_lr = false; } switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_character(treebuilder, token); break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: err = process_start_tag(treebuilder, token); break; case HUBBUB_TOKEN_END_TAG: err = process_end_tag(treebuilder, token); break; case HUBBUB_TOKEN_EOF: for (i = treebuilder->context.current_node; i > 0; i--) { element_type type = treebuilder->context.element_stack[i].type; if (!(type == DD || type == DT || type == LI || type == P || type == TBODY || type == TD || type == TFOOT || type == TH || type == THEAD || type == TR || type == BODY)) { /** \todo parse error */ break; } } break; } #if !defined(NDEBUG) && defined(DEBUG_IN_BODY) fprintf(stdout, "Processed\n"); element_stack_dump(treebuilder, stdout); formatting_list_dump(treebuilder, stdout); #endif return err; } /** * Process a character token * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_character(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; hubbub_string dummy = token->data.character; bool lr_flag = treebuilder->context.strip_leading_lr; const uint8_t *p; err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; if (treebuilder->context.strip_leading_lr) { const uint8_t *str = dummy.ptr; if (*str == '\n') { dummy.ptr++; dummy.len--; } treebuilder->context.strip_leading_lr = false; } if (dummy.len) { err = append_text(treebuilder, &dummy); if (err != HUBBUB_OK) { /* Restore LR stripping flag */ treebuilder->context.strip_leading_lr = lr_flag; return err; } } if (treebuilder->context.frameset_ok) { for (p = dummy.ptr; p < dummy.ptr + dummy.len; p++) { if (*p != 0x0009 && *p != 0x000a && *p != 0x000c && *p != 0x0020) { treebuilder->context.frameset_ok = false; break; } } } return HUBBUB_OK; } /** * Process a start tag * * \param treebuilder The treebuilder instance * \param token The token to process * \return HUBBUB_OK on success, * HUBBUB_REPROCESS to reprocess the token, * appropriate error otherwise. */ hubbub_error process_start_tag(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { err = process_html_in_body(treebuilder, token); } else if (type == BASE || type == COMMAND || type == LINK || type == META || type == NOFRAMES || type == SCRIPT || type == STYLE || type == TITLE) { /* Process as "in head" */ err = handle_in_head(treebuilder, token); } else if (type == BODY) { err = process_body_in_body(treebuilder, token); } else if (type == FRAMESET) { err = process_frameset_in_body(treebuilder, token); } else if (type == ADDRESS || type == ARTICLE || type == ASIDE || type == BLOCKQUOTE || type == CENTER || type == DATAGRID || type == DETAILS || type == DIALOG || type == DIR || type == DIV || type == DL || type == FIELDSET || type == FIGURE || type == FOOTER || type == HEADER || type == MENU || type == NAV || type == OL || type == P || type == SECTION || type == UL) { err = process_container_in_body(treebuilder, token); } else if (type == H1 || type == H2 || type == H3 || type == H4 || type == H5 || type == H6) { err = process_hN_in_body(treebuilder, token); } else if (type == PRE || type == LISTING) { err = process_container_in_body(treebuilder, token); if (err == HUBBUB_OK) { treebuilder->context.strip_leading_lr = true; treebuilder->context.frameset_ok = false; } } else if (type == FORM) { err = process_form_in_body(treebuilder, token); } else if (type == DD || type == DT || type == LI) { err = process_dd_dt_li_in_body(treebuilder, token, type); } else if (type == PLAINTEXT) { err = process_plaintext_in_body(treebuilder, token); } else if (type == A) { err = process_a_in_body(treebuilder, token); } else if (type == B || type == BIG || type == CODE || type == EM || type == FONT || type == I || type == S || type == SMALL || type == STRIKE || type == STRONG || type == TT || type == U) { err = process_presentational_in_body(treebuilder, token, type); } else if (type == NOBR) { err = process_nobr_in_body(treebuilder, token); } else if (type == BUTTON) { err = process_button_in_body(treebuilder, token); } else if (type == APPLET || type == MARQUEE || type == OBJECT) { err = process_applet_marquee_object_in_body(treebuilder, token, type); } else if (type == XMP) { err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; treebuilder->context.frameset_ok = false; err = parse_generic_rcdata(treebuilder, token, false); } else if (type == TABLE) { err = process_container_in_body(treebuilder, token); if (err == HUBBUB_OK) { treebuilder->context.frameset_ok = false; treebuilder->context.element_stack[ current_table(treebuilder)].tainted = false; treebuilder->context.mode = IN_TABLE; } } else if (type == AREA || type == BASEFONT || type == BGSOUND || type == BR || type == EMBED || type == IMG || type == INPUT || type == PARAM || type == SPACER || type == WBR) { err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; err = insert_element(treebuilder, &token->data.tag, false); if (err == HUBBUB_OK) treebuilder->context.frameset_ok = false; } else if (type == HR) { err = process_hr_in_body(treebuilder, token); } else if (type == IMAGE) { err = process_image_in_body(treebuilder, token); } else if (type == ISINDEX) { err = process_isindex_in_body(treebuilder, token); } else if (type == TEXTAREA) { err = process_textarea_in_body(treebuilder, token); } else if (type == IFRAME || type == NOEMBED || type == NOFRAMES || (treebuilder->context.enable_scripting && type == NOSCRIPT)) { if (type == IFRAME) treebuilder->context.frameset_ok = false; err = parse_generic_rcdata(treebuilder, token, false); } else if (type == SELECT) { err = process_select_in_body(treebuilder, token); if (err != HUBBUB_OK) return err; if (treebuilder->context.mode == IN_BODY) { treebuilder->context.mode = IN_SELECT; } else if (treebuilder->context.mode == IN_TABLE || treebuilder->context.mode == IN_CAPTION || treebuilder->context.mode == IN_COLUMN_GROUP || treebuilder->context.mode == IN_TABLE_BODY || treebuilder->context.mode == IN_ROW || treebuilder->context.mode == IN_CELL) { treebuilder->context.mode = IN_SELECT_IN_TABLE; } } else if (type == OPTGROUP || type == OPTION) { err = process_opt_in_body(treebuilder, token); } else if (type == RP || type == RT) { /** \todo ruby */ } else if (type == MATH || type == SVG) { hubbub_tag tag = token->data.tag; err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; adjust_foreign_attributes(treebuilder, &tag); if (type == SVG) { adjust_svg_attributes(treebuilder, &tag); tag.ns = HUBBUB_NS_SVG; } else { adjust_mathml_attributes(treebuilder, &tag); tag.ns = HUBBUB_NS_MATHML; } if (token->data.tag.self_closing) { err = insert_element(treebuilder, &tag, false); /** \todo ack sc flag */ } else { err = insert_element(treebuilder, &tag, true); if (err == HUBBUB_OK) { treebuilder->context.second_mode = treebuilder->context.mode; treebuilder->context.mode = IN_FOREIGN_CONTENT; } } } else if (type == CAPTION || type == COL || type == COLGROUP || type == FRAME || type == HEAD || type == TBODY || type == TD || type == TFOOT || type == TH || type == THEAD || type == TR) { /** \todo parse error */ } else { err = process_phrasing_in_body(treebuilder, token); } return err; } /** * Process an end tag * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token */ hubbub_error process_end_tag(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == BODY) { err = process_0body_in_body(treebuilder); /* Never reprocess */ if (err == HUBBUB_REPROCESS) err = HUBBUB_OK; } else if (type == HTML) { /* Act as if has been seen then, if * that wasn't ignored, reprocess this token */ err = process_0body_in_body(treebuilder); } else if (type == ADDRESS || type == ARTICLE || type == ASIDE || type == BLOCKQUOTE || type == CENTER || type == DIR || type == DATAGRID || type == DIV || type == DL || type == FIELDSET || type == FOOTER || type == HEADER || type == LISTING || type == MENU || type == NAV || type == OL || type == PRE || type == SECTION || type == UL) { err = process_0container_in_body(treebuilder, type); } else if (type == FORM) { err = process_0form_in_body(treebuilder); } else if (type == P) { err = process_0p_in_body(treebuilder); } else if (type == DD || type == DT || type == LI) { err = process_0dd_dt_li_in_body(treebuilder, type); } else if (type == H1 || type == H2 || type == H3 || type == H4 || type == H5 || type == H6) { err = process_0h_in_body(treebuilder, type); } else if (type == A || type == B || type == BIG || type == CODE || type == EM || type == FONT || type == I || type == NOBR || type == S || type == SMALL || type == STRIKE || type == STRONG || type == TT || type == U) { err = process_0presentational_in_body(treebuilder, type); } else if (type == APPLET || type == BUTTON || type == MARQUEE || type == OBJECT) { err = process_0applet_button_marquee_object_in_body( treebuilder, type); } else if (type == BR) { err = process_0br_in_body(treebuilder); } else if (type == AREA || type == BASEFONT || type == BGSOUND || type == EMBED || type == HR || type == IFRAME || type == IMAGE || type == IMG || type == INPUT || type == ISINDEX || type == NOEMBED || type == NOFRAMES || type == PARAM || type == SELECT || type == SPACER || type == TABLE || type == TEXTAREA || type == WBR || (treebuilder->context.enable_scripting && type == NOSCRIPT)) { /** \todo parse error */ } else { err = process_0generic_in_body(treebuilder, type); } return err; } /** * Process a html start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_html_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { /** \todo parse error */ return treebuilder->tree_handler->add_attributes( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[0].node, token->data.tag.attributes, token->data.tag.n_attributes); } /** * Process a body start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_body_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { /** \todo parse error */ if (treebuilder->context.current_node < 1 || treebuilder->context.element_stack[1].type != BODY) return HUBBUB_OK; return treebuilder->tree_handler->add_attributes( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[1].node, token->data.tag.attributes, token->data.tag.n_attributes); } /** * Process a frameset start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_frameset_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; /** \todo parse error */ if (treebuilder->context.current_node < 1 || treebuilder->context.element_stack[1].type != BODY) return HUBBUB_OK; if (treebuilder->context.frameset_ok == false) return HUBBUB_OK; err = remove_node_from_dom(treebuilder, treebuilder->context.element_stack[1].node); if (err != HUBBUB_OK) return err; err = element_stack_pop_until(treebuilder, BODY); assert(err == HUBBUB_OK); err = insert_element(treebuilder, &token->data.tag, true); if (err == HUBBUB_OK) treebuilder->context.mode = IN_FRAMESET; return err; } /** * Process a generic container start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_container_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; if (element_in_scope(treebuilder, P, false)) { err = process_0p_in_body(treebuilder); if (err != HUBBUB_OK) return err; } return insert_element(treebuilder, &token->data.tag, true); } /** * Process a hN start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_hN_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; element_type type; if (element_in_scope(treebuilder, P, false)) { err = process_0p_in_body(treebuilder); if (err != HUBBUB_OK) return err; } type = treebuilder->context.element_stack[ treebuilder->context.current_node].type; if (type == H1 || type == H2 || type == H3 || type == H4 || type == H5 || type == H6) { hubbub_ns ns; element_type otype; void *node; /** \todo parse error */ err = element_stack_pop(treebuilder, &ns, &otype, &node); assert(err == HUBBUB_OK); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } return insert_element(treebuilder, &token->data.tag, true); } /** * Process a form start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_form_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; if (treebuilder->context.form_element != NULL) { /** \todo parse error */ } else { if (element_in_scope(treebuilder, P, false)) { err = process_0p_in_body(treebuilder); if (err != HUBBUB_OK) return err; } err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) return err; /* Claim a reference on the node and * use it as the current form element */ treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); treebuilder->context.form_element = treebuilder->context.element_stack[ treebuilder->context.current_node].node; } return HUBBUB_OK; } /** * Process a dd, dt or li start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process * \param type The element type */ hubbub_error process_dd_dt_li_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token, element_type type) { hubbub_error err; element_context *stack = treebuilder->context.element_stack; uint32_t node; treebuilder->context.frameset_ok = false; if (element_in_scope(treebuilder, P, false)) { err = process_0p_in_body(treebuilder); if (err != HUBBUB_OK) return err; } /* Find last LI/(DD,DT) on stack, if any */ for (node = treebuilder->context.current_node; node > 0; node--) { element_type ntype = stack[node].type; if (type == LI && ntype == LI) break; if (((type == DD || type == DT) && (ntype == DD || ntype == DT))) break; if (!is_formatting_element(ntype) && !is_phrasing_element(ntype) && ntype != ADDRESS && ntype != DIV) break; } /* If we found one, then pop all nodes up to and including it */ if (stack[node].type == LI || stack[node].type == DD || stack[node].type == DT) { /* Check that we're only popping one node * and emit a parse error if not */ if (treebuilder->context.current_node > node) { /** \todo parse error */ } do { hubbub_ns ns; element_type otype; void *node; err = element_stack_pop(treebuilder, &ns, &otype, &node); assert(err == HUBBUB_OK); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } while (treebuilder->context.current_node >= node); } return insert_element(treebuilder, &token->data.tag, true); } /** * Process a plaintext start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_plaintext_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; hubbub_tokeniser_optparams params; if (element_in_scope(treebuilder, P, false)) { err = process_0p_in_body(treebuilder); if (err != HUBBUB_OK) return err; } err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) return err; params.content_model.model = HUBBUB_CONTENT_MODEL_PLAINTEXT; err = hubbub_tokeniser_setopt(treebuilder->tokeniser, HUBBUB_TOKENISER_CONTENT_MODEL, ¶ms); assert(err == HUBBUB_OK); return HUBBUB_OK; } /** * Process an "a" start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_a_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; formatting_list_entry *entry = aa_find_formatting_element(treebuilder, A); if (entry != NULL) { uint32_t index = entry->stack_index; void *node = entry->details.node; formatting_list_entry *entry2; /** \todo parse error */ /* Act as if were seen */ err = process_0presentational_in_body(treebuilder, A); if (err != HUBBUB_OK) return err; entry2 = aa_find_formatting_element(treebuilder, A); /* Remove from formatting list, if it's still there */ if (entry2 == entry && entry2->details.node == node) { hubbub_ns ons; element_type otype; void *onode; uint32_t oindex; err = formatting_list_remove(treebuilder, entry, &ons, &otype, &onode, &oindex); assert(err == HUBBUB_OK); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, onode); } /* Remove from the stack of open elements, if still there */ if (index <= treebuilder->context.current_node && treebuilder->context.element_stack[index].node == node) { hubbub_ns ns; element_type otype; void *onode; err = element_stack_remove(treebuilder, index, &ns, &otype, &onode); assert(err == HUBBUB_OK); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, onode); } } err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) return err; treebuilder->tree_handler->ref_node(treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); err = formatting_list_append(treebuilder, token->data.tag.ns, A, treebuilder->context.element_stack[ treebuilder->context.current_node].node, treebuilder->context.current_node); if (err != HUBBUB_OK) { hubbub_ns ns; element_type type; void *node; remove_node_from_dom(treebuilder, treebuilder->context.element_stack[ treebuilder->context.current_node].node); element_stack_pop(treebuilder, &ns, &type, &node); /* Unref twice (once for stack, once for formatting list) */ treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); return err; } return HUBBUB_OK; } /** * Process a b, big, em, font, i, s, small, * strike, strong, tt, or u start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process * \param type The element type */ hubbub_error process_presentational_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token, element_type type) { hubbub_error err; err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) return err; treebuilder->tree_handler->ref_node(treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); err = formatting_list_append(treebuilder, token->data.tag.ns, type, treebuilder->context.element_stack[ treebuilder->context.current_node].node, treebuilder->context.current_node); if (err != HUBBUB_OK) { hubbub_ns ns; element_type type; void *node; remove_node_from_dom(treebuilder, treebuilder->context.element_stack[ treebuilder->context.current_node].node); element_stack_pop(treebuilder, &ns, &type, &node); /* Unref twice (once for stack, once for formatting list) */ treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); return err; } return HUBBUB_OK; } /** * Process a nobr start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_nobr_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; if (element_in_scope(treebuilder, NOBR, false)) { /** \todo parse error */ /* Act as if were seen */ err = process_0presentational_in_body(treebuilder, NOBR); if (err != HUBBUB_OK) return err; /* Yes, again */ err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; } err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) return err; treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); err = formatting_list_append(treebuilder, token->data.tag.ns, NOBR, treebuilder->context.element_stack[ treebuilder->context.current_node].node, treebuilder->context.current_node); if (err != HUBBUB_OK) { hubbub_ns ns; element_type type; void *node; remove_node_from_dom(treebuilder, treebuilder->context.element_stack[ treebuilder->context.current_node].node); element_stack_pop(treebuilder, &ns, &type, &node); /* Unref twice (once for stack, once for formatting list) */ treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); return err; } return HUBBUB_OK; } /** * Process a button start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_button_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; if (element_in_scope(treebuilder, BUTTON, false)) { /** \todo parse error */ /* Act as if has been seen */ err = process_0applet_button_marquee_object_in_body( treebuilder, BUTTON); assert(err == HUBBUB_OK); } err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) return err; treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); err = formatting_list_append(treebuilder, token->data.tag.ns, BUTTON, treebuilder->context.element_stack[ treebuilder->context.current_node].node, treebuilder->context.current_node); if (err != HUBBUB_OK) { hubbub_ns ns; element_type type; void *node; remove_node_from_dom(treebuilder, treebuilder->context.element_stack[ treebuilder->context.current_node].node); element_stack_pop(treebuilder, &ns, &type, &node); /* Unref twice (once for stack, once for formatting list) */ treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); return err; } treebuilder->context.frameset_ok = false; return HUBBUB_OK; } /** * Process an applet, marquee or object start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process * \param type The element type */ hubbub_error process_applet_marquee_object_in_body( hubbub_treebuilder *treebuilder, const hubbub_token *token, element_type type) { hubbub_error err; err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) return err; treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); err = formatting_list_append(treebuilder, token->data.tag.ns, type, treebuilder->context.element_stack[ treebuilder->context.current_node].node, treebuilder->context.current_node); if (err != HUBBUB_OK) { hubbub_ns ns; element_type type; void *node; remove_node_from_dom(treebuilder, treebuilder->context.element_stack[ treebuilder->context.current_node].node); element_stack_pop(treebuilder, &ns, &type, &node); /* Unref twice (once for stack, once for formatting list) */ treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); return err; } treebuilder->context.frameset_ok = false; return HUBBUB_OK; } /** * Process an hr start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_hr_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; if (element_in_scope(treebuilder, P, false)) { err = process_0p_in_body(treebuilder); if (err != HUBBUB_OK) return err; } err = insert_element(treebuilder, &token->data.tag, false); if (err == HUBBUB_OK) treebuilder->context.frameset_ok = false; return err; } /** * Process an image start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_image_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; hubbub_tag tag; tag.ns = HUBBUB_NS_HTML; tag.name.ptr = (const uint8_t *) "img"; tag.name.len = SLEN("img"); tag.n_attributes = token->data.tag.n_attributes; tag.attributes = token->data.tag.attributes; err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; return insert_element(treebuilder, &tag, false); } /** * Process an isindex start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_isindex_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; hubbub_token dummy; hubbub_attribute *action = NULL; hubbub_attribute *prompt = NULL; hubbub_attribute *attrs = NULL; size_t n_attrs = 0; /** \todo parse error */ if (treebuilder->context.form_element != NULL) return HUBBUB_OK; /* First up, clone the token's attributes */ if (token->data.tag.n_attributes > 0) { uint32_t i; attrs = treebuilder->alloc(NULL, (token->data.tag.n_attributes + 1) * sizeof(hubbub_attribute), treebuilder->alloc_pw); if (attrs == NULL) return HUBBUB_NOMEM; for (i = 0; i < token->data.tag.n_attributes; i++) { hubbub_attribute *attr = &token->data.tag.attributes[i]; const uint8_t *name = attr->name.ptr; if (strncmp((const char *) name, "action", attr->name.len) == 0) { action = attr; } else if (strncmp((const char *) name, "prompt", attr->name.len) == 0) { prompt = attr; } else if (strncmp((const char *) name, "name", attr->name.len) == 0) { } else { attrs[n_attrs++] = *attr; } } attrs[n_attrs].ns = HUBBUB_NS_HTML; attrs[n_attrs].name.ptr = (const uint8_t *) "name"; attrs[n_attrs].name.len = SLEN("name"); attrs[n_attrs].value.ptr = (const uint8_t *) "isindex"; attrs[n_attrs].value.len = SLEN("isindex"); n_attrs++; } /* isindex algorithm */ /* Set up dummy as a start tag token */ dummy.type = HUBBUB_TOKEN_START_TAG; dummy.data.tag.ns = HUBBUB_NS_HTML; /* Act as if
were seen */ dummy.data.tag.name.ptr = (const uint8_t *) "form"; dummy.data.tag.name.len = SLEN("form"); dummy.data.tag.n_attributes = action != NULL ? 1 : 0; dummy.data.tag.attributes = action; err = process_form_in_body(treebuilder, &dummy); if (err != HUBBUB_OK) { treebuilder->alloc(attrs, 0, treebuilder->alloc_pw); return err; } /* Act as if
were seen */ dummy.data.tag.name.ptr = (const uint8_t *) "hr"; dummy.data.tag.name.len = SLEN("hr"); dummy.data.tag.n_attributes = 0; dummy.data.tag.attributes = NULL; err = process_hr_in_body(treebuilder, &dummy); if (err != HUBBUB_OK) { treebuilder->alloc(attrs, 0, treebuilder->alloc_pw); return err; } /* Act as if

were seen */ dummy.data.tag.name.ptr = (const uint8_t *) "p"; dummy.data.tag.name.len = SLEN("p"); dummy.data.tag.n_attributes = 0; dummy.data.tag.attributes = NULL; err = process_container_in_body(treebuilder, &dummy); if (err != HUBBUB_OK) { treebuilder->alloc(attrs, 0, treebuilder->alloc_pw); return err; } /* Act as if was seen */ err = process_0generic_in_body(treebuilder, LABEL); assert(err == HUBBUB_OK); /* Act as if

was seen */ err = process_0p_in_body(treebuilder); if (err != HUBBUB_OK) return err; /* Act as if
was seen */ dummy.data.tag.name.ptr = (const uint8_t *) "hr"; dummy.data.tag.name.len = SLEN("hr"); dummy.data.tag.n_attributes = 0; dummy.data.tag.attributes = NULL; err = process_hr_in_body(treebuilder, &dummy); if (err != HUBBUB_OK) return err; /* Act as if
was seen */ return process_0container_in_body(treebuilder, FORM); } /** * Process a textarea start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_textarea_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { treebuilder->context.strip_leading_lr = true; treebuilder->context.frameset_ok = false; return parse_generic_rcdata(treebuilder, token, true); } /** * Process a select start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_select_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; err = insert_element(treebuilder, &token->data.tag, true); if (err == HUBBUB_OK) treebuilder->context.frameset_ok = false; return err; } /** * Process an option or optgroup start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_opt_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; if (element_in_scope(treebuilder, OPTION, false)) { err = process_0generic_in_body(treebuilder, OPTION); /* Cannot fail */ assert(err == HUBBUB_OK); } err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; return insert_element(treebuilder, &token->data.tag, true); } /** * Process a phrasing start tag as if in "in body" * * \param treebuilder The treebuilder instance * \param token The token to process */ hubbub_error process_phrasing_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; return insert_element(treebuilder, &token->data.tag, true); } /** * Process a body end tag as if in "in body" * * \param treebuilder The treebuilder instance * \return True if processed, false otherwise */ hubbub_error process_0body_in_body(hubbub_treebuilder *treebuilder) { hubbub_error err = HUBBUB_OK; if (!element_in_scope(treebuilder, BODY, false)) { /** \todo parse error */ } else { element_context *stack = treebuilder->context.element_stack; uint32_t node; for (node = treebuilder->context.current_node; node > 0; node--) { element_type ntype = stack[node].type; if (ntype != DD && ntype != DT && ntype != LI && ntype != OPTGROUP && ntype != OPTION && ntype != P && ntype != RP && ntype != RT && ntype != TBODY && ntype != TD && ntype != TFOOT && ntype != TH && ntype != THEAD && ntype != TR && ntype != BODY) { /** \todo parse error */ } } if (treebuilder->context.mode == IN_BODY) treebuilder->context.mode = AFTER_BODY; err = HUBBUB_REPROCESS; } return err; } /** * Process a container end tag as if in "in body" * * \param treebuilder The treebuilder instance * \param type The element type */ hubbub_error process_0container_in_body(hubbub_treebuilder *treebuilder, element_type type) { if (!element_in_scope(treebuilder, type, false)) { /** \todo parse error */ } else { uint32_t popped = 0; element_type otype; close_implied_end_tags(treebuilder, UNKNOWN); do { hubbub_ns ns; void *node; element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); popped++; } while (otype != type); if (popped > 1) { /** \todo parse error */ } } return HUBBUB_OK; } /** * Process a form end tag as if in "in body" * * \param treebuilder The treebuilder instance */ hubbub_error process_0form_in_body(hubbub_treebuilder *treebuilder) { void *node = treebuilder->context.form_element; uint32_t idx = 0; if (treebuilder->context.form_element != NULL) treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, treebuilder->context.form_element); treebuilder->context.form_element = NULL; idx = element_in_scope(treebuilder, FORM, false); if (idx == 0 || node == NULL || treebuilder->context.element_stack[idx].node != node) { /** \todo parse error */ } else { hubbub_ns ns; element_type otype; void *onode; close_implied_end_tags(treebuilder, UNKNOWN); if (treebuilder->context.element_stack[ treebuilder->context.current_node].node != node) { /** \todo parse error */ } element_stack_remove(treebuilder, idx, &ns, &otype, &onode); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, onode); } return HUBBUB_OK; } /** * Process a p end tag as if in "in body" * * \param treebuilder The treebuilder instance */ hubbub_error process_0p_in_body(hubbub_treebuilder *treebuilder) { hubbub_error err = HUBBUB_OK; uint32_t popped = 0; if (treebuilder->context.element_stack[ treebuilder->context.current_node].type != P) { /** \todo parse error */ } while (element_in_scope(treebuilder, P, false)) { hubbub_ns ns; element_type type; void *node; err = element_stack_pop(treebuilder, &ns, &type, &node); assert(err == HUBBUB_OK); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); popped++; } if (popped == 0) { hubbub_token dummy; dummy.type = HUBBUB_TOKEN_START_TAG; dummy.data.tag.ns = HUBBUB_NS_HTML; dummy.data.tag.name.ptr = (const uint8_t *) "p"; dummy.data.tag.name.len = SLEN("p"); dummy.data.tag.n_attributes = 0; dummy.data.tag.attributes = NULL; err = process_container_in_body(treebuilder, &dummy); if (err != HUBBUB_OK) return err; /* Reprocess the end tag. This is safe as we've just * inserted a

into the current scope */ err = process_0p_in_body(treebuilder); /* Cannot fail */ assert(err == HUBBUB_OK); } return err; } /** * Process a dd, dt, or li end tag as if in "in body" * * \param treebuilder The treebuilder instance * \param type The element type */ hubbub_error process_0dd_dt_li_in_body(hubbub_treebuilder *treebuilder, element_type type) { if (!element_in_scope(treebuilder, type, false)) { /** \todo parse error */ } else { uint32_t popped = 0; element_type otype; close_implied_end_tags(treebuilder, type); do { hubbub_ns ns; void *node; element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); popped++; } while (otype != type); if (popped > 1) { /** \todo parse error */ } } return HUBBUB_OK; } /** * Process a h1, h2, h3, h4, h5, or h6 end tag as if in "in body" * * \param treebuilder The treebuilder instance * \param type The element type */ hubbub_error process_0h_in_body(hubbub_treebuilder *treebuilder, element_type type) { UNUSED(type); /** \todo optimise this */ if (element_in_scope(treebuilder, H1, false) || element_in_scope(treebuilder, H2, false) || element_in_scope(treebuilder, H3, false) || element_in_scope(treebuilder, H4, false) || element_in_scope(treebuilder, H5, false) || element_in_scope(treebuilder, H6, false)) { uint32_t popped = 0; element_type otype; close_implied_end_tags(treebuilder, UNKNOWN); do { hubbub_ns ns; void *node; element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); popped++; } while (otype != H1 && otype != H2 && otype != H3 && otype != H4 && otype != H5 && otype != H6); if (popped > 1) { /** \todo parse error */ } } else { /** \todo parse error */ } return HUBBUB_OK; } /** * Process a presentational end tag as if in "in body" * * \param treebuilder The treebuilder instance * \param type The element type */ hubbub_error process_0presentational_in_body(hubbub_treebuilder *treebuilder, element_type type) { hubbub_error err; /* Welcome to the adoption agency */ while (true) { element_context *stack = treebuilder->context.element_stack; formatting_list_entry *entry; uint32_t formatting_element; uint32_t common_ancestor; uint32_t furthest_block; bookmark bookmark; uint32_t last_node; void *reparented; void *fe_clone = NULL; void *clone_appended = NULL; hubbub_ns ons; element_type otype; void *onode; uint32_t oindex; /* 1 */ err = aa_find_and_validate_formatting_element(treebuilder, type, &entry); assert(err == HUBBUB_OK || err == HUBBUB_REPROCESS); if (err == HUBBUB_OK) return err; assert(entry->details.type == type); /* Take a copy of the stack index for use * during stack manipulation */ formatting_element = entry->stack_index; /* 2 & 3 */ err = aa_find_furthest_block(treebuilder, entry, &furthest_block); assert(err == HUBBUB_OK || err == HUBBUB_REPROCESS); if (err == HUBBUB_OK) return err; /* 4 */ common_ancestor = formatting_element - 1; /* 5 */ bookmark.prev = entry->prev; bookmark.next = entry->next; /* 6 */ err = aa_find_bookmark_location_reparenting_misnested( treebuilder, formatting_element, &furthest_block, &bookmark, &last_node); if (err != HUBBUB_OK) return err; /* 7 */ if (stack[common_ancestor].type == TABLE || stack[common_ancestor].type == TBODY || stack[common_ancestor].type == TFOOT || stack[common_ancestor].type == THEAD || stack[common_ancestor].type == TR) { err = aa_insert_into_foster_parent(treebuilder, stack[last_node].node, &reparented); } else { err = aa_reparent_node(treebuilder, stack[last_node].node, stack[common_ancestor].node, &reparented); } if (err != HUBBUB_OK) return err; treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, stack[last_node].node); /* If the reparented node is not the same as the one we were * previously using, then have it take the place of the other * one in the formatting list and stack. */ if (reparented != stack[last_node].node) { struct formatting_list_entry *node_entry; for (node_entry = treebuilder->context.formatting_list_end; node_entry != NULL; node_entry = node_entry->prev) { if (node_entry->stack_index == last_node) { treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, reparented); node_entry->details.node = reparented; treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, stack[last_node].node); break; } } /* Already have enough references, so don't need to * explicitly reference it here. */ stack[last_node].node = reparented; } /* 8 */ err = treebuilder->tree_handler->clone_node( treebuilder->tree_handler->ctx, entry->details.node, false, &fe_clone); if (err != HUBBUB_OK) return err; /* 9 */ err = treebuilder->tree_handler->reparent_children( treebuilder->tree_handler->ctx, stack[furthest_block].node, fe_clone); if (err != HUBBUB_OK) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, fe_clone); return err; } /* 10 */ err = treebuilder->tree_handler->append_child( treebuilder->tree_handler->ctx, stack[furthest_block].node, fe_clone, &clone_appended); if (err != HUBBUB_OK) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, fe_clone); return err; } if (clone_appended != fe_clone) { /* No longer interested in fe_clone */ treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, fe_clone); /* Need an extra reference, as we'll insert into the * formatting list and element stack */ treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, clone_appended); } /* 11 and 12 are reversed here so that we know the correct * stack index to use when inserting into the formatting list */ /* 12 */ err = aa_remove_element_stack_item(treebuilder, formatting_element, furthest_block); assert(err == HUBBUB_OK); /* Fix up furthest block index */ furthest_block--; /* Now, in the gap after furthest block, * we insert an entry for clone */ stack[furthest_block + 1].type = entry->details.type; stack[furthest_block + 1].node = clone_appended; /* 11 */ err = formatting_list_remove(treebuilder, entry, &ons, &otype, &onode, &oindex); assert(err == HUBBUB_OK); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, onode); err = formatting_list_insert(treebuilder, bookmark.prev, bookmark.next, ons, otype, clone_appended, furthest_block + 1); if (err != HUBBUB_OK) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, clone_appended); return err; } /* 13 */ } } /** * Adoption agency: find and validate the formatting element * * \param treebuilder The treebuilder instance * \param type Element type to search for * \param element Pointer to location to receive list entry * \return HUBBUB_REPROCESS to continue processing, * HUBBUB_OK to stop. */ hubbub_error aa_find_and_validate_formatting_element( hubbub_treebuilder *treebuilder, element_type type, formatting_list_entry **element) { formatting_list_entry *entry; entry = aa_find_formatting_element(treebuilder, type); if (entry == NULL || (entry->stack_index != 0 && element_in_scope(treebuilder, entry->details.type, false) != entry->stack_index)) { /** \todo parse error */ return HUBBUB_OK; } if (entry->stack_index == 0) { /* Not in element stack => remove from formatting list */ hubbub_ns ns; element_type type; void *node; uint32_t index; /** \todo parse error */ formatting_list_remove(treebuilder, entry, &ns, &type, &node, &index); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); return HUBBUB_OK; } if (entry->stack_index != treebuilder->context.current_node) { /** \todo parse error */ } *element = entry; return HUBBUB_REPROCESS; } /** * Adoption agency: find formatting element * * \param treebuilder The treebuilder instance * \param type Type of element to search for * \return Pointer to formatting element, or NULL if none found */ formatting_list_entry *aa_find_formatting_element( hubbub_treebuilder *treebuilder, element_type type) { formatting_list_entry *entry; for (entry = treebuilder->context.formatting_list_end; entry != NULL; entry = entry->prev) { /* Assumption: HTML and TABLE elements are not in the list */ if (is_scoping_element(entry->details.type) || entry->details.type == type) break; } /* Check if we stopped on a marker, rather than a formatting element */ if (entry != NULL && is_scoping_element(entry->details.type)) entry = NULL; return entry; } /** * Adoption agency: find furthest block * * \param treebuilder The treebuilder instance * \param formatting_element The formatting element * \param furthest_block Pointer to location to receive furthest block * \return HUBBUB_REPROCESS to continue processing (::furthest_block filled in), * HUBBUB_OK to stop. */ hubbub_error aa_find_furthest_block(hubbub_treebuilder *treebuilder, formatting_list_entry *formatting_element, uint32_t *furthest_block) { uint32_t fe_index = formatting_element->stack_index; uint32_t fb; for (fb = fe_index + 1; fb <= treebuilder->context.current_node; fb++) { element_type type = treebuilder->context.element_stack[fb].type; if (!(is_phrasing_element(type) || is_formatting_element(type))) break; } if (fb > treebuilder->context.current_node) { hubbub_ns ns; element_type type; void *node; uint32_t index; /* Pop all elements off the stack up to, * and including, the formatting element */ do { element_stack_pop(treebuilder, &ns, &type, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } while (treebuilder->context.current_node >= fe_index); /* Remove the formatting element from the list */ formatting_list_remove(treebuilder, formatting_element, &ns, &type, &node, &index); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); return HUBBUB_OK; } *furthest_block = fb; return HUBBUB_REPROCESS; } /** * Adoption agency: reparent a node * * \param treebuilder The treebuilder instance * \param node The node to reparent * \param new_parent The new parent * \param reparented Pointer to location to receive reparented node * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error aa_reparent_node(hubbub_treebuilder *treebuilder, void *node, void *new_parent, void **reparented) { hubbub_error err; err = remove_node_from_dom(treebuilder, node); if (err != HUBBUB_OK) return err; return treebuilder->tree_handler->append_child( treebuilder->tree_handler->ctx, new_parent, node, reparented); } /** * Adoption agency: this is step 6 * * \param treebuilder The treebuilder instance * \param formatting_element The stack index of the formatting element * \param furthest_block Pointer to index of furthest block in element * stack (updated on exit) * \param bookmark Pointer to bookmark (pre-initialised) * \param last_node Pointer to location to receive index of last node */ hubbub_error aa_find_bookmark_location_reparenting_misnested( hubbub_treebuilder *treebuilder, uint32_t formatting_element, uint32_t *furthest_block, bookmark *bookmark, uint32_t *last_node) { hubbub_error err; element_context *stack = treebuilder->context.element_stack; uint32_t node, last, fb; formatting_list_entry *node_entry; node = last = fb = *furthest_block; while (true) { void *reparented; /* i */ node--; /* ii */ for (node_entry = treebuilder->context.formatting_list_end; node_entry != NULL; node_entry = node_entry->prev) { if (node_entry->stack_index == node) break; } /* Node is not in list of active formatting elements */ if (node_entry == NULL) { err = aa_remove_element_stack_item(treebuilder, node, treebuilder->context.current_node); assert(err == HUBBUB_OK); /* Update furthest block index and the last node index, * as these are always below node in the stack */ fb--; last--; /* Fixup the current_node index */ treebuilder->context.current_node--; /* Back to i */ continue; } /* iii */ if (node == formatting_element) break; /* iv */ if (last == fb) { bookmark->prev = node_entry; bookmark->next = node_entry->next; } /* v */ err = aa_clone_and_replace_entries(treebuilder, node_entry); if (err != HUBBUB_OK) return err; /* vi */ err = aa_reparent_node(treebuilder, stack[last].node, stack[node].node, &reparented); if (err != HUBBUB_OK) return err; treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, stack[last].node); /* If the reparented node is not the same as the one we were * previously using, then have it take the place of the other * one in the formatting list and stack. */ if (reparented != stack[last].node) { for (node_entry = treebuilder->context.formatting_list_end; node_entry != NULL; node_entry = node_entry->prev) { if (node_entry->stack_index == last) { treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, reparented); node_entry->details.node = reparented; treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, stack[last].node); break; } } /* Already have enough references, so don't need to * explicitly reference it here. */ stack[last].node = reparented; } /* vii */ last = node; /* viii */ } *furthest_block = fb; *last_node = last; return HUBBUB_OK; } /** * Adoption agency: remove an entry from the stack at the given index * * \param treebuilder The treebuilder instance * \param index The index of the item to remove * \param limit The index of the last item to move * * Preconditions: index < limit, limit <= current_node * Postcondition: stack[limit] is empty */ hubbub_error aa_remove_element_stack_item(hubbub_treebuilder *treebuilder, uint32_t index, uint32_t limit) { element_context *stack = treebuilder->context.element_stack; uint32_t n; assert(index < limit); assert(limit <= treebuilder->context.current_node); /* First, scan over subsequent entries in the stack, * searching for them in the list of active formatting * entries. If found, update the corresponding * formatting list entry's stack index to match the * new stack location */ for (n = index + 1; n <= limit; n++) { if (is_formatting_element(stack[n].type) || (is_scoping_element(stack[n].type) && stack[n].type != HTML && stack[n].type != TABLE)) { formatting_list_entry *e; for (e = treebuilder->context.formatting_list_end; e != NULL; e = e->prev) { if (e->stack_index == n) e->stack_index--; } } } /* Reduce node's reference count */ treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx, stack[index].node); /* Now, shuffle the stack up one, removing node in the process */ memmove(&stack[index], &stack[index + 1], (limit - index) * sizeof(element_context)); return HUBBUB_OK; } /** * Adoption agency: shallow clone a node and replace its formatting list * and element stack entries * * \param treebuilder The treebuilder instance * \param element The item in the formatting list containing the node */ hubbub_error aa_clone_and_replace_entries(hubbub_treebuilder *treebuilder, formatting_list_entry *element) { hubbub_error err; hubbub_ns ons; element_type otype; uint32_t oindex; void *clone, *onode; /* Shallow clone of node */ err = treebuilder->tree_handler->clone_node( treebuilder->tree_handler->ctx, element->details.node, false, &clone); if (err != HUBBUB_OK) return err; /* Replace formatting list entry for node with clone */ err = formatting_list_replace(treebuilder, element, element->details.ns, element->details.type, clone, element->stack_index, &ons, &otype, &onode, &oindex); assert(err == HUBBUB_OK); treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx, onode); treebuilder->tree_handler->ref_node(treebuilder->tree_handler->ctx, clone); /* Replace node's stack entry with clone */ treebuilder->context.element_stack[element->stack_index].node = clone; treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx, onode); return HUBBUB_OK; } /** * Adoption agency: locate foster parent and insert node into it * * \param treebuilder The treebuilder instance * \param node The node to insert * \param inserted Pointer to location to receive inserted node * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error aa_insert_into_foster_parent(hubbub_treebuilder *treebuilder, void *node, void **inserted) { hubbub_error err; element_context *stack = treebuilder->context.element_stack; void *foster_parent = NULL; bool insert = false; uint32_t cur_table = current_table(treebuilder); stack[cur_table].tainted = true; if (cur_table == 0) { treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, stack[0].node); foster_parent = stack[0].node; } else { void *t_parent = NULL; treebuilder->tree_handler->get_parent( treebuilder->tree_handler->ctx, stack[cur_table].node, true, &t_parent); if (t_parent != NULL) { foster_parent = t_parent; insert = true; } else { treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, stack[cur_table - 1].node); foster_parent = stack[cur_table - 1].node; } } err = remove_node_from_dom(treebuilder, node); if (err != HUBBUB_OK) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, foster_parent); return err; } if (insert) { err = treebuilder->tree_handler->insert_before( treebuilder->tree_handler->ctx, foster_parent, node, stack[cur_table].node, inserted); } else { err = treebuilder->tree_handler->append_child( treebuilder->tree_handler->ctx, foster_parent, node, inserted); } if (err != HUBBUB_OK) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, foster_parent); return err; } treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx, foster_parent); return HUBBUB_OK; } /** * Process an applet, button, marquee, or object end tag as if in "in body" * * \param treebuilder The treebuilder instance * \param type The element type */ hubbub_error process_0applet_button_marquee_object_in_body( hubbub_treebuilder *treebuilder, element_type type) { if (!element_in_scope(treebuilder, type, false)) { /** \todo parse error */ } else { uint32_t popped = 0; element_type otype; close_implied_end_tags(treebuilder, UNKNOWN); do { hubbub_ns ns; void *node; element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); popped++; } while (otype != type); if (popped > 1) { /** \todo parse error */ } clear_active_formatting_list_to_marker(treebuilder); } return HUBBUB_OK; } /** * Process a br end tag as if in "in body" * * \param treebuilder The treebuilder instance */ hubbub_error process_0br_in_body(hubbub_treebuilder *treebuilder) { hubbub_error err; hubbub_tag tag; /** \todo parse error */ /* Act as if
has been seen. */ tag.ns = HUBBUB_NS_HTML; tag.name.ptr = (const uint8_t *) "br"; tag.name.len = SLEN("br"); tag.n_attributes = 0; tag.attributes = NULL; err = reconstruct_active_formatting_list(treebuilder); if (err != HUBBUB_OK) return err; return insert_element(treebuilder, &tag, false); } /** * Process a generic end tag as if in "in body" * * \param treebuilder The treebuilder instance * \param type The element type */ hubbub_error process_0generic_in_body(hubbub_treebuilder *treebuilder, element_type type) { element_context *stack = treebuilder->context.element_stack; uint32_t node = treebuilder->context.current_node; do { if (stack[node].type == type) { uint32_t popped = 0; element_type otype; close_implied_end_tags(treebuilder, UNKNOWN); while (treebuilder->context.current_node >= node) { hubbub_ns ns; void *node; element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); popped++; if (otype == type) break; } if (popped > 1) { /** \todo parse error */ } break; } else if (!is_formatting_element(stack[node].type) && !is_phrasing_element(stack[node].type)) { /** \todo parse error */ break; } } while (--node > 0); return HUBBUB_OK; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/after_frameset.c0000664000175000017500000000353211171337335022210 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle token in "after frameset" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_after_frameset(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, true); if (err == HUBBUB_REPROCESS) { /** \todo parse error */ /* Ignore the token */ err = HUBBUB_OK; } break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { err = handle_in_body(treebuilder, token); } else if (type == NOFRAMES) { err = handle_in_head(treebuilder, token); } else { /** \todo parse error */ } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /** \todo fragment case */ /** \todo parse error */ treebuilder->context.mode = AFTER_AFTER_FRAMESET; } else { /** \todo parse error */ } } break; case HUBBUB_TOKEN_EOF: break; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_column_group.c0000664000175000017500000000434111613627634022424 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle tokens in "in column group" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_in_column_group(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool handled = false; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, true); break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } else if (type == COL) { err = insert_element(treebuilder, &token->data.tag, false); /** \todo ack sc flag */ } else { err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == COLGROUP) { /** \todo fragment case */ handled = true; } else if (type == COL) { /** \todo parse error */ } else { err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_EOF: /** \todo fragment case */ err = HUBBUB_REPROCESS; break; } if (handled || err == HUBBUB_REPROCESS) { hubbub_ns ns; element_type otype; void *node; /* Pop the current node (which will be a colgroup) */ element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); treebuilder->context.mode = IN_TABLE; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/before_html.c0000664000175000017500000000556711171337335021521 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle token in "before html" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_before_html(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool handled = false; switch (token->type) { case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.document); break; case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, false); break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { handled = true; } else { err = HUBBUB_REPROCESS; } } break; case HUBBUB_TOKEN_END_TAG: case HUBBUB_TOKEN_EOF: err = HUBBUB_REPROCESS; break; } if (handled || err == HUBBUB_REPROCESS) { hubbub_error e; void *html, *appended; /* We can't use insert_element() here, as it assumes * that we're inserting into current_node. There is * no current_node to insert into at this point so * we get to do it manually. */ if (err == HUBBUB_REPROCESS) { /* Need to manufacture html element */ hubbub_tag tag; tag.ns = HUBBUB_NS_HTML; tag.name.ptr = (const uint8_t *) "html"; tag.name.len = SLEN("html"); tag.n_attributes = 0; tag.attributes = NULL; e = treebuilder->tree_handler->create_element( treebuilder->tree_handler->ctx, &tag, &html); } else { e = treebuilder->tree_handler->create_element( treebuilder->tree_handler->ctx, &token->data.tag, &html); } if (e != HUBBUB_OK) return e; e = treebuilder->tree_handler->append_child( treebuilder->tree_handler->ctx, treebuilder->context.document, html, &appended); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, html); if (e != HUBBUB_OK) return e; /* We can't use element_stack_push() here, as it * assumes that current_node is pointing at the index * before the one to insert at. For the first entry in * the stack, this does not hold so we must insert * manually. */ treebuilder->context.element_stack[0].type = HTML; treebuilder->context.element_stack[0].node = appended; treebuilder->context.current_node = 0; /** \todo cache selection algorithm */ treebuilder->context.mode = BEFORE_HEAD; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_row.c0000664000175000017500000000764211613627634020531 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Clear the stack back to a table row context. * * \param treebuilder The treebuilder instance */ static void table_clear_stack(hubbub_treebuilder *treebuilder) { element_type cur_node = current_node(treebuilder); while (cur_node != TR && cur_node != HTML) { hubbub_ns ns; element_type type; void *node; element_stack_pop(treebuilder, &ns, &type, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); cur_node = current_node(treebuilder); } return; } /** * Handle and anything that acts "as if" was emitted. * * \param treebuilder The treebuilder instance * \return True to reprocess the token, false otherwise */ static hubbub_error act_as_if_end_tag_tr(hubbub_treebuilder *treebuilder) { hubbub_ns ns; element_type otype; void *node; /** \todo fragment case */ table_clear_stack(treebuilder); element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node(treebuilder->tree_handler->ctx, node); treebuilder->context.mode = IN_TABLE_BODY; return HUBBUB_REPROCESS; } /** * Handle tokens in "in row" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_in_row(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == TH || type == TD) { table_clear_stack(treebuilder); err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) return err; treebuilder->context.mode = IN_CELL; /* ref node for formatting list */ treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); err = formatting_list_append(treebuilder, token->data.tag.ns, type, treebuilder->context.element_stack[ treebuilder->context.current_node].node, treebuilder->context.current_node); if (err != HUBBUB_OK) { hubbub_ns ns; element_type type; void *node; /* Revert changes */ remove_node_from_dom(treebuilder, treebuilder->context.element_stack[ treebuilder->context.current_node].node); element_stack_pop(treebuilder, &ns, &type, &node); return err; } } else if (type == CAPTION || type == COL || type == COLGROUP || type == TBODY || type == TFOOT || type == THEAD || type == TR) { err = act_as_if_end_tag_tr(treebuilder); } else { err = handle_in_table(treebuilder, token); } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == TR) { /* We're done with this token, but act_as_if_end_tag_tr * will return HUBBUB_REPROCESS. Therefore, ignore the * return value. */ (void) act_as_if_end_tag_tr(treebuilder); } else if (type == TABLE) { err = act_as_if_end_tag_tr(treebuilder); } else if (type == BODY || type == CAPTION || type == COL || type == COLGROUP || type == HTML || type == TD || type == TH) { /** \todo parse error */ /* Ignore the token */ } else { err = handle_in_table(treebuilder, token); } } break; case HUBBUB_TOKEN_CHARACTER: case HUBBUB_TOKEN_COMMENT: case HUBBUB_TOKEN_DOCTYPE: case HUBBUB_TOKEN_EOF: err = handle_in_table(treebuilder, token); break; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_select.c0000664000175000017500000000745311613627634021201 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle token in "in head" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_in_select(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; hubbub_ns ns; element_type otype; void *node; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = append_text(treebuilder, &token->data.character); break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { /* Process as if "in body" */ err = handle_in_body(treebuilder, token); } else if (type == OPTION) { if (current_node(treebuilder) == OPTION) { element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } err = insert_element(treebuilder, &token->data.tag, true); } else if (type == OPTGROUP) { if (current_node(treebuilder) == OPTION) { element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } if (current_node(treebuilder) == OPTGROUP) { element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } err = insert_element(treebuilder, &token->data.tag, true); } else if (type == SELECT || type == INPUT || type == TEXTAREA) { if (element_in_scope(treebuilder, SELECT, true)) { element_stack_pop_until(treebuilder, SELECT); reset_insertion_mode(treebuilder); } else { /* fragment case */ /** \todo parse error */ } if (type != SELECT) err = HUBBUB_REPROCESS; } else if (type == SCRIPT) { err = handle_in_head(treebuilder, token); } else { /** \todo parse error */ } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == OPTGROUP) { if (current_node(treebuilder) == OPTION && prev_node(treebuilder) == OPTGROUP) { element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } if (current_node(treebuilder) == OPTGROUP) { element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } else { /** \todo parse error */ } } else if (type == OPTION) { if (current_node(treebuilder) == OPTION) { element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } else { /** \todo parse error */ } } else if (type == SELECT) { if (element_in_scope(treebuilder, SELECT, true)) { element_stack_pop_until(treebuilder, SELECT); reset_insertion_mode(treebuilder); } else { /* fragment case */ /** \todo parse error */ } } } break; case HUBBUB_TOKEN_EOF: break; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_cell.c0000664000175000017500000000630611613627634020635 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Clear the stack back to a table row context. * * \param treebuilder The treebuilder instance */ static inline void close_cell(hubbub_treebuilder *treebuilder) { hubbub_ns ns; element_type otype = UNKNOWN; void *node; element_type type; if (element_in_scope(treebuilder, TD, true)) { type = TD; } else { type = TH; } /* Act as if an end tag token of type `type` has been seen */ close_implied_end_tags(treebuilder, UNKNOWN); /** \todo parse error */ while (otype != type) { element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } clear_active_formatting_list_to_marker(treebuilder); treebuilder->context.mode = IN_ROW; return; } /** * Handle tokens in "in cell" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_in_cell(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == CAPTION || type == COL || type == COLGROUP || type == TBODY || type == TD || type == TFOOT || type == TH || type == THEAD || type == TR) { /** \todo fragment case */ close_cell(treebuilder); err = HUBBUB_REPROCESS; } else { err = handle_in_body(treebuilder, token); } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == TH || type == TD) { if (element_in_scope(treebuilder, type, true)) { hubbub_ns ns; element_type otype = UNKNOWN; void *node; close_implied_end_tags(treebuilder, UNKNOWN); /** \todo parse error */ while (otype != type) { element_stack_pop(treebuilder, &ns, &otype, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } clear_active_formatting_list_to_marker( treebuilder); treebuilder->context.mode = IN_ROW; } else { /** \todo parse error */ } } else if (type == BODY || type == CAPTION || type == COL || type == COLGROUP || type == HTML) { /** \todo parse error */ } else if (type == TABLE || type == TBODY || type == TFOOT || type == THEAD || type == TR) { if (element_in_scope(treebuilder, type, true)) { close_cell(treebuilder); err = HUBBUB_REPROCESS; } else { /** \todo parse error */ } } else { err = handle_in_body(treebuilder, token); } } break; case HUBBUB_TOKEN_CHARACTER: case HUBBUB_TOKEN_COMMENT: case HUBBUB_TOKEN_DOCTYPE: case HUBBUB_TOKEN_EOF: err = handle_in_body(treebuilder, token); break; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_table.c0000664000175000017500000001403411613627634021002 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" #include "utils/string.h" /** * Clear the stack back to a table context: "the UA must, while the current * node is not a table element or an html element, pop elements from the stack * of open elements." */ static inline void clear_stack_table_context(hubbub_treebuilder *treebuilder) { hubbub_ns ns; element_type type = current_node(treebuilder); void *node; while (type != TABLE && type != HTML) { element_stack_pop(treebuilder, &ns, &type, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); type = current_node(treebuilder); } } /** * Process an input start tag in the "in table" insertion mode. */ static inline hubbub_error process_input_in_table( hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_REPROCESS; size_t i; for (i = 0; i < token->data.tag.n_attributes; i++) { hubbub_attribute *attr = &token->data.tag.attributes[i]; if (!hubbub_string_match_ci(attr->value.ptr, attr->value.len, (uint8_t *) "hidden", SLEN("hidden"))) { continue; } /** \todo parse error */ err = insert_element(treebuilder, &token->data.tag, true); } return err; } /** * Handle token in "in table" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_in_table(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; bool handled = true; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: if (treebuilder->context.element_stack[ current_table(treebuilder) ].tainted) { handled = false; } else { err = process_characters_expect_whitespace( treebuilder, token, true); handled = (err == HUBBUB_OK); } break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); bool tainted = treebuilder->context.element_stack[ current_table(treebuilder) ].tainted; if (type == CAPTION) { clear_stack_table_context(treebuilder); treebuilder->tree_handler->ref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); err = formatting_list_append(treebuilder, token->data.tag.ns, type, treebuilder->context.element_stack[ treebuilder->context.current_node].node, treebuilder->context.current_node); if (err != HUBBUB_OK) { treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, treebuilder->context.element_stack[ treebuilder->context.current_node].node); return err; } err = insert_element(treebuilder, &token->data.tag, true); if (err != HUBBUB_OK) { hubbub_ns ns; element_type type; void *node; uint32_t index; formatting_list_remove(treebuilder, treebuilder->context.formatting_list_end, &ns, &type, &node, &index); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); return err; } treebuilder->context.mode = IN_CAPTION; } else if (type == COLGROUP || type == COL) { hubbub_error e; hubbub_tag tag = token->data.tag; if (type == COL) { /* Insert colgroup and reprocess */ tag.name.ptr = (const uint8_t *) "colgroup"; tag.name.len = SLEN("colgroup"); tag.n_attributes = 0; tag.attributes = NULL; err = HUBBUB_REPROCESS; } clear_stack_table_context(treebuilder); e = insert_element(treebuilder, &tag, true); if (e != HUBBUB_OK) return e; treebuilder->context.mode = IN_COLUMN_GROUP; } else if (type == TBODY || type == TFOOT || type == THEAD || type == TD || type == TH || type == TR) { hubbub_error e; hubbub_tag tag = token->data.tag; if (type == TD || type == TH || type == TR) { /* Insert tbody and reprocess */ tag.name.ptr = (const uint8_t *) "tbody"; tag.name.len = SLEN("tbody"); tag.n_attributes = 0; tag.attributes = NULL; err = HUBBUB_REPROCESS; } clear_stack_table_context(treebuilder); e = insert_element(treebuilder, &tag, true); if (e != HUBBUB_OK) return e; treebuilder->context.mode = IN_TABLE_BODY; } else if (type == TABLE) { /** \todo parse error */ /* This should match "" handling */ element_stack_pop_until(treebuilder, TABLE); reset_insertion_mode(treebuilder); err = HUBBUB_REPROCESS; } else if (!tainted && (type == STYLE || type == SCRIPT)) { err = handle_in_head(treebuilder, token); } else if (!tainted && type == INPUT) { err = process_input_in_table(treebuilder, token); handled = (err == HUBBUB_OK); } else { handled = false; } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == TABLE) { /** \todo fragment case */ element_stack_pop_until(treebuilder, TABLE); reset_insertion_mode(treebuilder); } else if (type == BODY || type == CAPTION || type == COL || type == COLGROUP || type == HTML || type == TBODY || type == TD || type == TFOOT || type == TH || type == THEAD || type == TR) { /** \todo parse error */ } else { handled = false; } } break; case HUBBUB_TOKEN_EOF: break; } if (!handled) { treebuilder->context.in_table_foster = true; /** \todo parse error */ err = handle_in_body(treebuilder, token); treebuilder->context.in_table_foster = false; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_select_in_table.c0000664000175000017500000000275211613627634023033 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle token in "in select in table" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_in_select_in_table(hubbub_treebuilder *treebuilder, const hubbub_token *token) { bool handled = false; hubbub_error err = HUBBUB_OK; if (token->type == HUBBUB_TOKEN_END_TAG || token->type == HUBBUB_TOKEN_START_TAG) { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == CAPTION || type == TABLE || type == TBODY || type == TFOOT || type == THEAD || type == TR || type == TD || type == TH) { /** \todo parse error */ handled = true; if ((token->type == HUBBUB_TOKEN_END_TAG && element_in_scope(treebuilder, type, true)) || token->type == HUBBUB_TOKEN_START_TAG) { /** \todo fragment case */ element_stack_pop_until(treebuilder, SELECT); reset_insertion_mode(treebuilder); err = HUBBUB_REPROCESS; } } } if (!handled) { err = handle_in_select(treebuilder, token); } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_frameset.c0000664000175000017500000000457311613627634021530 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" /** * Handle token in "in frameset" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to handle * \return True to reprocess token, false otherwise */ hubbub_error handle_in_frameset(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = process_characters_expect_whitespace(treebuilder, token, true); if (err == HUBBUB_REPROCESS) { /** \todo parse error */ /* Ignore the token */ err = HUBBUB_OK; } break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == HTML) { err = handle_in_body(treebuilder, token); } else if (type == FRAMESET) { err = insert_element(treebuilder, &token->data.tag, true); } else if (type == FRAME) { err = insert_element(treebuilder, &token->data.tag, false); /** \todo ack sc flag */ } else if (type == NOFRAMES) { err = handle_in_head(treebuilder, token); } else { /** \todo parse error */ } } break; case HUBBUB_TOKEN_END_TAG: { element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (type == FRAMESET) { hubbub_ns ns; void *node; /* fragment case -- ignore */ if (current_node(treebuilder) == HTML) { /** \todo parse error */ break; } element_stack_pop(treebuilder, &ns, &type, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); if (current_node(treebuilder) != FRAMESET) { treebuilder->context.mode = AFTER_FRAMESET; } } else { /** \todo parse error */ } } break; case HUBBUB_TOKEN_EOF: /** \todo parse error */ break; } return err; } netsurf-2.9/hubbub-0.1.2/src/treebuilder/in_foreign_content.c0000664000175000017500000003423211652212563023072 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include "treebuilder/modes.h" #include "treebuilder/internal.h" #include "treebuilder/treebuilder.h" #include "utils/utils.h" #include "utils/string.h" /*** Attribute-correction stuff ***/ #define S(s) s, SLEN(s) /** * Mapping table for case changes */ typedef struct { const char *attr; /**< Lower case attribute name */ size_t len; /**< Length of name in bytes */ const char *proper; /**< Correctly cased version */ } case_changes; static const case_changes svg_attributes[] = { { S("attributename"), "attributeName" }, { S("attributetype"), "attributeType" }, { S("basefrequency"), "baseFrequency" }, { S("baseprofile"), "baseProfile" }, { S("calcmode"), "calcMode" }, { S("clippathunits"), "clipPathUnits" }, { S("contentscripttype"), "contentScriptType" }, { S("contentstyletype"), "contentStyleType" }, { S("diffuseconstant"), "diffuseConstant" }, { S("edgemode"), "edgeMode" }, { S("externalresourcesrequired"), "externalResourcesRequired" }, { S("filterres"), "filterRes" }, { S("filterunits"), "filterUnits" }, { S("glyphref"), "glyphRef" }, { S("gradienttransform"), "gradientTransform" }, { S("gradientunits"), "gradientUnits" }, { S("kernelmatrix"), "kernelMatrix" }, { S("kernelunitlength"), "kernelUnitLength" }, { S("keypoints"), "keyPoints" }, { S("keysplines"), "keySplines" }, { S("keytimes"), "keyTimes" }, { S("lengthadjust"), "lengthAdjust" }, { S("limitingconeangle"), "limitingConeAngle" }, { S("markerheight"), "markerHeight" }, { S("markerunits"), "markerUnits" }, { S("markerwidth"), "markerWidth" }, { S("maskcontentunits"), "maskContentUnits" }, { S("maskunits"), "maskUnits" }, { S("numoctaves"), "numOctaves" }, { S("pathlength"), "pathLength" }, { S("patterncontentunits"), "patternContentUnits" }, { S("patterntransform"), "patternTransform" }, { S("patternunits"), "patternUnits" }, { S("pointsatx"), "pointsAtX" }, { S("pointsaty"), "pointsAtY" }, { S("pointsatz"), "pointsAtZ" }, { S("preservealpha"), "preserveAlpha" }, { S("preserveaspectratio"), "preserveAspectRatio" }, { S("primitiveunits"), "primitiveUnits" }, { S("refx"), "refX" }, { S("refy"), "refY" }, { S("repeatcount"), "repeatCount" }, { S("repeatdur"), "repeatDur" }, { S("requiredextensions"), "requiredExtensions" }, { S("requiredfeatures"), "requiredFeatures" }, { S("specularconstant"), "specularConstant" }, { S("specularexponent"), "specularExponent" }, { S("spreadmethod"), "spreadMethod" }, { S("startoffset"), "startOffset" }, { S("stddeviation"), "stdDeviation" }, { S("stitchtiles"), "stitchTiles" }, { S("surfacescale"), "surfaceScale" }, { S("systemlanguage"), "systemLanguage" }, { S("tablevalues"), "tableValues" }, { S("targetx"), "targetX" }, { S("targety"), "targetY" }, { S("textlength"), "textLength" }, { S("viewbox"), "viewBox" }, { S("viewtarget"), "viewTarget" }, { S("xchannelselector"), "xChannelSelector" }, { S("ychannelselector"), "yChannelSelector" }, { S("zoomandpan"), "zoomAndPan" }, }; static const case_changes svg_tagnames[] = { { S("altglyph"), "altGlyph" }, { S("altglyphdef"), "altGlyphDef" }, { S("altglyphitem"), "altGlyphItem" }, { S("animatecolor"), "animateColor" }, { S("animatemotion"), "animateMotion" }, { S("animatetransform"), "animateTransform" }, { S("clippath"), "clipPath" }, { S("feblend"), "feBlend" }, { S("fecolormatrix"), "feColorMatrix" }, { S("fecomponenttransfer"), "feComponentTransfer" }, { S("fecomposite"), "feComposite" }, { S("feconvolvematrix"), "feConvolveMatrix" }, { S("fediffuselighting"), "feDiffuseLighting" }, { S("fedisplacementmap"), "feDisplacementMap" }, { S("fedistantlight"), "feDistantLight" }, { S("feflood"), "feFlood" }, { S("fefunca"), "feFuncA" }, { S("fefuncb"), "feFuncB" }, { S("fefuncg"), "feFuncG" }, { S("fefuncr"), "feFuncR" }, { S("fegaussianblur"), "feGaussianBlur" }, { S("feimage"), "feImage" }, { S("femerge"), "feMerge" }, { S("femergenode"), "feMergeNode" }, { S("femorphology"), "feMorphology" }, { S("feoffset"), "feOffset" }, { S("fepointlight"), "fePointLight" }, { S("fespecularlighting"), "feSpecularLighting" }, { S("fespotlight"), "feSpotLight" }, { S("fetile"), "feTile" }, { S("feturbulence"), "feTurbulence" }, { S("foreignobject"), "foreignObject" }, { S("glyphref"), "glyphRef" }, { S("lineargradient"), "linearGradient" }, { S("radialgradient"), "radialGradient" }, { S("textpath"), "textPath" }, }; #undef S /** * Adjust MathML attributes * * \param treebuilder Treebuilder instance * \param tag Tag to adjust the attributes of */ void adjust_mathml_attributes(hubbub_treebuilder *treebuilder, hubbub_tag *tag) { size_t i; UNUSED(treebuilder); for (i = 0; i < tag->n_attributes; i++) { hubbub_attribute *attr = &tag->attributes[i]; const uint8_t *name = attr->name.ptr; size_t len = attr->name.len; if (hubbub_string_match(name, len, (const uint8_t *) "definitionurl", SLEN("definitionurl"))) { attr->name.ptr = (uint8_t *) "definitionURL"; } } } /** * Adjust SVG attributes. * * \param treebuilder Treebuilder instance * \param tag Tag to adjust the attributes of */ void adjust_svg_attributes(hubbub_treebuilder *treebuilder, hubbub_tag *tag) { size_t i; UNUSED(treebuilder); for (i = 0; i < tag->n_attributes; i++) { hubbub_attribute *attr = &tag->attributes[i]; const uint8_t *name = attr->name.ptr; size_t len = attr->name.len; size_t j; for (j = 0; j < N_ELEMENTS(svg_attributes); j++) { if (hubbub_string_match(name, len, (uint8_t *) svg_attributes[j].attr, svg_attributes[j].len)) { attr->name.ptr = (uint8_t *) svg_attributes[j].proper; } } } } /** * Adjust SVG tagnmes. * * \param treebuilder Treebuilder instance * \param tag Tag to adjust the name of */ void adjust_svg_tagname(hubbub_treebuilder *treebuilder, hubbub_tag *tag) { const uint8_t *name = tag->name.ptr; size_t len = tag->name.len; size_t i; UNUSED(treebuilder); for (i = 0; i < N_ELEMENTS(svg_tagnames); i++) { if (hubbub_string_match(name, len, (uint8_t *) svg_tagnames[i].attr, svg_tagnames[i].len)) { tag->name.ptr = (uint8_t *) svg_tagnames[i].proper; } } } #define S(s) (uint8_t *) s, SLEN(s) /** * Adjust foreign attributes. * * \param treebuilder Treebuilder instance * \param tag Tag to adjust the attributes of */ void adjust_foreign_attributes(hubbub_treebuilder *treebuilder, hubbub_tag *tag) { size_t i; UNUSED(treebuilder); for (i = 0; i < tag->n_attributes; i++) { hubbub_attribute *attr = &tag->attributes[i]; const uint8_t *name = attr->name.ptr; /* 10 == strlen("xlink:href") */ if (attr->name.len >= 10 && strncmp((char *) name, "xlink:", SLEN("xlink:")) == 0) { size_t len = attr->name.len - 6; name += 6; if (hubbub_string_match(name, len, S("actuate")) || hubbub_string_match(name, len, S("arcrole")) || hubbub_string_match(name, len, S("href")) || hubbub_string_match(name, len, S("role")) || hubbub_string_match(name, len, S("show")) || hubbub_string_match(name, len, S("title")) || hubbub_string_match(name, len, S("type"))) { attr->ns = HUBBUB_NS_XLINK; attr->name.ptr += 6; attr->name.len -= 6; } /* 8 == strlen("xml:base") */ } else if (attr->name.len >= 8 && strncmp((char *) name, "xml:", SLEN("xml:")) == 0) { size_t len = attr->name.len - 4; name += 4; if (hubbub_string_match(name, len, S("base")) || hubbub_string_match(name, len, S("lang")) || hubbub_string_match(name, len, S("space"))) { attr->ns = HUBBUB_NS_XML; attr->name.ptr += 4; attr->name.len -= 4; } } else if (hubbub_string_match(name, attr->name.len, S("xmlns"))) { attr->ns = HUBBUB_NS_XMLNS; } else if (hubbub_string_match(name, attr->name.len, S("xmlns:xlink"))) { attr->ns = HUBBUB_NS_XMLNS; attr->name.ptr += 6; attr->name.len -= 6; } } } #undef S /*** Foreign content insertion mode ***/ /** * Returns true iff there is an element in scope that has a namespace other * than the HTML namespace. */ static bool element_in_scope_in_non_html_ns(hubbub_treebuilder *treebuilder) { element_context *stack = treebuilder->context.element_stack; uint32_t node; assert((signed) treebuilder->context.current_node >= 0); for (node = treebuilder->context.current_node; node > 0; node--) { element_type node_type = stack[node].type; /* The list of element types given in the spec here are the * scoping elements excluding TABLE and HTML. TABLE is handled * in the previous conditional and HTML should only occur * as the first node in the stack, which is never processed * in this loop. */ if (node_type == TABLE || is_scoping_element(node_type)) break; if (stack[node].ns != HUBBUB_NS_HTML) return true; } return false; } /** * Process a token as if in the secondary insertion mode. */ static hubbub_error process_as_in_secondary(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err; /* Because we don't support calling insertion modes directly, * instead we set the current mode to the secondary mode, * call the token handler, and then reset the mode afterward * as long as it's unchanged, as this has the same effect */ treebuilder->context.mode = treebuilder->context.second_mode; err = hubbub_treebuilder_token_handler(token, treebuilder); if (err != HUBBUB_OK) { treebuilder->context.mode = IN_FOREIGN_CONTENT; return err; } if (treebuilder->context.mode == treebuilder->context.second_mode) treebuilder->context.mode = IN_FOREIGN_CONTENT; if (treebuilder->context.mode == IN_FOREIGN_CONTENT && !element_in_scope_in_non_html_ns(treebuilder)) { treebuilder->context.mode = treebuilder->context.second_mode; } return HUBBUB_OK; } /** * Break out of foreign content as a result of certain start tags or EOF. */ static void foreign_break_out(hubbub_treebuilder *treebuilder) { element_context *stack = treebuilder->context.element_stack; /** \todo parse error */ while (stack[treebuilder->context.current_node].ns != HUBBUB_NS_HTML) { hubbub_ns ns; element_type type; void *node; element_stack_pop(treebuilder, &ns, &type, &node); treebuilder->tree_handler->unref_node( treebuilder->tree_handler->ctx, node); } treebuilder->context.mode = treebuilder->context.second_mode; } /** * Handle tokens in "in foreign content" insertion mode * * \param treebuilder The treebuilder instance * \param token The token to process * \return True to reprocess the token, false otherwise */ hubbub_error handle_in_foreign_content(hubbub_treebuilder *treebuilder, const hubbub_token *token) { hubbub_error err = HUBBUB_OK; switch (token->type) { case HUBBUB_TOKEN_CHARACTER: err = append_text(treebuilder, &token->data.character); break; case HUBBUB_TOKEN_COMMENT: err = process_comment_append(treebuilder, token, treebuilder->context.element_stack[ treebuilder->context.current_node].node); break; case HUBBUB_TOKEN_DOCTYPE: /** \todo parse error */ break; case HUBBUB_TOKEN_START_TAG: { hubbub_ns cur_node_ns = treebuilder->context.element_stack[ treebuilder->context.current_node].ns; element_type cur_node = current_node(treebuilder); element_type type = element_type_from_name(treebuilder, &token->data.tag.name); if (cur_node_ns == HUBBUB_NS_HTML || (cur_node_ns == HUBBUB_NS_MATHML && (type != MGLYPH && type != MALIGNMARK) && (cur_node == MI || cur_node == MO || cur_node == MN || cur_node == MS || cur_node == MTEXT)) || (type == SVG && (cur_node_ns == HUBBUB_NS_MATHML && cur_node == ANNOTATION_XML)) || (cur_node_ns == HUBBUB_NS_SVG && (cur_node == FOREIGNOBJECT || cur_node == DESC || cur_node == TITLE))) { err = process_as_in_secondary(treebuilder, token); } else if (type == B || type == BIG || type == BLOCKQUOTE || type == BODY || type == BR || type == CENTER || type == CODE || type == DD || type == DIV || type == DL || type == DT || type == EM || type == EMBED || type == H1 || type == H2 || type == H3 || type == H4 || type == H5 || type == H6 || type == HEAD || type == HR || type == I || type == IMG || type == LI || type == LISTING || type == MENU || type == META || type == NOBR || type == OL || type == P || type == PRE || type == RUBY || type == S || type == SMALL || type == SPAN || type == STRONG || type == STRIKE || type == SUB || type == SUP || type == TABLE || type == TT || type == U || type == UL || type == VAR) { foreign_break_out(treebuilder); err = HUBBUB_REPROCESS; } else if (type == FONT) { const hubbub_tag *tag = &token->data.tag; size_t i; for (i = 0; i < tag->n_attributes; i++) { hubbub_attribute *attr = &tag->attributes[i]; const uint8_t *name = attr->name.ptr; size_t len = attr->name.len; if (hubbub_string_match(name, len, (const uint8_t *) "color", SLEN("color")) || hubbub_string_match(name, len, (const uint8_t *) "face", SLEN("face")) || hubbub_string_match(name, len, (const uint8_t *) "size", SLEN("size"))) break; } if (i != tag->n_attributes) { foreign_break_out(treebuilder); err = HUBBUB_REPROCESS; } } else { hubbub_tag tag = token->data.tag; adjust_foreign_attributes(treebuilder, &tag); if (cur_node_ns == HUBBUB_NS_SVG) { adjust_svg_tagname(treebuilder, &tag); adjust_svg_attributes(treebuilder, &tag); } /* Set to the right namespace and insert */ tag.ns = cur_node_ns; if (token->data.tag.self_closing) { err = insert_element(treebuilder, &tag, false); /** \todo ack sc flag */ } else { err = insert_element(treebuilder, &tag, true); } } } break; case HUBBUB_TOKEN_END_TAG: err = process_as_in_secondary(treebuilder, token); break; case HUBBUB_TOKEN_EOF: foreign_break_out(treebuilder); err = HUBBUB_REPROCESS; break; } return err; } netsurf-2.9/hubbub-0.1.2/src/parser.c0000664000175000017500000002150411217147376016213 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007-8 John-Mark Bell */ #include #include #include #include #include #include "charset/detect.h" #include "tokeniser/tokeniser.h" #include "treebuilder/treebuilder.h" #include "utils/parserutilserror.h" /** * Hubbub parser object */ struct hubbub_parser { parserutils_inputstream *stream; /**< Input stream instance */ hubbub_tokeniser *tok; /**< Tokeniser instance */ hubbub_treebuilder *tb; /**< Treebuilder instance */ hubbub_allocator_fn alloc; /**< Memory (de)allocation function */ void *pw; /**< Client data */ }; /** * Create a hubbub parser * * \param enc Source document encoding, or NULL to autodetect * \param fix_enc Permit fixing up of encoding if it's frequently misused * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data (may be NULL) * \param parser Pointer to location to receive parser instance * \return HUBBUB_OK on success, * HUBBUB_BADPARM on bad parameters, * HUBBUB_NOMEM on memory exhaustion, * HUBBUB_BADENCODING if ::enc is unsupported */ hubbub_error hubbub_parser_create(const char *enc, bool fix_enc, hubbub_allocator_fn alloc, void *pw, hubbub_parser **parser) { parserutils_error perror; hubbub_error error; hubbub_parser *p; if (alloc == NULL || parser == NULL) return HUBBUB_BADPARM; p = alloc(NULL, sizeof(hubbub_parser), pw); if (p == NULL) return HUBBUB_NOMEM; /* If we have an encoding and we're permitted to fix up likely broken * ones, then attempt to do so. */ if (enc != NULL && fix_enc == true) { uint16_t mibenum = parserutils_charset_mibenum_from_name(enc, strlen(enc)); if (mibenum != 0) { hubbub_charset_fix_charset(&mibenum); enc = parserutils_charset_mibenum_to_name(mibenum); } } perror = parserutils_inputstream_create(enc, enc != NULL ? HUBBUB_CHARSET_CONFIDENT : HUBBUB_CHARSET_UNKNOWN, hubbub_charset_extract, alloc, pw, &p->stream); if (perror != PARSERUTILS_OK) { alloc(p, 0, pw); return hubbub_error_from_parserutils_error(perror); } error = hubbub_tokeniser_create(p->stream, alloc, pw, &p->tok); if (error != HUBBUB_OK) { parserutils_inputstream_destroy(p->stream); alloc(p, 0, pw); return error; } error = hubbub_treebuilder_create(p->tok, alloc, pw, &p->tb); if (error != HUBBUB_OK) { hubbub_tokeniser_destroy(p->tok); parserutils_inputstream_destroy(p->stream); alloc(p, 0, pw); return error; } p->alloc = alloc; p->pw = pw; *parser = p; return HUBBUB_OK; } /** * Destroy a hubbub parser * * \param parser Parser instance to destroy * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error hubbub_parser_destroy(hubbub_parser *parser) { if (parser == NULL) return HUBBUB_BADPARM; hubbub_treebuilder_destroy(parser->tb); hubbub_tokeniser_destroy(parser->tok); parserutils_inputstream_destroy(parser->stream); parser->alloc(parser, 0, parser->pw); return HUBBUB_OK; } /** * Configure a hubbub parser * * \param parser Parser instance to configure * \param type Option to set * \param params Option-specific parameters * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error hubbub_parser_setopt(hubbub_parser *parser, hubbub_parser_opttype type, hubbub_parser_optparams *params) { hubbub_error result = HUBBUB_OK; if (parser == NULL || params == NULL) return HUBBUB_BADPARM; switch (type) { case HUBBUB_PARSER_TOKEN_HANDLER: if (parser->tb != NULL) { /* Client is defining their own token handler, * so we must destroy the default treebuilder */ hubbub_treebuilder_destroy(parser->tb); parser->tb = NULL; } result = hubbub_tokeniser_setopt(parser->tok, HUBBUB_TOKENISER_TOKEN_HANDLER, (hubbub_tokeniser_optparams *) params); break; case HUBBUB_PARSER_ERROR_HANDLER: /* The error handler does not cascade, so tell both the * treebuilder (if extant) and the tokeniser. */ if (parser->tb != NULL) { result = hubbub_treebuilder_setopt(parser->tb, HUBBUB_TREEBUILDER_ERROR_HANDLER, (hubbub_treebuilder_optparams *) params); } if (result == HUBBUB_OK) { result = hubbub_tokeniser_setopt(parser->tok, HUBBUB_TOKENISER_ERROR_HANDLER, (hubbub_tokeniser_optparams *) params); } break; case HUBBUB_PARSER_CONTENT_MODEL: result = hubbub_tokeniser_setopt(parser->tok, HUBBUB_TOKENISER_CONTENT_MODEL, (hubbub_tokeniser_optparams *) params); break; case HUBBUB_PARSER_TREE_HANDLER: if (parser->tb != NULL) { result = hubbub_treebuilder_setopt(parser->tb, HUBBUB_TREEBUILDER_TREE_HANDLER, (hubbub_treebuilder_optparams *) params); } break; case HUBBUB_PARSER_DOCUMENT_NODE: if (parser->tb != NULL) { result = hubbub_treebuilder_setopt(parser->tb, HUBBUB_TREEBUILDER_DOCUMENT_NODE, (hubbub_treebuilder_optparams *) params); } break; case HUBBUB_PARSER_ENABLE_SCRIPTING: if (parser->tb != NULL) { result = hubbub_treebuilder_setopt(parser->tb, HUBBUB_TREEBUILDER_ENABLE_SCRIPTING, (hubbub_treebuilder_optparams *) params); } break; default: result = HUBBUB_INVALID; } return result; } /** * Pass a chunk of data to a hubbub parser for parsing * * \param parser Parser instance to use * \param data Data to parse (encoded in the input charset) * \param len Length, in bytes, of data * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error hubbub_parser_parse_chunk(hubbub_parser *parser, const uint8_t *data, size_t len) { parserutils_error perror; hubbub_error error; if (parser == NULL || data == NULL) return HUBBUB_BADPARM; perror = parserutils_inputstream_append(parser->stream, data, len); if (perror != PARSERUTILS_OK) return hubbub_error_from_parserutils_error(perror); error = hubbub_tokeniser_run(parser->tok); if (error == HUBBUB_BADENCODING) { /* Ok, we autodetected an encoding that we don't actually * support. We've not actually processed any data at this * point so fall back to Windows-1252 and hope for the best */ perror = parserutils_inputstream_change_charset(parser->stream, "Windows-1252", HUBBUB_CHARSET_TENTATIVE); /* Under no circumstances should we get here if we've managed * to process data. If there is a way, I want to know about it */ assert(perror != PARSERUTILS_INVALID); if (perror != PARSERUTILS_OK) return hubbub_error_from_parserutils_error(perror); /* Retry the tokenisation */ error = hubbub_tokeniser_run(parser->tok); } if (error != HUBBUB_OK) return error; return HUBBUB_OK; } #if 0 /** * Pass a chunk of extraneous data to a hubbub parser for parsing * * \param parser Parser instance to use * \param data Data to parse (encoded in UTF-8) * \param len Length, in byte, of data * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error hubbub_parser_parse_extraneous_chunk(hubbub_parser *parser, const uint8_t *data, size_t len) { hubbub_error error; /** \todo In some cases, we don't actually want script-inserted * data to be parsed until later. We'll need some way of flagging * this through the public API, and the inputstream API will need * some way of marking the insertion point so that, when the * tokeniser is run, only the inserted chunk is parsed. */ if (parser == NULL || data == NULL) return HUBBUB_BADPARM; error = parserutils_inputstream_insert(parser->stream, data, len); if (error != HUBBUB_OK) return error; error = hubbub_tokeniser_run(parser->tok); if (error != HUBBUB_OK) return error; return HUBBUB_OK; } #endif /** * Inform the parser that the last chunk of data has been parsed * * \param parser Parser to inform * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error hubbub_parser_completed(hubbub_parser *parser) { parserutils_error perror; hubbub_error error; if (parser == NULL) return HUBBUB_BADPARM; perror = parserutils_inputstream_append(parser->stream, NULL, 0); if (perror != PARSERUTILS_OK) return hubbub_error_from_parserutils_error(perror); error = hubbub_tokeniser_run(parser->tok); if (error != HUBBUB_OK) return error; return HUBBUB_OK; } /** * Read the document charset * * \param parser Parser instance to query * \param source Pointer to location to receive charset source * \return Pointer to charset name (constant; do not free), or NULL if unknown */ const char *hubbub_parser_read_charset(hubbub_parser *parser, hubbub_charset_source *source) { const char *name; uint32_t src; if (parser == NULL || source == NULL) return NULL; name = parserutils_inputstream_read_charset(parser->stream, &src); *source = (hubbub_charset_source) src; return name; } netsurf-2.9/hubbub-0.1.2/src/Makefile0000664000175000017500000000011311476510167016203 0ustar vincevince# Sources DIR_SOURCES := parser.c include build/makefiles/Makefile.subdir netsurf-2.9/hubbub-0.1.2/src/utils/0000775000175000017500000000000011734430254015703 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/src/utils/string.h0000664000175000017500000000077611047725262017377 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #ifndef hubbub_string_h_ #define hubbub_string_h_ /** Match two strings case-sensitively */ bool hubbub_string_match(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len); /** Match two strings case-insensitively */ bool hubbub_string_match_ci(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len); #endif netsurf-2.9/hubbub-0.1.2/src/utils/parserutilserror.h0000664000175000017500000000216611130647644021513 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef hubbub_utils_parserutilserror_h_ #define hubbub_utils_parserutilserror_h_ #include #include /** * Convert a ParserUtils error into a Hubbub error * * \param error The ParserUtils error to convert * \return The corresponding Hubbub error */ static inline hubbub_error hubbub_error_from_parserutils_error( parserutils_error error) { if (error == PARSERUTILS_OK) return HUBBUB_OK; else if (error == PARSERUTILS_NOMEM) return HUBBUB_NOMEM; else if (error == PARSERUTILS_BADPARM) return HUBBUB_BADPARM; else if (error == PARSERUTILS_INVALID) return HUBBUB_INVALID; else if (error == PARSERUTILS_FILENOTFOUND) return HUBBUB_FILENOTFOUND; else if (error == PARSERUTILS_NEEDDATA) return HUBBUB_NEEDDATA; else if (error == PARSERUTILS_BADENCODING) return HUBBUB_BADENCODING; else if (error == PARSERUTILS_EOF) return HUBBUB_OK; return HUBBUB_UNKNOWN; } #endif netsurf-2.9/hubbub-0.1.2/src/utils/Makefile0000664000175000017500000000012411476510167017345 0ustar vincevince# Sources DIR_SOURCES := errors.c string.c include build/makefiles/Makefile.subdir netsurf-2.9/hubbub-0.1.2/src/utils/string.c0000664000175000017500000000236211226357450017362 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 Andrew Sidwell */ #include #include #include #include #include "utils/string.h" /** * Check that one string is exactly equal to another * * \param a String to compare * \param a_len Length of first string * \param b String to compare * \param b_len Length of second string */ bool hubbub_string_match(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len) { if (a_len != b_len) return false; return memcmp((const char *) a, (const char *) b, b_len) == 0; } /** * Check that one string is case-insensitively equal to another * * \param a String to compare * \param a_len Length of first string * \param b String to compare * \param b_len Length of second string */ bool hubbub_string_match_ci(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len) { if (a_len != b_len) return false; while (b_len-- > 0) { uint8_t aa = *(a++); uint8_t bb = *(b++); aa = ('a' <= aa && aa <= 'z') ? (aa - 0x20) : aa; bb = ('a' <= bb && bb <= 'z') ? (bb - 0x20) : bb; if (aa != bb) return false; } return true; } netsurf-2.9/hubbub-0.1.2/src/utils/errors.c0000664000175000017500000000225411165524766017400 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include #include /** * Convert a hubbub error code to a string * * \param error The error code to convert * \return Pointer to string representation of error, or NULL if unknown. */ const char *hubbub_error_to_string(hubbub_error error) { const char *result = NULL; switch (error) { case HUBBUB_OK: result = "No error"; break; case HUBBUB_REPROCESS: result = "Internal (reprocess token)"; break; case HUBBUB_ENCODINGCHANGE: result = "Encoding of document has changed"; break; case HUBBUB_NOMEM: result = "Insufficient memory"; break; case HUBBUB_BADPARM: result = "Bad parameter"; break; case HUBBUB_INVALID: result = "Invalid input"; break; case HUBBUB_FILENOTFOUND: result = "File not found"; break; case HUBBUB_NEEDDATA: result = "Insufficient data"; break; case HUBBUB_BADENCODING: result = "Unsupported charset"; break; case HUBBUB_UNKNOWN: result = "Unknown error"; break; } return result; } netsurf-2.9/hubbub-0.1.2/src/utils/utils.h0000664000175000017500000000163211223142410017201 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef hubbub_utils_h_ #define hubbub_utils_h_ #ifdef BUILD_TARGET_riscos /* If we're building with Norcroft, then we need to haul in * unixlib.h from TCPIPLibs for useful things like strncasecmp */ #ifdef __CC_NORCROFT #include #endif #endif #ifdef BUILD_TARGET_windows #define strncasecmp _strnicmp #endif #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #ifndef SLEN /* Calculate length of a string constant */ #define SLEN(s) (sizeof((s)) - 1) /* -1 for '\0' */ #endif #ifndef UNUSED #define UNUSED(x) ((x)=(x)) #endif /* Useful for iterating over arrays */ #define N_ELEMENTS(x) sizeof((x)) / sizeof((x)[0]) #endif netsurf-2.9/hubbub-0.1.2/src/charset/0000775000175000017500000000000011734430254016174 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/src/charset/Makefile0000664000175000017500000000010111162164230017615 0ustar vincevinceDIR_SOURCES := detect.c include build/makefiles/Makefile.subdir netsurf-2.9/hubbub-0.1.2/src/charset/detect.h0000664000175000017500000000134511075137105017615 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef hubbub_charset_detect_h_ #define hubbub_charset_detect_h_ #include #include /* Extract a charset from a chunk of data */ parserutils_error hubbub_charset_extract(const uint8_t *data, size_t len, uint16_t *mibenum, uint32_t *source); /* Parse a Content-Type string for an encoding */ uint16_t hubbub_charset_parse_content(const uint8_t *value, uint32_t valuelen); /* Fix up frequently misused character sets */ void hubbub_charset_fix_charset(uint16_t *charset); #endif netsurf-2.9/hubbub-0.1.2/src/charset/detect.c0000664000175000017500000003734611130710731017614 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include #include #include #include #include #include "utils/utils.h" #include "detect.h" static uint16_t hubbub_charset_read_bom(const uint8_t *data, size_t len); static uint16_t hubbub_charset_scan_meta(const uint8_t *data, size_t len); static uint16_t hubbub_charset_parse_attributes(const uint8_t **pos, const uint8_t *end); static bool hubbub_charset_get_attribute(const uint8_t **data, const uint8_t *end, const uint8_t **name, uint32_t *namelen, const uint8_t **value, uint32_t *valuelen); /** * Extract a charset from a chunk of data * * \param data Pointer to buffer containing data * \param len Buffer length * \param mibenum Pointer to location containing current MIB enum * \param source Pointer to location containint current charset source * \return PARSERUTILS_OK on success, appropriate error otherwise * * ::mibenum and ::source will be updated on exit * * The larger a chunk of data fed to this routine, the better, as it allows * charset autodetection access to a larger dataset for analysis. */ parserutils_error hubbub_charset_extract(const uint8_t *data, size_t len, uint16_t *mibenum, uint32_t *source) { uint16_t charset = 0; if (data == NULL || mibenum == NULL || source == NULL) return PARSERUTILS_BADPARM; /** * Meaning of *source on entry: * * CONFIDENT - Do not pass Go, do not attempt auto-detection. * TENTATIVE - We've tried to autodetect already, but subsequently * discovered that we don't actually support the detected * charset. Thus, we've defaulted to Windows-1252. Don't * perform auto-detection again, as it would be futile. * (This bit diverges from the spec) * UNKNOWN - No autodetection performed yet. Get on with it. */ /* 1. */ /* If the source is dictated, there's nothing for us to do */ if (*source == HUBBUB_CHARSET_CONFIDENT || *source == HUBBUB_CHARSET_TENTATIVE) { return PARSERUTILS_OK; } /* 2. */ /** \todo We probably want to wait for ~512 bytes of data / 500ms here */ /* 3. */ /* We need at least 3 bytes of data */ if (len < 3) goto default_encoding; /* First, look for a BOM */ charset = hubbub_charset_read_bom(data, len); if (charset != 0) { *mibenum = charset; *source = HUBBUB_CHARSET_CONFIDENT; return PARSERUTILS_OK; } /* 4. */ /* No BOM was found, so we must look for a meta charset within * the document itself. */ charset = hubbub_charset_scan_meta(data, len); if (charset != 0) { /* Fix charsets according to HTML5, * section 8.2.2.2. Character encoding requirements */ hubbub_charset_fix_charset(&charset); /* If we've encountered a meta charset for a non-ASCII- * compatible encoding, don't trust it. * * Firstly, it should have been sent with a BOM (and thus * detected above). * * Secondly, we've just used an ASCII-only parser to * extract the encoding from the document. Therefore, * the document plainly isn't what the meta charset * claims it is. * * What we do in this case is to ignore the meta charset's * claims and leave the charset determination to the * autodetection routines (or the fallback case if they * fail). */ if (charset != parserutils_charset_mibenum_from_name( "UTF-32", SLEN("UTF-32")) && charset != parserutils_charset_mibenum_from_name( "UTF-32LE", SLEN("UTF-32LE")) && charset != parserutils_charset_mibenum_from_name( "UTF-32BE", SLEN("UTF-32BE"))) { *mibenum = charset; *source = HUBBUB_CHARSET_TENTATIVE; return PARSERUTILS_OK; } } /* No charset was specified within the document, attempt to * autodetect the encoding from the data that we have available. */ /** \todo Charset autodetection */ /* We failed to autodetect a charset, so use the default fallback */ default_encoding: /* 7. */ charset = parserutils_charset_mibenum_from_name("Windows-1252", SLEN("Windows-1252")); if (charset == 0) charset = parserutils_charset_mibenum_from_name("ISO-8859-1", SLEN("ISO-8859-1")); *mibenum = charset; *source = HUBBUB_CHARSET_TENTATIVE; return PARSERUTILS_OK; } /** * Inspect the beginning of a buffer of data for the presence of a * UTF Byte Order Mark. * * \param data Pointer to buffer containing data * \param len Buffer length * \return MIB enum representing encoding described by BOM, or 0 if not found */ uint16_t hubbub_charset_read_bom(const uint8_t *data, size_t len) { if (data == NULL) return 0; /* We require at least 3 bytes of data */ if (len < 3) return 0; if (data[0] == 0xFE && data[1] == 0xFF) { return parserutils_charset_mibenum_from_name("UTF-16BE", SLEN("UTF-16BE")); } else if (data[0] == 0xFF && data[1] == 0xFE) { return parserutils_charset_mibenum_from_name("UTF-16LE", SLEN("UTF-16LE")); } else if (data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) { return parserutils_charset_mibenum_from_name("UTF-8", SLEN("UTF-8")); } return 0; } #define PEEK(a) \ (pos < end - SLEN(a) && \ strncasecmp((const char *) pos, a, SLEN(a)) == 0) #define ADVANCE(a) \ while (pos < end - SLEN(a)) { \ if (PEEK(a)) \ break; \ pos++; \ } \ \ if (pos == end - SLEN(a)) \ return 0; #define ISSPACE(a) \ (a == 0x09 || a == 0x0a || a == 0x0c || \ a == 0x0d || a == 0x20 || a == 0x2f) /** * Search for a meta charset within a buffer of data * * \param data Pointer to buffer containing data * \param len Length of buffer * \return MIB enum representing encoding, or 0 if none found */ uint16_t hubbub_charset_scan_meta(const uint8_t *data, size_t len) { const uint8_t *pos = data; const uint8_t *end; uint16_t mibenum; if (data == NULL) return 0; end = pos + min(512, len); /* 1. */ while (pos < end) { /* a */ if (PEEK(""); /* b */ } else if (PEEK("= end - 1) return 0; if (ISSPACE(*(pos + SLEN("= end) return 0; } /* c */ } else if ((PEEK("' || *pos == '<') break; pos++; } if (pos >= end) return 0; /* 3 */ if (*pos != '<') { const uint8_t *n; const uint8_t *v; uint32_t nl, vl; while (hubbub_charset_get_attribute(&pos, end, &n, &nl, &v, &vl)) ; /* do nothing */ /* 2 */ } else continue; /* d */ } else if (PEEK(""); } /* e - do nothing */ /* 2 */ pos++; } return 0; } /** * Parse attributes on a meta tag * * \param pos Pointer to pointer to current location (updated on exit) * \param end Pointer to end of data stream * \return MIB enum of detected encoding, or 0 if none found */ uint16_t hubbub_charset_parse_attributes(const uint8_t **pos, const uint8_t *end) { const uint8_t *name; const uint8_t *value; uint32_t namelen, valuelen; uint16_t mibenum = 0; if (pos == NULL || *pos == NULL || end == NULL) return 0; /* 2 */ while (hubbub_charset_get_attribute(pos, end, &name, &namelen, &value, &valuelen)) { /* 3 done by default */ /* 4 */ if (namelen == SLEN("charset") && valuelen > 0 && strncasecmp((const char *) name, "charset", SLEN("charset")) == 0) { /* strip value */ while (ISSPACE(*value)) { value++; valuelen--; } while (valuelen > 0 && ISSPACE(value[valuelen - 1])) valuelen--; mibenum = parserutils_charset_mibenum_from_name( (const char *) value, valuelen); /* 5 */ } else if (namelen == SLEN("content") && valuelen > 0 && strncasecmp((const char *) name, "content", SLEN("content")) == 0) { mibenum = hubbub_charset_parse_content(value, valuelen); } /* 6 */ if (mibenum == parserutils_charset_mibenum_from_name( "UTF-16LE", SLEN("UTF-16LE")) || mibenum == parserutils_charset_mibenum_from_name( "UTF-16BE", SLEN("UTF-16BE")) || mibenum == parserutils_charset_mibenum_from_name( "UTF-16", SLEN("UTF-16"))) { mibenum = parserutils_charset_mibenum_from_name( "UTF-8", SLEN("UTF-8")); } /* 7 */ if (mibenum != 0) { /* confidence = tentative; */ return mibenum; } } return 0; } /** * Parse a content= attribute's value * * \param value Attribute's value * \param valuelen Length of value * \return MIB enum of detected encoding, or 0 if none found */ uint16_t hubbub_charset_parse_content(const uint8_t *value, uint32_t valuelen) { const uint8_t *end; const uint8_t *tentative = NULL; uint32_t tentative_len = 0; if (value == NULL) return 0; end = value + valuelen; /* 1 */ while (value < end) { if (*value == ';') { value++; break; } value++; } if (value >= end) return 0; /* 2 */ while (value < end && ISSPACE(*value)) { value++; } if (value >= end) return 0; /* 3 */ if (value < end - SLEN("charset") && strncasecmp((const char *) value, "charset", SLEN("charset")) != 0) return 0; value += SLEN("charset"); /* 4 */ while (value < end && ISSPACE(*value)) { value++; } if (value >= end) return 0; /* 5 */ if (*value != '=') return 0; /* skip '=' */ value++; /* 6 */ while (value < end && ISSPACE(*value)) { value++; } if (value >= end) return 0; /* 7 */ tentative = value; /* a */ if (*value == '"') { while (++value < end && *value != '"') { tentative_len++; } if (value < end) tentative++; else tentative = NULL; /* b */ } else if (*value == '\'') { while (++value < end && *value != '\'') { tentative_len++; } if (value < end) tentative++; else tentative = NULL; /* c */ } else { while (value < end && !ISSPACE(*value)) { value++; tentative_len++; } } /* 8 */ if (tentative != NULL) { return parserutils_charset_mibenum_from_name( (const char *) tentative, tentative_len); } /* 9 */ return 0; } /** * Extract an attribute from the data stream * * \param data Pointer to pointer to current location (updated on exit) * \param end Pointer to end of data stream * \param name Pointer to location to receive attribute name * \param namelen Pointer to location to receive attribute name length * \param value Pointer to location to receive attribute value * \param valuelen Pointer to location to receive attribute value langth * \return true if attribute extracted, false otherwise. * * Note: The caller should heed the returned lengths; these are the only * indicator that useful content resides in name or value. */ bool hubbub_charset_get_attribute(const uint8_t **data, const uint8_t *end, const uint8_t **name, uint32_t *namelen, const uint8_t **value, uint32_t *valuelen) { const uint8_t *pos; if (data == NULL || *data == NULL || end == NULL || name == NULL || namelen == NULL || value == NULL || valuelen == NULL) return false; pos = *data; /* 1. Skip leading spaces or '/' characters */ while (pos < end && (ISSPACE(*pos) || *pos == '/')) { pos++; } if (pos >= end) { *data = pos; return false; } /* 2. Invalid element open character */ if (*pos == '<') { pos--; *data = pos; return false; } /* 3. End of element */ if (*pos == '>') { *data = pos; return false; } /* 4. Initialise name & value to empty string */ *name = pos; *namelen = 0; *value = (const uint8_t *) ""; *valuelen = 0; /* 5. Extract name */ while (pos < end) { /* a */ if (*pos == '=') { break; } /* b */ if (ISSPACE(*pos)) { break; } /* c */ if (*pos == '/' || *pos == '<' || *pos == '>') { *data = pos; return true; } /* d is handled by strncasecmp in _parse_attributes */ /* e */ (*namelen)++; /* 6 */ pos++; } if (pos >= end) { *data = pos; return false; } if (ISSPACE(*pos)) { /* 7. Skip trailing spaces */ while (pos < end && ISSPACE(*pos)) { pos++; } if (pos >= end) { *data = pos; return false; } /* 8. Must be '=' */ if (*pos != '=') { pos--; *data = pos; return true; } } /* 9. Skip '=' */ pos++; /* 10. Skip any spaces after '=' */ while (pos < end && ISSPACE(*pos)) { pos++; } if (pos >= end) { *data = pos; return false; } /* 11. Extract value, if quoted */ /* a */ if (*pos == '\'' || *pos == '"') { /* 1 */ const uint8_t *quote = pos; /* 2 */ while (++pos < end) { /* 3 */ if (*pos == *quote) { *value = (quote + 1); *data = ++pos; return true; } /* 4 is handled by strncasecmp */ /* 5 */ (*valuelen)++; /* 6 */ } if (pos >= end) { *data = pos; return false; } } /* b */ if (*pos == '<' || *pos == '>') { *data = pos; return true; } /* c is handled by strncasecmp */ /* d */ *value = pos; while (pos < end) { /* 12. Extract unquoted value */ /* a */ if (ISSPACE(*pos) || *pos == '<' || *pos == '>') { *data = pos; return true; } /* b is handled by strncasecmp */ /* c */ (*valuelen)++; /* 13. Advance */ pos++; } if (pos >= end) { *data = pos; return false; } /* should never be reached */ abort(); return false; } /** * Fix charsets, according to the override table in HTML5, * section 8.2.2.2. Character encoding requirements * * * \param charset Pointer to charset value to fix */ void hubbub_charset_fix_charset(uint16_t *charset) { uint16_t tmp = 0; assert(*charset != 0); /* ISO-8859-1 -> Windows-1252 */ if (*charset == parserutils_charset_mibenum_from_name( "ISO-8859-1", SLEN("ISO-8859-1"))) { tmp = parserutils_charset_mibenum_from_name( "Windows-1252", SLEN("Windows-1252")); assert(tmp != 0 && "Windows-1252 MUST be supported"); /* ISO-8859-9 -> Windows-1254 */ } else if (*charset == parserutils_charset_mibenum_from_name( "ISO-8859-9", SLEN("ISO-8859-9"))) { tmp = parserutils_charset_mibenum_from_name( "Windows-1254", SLEN("Windows-1254")); /* ISO-8859-11 -> Windows-874 */ } else if (*charset == parserutils_charset_mibenum_from_name( "ISO-8859-11", SLEN("ISO-8859-11"))) { tmp = parserutils_charset_mibenum_from_name( "Windows-874", SLEN("Windows-874")); /* KS_C_5601-1987 and EUC-KR -> Windows-949 */ } else if (*charset == parserutils_charset_mibenum_from_name( "KS_C_5601-1987", SLEN("KS_C_5601-1987")) || *charset == parserutils_charset_mibenum_from_name( "EUC-KR", SLEN("EUC-KR"))) { tmp = parserutils_charset_mibenum_from_name( "Windows-949", SLEN("Windows-949")); /* TIS-620 -> Windows-874 */ } else if (*charset == parserutils_charset_mibenum_from_name( "TIS-620", SLEN("TIS-620"))) { tmp = parserutils_charset_mibenum_from_name( "Windows-874", SLEN("Windows-874")); /* x-x-big5 -> Big5 */ } else if (*charset == parserutils_charset_mibenum_from_name( "x-x-big5", SLEN("x-x-big5"))) { tmp = parserutils_charset_mibenum_from_name( "Big5", SLEN("Big5")); /* GB2312 and GB_2312-80 -> GBK */ } else if (*charset == parserutils_charset_mibenum_from_name( "GB2312", SLEN("GB2312")) || *charset == parserutils_charset_mibenum_from_name( "GB_2312-80", SLEN("GB_2312-80"))) { tmp = parserutils_charset_mibenum_from_name( "GBK", SLEN("GBK")); } if (tmp != 0) *charset = tmp; } netsurf-2.9/hubbub-0.1.2/src/tokeniser/0000775000175000017500000000000011734430254016546 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/src/tokeniser/tokeniser.h0000664000175000017500000000341111165526007020721 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef hubbub_tokeniser_tokeniser_h_ #define hubbub_tokeniser_tokeniser_h_ #include #include #include #include #include #include typedef struct hubbub_tokeniser hubbub_tokeniser; /** * Hubbub tokeniser option types */ typedef enum hubbub_tokeniser_opttype { HUBBUB_TOKENISER_TOKEN_HANDLER, HUBBUB_TOKENISER_ERROR_HANDLER, HUBBUB_TOKENISER_CONTENT_MODEL, HUBBUB_TOKENISER_PROCESS_CDATA } hubbub_tokeniser_opttype; /** * Hubbub tokeniser option parameters */ typedef union hubbub_tokeniser_optparams { struct { hubbub_token_handler handler; void *pw; } token_handler; /**< Token handling callback */ struct { hubbub_error_handler handler; void *pw; } error_handler; /**< Error handling callback */ struct { hubbub_content_model model; } content_model; /**< Current content model */ bool process_cdata; /**< Whether to process CDATA sections*/ } hubbub_tokeniser_optparams; /* Create a hubbub tokeniser */ hubbub_error hubbub_tokeniser_create(parserutils_inputstream *input, hubbub_allocator_fn alloc, void *pw, hubbub_tokeniser **tokeniser); /* Destroy a hubbub tokeniser */ hubbub_error hubbub_tokeniser_destroy(hubbub_tokeniser *tokeniser); /* Configure a hubbub tokeniser */ hubbub_error hubbub_tokeniser_setopt(hubbub_tokeniser *tokeniser, hubbub_tokeniser_opttype type, hubbub_tokeniser_optparams *params); /* Process remaining data in the input stream */ hubbub_error hubbub_tokeniser_run(hubbub_tokeniser *tokeniser); #endif netsurf-2.9/hubbub-0.1.2/src/tokeniser/entities.h0000664000175000017500000000100111476510167020540 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef hubbub_tokeniser_entities_h_ #define hubbub_tokeniser_entities_h_ #include #include #include /* Step-wise search for an entity in the dictionary */ hubbub_error hubbub_entities_search_step(uint8_t c, uint32_t *result, int32_t *context); #endif netsurf-2.9/hubbub-0.1.2/src/tokeniser/entities.c0000664000175000017500000000602111476510167020542 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include "utils/utils.h" #include "tokeniser/entities.h" /** Node in our entity tree */ typedef struct hubbub_entity_node { /* Do not reorder this without fixing make-entities.pl */ uint8_t split; /**< Data to split on */ int32_t lt; /**< Subtree for data less than split */ int32_t eq; /**< Subtree for data equal to split */ int32_t gt; /**< Subtree for data greater than split */ uint32_t value; /**< Data for this node */ } hubbub_entity_node; #include "entities.inc" /** * Step-wise search for a key in our entity tree * * \param c Character to look for * \param result Pointer to location for result * \param context Pointer to location for search context * \return HUBBUB_OK if key found, * HUBBUB_NEEDDATA if more steps are required * HUBBUB_INVALID if nothing matches * * The value pointed to by ::context must be NULL for the first call. * Thereafter, pass in the same value as returned by the previous call. * The context is opaque to the caller and should not be inspected. * * The location pointed to by ::result will be set to NULL unless a match * is found. */ static hubbub_error hubbub_entity_tree_search_step(uint8_t c, uint32_t *result, int32_t *context) { bool match = false; int32_t p; if (result == NULL || context == NULL) return HUBBUB_BADPARM; if (*context == -1) { p = dict_root; } else { p = *context; } while (p != -1) { if (c < dict[p].split) { p = dict[p].lt; } else if (c == dict[p].split) { if (dict[p].split == '\0') { match = true; p = -1; } else if (dict[p].eq != -1 && dict[dict[p].eq].split == '\0') { match = true; *result = dict[dict[p].eq].value; p = dict[p].eq; } else if (dict[p].value != 0) { match = true; *result = dict[p].value; p = dict[p].eq; } else { p = dict[p].eq; } break; } else { p = dict[p].gt; } } *context = p; return (match) ? HUBBUB_OK : (p == -1) ? HUBBUB_INVALID : HUBBUB_NEEDDATA; } /** * Step-wise search for an entity in the dictionary * * \param c Character to look for * \param result Pointer to location for result * \param context Pointer to location for search context * \return HUBBUB_OK if key found, * HUBBUB_NEEDDATA if more steps are required * HUBBUB_INVALID if nothing matches * * The value pointed to by ::context should be -1 for the first call. * Thereafter, pass in the same value as returned by the previous call. * The context is opaque to the caller and should not be inspected. * * The location pointed to by ::result will be set to U+FFFD unless a match * is found. */ hubbub_error hubbub_entities_search_step(uint8_t c, uint32_t *result, int32_t *context) { if (result == NULL) return HUBBUB_BADPARM; *result = 0xFFFD; return hubbub_entity_tree_search_step(c, result, context); } netsurf-2.9/hubbub-0.1.2/src/tokeniser/Makefile0000664000175000017500000000054611477251345020221 0ustar vincevince# Sources DIR_SOURCES := entities.c tokeniser.c $(DIR)entities.c: $(DIR)entities.inc $(DIR)entities.inc: build/make-entities.pl build/Entities $(VQ)$(ECHO) "ENTITIES: $@" $(Q)$(PERL) build/make-entities.pl ifeq ($(findstring clean,$(MAKECMDGOALS)),clean) CLEAN_ITEMS := $(CLEAN_ITEMS) $(DIR)entities.inc endif include build/makefiles/Makefile.subdir netsurf-2.9/hubbub-0.1.2/src/tokeniser/tokeniser.c0000664000175000017500000026025011613627634020730 0ustar vincevince/* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell * Copyright 2008 Andrew Sidwell */ #include #include #include #include #include #include "utils/parserutilserror.h" #include "utils/utils.h" #include "tokeniser/entities.h" #include "tokeniser/tokeniser.h" /** * Table of mappings between Windows-1252 codepoints 128-159 and UCS4 */ static const uint32_t cp1252Table[32] = { 0x20AC, 0xFFFD, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFD, 0x017D, 0xFFFD, 0xFFFD, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFD, 0x017E, 0x0178 }; /** * UTF-8 encoding of U+FFFD REPLACEMENT CHARACTER */ static const uint8_t u_fffd[3] = { '\xEF', '\xBF', '\xBD' }; static const hubbub_string u_fffd_str = { u_fffd, sizeof(u_fffd) }; /** * String for when we want to emit newlines */ static const uint8_t lf = '\n'; static const hubbub_string lf_str = { &lf, 1 }; /** * Tokeniser states */ typedef enum hubbub_tokeniser_state { STATE_DATA, STATE_CHARACTER_REFERENCE_DATA, STATE_TAG_OPEN, STATE_CLOSE_TAG_OPEN, STATE_TAG_NAME, STATE_BEFORE_ATTRIBUTE_NAME, STATE_ATTRIBUTE_NAME, STATE_AFTER_ATTRIBUTE_NAME, STATE_BEFORE_ATTRIBUTE_VALUE, STATE_ATTRIBUTE_VALUE_DQ, STATE_ATTRIBUTE_VALUE_SQ, STATE_ATTRIBUTE_VALUE_UQ, STATE_CHARACTER_REFERENCE_IN_ATTRIBUTE_VALUE, STATE_AFTER_ATTRIBUTE_VALUE_Q, STATE_SELF_CLOSING_START_TAG, STATE_BOGUS_COMMENT, STATE_MARKUP_DECLARATION_OPEN, STATE_MATCH_COMMENT, STATE_COMMENT_START, STATE_COMMENT_START_DASH, STATE_COMMENT, STATE_COMMENT_END_DASH, STATE_COMMENT_END, STATE_MATCH_DOCTYPE, STATE_DOCTYPE, STATE_BEFORE_DOCTYPE_NAME, STATE_DOCTYPE_NAME, STATE_AFTER_DOCTYPE_NAME, STATE_MATCH_PUBLIC, STATE_BEFORE_DOCTYPE_PUBLIC, STATE_DOCTYPE_PUBLIC_DQ, STATE_DOCTYPE_PUBLIC_SQ, STATE_AFTER_DOCTYPE_PUBLIC, STATE_MATCH_SYSTEM, STATE_BEFORE_DOCTYPE_SYSTEM, STATE_DOCTYPE_SYSTEM_DQ, STATE_DOCTYPE_SYSTEM_SQ, STATE_AFTER_DOCTYPE_SYSTEM, STATE_BOGUS_DOCTYPE, STATE_MATCH_CDATA, STATE_CDATA_BLOCK, STATE_NUMBERED_ENTITY, STATE_NAMED_ENTITY } hubbub_tokeniser_state; /** * Context for tokeniser */ typedef struct hubbub_tokeniser_context { size_t pending; /**< Count of pending chars */ hubbub_string current_comment; /**< Current comment text */ hubbub_token_type current_tag_type; /**< Type of current_tag */ hubbub_tag current_tag; /**< Current tag */ hubbub_doctype current_doctype; /**< Current doctype */ hubbub_tokeniser_state prev_state; /**< Previous state */ uint8_t last_start_tag_name[10]; /**< Name of the last start tag * emitted */ size_t last_start_tag_len; /**< Length of last start tag */ struct { uint32_t count; bool match; } close_tag_match; /**< State for matching close * tags */ struct { uint32_t count; /**< Index into "DOCTYPE" */ } match_doctype; /**< State for matching doctype */ struct { uint32_t count; /**< Index into "[CDATA[" */ uint32_t end; /**< Index into "]]>" */ } match_cdata; /**< State for matching cdata */ struct { size_t offset; /**< Offset in buffer */ uint32_t length; /**< Length of entity */ uint32_t codepoint; /**< UCS4 codepoint */ bool complete; /**< True if match complete */ uint32_t poss_length; /**< Optimistic length * when matching named * character references */ uint8_t base; /**< Base for numeric * entities */ int32_t context; /**< Context for named * entity search */ size_t prev_len; /**< Previous byte length * of str */ bool had_data; /**< Whether we read * anything after &#(x)? */ bool overflow; /**< Whether this entity has * has overflowed the maximum * numeric entity value */ hubbub_tokeniser_state return_state; /**< State we were * called from */ } match_entity; /**< Entity matching state */ struct { uint32_t line; /**< Current line of input */ uint32_t col; /**< Current character in * line */ } position; /**< Position in source data */ uint32_t allowed_char; /**< Used for quote matching */ } hubbub_tokeniser_context; /** * Tokeniser data structure */ struct hubbub_tokeniser { hubbub_tokeniser_state state; /**< Current tokeniser state */ hubbub_content_model content_model; /**< Current content * model flag */ bool escape_flag; /**< Escape flag **/ bool process_cdata_section; /**< Whether to process CDATA sections*/ parserutils_inputstream *input; /**< Input stream */ parserutils_buffer *buffer; /**< Input buffer */ hubbub_tokeniser_context context; /**< Tokeniser context */ hubbub_token_handler token_handler; /**< Token handling callback */ void *token_pw; /**< Token handler data */ hubbub_error_handler error_handler; /**< Error handling callback */ void *error_pw; /**< Error handler data */ hubbub_allocator_fn alloc; /**< Memory (de)allocation function */ void *alloc_pw; /**< Client private data */ }; static hubbub_error hubbub_tokeniser_handle_data(hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_character_reference_data( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_tag_open( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_close_tag_open( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_tag_name( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_before_attribute_name( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_attribute_name( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_after_attribute_name( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_before_attribute_value( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_attribute_value_dq( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_attribute_value_sq( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_attribute_value_uq( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_character_reference_in_attribute_value( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_after_attribute_value_q( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_self_closing_start_tag( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_bogus_comment( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_markup_declaration_open( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_match_comment( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_comment( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_match_doctype( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_doctype( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_before_doctype_name( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_doctype_name( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_after_doctype_name( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_match_public( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_before_doctype_public( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_doctype_public_dq( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_doctype_public_sq( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_after_doctype_public( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_match_system( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_before_doctype_system( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_doctype_system_dq( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_doctype_system_sq( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_after_doctype_system( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_bogus_doctype( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_match_cdata( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_cdata_block( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_consume_character_reference( hubbub_tokeniser *tokeniser, size_t off); static hubbub_error hubbub_tokeniser_handle_numbered_entity( hubbub_tokeniser *tokeniser); static hubbub_error hubbub_tokeniser_handle_named_entity( hubbub_tokeniser *tokeniser); static inline hubbub_error emit_character_token(hubbub_tokeniser *tokeniser, const hubbub_string *chars); static inline hubbub_error emit_current_chars(hubbub_tokeniser *tokeniser); static inline hubbub_error emit_current_tag(hubbub_tokeniser *tokeniser); static inline hubbub_error emit_current_comment(hubbub_tokeniser *tokeniser); static inline hubbub_error emit_current_doctype(hubbub_tokeniser *tokeniser, bool force_quirks); static hubbub_error hubbub_tokeniser_emit_token(hubbub_tokeniser *tokeniser, hubbub_token *token); /** * Create a hubbub tokeniser * * \param input Input stream instance * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data (may be NULL) * \param tokeniser Pointer to location to receive tokeniser instance * \return HUBBUB_OK on success, * HUBBUB_BADPARM on bad parameters, * HUBBUB_NOMEM on memory exhaustion */ hubbub_error hubbub_tokeniser_create(parserutils_inputstream *input, hubbub_allocator_fn alloc, void *pw, hubbub_tokeniser **tokeniser) { parserutils_error perror; hubbub_tokeniser *tok; if (input == NULL || alloc == NULL || tokeniser == NULL) return HUBBUB_BADPARM; tok = alloc(NULL, sizeof(hubbub_tokeniser), pw); if (tok == NULL) return HUBBUB_NOMEM; perror = parserutils_buffer_create(alloc, pw, &tok->buffer); if (perror != PARSERUTILS_OK) { alloc(tok, 0, pw); return hubbub_error_from_parserutils_error(perror); } tok->state = STATE_DATA; tok->content_model = HUBBUB_CONTENT_MODEL_PCDATA; tok->escape_flag = false; tok->process_cdata_section = false; tok->input = input; tok->token_handler = NULL; tok->token_pw = NULL; tok->error_handler = NULL; tok->error_pw = NULL; tok->alloc = alloc; tok->alloc_pw = pw; memset(&tok->context, 0, sizeof(hubbub_tokeniser_context)); *tokeniser = tok; return HUBBUB_OK; } /** * Destroy a hubbub tokeniser * * \param tokeniser The tokeniser instance to destroy * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error hubbub_tokeniser_destroy(hubbub_tokeniser *tokeniser) { if (tokeniser == NULL) return HUBBUB_BADPARM; if (tokeniser->context.current_tag.attributes != NULL) { tokeniser->alloc(tokeniser->context.current_tag.attributes, 0, tokeniser->alloc_pw); } parserutils_buffer_destroy(tokeniser->buffer); tokeniser->alloc(tokeniser, 0, tokeniser->alloc_pw); return HUBBUB_OK; } /** * Configure a hubbub tokeniser * * \param tokeniser The tokeniser instance to configure * \param type The option type to set * \param params Option-specific parameters * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error hubbub_tokeniser_setopt(hubbub_tokeniser *tokeniser, hubbub_tokeniser_opttype type, hubbub_tokeniser_optparams *params) { if (tokeniser == NULL || params == NULL) return HUBBUB_BADPARM; switch (type) { case HUBBUB_TOKENISER_TOKEN_HANDLER: tokeniser->token_handler = params->token_handler.handler; tokeniser->token_pw = params->token_handler.pw; break; case HUBBUB_TOKENISER_ERROR_HANDLER: tokeniser->error_handler = params->error_handler.handler; tokeniser->error_pw = params->error_handler.pw; break; case HUBBUB_TOKENISER_CONTENT_MODEL: tokeniser->content_model = params->content_model.model; break; case HUBBUB_TOKENISER_PROCESS_CDATA: tokeniser->process_cdata_section = params->process_cdata; break; } return HUBBUB_OK; } /** * Process remaining data in the input stream * * \param tokeniser The tokeniser instance to invoke * \return HUBBUB_OK on success, appropriate error otherwise */ hubbub_error hubbub_tokeniser_run(hubbub_tokeniser *tokeniser) { hubbub_error cont = HUBBUB_OK; if (tokeniser == NULL) return HUBBUB_BADPARM; #if 0 #define state(x) \ case x: \ printf( #x "\n"); #else #define state(x) \ case x: #endif while (cont == HUBBUB_OK) { switch (tokeniser->state) { state(STATE_DATA) cont = hubbub_tokeniser_handle_data(tokeniser); break; state(STATE_CHARACTER_REFERENCE_DATA) cont = hubbub_tokeniser_handle_character_reference_data( tokeniser); break; state(STATE_TAG_OPEN) cont = hubbub_tokeniser_handle_tag_open(tokeniser); break; state(STATE_CLOSE_TAG_OPEN) cont = hubbub_tokeniser_handle_close_tag_open( tokeniser); break; state(STATE_TAG_NAME) cont = hubbub_tokeniser_handle_tag_name(tokeniser); break; state(STATE_BEFORE_ATTRIBUTE_NAME) cont = hubbub_tokeniser_handle_before_attribute_name( tokeniser); break; state(STATE_ATTRIBUTE_NAME) cont = hubbub_tokeniser_handle_attribute_name( tokeniser); break; state(STATE_AFTER_ATTRIBUTE_NAME) cont = hubbub_tokeniser_handle_after_attribute_name( tokeniser); break; state(STATE_BEFORE_ATTRIBUTE_VALUE) cont = hubbub_tokeniser_handle_before_attribute_value( tokeniser); break; state(STATE_ATTRIBUTE_VALUE_DQ) cont = hubbub_tokeniser_handle_attribute_value_dq( tokeniser); break; state(STATE_ATTRIBUTE_VALUE_SQ) cont = hubbub_tokeniser_handle_attribute_value_sq( tokeniser); break; state(STATE_ATTRIBUTE_VALUE_UQ) cont = hubbub_tokeniser_handle_attribute_value_uq( tokeniser); break; state(STATE_CHARACTER_REFERENCE_IN_ATTRIBUTE_VALUE) cont = hubbub_tokeniser_handle_character_reference_in_attribute_value( tokeniser); break; state(STATE_AFTER_ATTRIBUTE_VALUE_Q) cont = hubbub_tokeniser_handle_after_attribute_value_q( tokeniser); break; state(STATE_SELF_CLOSING_START_TAG) cont = hubbub_tokeniser_handle_self_closing_start_tag( tokeniser); break; state(STATE_BOGUS_COMMENT) cont = hubbub_tokeniser_handle_bogus_comment( tokeniser); break; state(STATE_MARKUP_DECLARATION_OPEN) cont = hubbub_tokeniser_handle_markup_declaration_open( tokeniser); break; state(STATE_MATCH_COMMENT) cont = hubbub_tokeniser_handle_match_comment( tokeniser); break; case STATE_COMMENT_START: case STATE_COMMENT_START_DASH: case STATE_COMMENT: case STATE_COMMENT_END_DASH: case STATE_COMMENT_END: cont = hubbub_tokeniser_handle_comment(tokeniser); break; state(STATE_MATCH_DOCTYPE) cont = hubbub_tokeniser_handle_match_doctype( tokeniser); break; state(STATE_DOCTYPE) cont = hubbub_tokeniser_handle_doctype(tokeniser); break; state(STATE_BEFORE_DOCTYPE_NAME) cont = hubbub_tokeniser_handle_before_doctype_name( tokeniser); break; state(STATE_DOCTYPE_NAME) cont = hubbub_tokeniser_handle_doctype_name( tokeniser); break; state(STATE_AFTER_DOCTYPE_NAME) cont = hubbub_tokeniser_handle_after_doctype_name( tokeniser); break; state(STATE_MATCH_PUBLIC) cont = hubbub_tokeniser_handle_match_public( tokeniser); break; state(STATE_BEFORE_DOCTYPE_PUBLIC) cont = hubbub_tokeniser_handle_before_doctype_public( tokeniser); break; state(STATE_DOCTYPE_PUBLIC_DQ) cont = hubbub_tokeniser_handle_doctype_public_dq( tokeniser); break; state(STATE_DOCTYPE_PUBLIC_SQ) cont = hubbub_tokeniser_handle_doctype_public_sq( tokeniser); break; state(STATE_AFTER_DOCTYPE_PUBLIC) cont = hubbub_tokeniser_handle_after_doctype_public( tokeniser); break; state(STATE_MATCH_SYSTEM) cont = hubbub_tokeniser_handle_match_system( tokeniser); break; state(STATE_BEFORE_DOCTYPE_SYSTEM) cont = hubbub_tokeniser_handle_before_doctype_system( tokeniser); break; state(STATE_DOCTYPE_SYSTEM_DQ) cont = hubbub_tokeniser_handle_doctype_system_dq( tokeniser); break; state(STATE_DOCTYPE_SYSTEM_SQ) cont = hubbub_tokeniser_handle_doctype_system_sq( tokeniser); break; state(STATE_AFTER_DOCTYPE_SYSTEM) cont = hubbub_tokeniser_handle_after_doctype_system( tokeniser); break; state(STATE_BOGUS_DOCTYPE) cont = hubbub_tokeniser_handle_bogus_doctype( tokeniser); break; state(STATE_MATCH_CDATA) cont = hubbub_tokeniser_handle_match_cdata( tokeniser); break; state(STATE_CDATA_BLOCK) cont = hubbub_tokeniser_handle_cdata_block( tokeniser); break; state(STATE_NUMBERED_ENTITY) cont = hubbub_tokeniser_handle_numbered_entity( tokeniser); break; state(STATE_NAMED_ENTITY) cont = hubbub_tokeniser_handle_named_entity( tokeniser); break; } } return (cont == HUBBUB_NEEDDATA) ? HUBBUB_OK : cont; } /** * Various macros for manipulating buffers. * * \todo make some of these inline functions (type-safety) * \todo document them properly here */ #define START_BUF(str, cptr, length) \ do { \ parserutils_error perror; \ perror = parserutils_buffer_append(tokeniser->buffer, \ (uint8_t *) (cptr), (length)); \ if (perror != PARSERUTILS_OK) \ return hubbub_error_from_parserutils_error(perror); \ (str).len = (length); \ } while (0) #define COLLECT(str, cptr, length) \ do { \ parserutils_error perror; \ assert(str.len != 0); \ perror = parserutils_buffer_append(tokeniser->buffer, \ (uint8_t *) (cptr), (length)); \ if (perror != PARSERUTILS_OK) \ return hubbub_error_from_parserutils_error(perror); \ (str).len += (length); \ } while (0) #define COLLECT_MS(str, cptr, length) \ do { \ parserutils_error perror; \ perror = parserutils_buffer_append(tokeniser->buffer, \ (uint8_t *) (cptr), (length)); \ if (perror != PARSERUTILS_OK) \ return hubbub_error_from_parserutils_error(perror); \ (str).len += (length); \ } while (0) /* this should always be called with an empty "chars" buffer */ hubbub_error hubbub_tokeniser_handle_data(hubbub_tokeniser *tokeniser) { parserutils_error error; hubbub_token token; const uint8_t *cptr; size_t len; while ((error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len)) == PARSERUTILS_OK) { const uint8_t c = *cptr; if (c == '&' && (tokeniser->content_model == HUBBUB_CONTENT_MODEL_PCDATA || tokeniser->content_model == HUBBUB_CONTENT_MODEL_RCDATA) && tokeniser->escape_flag == false) { tokeniser->state = STATE_CHARACTER_REFERENCE_DATA; /* Don't eat the '&'; it'll be handled by entity * consumption */ break; } else if (c == '-' && tokeniser->escape_flag == false && (tokeniser->content_model == HUBBUB_CONTENT_MODEL_RCDATA || tokeniser->content_model == HUBBUB_CONTENT_MODEL_CDATA) && tokeniser->context.pending >= 3) { size_t ignore; error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending - 3, &cptr, &ignore); assert(error == PARSERUTILS_OK); if (strncmp((char *)cptr, "", SLEN("-->")) == 0) { tokeniser->escape_flag = false; } tokeniser->context.pending += len; } else if (c == '\0') { if (tokeniser->context.pending > 0) { /* Emit any pending characters */ emit_current_chars(tokeniser); } /* Emit a replacement character */ emit_character_token(tokeniser, &u_fffd_str); /* Advance past NUL */ parserutils_inputstream_advance(tokeniser->input, 1); } else if (c == '\r') { error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending + len, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { break; } if (tokeniser->context.pending > 0) { /* Emit any pending characters */ emit_current_chars(tokeniser); } if (error == PARSERUTILS_EOF || *cptr != '\n') { /* Emit newline */ emit_character_token(tokeniser, &lf_str); } /* Advance over */ parserutils_inputstream_advance(tokeniser->input, 1); } else { /* Just collect into buffer */ tokeniser->context.pending += len; } } if (tokeniser->state != STATE_TAG_OPEN && (tokeniser->state != STATE_DATA || error == PARSERUTILS_EOF) && tokeniser->context.pending > 0) { /* Emit any pending characters */ emit_current_chars(tokeniser); } if (error == PARSERUTILS_EOF) { token.type = HUBBUB_TOKEN_EOF; hubbub_tokeniser_emit_token(tokeniser, &token); } if (error == PARSERUTILS_EOF) { return HUBBUB_NEEDDATA; } else { return hubbub_error_from_parserutils_error(error); } } /* emit any pending tokens before calling */ hubbub_error hubbub_tokeniser_handle_character_reference_data( hubbub_tokeniser *tokeniser) { assert(tokeniser->context.pending == 0); if (tokeniser->context.match_entity.complete == false) { return hubbub_tokeniser_consume_character_reference(tokeniser, tokeniser->context.pending); } else { hubbub_token token; uint8_t utf8[6]; uint8_t *utf8ptr = utf8; size_t len = sizeof(utf8); token.type = HUBBUB_TOKEN_CHARACTER; if (tokeniser->context.match_entity.codepoint) { parserutils_charset_utf8_from_ucs4( tokeniser->context.match_entity.codepoint, &utf8ptr, &len); token.data.character.ptr = utf8; token.data.character.len = sizeof(utf8) - len; hubbub_tokeniser_emit_token(tokeniser, &token); /* +1 for ampersand */ parserutils_inputstream_advance(tokeniser->input, tokeniser->context.match_entity.length + 1); } else { parserutils_error error; const uint8_t *cptr = NULL; error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error( error); } token.data.character.ptr = cptr; token.data.character.len = len; hubbub_tokeniser_emit_token(tokeniser, &token); parserutils_inputstream_advance(tokeniser->input, len); } /* Reset for next time */ tokeniser->context.match_entity.complete = false; tokeniser->state = STATE_DATA; } return HUBBUB_OK; } /* this state always switches to another state straight away */ /* this state expects the current character to be '<' */ hubbub_error hubbub_tokeniser_handle_tag_open(hubbub_tokeniser *tokeniser) { hubbub_tag *ctag = &tokeniser->context.current_tag; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; assert(tokeniser->context.pending == 1); /* assert(tokeniser->context.chars.ptr[0] == '<'); */ error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { /* Return to data state with '<' still in "chars" */ tokeniser->state = STATE_DATA; return HUBBUB_OK; } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '/') { tokeniser->context.pending += len; tokeniser->context.close_tag_match.match = false; tokeniser->context.close_tag_match.count = 0; tokeniser->state = STATE_CLOSE_TAG_OPEN; } else if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_RCDATA || tokeniser->content_model == HUBBUB_CONTENT_MODEL_CDATA) { /* Return to data state with '<' still in "chars" */ tokeniser->state = STATE_DATA; } else if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_PCDATA) { if (c == '!') { parserutils_inputstream_advance(tokeniser->input, SLEN("context.pending = 0; tokeniser->state = STATE_MARKUP_DECLARATION_OPEN; } else if ('A' <= c && c <= 'Z') { uint8_t lc = (c + 0x20); START_BUF(ctag->name, &lc, len); ctag->n_attributes = 0; tokeniser->context.current_tag_type = HUBBUB_TOKEN_START_TAG; tokeniser->context.pending += len; tokeniser->state = STATE_TAG_NAME; } else if ('a' <= c && c <= 'z') { START_BUF(ctag->name, cptr, len); ctag->n_attributes = 0; tokeniser->context.current_tag_type = HUBBUB_TOKEN_START_TAG; tokeniser->context.pending += len; tokeniser->state = STATE_TAG_NAME; } else if (c == '>') { /** \todo parse error */ tokeniser->context.pending += len; tokeniser->state = STATE_DATA; } else if (c == '?') { /** \todo parse error */ /* Cursor still at "<", need to advance past it */ parserutils_inputstream_advance( tokeniser->input, SLEN("<")); tokeniser->context.pending = 0; tokeniser->state = STATE_BOGUS_COMMENT; } else { /* Return to data state with '<' still in "chars" */ tokeniser->state = STATE_DATA; } } return HUBBUB_OK; } /* this state expects tokeniser->context.chars to be "context; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; assert(tokeniser->context.pending == 2); /* assert(tokeniser->context.chars.ptr[0] == '<'); */ /* assert(tokeniser->context.chars.ptr[1] == '/'); */ /**\todo fragment case */ if (tokeniser->content_model == HUBBUB_CONTENT_MODEL_RCDATA || tokeniser->content_model == HUBBUB_CONTENT_MODEL_CDATA) { uint8_t *start_tag_name = tokeniser->context.last_start_tag_name; size_t start_tag_len = tokeniser->context.last_start_tag_len; while ((error = parserutils_inputstream_peek(tokeniser->input, ctx->pending + ctx->close_tag_match.count, &cptr, &len)) == PARSERUTILS_OK) { c = *cptr; if ((start_tag_name[ctx->close_tag_match.count] & ~0x20) != (c & ~0x20)) { break; } ctx->close_tag_match.count += len; if (ctx->close_tag_match.count == start_tag_len) { ctx->close_tag_match.match = true; break; } } if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } if (ctx->close_tag_match.match == true) { error = parserutils_inputstream_peek( tokeniser->input, ctx->pending + ctx->close_tag_match.count, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error( error); } else if (error != PARSERUTILS_EOF) { c = *cptr; if (c != '\t' && c != '\n' && c != '\f' && c != ' ' && c != '>' && c != '/') { ctx->close_tag_match.match = false; } } } } if (ctx->close_tag_match.match == false && tokeniser->content_model != HUBBUB_CONTENT_MODEL_PCDATA) { /* We should emit "state = STATE_DATA; } else { error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error == PARSERUTILS_EOF) { /** \todo parse error */ /* Return to data state with "state = STATE_DATA; return HUBBUB_OK; } else if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error(error); } c = *cptr; if ('A' <= c && c <= 'Z') { uint8_t lc = (c + 0x20); START_BUF(tokeniser->context.current_tag.name, &lc, len); tokeniser->context.current_tag.n_attributes = 0; tokeniser->context.current_tag_type = HUBBUB_TOKEN_END_TAG; tokeniser->context.pending += len; tokeniser->state = STATE_TAG_NAME; } else if ('a' <= c && c <= 'z') { START_BUF(tokeniser->context.current_tag.name, cptr, len); tokeniser->context.current_tag.n_attributes = 0; tokeniser->context.current_tag_type = HUBBUB_TOKEN_END_TAG; tokeniser->context.pending += len; tokeniser->state = STATE_TAG_NAME; } else if (c == '>') { /* Cursor still at "" */ tokeniser->context.pending += len; /* Now need to advance past "" */ parserutils_inputstream_advance(tokeniser->input, tokeniser->context.pending); tokeniser->context.pending = 0; /** \todo parse error */ tokeniser->state = STATE_DATA; } else { /** \todo parse error */ /* Cursor still at "input, tokeniser->context.pending); tokeniser->context.pending = 0; tokeniser->state = STATE_BOGUS_COMMENT; } } return HUBBUB_OK; } /* this state expects tokeniser->context.current_tag to already have its first character set */ hubbub_error hubbub_tokeniser_handle_tag_name(hubbub_tokeniser *tokeniser) { hubbub_tag *ctag = &tokeniser->context.current_tag; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; assert(tokeniser->context.pending > 0); /* assert(tokeniser->context.chars.ptr[0] == '<'); */ assert(ctag->name.len > 0); /* assert(ctag->name.ptr); */ error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { tokeniser->context.pending += len; tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else if (c == '\0') { COLLECT(ctag->name, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else if (c == '/') { tokeniser->context.pending += len; tokeniser->state = STATE_SELF_CLOSING_START_TAG; } else if ('A' <= c && c <= 'Z') { uint8_t lc = (c + 0x20); COLLECT(ctag->name, &lc, len); tokeniser->context.pending += len; } else { COLLECT(ctag->name, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_before_attribute_name( hubbub_tokeniser *tokeniser) { hubbub_tag *ctag = &tokeniser->context.current_tag; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { /* pass over in silence */ tokeniser->context.pending += len; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else if (c == '/') { tokeniser->context.pending += len; tokeniser->state = STATE_SELF_CLOSING_START_TAG; } else { hubbub_attribute *attr; if (c == '"' || c == '\'' || c == '=') { /** \todo parse error */ } attr = tokeniser->alloc(ctag->attributes, (ctag->n_attributes + 1) * sizeof(hubbub_attribute), tokeniser->alloc_pw); if (attr == NULL) return HUBBUB_NOMEM; ctag->attributes = attr; if ('A' <= c && c <= 'Z') { uint8_t lc = (c + 0x20); START_BUF(attr[ctag->n_attributes].name, &lc, len); } else if (c == '\0') { START_BUF(attr[ctag->n_attributes].name, u_fffd, sizeof(u_fffd)); } else { START_BUF(attr[ctag->n_attributes].name, cptr, len); } attr[ctag->n_attributes].ns = HUBBUB_NS_NULL; attr[ctag->n_attributes].value.ptr = NULL; attr[ctag->n_attributes].value.len = 0; ctag->n_attributes++; tokeniser->context.pending += len; tokeniser->state = STATE_ATTRIBUTE_NAME; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_attribute_name(hubbub_tokeniser *tokeniser) { hubbub_tag *ctag = &tokeniser->context.current_tag; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; assert(ctag->attributes[ctag->n_attributes - 1].name.len > 0); error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { tokeniser->context.pending += len; tokeniser->state = STATE_AFTER_ATTRIBUTE_NAME; } else if (c == '=') { tokeniser->context.pending += len; tokeniser->state = STATE_BEFORE_ATTRIBUTE_VALUE; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else if (c == '/') { tokeniser->context.pending += len; tokeniser->state = STATE_SELF_CLOSING_START_TAG; } else if (c == '\0') { COLLECT(ctag->attributes[ctag->n_attributes - 1].name, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else if ('A' <= c && c <= 'Z') { uint8_t lc = (c + 0x20); COLLECT(ctag->attributes[ctag->n_attributes - 1].name, &lc, len); tokeniser->context.pending += len; } else { COLLECT(ctag->attributes[ctag->n_attributes - 1].name, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_after_attribute_name( hubbub_tokeniser *tokeniser) { hubbub_tag *ctag = &tokeniser->context.current_tag; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { tokeniser->context.pending += len; } else if (c == '=') { tokeniser->context.pending += len; tokeniser->state = STATE_BEFORE_ATTRIBUTE_VALUE; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else if (c == '/') { tokeniser->context.pending += len; tokeniser->state = STATE_SELF_CLOSING_START_TAG; } else { hubbub_attribute *attr; if (c == '"' || c == '\'') { /** \todo parse error */ } attr = tokeniser->alloc(ctag->attributes, (ctag->n_attributes + 1) * sizeof(hubbub_attribute), tokeniser->alloc_pw); if (attr == NULL) return HUBBUB_NOMEM; ctag->attributes = attr; if ('A' <= c && c <= 'Z') { uint8_t lc = (c + 0x20); START_BUF(attr[ctag->n_attributes].name, &lc, len); } else if (c == '\0') { START_BUF(attr[ctag->n_attributes].name, u_fffd, sizeof(u_fffd)); } else { START_BUF(attr[ctag->n_attributes].name, cptr, len); } attr[ctag->n_attributes].ns = HUBBUB_NS_NULL; attr[ctag->n_attributes].value.ptr = NULL; attr[ctag->n_attributes].value.len = 0; ctag->n_attributes++; tokeniser->context.pending += len; tokeniser->state = STATE_ATTRIBUTE_NAME; } return HUBBUB_OK; } /* this state is only ever triggered by an '=' */ hubbub_error hubbub_tokeniser_handle_before_attribute_value( hubbub_tokeniser *tokeniser) { hubbub_tag *ctag = &tokeniser->context.current_tag; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { /** \todo parse error */ tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { tokeniser->context.pending += len; } else if (c == '"') { tokeniser->context.pending += len; tokeniser->state = STATE_ATTRIBUTE_VALUE_DQ; } else if (c == '&') { /* Don't consume the '&' -- reprocess in UQ state */ tokeniser->state = STATE_ATTRIBUTE_VALUE_UQ; } else if (c == '\'') { tokeniser->context.pending += len; tokeniser->state = STATE_ATTRIBUTE_VALUE_SQ; } else if (c == '>') { /** \todo parse error */ tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else if (c == '\0') { START_BUF(ctag->attributes[ctag->n_attributes - 1].value, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; tokeniser->state = STATE_ATTRIBUTE_VALUE_UQ; } else { if (c == '=') { /** \todo parse error */ } START_BUF(ctag->attributes[ctag->n_attributes - 1].value, cptr, len); tokeniser->context.pending += len; tokeniser->state = STATE_ATTRIBUTE_VALUE_UQ; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_attribute_value_dq( hubbub_tokeniser *tokeniser) { hubbub_tag *ctag = &tokeniser->context.current_tag; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '"') { tokeniser->context.pending += len; tokeniser->state = STATE_AFTER_ATTRIBUTE_VALUE_Q; } else if (c == '&') { tokeniser->context.prev_state = tokeniser->state; tokeniser->state = STATE_CHARACTER_REFERENCE_IN_ATTRIBUTE_VALUE; tokeniser->context.allowed_char = '"'; /* Don't eat the '&'; it'll be handled by entity consumption */ } else if (c == '\0') { COLLECT_MS(ctag->attributes[ctag->n_attributes - 1].value, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else if (c == '\r') { error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending + len, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } else if (error == PARSERUTILS_EOF || *cptr != '\n') { COLLECT_MS(ctag->attributes[ ctag->n_attributes - 1].value, &lf, sizeof(lf)); } /* Consume '\r' */ tokeniser->context.pending += 1; } else { COLLECT_MS(ctag->attributes[ctag->n_attributes - 1].value, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_attribute_value_sq( hubbub_tokeniser *tokeniser) { hubbub_tag *ctag = &tokeniser->context.current_tag; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\'') { tokeniser->context.pending += len; tokeniser->state = STATE_AFTER_ATTRIBUTE_VALUE_Q; } else if (c == '&') { tokeniser->context.prev_state = tokeniser->state; tokeniser->state = STATE_CHARACTER_REFERENCE_IN_ATTRIBUTE_VALUE; tokeniser->context.allowed_char = '\''; /* Don't eat the '&'; it'll be handled by entity consumption */ } else if (c == '\0') { COLLECT_MS(ctag->attributes[ctag->n_attributes - 1].value, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else if (c == '\r') { error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending + len, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } else if (error == PARSERUTILS_EOF || *cptr != '\n') { COLLECT_MS(ctag->attributes[ ctag->n_attributes - 1].value, &lf, sizeof(lf)); } /* Consume \r */ tokeniser->context.pending += 1; } else { COLLECT_MS(ctag->attributes[ctag->n_attributes - 1].value, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_attribute_value_uq( hubbub_tokeniser *tokeniser) { hubbub_tag *ctag = &tokeniser->context.current_tag; uint8_t c; size_t len; const uint8_t *cptr; parserutils_error error; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; assert(c == '&' || ctag->attributes[ctag->n_attributes - 1].value.len >= 1); if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { tokeniser->context.pending += len; tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME; } else if (c == '&') { tokeniser->context.prev_state = tokeniser->state; tokeniser->state = STATE_CHARACTER_REFERENCE_IN_ATTRIBUTE_VALUE; /* Don't eat the '&'; it'll be handled by entity consumption */ } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else if (c == '\0') { COLLECT(ctag->attributes[ctag->n_attributes - 1].value, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else { if (c == '"' || c == '\'' || c == '=') { /** \todo parse error */ } COLLECT(ctag->attributes[ctag->n_attributes - 1].value, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_character_reference_in_attribute_value( hubbub_tokeniser *tokeniser) { if (tokeniser->context.match_entity.complete == false) { return hubbub_tokeniser_consume_character_reference(tokeniser, tokeniser->context.pending); } else { hubbub_tag *ctag = &tokeniser->context.current_tag; hubbub_attribute *attr = &ctag->attributes[ ctag->n_attributes - 1]; uint8_t utf8[6]; uint8_t *utf8ptr = utf8; size_t len = sizeof(utf8); if (tokeniser->context.match_entity.codepoint) { parserutils_charset_utf8_from_ucs4( tokeniser->context.match_entity.codepoint, &utf8ptr, &len); COLLECT_MS(attr->value, utf8, sizeof(utf8) - len); /* +1 for the ampersand */ tokeniser->context.pending += tokeniser->context.match_entity.length + 1; } else { size_t len = 0; const uint8_t *cptr = NULL; parserutils_error error; error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error( error); } /* Insert the ampersand */ COLLECT_MS(attr->value, cptr, len); tokeniser->context.pending += len; } /* Reset for next time */ tokeniser->context.match_entity.complete = false; /* And back to the previous state */ tokeniser->state = tokeniser->context.prev_state; } return HUBBUB_OK; } /* always switches state */ hubbub_error hubbub_tokeniser_handle_after_attribute_value_q( hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { tokeniser->context.pending += len; tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else if (c == '/') { tokeniser->context.pending += len; tokeniser->state = STATE_SELF_CLOSING_START_TAG; } else { /** \todo parse error */ /* Reprocess character in before attribute name state */ tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_self_closing_start_tag( hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_tag(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; tokeniser->context.current_tag.self_closing = true; return emit_current_tag(tokeniser); } else { /* Reprocess character in before attribute name state */ tokeniser->state = STATE_BEFORE_ATTRIBUTE_NAME; } return HUBBUB_OK; } /* this state expects tokeniser->context.chars to be empty on first entry */ hubbub_error hubbub_tokeniser_handle_bogus_comment(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_comment(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_comment(tokeniser); } else if (c == '\0') { error = parserutils_buffer_append(tokeniser->buffer, u_fffd, sizeof(u_fffd)); if (error != PARSERUTILS_OK) return hubbub_error_from_parserutils_error(error); tokeniser->context.pending += len; } else if (c == '\r') { error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } else if (error == PARSERUTILS_EOF || *cptr != '\n') { error = parserutils_buffer_append(tokeniser->buffer, &lf, sizeof(lf)); if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error( error); } } tokeniser->context.pending += len; } else { error = parserutils_buffer_append(tokeniser->buffer, (uint8_t *) cptr, len); if (error != PARSERUTILS_OK) return hubbub_error_from_parserutils_error(error); tokeniser->context.pending += len; } return HUBBUB_OK; } /* this state always switches to another state straight away */ hubbub_error hubbub_tokeniser_handle_markup_declaration_open( hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; assert(tokeniser->context.pending == 0); error = parserutils_inputstream_peek(tokeniser->input, 0, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_BOGUS_COMMENT; return HUBBUB_OK; } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '-') { tokeniser->context.pending = len; tokeniser->state = STATE_MATCH_COMMENT; } else if ((c & ~0x20) == 'D') { tokeniser->context.pending = len; tokeniser->context.match_doctype.count = len; tokeniser->state = STATE_MATCH_DOCTYPE; } else if (tokeniser->process_cdata_section == true && c == '[') { tokeniser->context.pending = len; tokeniser->context.match_cdata.count = len; tokeniser->state = STATE_MATCH_CDATA; } else { tokeniser->state = STATE_BOGUS_COMMENT; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_match_comment(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->context.pending = tokeniser->context.current_comment.len = 0; tokeniser->state = STATE_BOGUS_COMMENT; return HUBBUB_OK; } else { return hubbub_error_from_parserutils_error(error); } } tokeniser->context.pending = tokeniser->context.current_comment.len = 0; if (*cptr == '-') { parserutils_inputstream_advance(tokeniser->input, SLEN("--")); tokeniser->state = STATE_COMMENT_START; } else { tokeniser->state = STATE_BOGUS_COMMENT; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_comment(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_comment(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '>' && (tokeniser->state == STATE_COMMENT_START_DASH || tokeniser->state == STATE_COMMENT_START || tokeniser->state == STATE_COMMENT_END)) { tokeniser->context.pending += len; /** \todo parse error if state != COMMENT_END */ tokeniser->state = STATE_DATA; return emit_current_comment(tokeniser); } else if (c == '-') { if (tokeniser->state == STATE_COMMENT_START) { tokeniser->state = STATE_COMMENT_START_DASH; } else if (tokeniser->state == STATE_COMMENT_START_DASH) { tokeniser->state = STATE_COMMENT_END; } else if (tokeniser->state == STATE_COMMENT) { tokeniser->state = STATE_COMMENT_END_DASH; } else if (tokeniser->state == STATE_COMMENT_END_DASH) { tokeniser->state = STATE_COMMENT_END; } else if (tokeniser->state == STATE_COMMENT_END) { error = parserutils_buffer_append(tokeniser->buffer, (uint8_t *) "-", SLEN("-")); if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error( error); } } tokeniser->context.pending += len; } else { if (tokeniser->state == STATE_COMMENT_START_DASH || tokeniser->state == STATE_COMMENT_END_DASH) { error = parserutils_buffer_append(tokeniser->buffer, (uint8_t *) "-", SLEN("-")); if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error( error); } } else if (tokeniser->state == STATE_COMMENT_END) { error = parserutils_buffer_append(tokeniser->buffer, (uint8_t *) "--", SLEN("--")); if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error( error); } } if (c == '\0') { error = parserutils_buffer_append(tokeniser->buffer, u_fffd, sizeof(u_fffd)); if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error( error); } } else if (c == '\r') { size_t next_len; error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending + len, &cptr, &next_len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error( error); } else if (error != PARSERUTILS_EOF && *cptr != '\n') { error = parserutils_buffer_append( tokeniser->buffer, &lf, sizeof(lf)); if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error( error); } } } else { error = parserutils_buffer_append(tokeniser->buffer, cptr, len); if (error != PARSERUTILS_OK) { return hubbub_error_from_parserutils_error( error); } } tokeniser->context.pending += len; tokeniser->state = STATE_COMMENT; } return HUBBUB_OK; } #define DOCTYPE "DOCTYPE" #define DOCTYPE_LEN (SLEN(DOCTYPE) - 1) hubbub_error hubbub_tokeniser_handle_match_doctype(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.match_doctype.count, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->context.current_comment.len = tokeniser->context.pending = 0; tokeniser->state = STATE_BOGUS_COMMENT; return HUBBUB_OK; } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; assert(tokeniser->context.match_doctype.count <= DOCTYPE_LEN); if (DOCTYPE[tokeniser->context.match_doctype.count] != (c & ~0x20)) { tokeniser->context.current_comment.len = tokeniser->context.pending = 0; tokeniser->state = STATE_BOGUS_COMMENT; return HUBBUB_OK; } tokeniser->context.pending += len; if (tokeniser->context.match_doctype.count == DOCTYPE_LEN) { /* Skip over the DOCTYPE bit */ parserutils_inputstream_advance(tokeniser->input, tokeniser->context.pending); memset(&tokeniser->context.current_doctype, 0, sizeof tokeniser->context.current_doctype); tokeniser->context.current_doctype.public_missing = true; tokeniser->context.current_doctype.system_missing = true; tokeniser->context.pending = 0; tokeniser->state = STATE_DOCTYPE; } tokeniser->context.match_doctype.count++; return HUBBUB_OK; } #undef DOCTYPE #undef DOCTYPE_LEN hubbub_error hubbub_tokeniser_handle_doctype(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_BEFORE_DOCTYPE_NAME; return HUBBUB_OK; } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { tokeniser->context.pending += len; } tokeniser->state = STATE_BEFORE_DOCTYPE_NAME; return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_before_doctype_name( hubbub_tokeniser *tokeniser) { hubbub_doctype *cdoc = &tokeniser->context.current_doctype; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { /** \todo parse error */ /* Emit current doctype, force-quirks on */ tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { /* pass over in silence */ tokeniser->context.pending += len; } else if (c == '>') { /** \todo parse error */ tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { if (c == '\0') { START_BUF(cdoc->name, u_fffd, sizeof(u_fffd)); } else if ('A' <= c && c <= 'Z') { uint8_t lc = c + 0x20; START_BUF(cdoc->name, &lc, len); } else { START_BUF(cdoc->name, cptr, len); } tokeniser->context.pending += len; tokeniser->state = STATE_DOCTYPE_NAME; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_doctype_name(hubbub_tokeniser *tokeniser) { hubbub_doctype *cdoc = &tokeniser->context.current_doctype; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { tokeniser->context.pending += len; tokeniser->state = STATE_AFTER_DOCTYPE_NAME; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, false); } else if (c == '\0') { COLLECT(cdoc->name, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else if ('A' <= c && c <= 'Z') { uint8_t lc = c + 0x20; COLLECT(cdoc->name, &lc, len); tokeniser->context.pending += len; } else { COLLECT(cdoc->name, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_after_doctype_name( hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; tokeniser->context.pending += len; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { /* pass over in silence */ } else if (c == '>') { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, false); } else if ((c & ~0x20) == 'P') { tokeniser->context.match_doctype.count = 1; tokeniser->state = STATE_MATCH_PUBLIC; } else if ((c & ~0x20) == 'S') { tokeniser->context.match_doctype.count = 1; tokeniser->state = STATE_MATCH_SYSTEM; } else { tokeniser->state = STATE_BOGUS_DOCTYPE; tokeniser->context.current_doctype.force_quirks = true; } return HUBBUB_OK; } #define PUBLIC "PUBLIC" #define PUBLIC_LEN (SLEN(PUBLIC) - 1) hubbub_error hubbub_tokeniser_handle_match_public(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->context.current_doctype.force_quirks = true; tokeniser->state = STATE_BOGUS_DOCTYPE; return HUBBUB_OK; } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; assert(tokeniser->context.match_doctype.count <= PUBLIC_LEN); if (PUBLIC[tokeniser->context.match_doctype.count] != (c & ~0x20)) { tokeniser->context.current_doctype.force_quirks = true; tokeniser->state = STATE_BOGUS_DOCTYPE; return HUBBUB_OK; } tokeniser->context.pending += len; if (tokeniser->context.match_doctype.count == PUBLIC_LEN) { tokeniser->state = STATE_BEFORE_DOCTYPE_PUBLIC; } tokeniser->context.match_doctype.count++; return HUBBUB_OK; } #undef PUBLIC #undef PUBLIC_LEN hubbub_error hubbub_tokeniser_handle_before_doctype_public( hubbub_tokeniser *tokeniser) { hubbub_doctype *cdoc = &tokeniser->context.current_doctype; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; tokeniser->context.pending += len; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { /* pass over in silence */ } else if (c == '"') { cdoc->public_missing = false; cdoc->public_id.len = 0; tokeniser->state = STATE_DOCTYPE_PUBLIC_DQ; } else if (c == '\'') { cdoc->public_missing = false; cdoc->public_id.len = 0; tokeniser->state = STATE_DOCTYPE_PUBLIC_SQ; } else if (c == '>') { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { cdoc->force_quirks = true; tokeniser->state = STATE_BOGUS_DOCTYPE; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_doctype_public_dq( hubbub_tokeniser *tokeniser) { hubbub_doctype *cdoc = &tokeniser->context.current_doctype; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '"') { tokeniser->context.pending += len; tokeniser->state = STATE_AFTER_DOCTYPE_PUBLIC; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else if (c == '\0') { COLLECT_MS(cdoc->public_id, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else if (c == '\r') { error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } else if (error == PARSERUTILS_EOF || *cptr != '\n') { COLLECT_MS(cdoc->public_id, &lf, sizeof(lf)); } /* Collect '\r' */ tokeniser->context.pending += 1; } else { COLLECT_MS(cdoc->public_id, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_doctype_public_sq( hubbub_tokeniser *tokeniser) { hubbub_doctype *cdoc = &tokeniser->context.current_doctype; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\'') { tokeniser->context.pending += len; tokeniser->state = STATE_AFTER_DOCTYPE_PUBLIC; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else if (c == '\0') { COLLECT_MS(cdoc->public_id, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else if (c == '\r') { error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } else if (error == PARSERUTILS_EOF || *cptr != '\n') { COLLECT_MS(cdoc->public_id, &lf, sizeof(lf)); } /* Collect '\r' */ tokeniser->context.pending += 1; } else { COLLECT_MS(cdoc->public_id, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_after_doctype_public( hubbub_tokeniser *tokeniser) { hubbub_doctype *cdoc = &tokeniser->context.current_doctype; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; tokeniser->context.pending += len; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { /* pass over in silence */ } else if (c == '"') { cdoc->system_missing = false; cdoc->system_id.len = 0; tokeniser->state = STATE_DOCTYPE_SYSTEM_DQ; } else if (c == '\'') { cdoc->system_missing = false; cdoc->system_id.len = 0; tokeniser->state = STATE_DOCTYPE_SYSTEM_SQ; } else if (c == '>') { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, false); } else { cdoc->force_quirks = true; tokeniser->state = STATE_BOGUS_DOCTYPE; } return HUBBUB_OK; } #define SYSTEM "SYSTEM" #define SYSTEM_LEN (SLEN(SYSTEM) - 1) hubbub_error hubbub_tokeniser_handle_match_system(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK){ if (error == PARSERUTILS_EOF) { tokeniser->context.current_doctype.force_quirks = true; tokeniser->state = STATE_BOGUS_DOCTYPE; return HUBBUB_OK; } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; assert(tokeniser->context.match_doctype.count <= SYSTEM_LEN); if (SYSTEM[tokeniser->context.match_doctype.count] != (c & ~0x20)) { tokeniser->context.current_doctype.force_quirks = true; tokeniser->state = STATE_BOGUS_DOCTYPE; return HUBBUB_OK; } tokeniser->context.pending += len; if (tokeniser->context.match_doctype.count == SYSTEM_LEN) { tokeniser->state = STATE_BEFORE_DOCTYPE_SYSTEM; } tokeniser->context.match_doctype.count++; return HUBBUB_OK; } #undef SYSTEM #undef SYSTEM_LEN hubbub_error hubbub_tokeniser_handle_before_doctype_system( hubbub_tokeniser *tokeniser) { hubbub_doctype *cdoc = &tokeniser->context.current_doctype; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; tokeniser->context.pending += len; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { /* pass over */ } else if (c == '"') { cdoc->system_missing = false; cdoc->system_id.len = 0; tokeniser->state = STATE_DOCTYPE_SYSTEM_DQ; } else if (c == '\'') { cdoc->system_missing = false; cdoc->system_id.len = 0; tokeniser->state = STATE_DOCTYPE_SYSTEM_SQ; } else if (c == '>') { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { cdoc->force_quirks = true; tokeniser->state = STATE_BOGUS_DOCTYPE; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_doctype_system_dq( hubbub_tokeniser *tokeniser) { hubbub_doctype *cdoc = &tokeniser->context.current_doctype; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '"') { tokeniser->context.pending += len; tokeniser->state = STATE_AFTER_DOCTYPE_SYSTEM; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else if (c == '\0') { COLLECT_MS(cdoc->system_id, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else if (c == '\r') { error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } else if (error == PARSERUTILS_EOF || *cptr != '\n') { COLLECT_MS(cdoc->system_id, &lf, sizeof(lf)); } /* Collect '\r' */ tokeniser->context.pending += 1; } else { COLLECT_MS(cdoc->system_id, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_doctype_system_sq( hubbub_tokeniser *tokeniser) { hubbub_doctype *cdoc = &tokeniser->context.current_doctype; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == '\'') { tokeniser->context.pending += len; tokeniser->state = STATE_AFTER_DOCTYPE_SYSTEM; } else if (c == '>') { tokeniser->context.pending += len; tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else if (c == '\0') { COLLECT_MS(cdoc->system_id, u_fffd, sizeof(u_fffd)); tokeniser->context.pending += len; } else if (c == '\r') { error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } else if (error == PARSERUTILS_EOF || *cptr != '\n') { COLLECT_MS(cdoc->system_id, &lf, sizeof(lf)); } /* Collect '\r' */ tokeniser->context.pending += 1; } else { COLLECT_MS(cdoc->system_id, cptr, len); tokeniser->context.pending += len; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_after_doctype_system( hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, true); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; tokeniser->context.pending += len; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '\r') { /* pass over in silence */ } else if (c == '>') { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, false); } else { tokeniser->state = STATE_BOGUS_DOCTYPE; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_bogus_doctype(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, false); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; tokeniser->context.pending += len; if (c == '>') { tokeniser->state = STATE_DATA; return emit_current_doctype(tokeniser, false); } return HUBBUB_OK; } #define CDATA "[CDATA[" #define CDATA_LEN (SLEN(CDATA) - 1) hubbub_error hubbub_tokeniser_handle_match_cdata(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->context.current_comment.len = tokeniser->context.pending = 0; tokeniser->state = STATE_BOGUS_COMMENT; return HUBBUB_OK; } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; assert(tokeniser->context.match_cdata.count <= CDATA_LEN); if (CDATA[tokeniser->context.match_cdata.count] != (c & ~0x20)) { tokeniser->context.current_comment.len = tokeniser->context.pending = 0; tokeniser->state = STATE_BOGUS_COMMENT; return HUBBUB_OK; } tokeniser->context.pending += len; if (tokeniser->context.match_cdata.count == CDATA_LEN) { parserutils_inputstream_advance(tokeniser->input, tokeniser->context.match_cdata.count + len); tokeniser->context.pending = 0; tokeniser->context.match_cdata.end = 0; tokeniser->state = STATE_CDATA_BLOCK; } tokeniser->context.match_cdata.count += len; return HUBBUB_OK; } #undef CDATA #undef CDATA_LEN hubbub_error hubbub_tokeniser_handle_cdata_block(hubbub_tokeniser *tokeniser) { size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, tokeniser->context.pending, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->state = STATE_DATA; return emit_current_chars(tokeniser); } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; if (c == ']' && (tokeniser->context.match_cdata.end == 0 || tokeniser->context.match_cdata.end == 1)) { tokeniser->context.pending += len; tokeniser->context.match_cdata.end += len; } else if (c == '>' && tokeniser->context.match_cdata.end == 2) { /* Remove the previous two "]]" */ tokeniser->context.pending -= 2; /* Emit any pending characters */ emit_current_chars(tokeniser); /* Now move past the "]]>" bit */ parserutils_inputstream_advance(tokeniser->input, SLEN("]]>")); tokeniser->state = STATE_DATA; } else if (c == '\0') { if (tokeniser->context.pending > 0) { /* Emit any pending characters */ emit_current_chars(tokeniser); } /* Perform NUL-byte replacement */ emit_character_token(tokeniser, &u_fffd_str); parserutils_inputstream_advance(tokeniser->input, len); tokeniser->context.match_cdata.end = 0; } else if (c == '\r') { error = parserutils_inputstream_peek( tokeniser->input, tokeniser->context.pending + len, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } if (tokeniser->context.pending > 0) { /* Emit any pending characters */ emit_current_chars(tokeniser); } if (error == PARSERUTILS_EOF || *cptr != '\n') { /* Emit newline */ emit_character_token(tokeniser, &lf_str); } /* Advance over \r */ parserutils_inputstream_advance(tokeniser->input, 1); tokeniser->context.match_cdata.end = 0; } else { tokeniser->context.pending += len; tokeniser->context.match_cdata.end = 0; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_consume_character_reference( hubbub_tokeniser *tokeniser, size_t pos) { uint32_t allowed_char = tokeniser->context.allowed_char; size_t len; const uint8_t *cptr; parserutils_error error; uint8_t c; size_t off; error = parserutils_inputstream_peek(tokeniser->input, pos, &cptr, &len); /* We should always start on an ampersand */ assert(error == PARSERUTILS_OK); assert(len == 1 && *cptr == '&'); off = pos + len; /* Look at the character after the ampersand */ error = parserutils_inputstream_peek(tokeniser->input, off, &cptr, &len); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_EOF) { tokeniser->context.match_entity.complete = true; tokeniser->context.match_entity.codepoint = 0; return HUBBUB_OK; } else { return hubbub_error_from_parserutils_error(error); } } c = *cptr; /* Set things up */ tokeniser->context.match_entity.offset = off; tokeniser->context.match_entity.poss_length = 0; tokeniser->context.match_entity.length = 0; tokeniser->context.match_entity.base = 0; tokeniser->context.match_entity.codepoint = 0; tokeniser->context.match_entity.had_data = false; tokeniser->context.match_entity.return_state = tokeniser->state; tokeniser->context.match_entity.complete = false; tokeniser->context.match_entity.overflow = false; tokeniser->context.match_entity.context = -1; tokeniser->context.match_entity.prev_len = len; /* Reset allowed character for future calls */ tokeniser->context.allowed_char = '\0'; if (c == '\t' || c == '\n' || c == '\f' || c == ' ' || c == '<' || c == '&' || (allowed_char && c == allowed_char)) { tokeniser->context.match_entity.complete = true; tokeniser->context.match_entity.codepoint = 0; } else if (c == '#') { tokeniser->context.match_entity.length += len; tokeniser->state = STATE_NUMBERED_ENTITY; } else { tokeniser->state = STATE_NAMED_ENTITY; } return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_numbered_entity( hubbub_tokeniser *tokeniser) { hubbub_tokeniser_context *ctx = &tokeniser->context; size_t len; const uint8_t *cptr; parserutils_error error; error = parserutils_inputstream_peek(tokeniser->input, ctx->match_entity.offset + ctx->match_entity.length, &cptr, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } if (error != PARSERUTILS_EOF && ctx->match_entity.base == 0) { uint8_t c = *cptr; if ((c & ~0x20) == 'X') { ctx->match_entity.base = 16; ctx->match_entity.length += len; } else { ctx->match_entity.base = 10; } } while ((error = parserutils_inputstream_peek(tokeniser->input, ctx->match_entity.offset + ctx->match_entity.length, &cptr, &len)) == PARSERUTILS_OK) { uint8_t c = *cptr; if (ctx->match_entity.base == 10 && ('0' <= c && c <= '9')) { ctx->match_entity.had_data = true; ctx->match_entity.codepoint = ctx->match_entity.codepoint * 10 + (c - '0'); ctx->match_entity.length += len; } else if (ctx->match_entity.base == 16 && (('0' <= c && c <= '9') || ('A' <= (c & ~0x20) && (c & ~0x20) <= 'F'))) { ctx->match_entity.had_data = true; ctx->match_entity.codepoint *= 16; if ('0' <= c && c <= '9') { ctx->match_entity.codepoint += (c - '0'); } else { ctx->match_entity.codepoint += ((c & ~0x20) - 'A' + 10); } ctx->match_entity.length += len; } else { break; } if (ctx->match_entity.codepoint >= 0x10FFFF) { ctx->match_entity.overflow = true; } } if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } /* Eat trailing semicolon, if any */ if (error != PARSERUTILS_EOF && *cptr == ';') { ctx->match_entity.length += len; } /* Had data, so calculate final codepoint */ if (ctx->match_entity.had_data) { uint32_t cp = ctx->match_entity.codepoint; if (0x80 <= cp && cp <= 0x9F) { cp = cp1252Table[cp - 0x80]; } else if (cp == 0x0D) { cp = 0x000A; } else if (ctx->match_entity.overflow || cp <= 0x0008 || cp == 0x000B || (0x000E <= cp && cp <= 0x001F) || (0x007F <= cp && cp <= 0x009F) || (0xD800 <= cp && cp <= 0xDFFF) || (0xFDD0 <= cp && cp <= 0xFDEF) || (cp & 0xFFFE) == 0xFFFE) { /* the check for cp > 0x10FFFF per spec is performed * in the loop above to avoid overflow */ cp = 0xFFFD; } ctx->match_entity.codepoint = cp; } /* Flag completion */ ctx->match_entity.complete = true; /* And back to the state we were entered in */ tokeniser->state = ctx->match_entity.return_state; return HUBBUB_OK; } hubbub_error hubbub_tokeniser_handle_named_entity(hubbub_tokeniser *tokeniser) { hubbub_tokeniser_context *ctx = &tokeniser->context; size_t len; const uint8_t *cptr; parserutils_error error; while ((error = parserutils_inputstream_peek(tokeniser->input, ctx->match_entity.offset + ctx->match_entity.poss_length, &cptr, &len)) == PARSERUTILS_OK) { uint32_t cp; uint8_t c = *cptr; hubbub_error error; if (c > 0x7F) { /* Entity names are ASCII only */ break; } error = hubbub_entities_search_step(c, &cp, &ctx->match_entity.context); if (error == HUBBUB_OK) { /* Had a match - store it for later */ ctx->match_entity.codepoint = cp; ctx->match_entity.length = ctx->match_entity.poss_length + len; ctx->match_entity.poss_length = ctx->match_entity.length; } else if (error == HUBBUB_INVALID) { /* No further matches - use last found */ break; } else { /* Need more data */ ctx->match_entity.poss_length += len; } } if (error != PARSERUTILS_OK && error != PARSERUTILS_EOF) { return hubbub_error_from_parserutils_error(error); } if (ctx->match_entity.length > 0) { uint8_t c; error = parserutils_inputstream_peek(tokeniser->input, ctx->match_entity.offset + ctx->match_entity.length - 1, &cptr, &len); /* We're re-reading a character we've already read after. * Therefore, there's no way that an error may occur as * a result. */ assert(error == PARSERUTILS_OK); c = *cptr; if ((tokeniser->context.match_entity.return_state == STATE_CHARACTER_REFERENCE_IN_ATTRIBUTE_VALUE) && c != ';') { error = parserutils_inputstream_peek(tokeniser->input, ctx->match_entity.offset + ctx->match_entity.length, &cptr, &len); /* We must have attempted to read one more character * than was present in the entity name, as that is the * only way to break out of the loop above. If that * failed, then any non-EOF case will have been handled * by the if statement after the loop thus it cannot * occur here. */ assert(error == PARSERUTILS_OK || error == PARSERUTILS_EOF); if (error == PARSERUTILS_EOF) { ctx->match_entity.codepoint = 0; } c = *cptr; if ((0x0030 <= c && c <= 0x0039) || (0x0041 <= c && c <= 0x005A) || (0x0061 <= c && c <= 0x007A)) { ctx->match_entity.codepoint = 0; } } } /* Flag completion */ ctx->match_entity.complete = true; /* And back to the state from whence we came */ tokeniser->state = ctx->match_entity.return_state; return HUBBUB_OK; } /*** Token emitting bits ***/ /** * Emit a character token. * * \param tokeniser Tokeniser instance * \param chars Pointer to hubbub_string to emit * \return true */ hubbub_error emit_character_token(hubbub_tokeniser *tokeniser, const hubbub_string *chars) { hubbub_token token; token.type = HUBBUB_TOKEN_CHARACTER; token.data.character = *chars; return hubbub_tokeniser_emit_token(tokeniser, &token); } /** * Emit the current pending characters being stored in the tokeniser context. * * \param tokeniser Tokeniser instance * \return true */ hubbub_error emit_current_chars(hubbub_tokeniser *tokeniser) { hubbub_token token; size_t len; const uint8_t *cptr = NULL; parserutils_error error; /* Calling this with nothing to output is a probable bug */ assert(tokeniser->context.pending > 0); error = parserutils_inputstream_peek(tokeniser->input, 0, &cptr, &len); if (error != PARSERUTILS_OK) return hubbub_error_from_parserutils_error(error); token.type = HUBBUB_TOKEN_CHARACTER; token.data.character.ptr = cptr; token.data.character.len = tokeniser->context.pending; return hubbub_tokeniser_emit_token(tokeniser, &token); } /** * Emit the current tag token being stored in the tokeniser context. * * \param tokeniser Tokeniser instance * \return true */ hubbub_error emit_current_tag(hubbub_tokeniser *tokeniser) { hubbub_error err; hubbub_token token; uint32_t n_attributes; hubbub_attribute *attrs; uint8_t *ptr; uint32_t i, j; /* Emit current tag */ token.type = tokeniser->context.current_tag_type; token.data.tag = tokeniser->context.current_tag; token.data.tag.ns = HUBBUB_NS_HTML; n_attributes = token.data.tag.n_attributes; attrs = token.data.tag.attributes; /* Set pointers correctly... */ ptr = tokeniser->buffer->data; token.data.tag.name.ptr = tokeniser->buffer->data; ptr += token.data.tag.name.len; for (i = 0; i < n_attributes; i++) { attrs[i].name.ptr = ptr; ptr += attrs[i].name.len; attrs[i].value.ptr = ptr; ptr += attrs[i].value.len; } /* Discard duplicate attributes */ for (i = 0; i < n_attributes; i++) { for (j = 0; j < n_attributes; j++) { uint32_t move; if (j == i || attrs[i].name.len != attrs[j].name.len || strncmp((char *) attrs[i].name.ptr, (char *) attrs[j].name.ptr, attrs[i].name.len) != 0) { /* Attributes don't match */ continue; } assert(i < j); /* Calculate amount to move */ move = (n_attributes - 1 - j) * sizeof(hubbub_attribute); if (move > 0) { memmove(&attrs[j],&attrs[j+1], move); } /* We've deleted an item, so we need to * reprocess this index */ j--; /* And reduce the number of attributes */ n_attributes--; } } token.data.tag.n_attributes = n_attributes; err = hubbub_tokeniser_emit_token(tokeniser, &token); if (token.type == HUBBUB_TOKEN_START_TAG) { /* Save start tag name for R?CDATA */ if (token.data.tag.name.len < sizeof(tokeniser->context.last_start_tag_name)) { strncpy((char *) tokeniser->context.last_start_tag_name, (const char *) token.data.tag.name.ptr, token.data.tag.name.len); tokeniser->context.last_start_tag_len = token.data.tag.name.len; } else { tokeniser->context.last_start_tag_name[0] = '\0'; tokeniser->context.last_start_tag_len = 0; } } else /* if (token->type == HUBBUB_TOKEN_END_TAG) */ { /* Reset content model after R?CDATA elements */ tokeniser->content_model = HUBBUB_CONTENT_MODEL_PCDATA; } /* Reset the self-closing flag */ tokeniser->context.current_tag.self_closing = false; return err; } /** * Emit the current comment token being stored in the tokeniser context. * * \param tokeniser Tokeniser instance * \return true */ hubbub_error emit_current_comment(hubbub_tokeniser *tokeniser) { hubbub_token token; token.type = HUBBUB_TOKEN_COMMENT; token.data.comment.ptr = tokeniser->buffer->data; token.data.comment.len = tokeniser->buffer->length; return hubbub_tokeniser_emit_token(tokeniser, &token); } /** * Emit the current doctype token being stored in the tokeniser context. * * \param tokeniser Tokeniser instance * \param force_quirks Force quirks mode on this document * \return true */ hubbub_error emit_current_doctype(hubbub_tokeniser *tokeniser, bool force_quirks) { hubbub_token token; /* Emit doctype */ token.type = HUBBUB_TOKEN_DOCTYPE; token.data.doctype = tokeniser->context.current_doctype; if (force_quirks == true) token.data.doctype.force_quirks = true; /* Set pointers correctly */ token.data.doctype.name.ptr = tokeniser->buffer->data; if (token.data.doctype.public_missing == false) { token.data.doctype.public_id.ptr = tokeniser->buffer->data + token.data.doctype.name.len; } if (token.data.doctype.system_missing == false) { token.data.doctype.system_id.ptr = tokeniser->buffer->data + token.data.doctype.name.len + token.data.doctype.public_id.len; } return hubbub_tokeniser_emit_token(tokeniser, &token); } /** * Emit a token, performing sanity checks if necessary * * \param tokeniser Tokeniser instance * \param token Token to emit */ hubbub_error hubbub_tokeniser_emit_token(hubbub_tokeniser *tokeniser, hubbub_token *token) { hubbub_error err = HUBBUB_OK; assert(tokeniser != NULL); assert(token != NULL); #ifndef NDEBUG /* Sanity checks */ switch (token->type) { case HUBBUB_TOKEN_DOCTYPE: assert(memchr(token->data.doctype.name.ptr, 0xff, token->data.doctype.name.len) == NULL); if (token->data.doctype.public_missing == false) assert(memchr(token->data.doctype.public_id.ptr, 0xff, token->data.doctype.public_id.len) == NULL); if (token->data.doctype.system_missing == false) assert(memchr(token->data.doctype.system_id.ptr, 0xff, token->data.doctype.system_id.len) == NULL); break; case HUBBUB_TOKEN_START_TAG: case HUBBUB_TOKEN_END_TAG: { uint32_t i; assert(memchr(token->data.tag.name.ptr, 0xff, token->data.tag.name.len) == NULL); for (i = 0; i < token->data.tag.n_attributes; i++) { hubbub_attribute *attr = &token->data.tag.attributes[i]; assert(memchr(attr->name.ptr, 0xff, attr->name.len) == NULL); assert(memchr(attr->value.ptr, 0xff, attr->value.len) == NULL); } } break; case HUBBUB_TOKEN_COMMENT: assert(memchr(token->data.comment.ptr, 0xff, token->data.comment.len) == NULL); break; case HUBBUB_TOKEN_CHARACTER: assert(memchr(token->data.character.ptr, 0xff, token->data.character.len) == NULL); break; case HUBBUB_TOKEN_EOF: break; } #endif /* Emit the token */ if (tokeniser->token_handler) { err = tokeniser->token_handler(token, tokeniser->token_pw); } /* Discard current buffer */ if (tokeniser->buffer->length) { parserutils_buffer_discard(tokeniser->buffer, 0, tokeniser->buffer->length); } /* Advance the pointer */ if (tokeniser->context.pending) { parserutils_inputstream_advance(tokeniser->input, tokeniser->context.pending); tokeniser->context.pending = 0; } return err; } netsurf-2.9/hubbub-0.1.2/README0000664000175000017500000000637711173215265014651 0ustar vincevinceHubbub -- an HTML parser ======================== Overview -------- Hubbub is a flexible HTML parser. It aims to comply with the HTML5 specification. Requirements ------------ Hubbub requires the following tools: + A C99 capable C compiler + GNU make or compatible + Perl (for the testcases) + Pkg-config (for the testcases) + xsltproc (for the entity fetcher) + wget (for the entity fetcher) + doxygen (for the API documentation) Hubbub also requires the following libraries to be installed: + An iconv implementation (e.g. libiconv) + LibParserUtils -- see below for further information + JSON-C (for the testcases) -- see below for further information Hubbub can make use of the following, for debugging and testing purposes: + gcov and lcov, for test coverage data LibParserUtils -------------- To compile Hubbub, you will need LibParserUtils. This can be obtained from SVN: $ svn co svn://svn.netsurf-browser.org/trunk/libparserutils/ Follow the instructions in LibParserUtils' README file to build and install it. Note: By default, libparserutils only supports a few character sets. It may, however, be configured to use iconv() to provide charset conversion. See LibParserUtils' README for further information. JSON-C ------ To run tests, you will need JSON-C. You can obtain the version that Hubbub needs from SVN: $ svn co svn://svn.netsurf-browser.org/trunk/json-c/json-c/ Build and install JSON-C as follows: $ sh autogen.sh $ make install Compilation ----------- The exact type of build may be configured by passing parameters to make. Common usage is described below. For a static library: $ make For a shared library: $ make COMPONENT_TYPE=lib-shared For a static library with debug enabled: $ make BUILD=debug To cross-compile a static library: $ make TARGET= Verification ------------ The library's functionality may be verified, thus: $ make test If you wish to see test coverage statistics, run: $ make coverage Then open build/coverage/index.html in a web browser. In both cases, ensure that the same parameters to make are passed as when building the library. (Un)installation ---------------- To install the library: $ make install Ensure that the same parameters to make are passed as when building the library. To specify the installation prefix: $ make install PREFIX=/path/to/prefix To specify a staging directory for packaging: $ make install DESTDIR=/path/to/directory Items will be installed to $(DESTDIR)$(PREFIX)/ To uninstall: $ make uninstall API documentation ----------------- Use doxygen to auto-generate API documentation, thus: $ make docs Then open build/docs/html/index.html in a web browser. The "examples" directory contains commented examples of how to use Hubbub. The test driver code in test/ may also provide some useful pointers. A note on character set aliases ------------------------------- Hubbub uses an external mapping file to encode relationships between character set names. This is the "Aliases" file. A copy may be found at test/data/Aliases. The path to this file is required when calling hubbub_initialise(). netsurf-2.9/hubbub-0.1.2/docs/0000775000175000017500000000000011734430254014704 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/docs/doxygen.conf0000664000175000017500000015644411027611343017241 0ustar vincevince# Doxyfile 1.5.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = Hubbub # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = $Id: doxygen.conf 4425 2008-06-23 03:05:07Z takkaria $ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = docs/api/ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, # and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = src src/charset src/input src/tokeniser src/treebuilder src/utils include/hubbub # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = YES # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = YES #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is enabled by default, which results in a transparent # background. Warning: Depending on the platform used, enabling this option # may lead to badly anti-aliased labels on the edges of a graph (i.e. they # become hard to read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO netsurf-2.9/hubbub-0.1.2/docs/Todo0000664000175000017500000000131511047727527015545 0ustar vincevinceTODO list ========= + Error checking + Documentation + Implement one or more tree builders - test/tree2.c would serve as a basic tree builder - NetSurf's libxml2 binding could do with being brought back here somehow + Parse error reporting (incl. acknowledging self-closing flags) + Implement extraneous chunk insertion/tokenisation + Statistical charset autodetection + Shared library, for those platforms that support such things - requires possibly prefixing more things with hubbub_ + Optimise it - being clever with e.g. attribute allocation in tokeniser - tag name interning / replacing element_type_from_name() - Hixie's data (http://tinyurl.com/hixie-html5-data-2007) netsurf-2.9/hubbub-0.1.2/docs/Architecture0000664000175000017500000000437211171337551017260 0ustar vincevinceHubbub parser architecture ========================== Introduction ------------ Hubbub is a flexible HTML parser. It offers two interfaces: * a SAX-style event interface * a DOM-style tree-based interface Overview -------- Hubbub is comprised of two parts: * a tokeniser * a tree builder Tokeniser --------- The tokeniser divides the data held in the document buffer into chunks. It sends SAX-style events for each chunk. Tree builder ------------ The tree builder constructs a DOM-like tree from the SAX events emitted by the tokeniser. The exact representation of the tree is up to the client, which must provide a number of tree building handler functions. Memory usage and ownership -------------------------- Memory usage within the library is well defined, as is ownership of allocated memory. Raw input data provided by the library client is owned by the client. SAX events which refer to document segments contain direct references to internal data. Token objects are transient and data within them are no longer valid once the event handler has returned control to the tokeniser. All data returned by a SAX event is owned by the library. The tree builder will use client callbacks to create the objects used within the tree. Tree objects may be reference counted (the client may do nothing in the ref/unref callbacks and use garbage collection instead). The resultant tree is owned by the client. Parse errors ------------ Notification of parse errors is made through a dedicated event. This event contains the line/column offset of the error location, along with a message detailing the error. Exceptional circumstances ------------------------- Exceptional circumstances (such as memory exhaustion) are reported immediately. The parser's state in such situations is undefined. There is no recovery mechanism. Therefore, if the client is able to recover from the exceptional circumstance (e.g. by making more free memory available) the only valid way to proceed is to create a new parser instance and start parsing from scratch. The client should ensure that they destroy the old parser instance and any DOM tree produced by it, to avoid resource leaks. netsurf-2.9/hubbub-0.1.2/docs/Macros0000664000175000017500000000550111044347624016056 0ustar vincevinceThe data which Hubbub is fed (the input stream) gets buffered into a UTF-8 buffer. This buffer only holds a subset of the input stream at any given time. To avoid unnecessary copying (which is both a speed and memory loss), Hubbub tries to make all emitted strings point into this buffer, which is then advanced after tokens have been emitted. This is not always possible, however, because HTML5 specifies behaviour which requires changing various characters to various other characters, and these sets of characters may not have the same length. These cases are: - CR handling -- CRLFs and CRs are converted to LFs - tag and attribute names are lowercased - entities are allowed in attribute names - NUL bytes must be turned into U+FFFD REPLACEMENT CHARACTER When collecting the strings it will emit, Hubbub starts by assuming that no transformations on the input stream will be required. However, if it hits one of the above cases, then it copies all of the collected characters into a buffer and switches to using that instead. This means that every time a character is collected and it is possible that that character could be collected into a buffer, the code must check if it should be collected into a buffer. To allow this check, and others, to happen when necessary and never otherwise, Hubbub uses a set of macros to collect characters, detailed below. Hubbub strings are (beginning,length) pairs. This means that once the beginning is set to a position in the input stream, the string can collect further character runs in the stream simply by adding to the length part. This makes extending strings very efficient. | COLLECT(hubbub_string str, uintptr_t cptr, size_t length) This collects the character pointed to "cptr" (of size "length") into "str", whether str is a buffered or unbuffered string, but only if "str" already points to collected characters. | COLLECT_NOBUF(hubbub_string str, size_t length) This collects "length" bytes into "str", but only if "str" already points to collected characters. (There is no need to pass the character, since this just increases the length of the string.) | COLLECT_MS(hubbub_string str, uintptr_t cptr, size_t length) If "str" is currently zero-length, this acts like START(str, cptr, length). Otherwise, it just acts like COLLECT(str, cptr, length). | START(hubbub_string str, uintptr_t cptr, size_t length) This sets the string "str"'s start to "cptr" and its length to "length". | START_BUF(hubbub_string str, uintptr_t cptr, size_t length) This buffers the character of length "length" pointed to by "c" and then sets "str" to point to it. | SWITCH(hubbub_string str) This switches the string "str" from unbuffered to buffered; it copies all characters currently collected in "str" to the buffer and then updates it to point there. netsurf-2.9/hubbub-0.1.2/docs/Treebuilder0000664000175000017500000001712611047712734017107 0ustar vincevinceHubbub treebuilding interface ============================= Introduction ------------ hubbub uses an interface to build a tree. this is what the functions should do. Types ----- hubbub_string ------------- Reference counting ------------------ The callback interface provides hooks to allow tree nodes to be reference counted. There is, however, no requirement that the client actually performs reference counting. It is perfectly acceptable to use some other object use tracking scheme (e.g. garbage collection). The descriptions below describe the expected reference counting behaviour, regardless. Callback behaviour ------------------ The first parameter to all callbacks is the context passed to the library on initialisation. All node creation functions should return 0 on success, and something else on failure. Node creation ------------- | int hubbub_tree_create_comment(void *ctx, | const hubbub_string *data, | void **result); | | int hubbub_tree_create_doctype(void *ctx, | const hubbub_doctype *doctype, | void **result); | | int hubbub_tree_create_element(void *ctx, | const hubbub_tag *tag, | void **result); | | int hubbub_tree_create_text(void *ctx, | const hubbub_string *data, | void **result); All node creation functions must create a node with the information passed in their second argument, and place a pointer to that node in *result. The reference count of the created node must be set to 1. | int hubbub_tree_clone_node(void *ctx, | void *node, | bool deep, | void **result); If deep == false, then this function must duplicate "node" and none of its children, and place a pointer to the clone in *result. It must also set the reference count of the clone to 1. The clone must be isolated from the document tree (it must have no parent or sibling nodes). If deep == true, then this function must duplicate "node" and all of its children. A pointer to the clone of "node" must be placed in *result. The reference count of the clone must be set to 1. The reference count of all other created nodes must be set to 0. The clone must also be isolated from the document tree (it must have no parent or sibling nodes). Reference counting ------------------ | int hubbub_tree_ref_node(void *ctx, void *node); | int hubbub_tree_unref_node(void *ctx, void *node); These functions should increase and decrease the reference count of "node", respectively. If the reference count of "node" falls to zero, and it is isolated from the document tree (it has no parent or sibling nodes), then it must be destroyed. Tree manipulation ----------------- | int hubbub_tree_append_child(void *ctx, | void *parent, | void *child, | void **result); This function must append the node "child" to the end of the list of children of the node "parent", and place a pointer to the newly-inserted node in *result. If the node "child" is a text node, and the last child node of "parent" is also a text node, then instead the text of "child" must be appended to that node, and a pointer to the node thus appended to must be placed in *result. In any case, the reference count of the node pointed to by *result at the end of these steps must be incremented. | int hubbub_tree_insert_before(void *ctx, | void *parent, | void *child, | void *ref_child, | void **result); This function must insert the node "child" into the list of children of "parent" immediately before the node "ref_child", and place a pointer to the newly-inserted node in *result. If the node "child" is a text node, and the node "ref_child" or the node before "ref_child" is also a text node, then instead the text of "child" must be prepended to the text of "ref_child", or appended to the text of node before "ref_node", and a pointer to the node thus appended to must be placed in *result. In any case, the reference count of the node pointed to by *result at the end of these steps must be incremented. | int hubbub_tree_remove_child(void *ctx, | void *parent, | void *child, | void **result); This function must remove the node "child" from the document tree. It must increment the reference count of the node "child", and place a pointer to the newly-removed node in *result. | int hubbub_tree_reparent_children(void *ctx, | void *node, | void *new_parent); This function must detach all children from "node" and insert them into "new_parent" in the same order as they were found in "node". | int hubbub_tree_get_parent(void *ctx, | void *node, | bool element_only, | void **result); This function must retrieve the parent of "node". If there is no parent node, then NULL must be placed in *result. Otherwise, it must increment the reference count of the parent, and place a pointer to the parent in *result. If "element_only" == true and the retrieved parent is not an element node, then act as if no parent exists. | int hubbub_tree_has_children(void *ctx, | void *node, | bool *result); If "node" has any child nodes attached to it, then *result must be set to true. Otherwise, *result must be set to false. | int hubbub_tree_form_associate(void *ctx, | void *form, | void *node); This function must associate "node" with the node "form" (which is the currently active form element). | int hubbub_tree_add_attributes(void *ctx, | void *node, | const hubbub_attribute *attributes, | uint32_t n_attributes); For each attribute in the array "attributes", this function must check to see if there is such an attribute already present on "node". If there is not such an attribute, then the attribute must be added to "node". | int hubbub_tree_set_quirks_mode(void *ctx, | hubbub_quirks_mode mode); This function must set the quirks mode flag of the document to "mode". | int hubbub_tree_encoding_change(void *ctx, | const char *name); This function is called when a meta tag which specifies a charset is seen in the treebuilder. [1] The client is responsible for checking if the encoding the document is being processed as should actually be changed, and if it should, this function should return 1. In this case, the parser instance will return the error code HUBBUB_ENCODINGCHANGE when it returns from parsing the chunk that triggered the encoding change. The parser instance should then be destroyed and a new one created with that encoding specified. [1] http://www.whatwg.org/specs/web-apps/current-work/#in-head netsurf-2.9/hubbub-0.1.2/docs/Updated0000664000175000017500000000010011155563606016211 0ustar vincevinceTreebuilder and tokeniser up-to-date with 10th March 2009 spec. netsurf-2.9/hubbub-0.1.2/test/0000775000175000017500000000000011734430254014733 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/test/regression/0000775000175000017500000000000011734430252017111 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/test/tokeniser3.c0000664000175000017500000003063011476512132017166 0ustar vincevince#include #include #include #include #include #include #include "utils/utils.h" #include "tokeniser/tokeniser.h" #include "testutils.h" typedef struct context { const uint8_t *input; size_t input_len; struct array_list *output; int output_index; size_t char_off; const char *last_start_tag; struct array_list *content_model; bool process_cdata; } context; static void run_test(context *ctx); static hubbub_error token_handler(const hubbub_token *token, void *pw); static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { struct json_object *json; struct array_list *tests; struct lh_entry *entry; char *key; struct json_object *val; int i; context ctx; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } json = json_object_from_file(argv[1]); assert(!is_error(json)); assert(strcmp((char *) ((json_object_get_object(json)->head)->k), "tests") == 0); /* Get array of tests */ tests = json_object_get_array((struct json_object *) (json_object_get_object(json)->head)->v); for (i = 0; i < array_list_length(tests); i++) { /* Get test */ struct json_object *test = (struct json_object *) array_list_get_idx(tests, i); ctx.last_start_tag = NULL; ctx.content_model = NULL; ctx.process_cdata = false; /* Extract settings */ for (entry = json_object_get_object(test)->head; entry; entry = entry->next) { key = (char *) entry->k; val = (struct json_object *) entry->v; if (strcmp(key, "description") == 0) { printf("Test: %s\n", json_object_get_string(val)); } else if (strcmp(key, "input") == 0) { int len; ctx.input = (const uint8_t *) json_object_get_string_len(val, &len); ctx.input_len = len; } else if (strcmp(key, "output") == 0) { ctx.output = json_object_get_array(val); ctx.output_index = 0; ctx.char_off = 0; } else if (strcmp(key, "lastStartTag") == 0) { ctx.last_start_tag = (const char *) json_object_get_string(val); } else if (strcmp(key, "contentModelFlags") == 0) { ctx.content_model = json_object_get_array(val); } else if (strcmp(key, "processCDATA") == 0) { ctx.process_cdata = json_object_get_boolean(val); } } /* And run the test */ run_test(&ctx); } printf("PASS\n"); return 0; } void run_test(context *ctx) { parserutils_inputstream *stream; hubbub_tokeniser *tok; hubbub_tokeniser_optparams params; int i, max_i; size_t j; struct array_list *outputsave = ctx->output; if (ctx->content_model == NULL) { max_i = 1; } else { max_i = array_list_length(ctx->content_model); } /* We test for each of the content models specified */ for (i = 0; i < max_i; i++) { /* Reset expected output */ ctx->output = outputsave; ctx->output_index = 0; ctx->char_off = 0; assert(parserutils_inputstream_create("UTF-8", 0, NULL, myrealloc, NULL, &stream) == PARSERUTILS_OK); assert(hubbub_tokeniser_create(stream, myrealloc, NULL, &tok) == HUBBUB_OK); if (ctx->last_start_tag != NULL) { /* Fake up a start tag, in PCDATA state */ size_t len = strlen(ctx->last_start_tag) + 3; uint8_t *buf = alloca(len); snprintf((char *) buf, len, "<%s>", ctx->last_start_tag); assert(parserutils_inputstream_append(stream, buf, len - 1) == HUBBUB_OK); assert(hubbub_tokeniser_run(tok) == HUBBUB_OK); } if (ctx->process_cdata) { params.process_cdata = ctx->process_cdata; assert(hubbub_tokeniser_setopt(tok, HUBBUB_TOKENISER_PROCESS_CDATA, ¶ms) == HUBBUB_OK); } params.token_handler.handler = token_handler; params.token_handler.pw = ctx; assert(hubbub_tokeniser_setopt(tok, HUBBUB_TOKENISER_TOKEN_HANDLER, ¶ms) == HUBBUB_OK); if (ctx->content_model == NULL) { params.content_model.model = HUBBUB_CONTENT_MODEL_PCDATA; } else { char *cm = json_object_get_string( (struct json_object *) array_list_get_idx(ctx->content_model, i)); if (strcmp(cm, "PCDATA") == 0) { params.content_model.model = HUBBUB_CONTENT_MODEL_PCDATA; } else if (strcmp(cm, "RCDATA") == 0) { params.content_model.model = HUBBUB_CONTENT_MODEL_RCDATA; } else if (strcmp(cm, "CDATA") == 0) { params.content_model.model = HUBBUB_CONTENT_MODEL_CDATA; } else { params.content_model.model = HUBBUB_CONTENT_MODEL_PLAINTEXT; } } assert(hubbub_tokeniser_setopt(tok, HUBBUB_TOKENISER_CONTENT_MODEL, ¶ms) == HUBBUB_OK); printf("Input: '%.*s' (%d)\n", (int) ctx->input_len, (const char *) ctx->input, (int) ctx->input_len); for (j = 0; j < ctx->input_len; j++) { assert(parserutils_inputstream_append(stream, ctx->input + j, 1) == HUBBUB_OK); assert(hubbub_tokeniser_run(tok) == HUBBUB_OK); } assert(parserutils_inputstream_append(stream, NULL, 0) == HUBBUB_OK); assert(hubbub_tokeniser_run(tok) == HUBBUB_OK); hubbub_tokeniser_destroy(tok); parserutils_inputstream_destroy(stream); } } hubbub_error token_handler(const hubbub_token *token, void *pw) { static const char *token_names[] = { "DOCTYPE", "StartTag", "EndTag", "Comment", "Character", "EOF" }; size_t i; context *ctx = (context *) pw; struct json_object *obj = NULL; struct array_list *items; for (; ctx->output_index < array_list_length(ctx->output); ctx->output_index++) { /* Get object for index */ obj = (struct json_object *) array_list_get_idx(ctx->output, ctx->output_index); /* If it's not a string, we've found the expected output */ if (json_object_get_type(obj) != json_type_string) break; /* Otherwise, it must be a parse error */ assert(strcmp(json_object_get_string(obj), "ParseError") == 0); } /* If we've run off the end, this is an error -- the tokeniser has * produced more tokens than expected. We allow for the generation * of a terminating EOF token, however. */ assert("too many tokens" && (ctx->output_index < array_list_length(ctx->output) || token->type == HUBBUB_TOKEN_EOF)); /* Got a terminating EOF -- no error */ if (ctx->output_index >= array_list_length(ctx->output)) return HUBBUB_OK; /* Now increment the output index so we don't re-expect this token */ ctx->output_index++; /* Expected output must be an array */ assert(json_object_get_type(obj) == json_type_array); items = json_object_get_array(obj); printf("got %s: expected %s\n", token_names[token->type], json_object_get_string((struct json_object *) array_list_get_idx(items, 0))); /* Make sure we got the token we expected */ assert(strcmp(token_names[token->type], json_object_get_string((struct json_object *) array_list_get_idx(items, 0))) == 0); switch (token->type) { case HUBBUB_TOKEN_DOCTYPE: { char *expname = json_object_get_string( array_list_get_idx(items, 1)); char *exppub = json_object_get_string( array_list_get_idx(items, 2)); char *expsys = json_object_get_string( array_list_get_idx(items, 3)); bool expquirks = !json_object_get_boolean( array_list_get_idx(items, 4)); const char *gotname = (const char *) token->data.doctype.name.ptr; const char *gotpub, *gotsys; printf("'%.*s' %sids:\n", (int) token->data.doctype.name.len, gotname, token->data.doctype.force_quirks ? "(force-quirks) " : ""); if (token->data.doctype.public_missing) { gotpub = NULL; printf("\tpublic: missing\n"); } else { gotpub = (const char *) token->data.doctype.public_id.ptr; printf("\tpublic: '%.*s' (%d)\n", (int) token->data.doctype.public_id.len, gotpub, (int) token->data.doctype.public_id.len); } if (token->data.doctype.system_missing) { gotsys = NULL; printf("\tsystem: missing\n"); } else { gotsys = (const char *) token->data.doctype.system_id.ptr; printf("\tsystem: '%.*s' (%d)\n", (int) token->data.doctype.system_id.len, gotsys, (int) token->data.doctype.system_id.len); } assert(token->data.doctype.name.len == strlen(expname)); assert(strncmp(gotname, expname, strlen(expname)) == 0); assert((exppub == NULL) == (token->data.doctype.public_missing == true)); if (exppub) { assert(token->data.doctype.public_id.len == strlen(exppub)); assert(strncmp(gotpub, exppub, strlen(exppub)) == 0); } assert((expsys == NULL) == (token->data.doctype.system_missing == true)); if (gotsys) { assert(token->data.doctype.system_id.len == strlen(expsys)); assert(strncmp(gotsys, expsys, strlen(expsys)) == 0); } assert(expquirks == token->data.doctype.force_quirks); } break; case HUBBUB_TOKEN_START_TAG: { char *expname = json_object_get_string( array_list_get_idx(items, 1)); struct lh_entry *expattrs = json_object_get_object( array_list_get_idx(items, 2))->head; bool self_closing = json_object_get_boolean( array_list_get_idx(items, 3)); const char *tagname = (const char *) token->data.tag.name.ptr; printf("expected: '%s' %s\n", expname, (self_closing) ? "(self-closing) " : ""); printf(" got: '%.*s' %s\n", (int) token->data.tag.name.len, tagname, (token->data.tag.self_closing) ? "(self-closing) " : ""); if (token->data.tag.n_attributes > 0) { printf("attributes:\n"); } assert(token->data.tag.name.len == strlen(expname)); assert(strncmp(tagname, expname, strlen(expname)) == 0); assert((token->data.tag.n_attributes == 0) == (expattrs == NULL)); assert(self_closing == token->data.tag.self_closing); for (i = 0; i < token->data.tag.n_attributes; i++) { char *expname = (char *) expattrs->k; char *expval = json_object_get_string( (struct json_object *) expattrs->v); const char *gotname = (const char *) token->data.tag.attributes[i].name.ptr; size_t namelen = token->data.tag.attributes[i].name.len; const char *gotval = (const char *) token->data.tag.attributes[i].value.ptr; size_t vallen = token->data.tag.attributes[i].value.len; printf("\t'%.*s' = '%.*s'\n", (int) namelen, gotname, (int) vallen, gotval); assert(namelen == strlen(expname)); assert(strncmp(gotname, expname, strlen(expname)) == 0); assert(vallen == strlen(expval)); assert(strncmp(gotval, expval, strlen(expval)) == 0); expattrs = expattrs->next; } assert(expattrs == NULL); } break; case HUBBUB_TOKEN_END_TAG: { char *expname = json_object_get_string( array_list_get_idx(items, 1)); const char *tagname = (const char *) token->data.tag.name.ptr; printf("'%.*s' %s\n", (int) token->data.tag.name.len, tagname, (token->data.tag.n_attributes > 0) ? "attributes:" : ""); assert(token->data.tag.name.len == strlen(expname)); assert(strncmp(tagname, expname, strlen(expname)) == 0); } break; case HUBBUB_TOKEN_COMMENT: { char *expstr = json_object_get_string( array_list_get_idx(items, 1)); const char *gotstr = (const char *) token->data.comment.ptr; printf("expected: '%s'\n", expstr); printf(" got: '%.*s'\n", (int) token->data.comment.len, gotstr); assert(token->data.comment.len == strlen(expstr)); assert(strncmp(gotstr, expstr, strlen(expstr)) == 0); } break; case HUBBUB_TOKEN_CHARACTER: { int expstrlen; char *expstr = json_object_get_string_len( array_list_get_idx(items, 1), &expstrlen); const char *gotstr = (const char *) token->data.character.ptr; size_t len = min(token->data.character.len, expstrlen - ctx->char_off); printf("expected: '%.*s'\n", (int) len, expstr + ctx->char_off); printf(" got: '%.*s'\n", (int) token->data.character.len, gotstr); assert(memcmp(gotstr, expstr + ctx->char_off, len) == 0); if (len < token->data.character.len) { /* Expected token only contained part of the data * Calculate how much is left, then try again with * the next expected token */ hubbub_token t; t.type = HUBBUB_TOKEN_CHARACTER; t.data.character.ptr += len; t.data.character.len -= len; ctx->char_off = 0; token_handler(&t, pw); } else if (strlen(expstr + ctx->char_off) > token->data.character.len) { /* Tokeniser output only contained part of the data * in the expected token; calculate the offset into * the token and process the remainder next time */ ctx->char_off += len; ctx->output_index--; } else { /* Exact match - clear offset */ ctx->char_off = 0; } } break; case HUBBUB_TOKEN_EOF: printf("\n"); break; } return HUBBUB_OK; } netsurf-2.9/hubbub-0.1.2/test/README0000664000175000017500000000450610637320531015615 0ustar vincevinceHubbub testcases ================ Testcases for hubbub are self-contained binaries which test various parts of the hubbub library. These may make use of external data files to drive the testing. Testcase command lines ---------------------- Testcase command lines are in a unified format, thus: [ ] The aliases file parameter will always be specified (as it is required for the library to work at all). The data file parameter is optional and may be provided on a test-by-test basis. Testcase output --------------- Testcases may output anything at all to stdout. The final line of the output must begin with either PASS or FAIL (case sensitive), indicating the success status of the test. Test Index ---------- In the test sources directory, is a file, named INDEX, which provides an index of all available test binaries. Any new test applications should be added to this index as they are created. The test index file format is as follows: file = *line line = ( entry / comment / blank ) LF entry = testname 1*HTAB description [ 1*HTAB datadir ] comment = "#" *non-newline blank = 0 testname = 1*non-reserved description = 1*non-reserved datadir = 1*non-reserved non-newline = VCHAR / WSP non-reserved = VCHAR / SP Each entry contains a mandatory binary name and description followed by an optional data directory specifier. The data directory specifier is used to state the name of the directory containing data files for the test name. This directory will be searched for within the "data" directory in the source tree. If a data directory is specified, the test binary will be invoked for each data file listed within the data directory INDEX, passing the filename as the second parameter (, above). Data Index ---------- Each test data directory contains a file, named INDEX, which provides an index of all available test data files. The data index file format is as follows: file = *line line = ( entry / comment / blank ) LF entry = dataname 1*HTAB description comment = "#" *non-newline blank = 0 dataname = 1*non-reserved description = 1*non-reserved non-newline = VCHAR / WSP non-reserved = VCHAR / SP Each entry contains a mandatory data file name and description. netsurf-2.9/hubbub-0.1.2/test/entities.c0000664000175000017500000000141311476510167016727 0ustar vincevince#include "tokeniser/entities.h" #include "testutils.h" int main(int argc, char **argv) { uint32_t result; int32_t context = -1; UNUSED(argc); UNUSED(argv); assert(hubbub_entities_search_step('A', &result, &context) == HUBBUB_NEEDDATA); assert(hubbub_entities_search_step('E', &result, &context) == HUBBUB_NEEDDATA); assert(hubbub_entities_search_step('l', &result, &context) == HUBBUB_NEEDDATA); assert(hubbub_entities_search_step('i', &result, &context) == HUBBUB_NEEDDATA); assert(hubbub_entities_search_step('g', &result, &context) == HUBBUB_OK); assert(hubbub_entities_search_step(';', &result, &context) == HUBBUB_OK); assert(hubbub_entities_search_step('z', &result, &context) == HUBBUB_INVALID); printf("PASS\n"); return 0; } netsurf-2.9/hubbub-0.1.2/test/tree2.c0000664000175000017500000004650111476512132016125 0ustar vincevince/* * Tree construction tester. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "utils/utils.h" #include "testutils.h" typedef struct attr_t attr_t; typedef struct node_t node_t; typedef struct buf_t buf_t; struct attr_t { hubbub_ns ns; char *name; char *value; }; struct node_t { enum { DOCTYPE, COMMENT, ELEMENT, CHARACTER } type; union { struct { char *name; char *public_id; char *system_id; } doctype; struct { hubbub_ns ns; char *name; attr_t *attrs; size_t n_attrs; } element; char *content; /**< For comments, characters **/ } data; node_t *next; node_t *prev; node_t *child; node_t *parent; uint32_t refcnt; }; struct buf_t { char *buf; size_t len; size_t pos; }; #define NUM_NAMESPACES 7 const char * const ns_names[NUM_NAMESPACES] = { NULL, NULL /*html*/, "math", "svg", "xlink", "xml", "xmlns" }; node_t *Document; static void node_print(buf_t *buf, node_t *node, unsigned depth); static hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result); static hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, void **result); static hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result); static hubbub_error create_text(void *ctx, const hubbub_string *data, void **result); static hubbub_error ref_node(void *ctx, void *node); static hubbub_error unref_node(void *ctx, void *node); static hubbub_error append_child(void *ctx, void *parent, void *child, void **result); static hubbub_error insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result); static hubbub_error remove_child(void *ctx, void *parent, void *child, void **result); static hubbub_error clone_node(void *ctx, void *node, bool deep, void **result); static hubbub_error reparent_children(void *ctx, void *node, void *new_parent); static hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result); static hubbub_error has_children(void *ctx, void *node, bool *result); static hubbub_error form_associate(void *ctx, void *form, void *node); static hubbub_error add_attributes(void *ctx, void *node, const hubbub_attribute *attributes, uint32_t n_attributes); static hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode); static void delete_node(node_t *node); static void delete_attr(attr_t *attr); static hubbub_tree_handler tree_handler = { create_comment, create_doctype, create_element, create_text, ref_node, unref_node, append_child, insert_before, remove_child, clone_node, reparent_children, get_parent, has_children, form_associate, add_attributes, set_quirks_mode, NULL, NULL }; static void *myrealloc(void *ptr, size_t len, void *pw) { void *ret; UNUSED(pw); /* A half-arsed attempt at filling freshly allocated space with junk. */ if (ptr == NULL) { ret = malloc(len); if (ret != NULL) memset(ret, 0xdf, len); } else { ret = realloc(ptr, len); } return ret; } /* * Create, initialise, and return, a parser instance. */ static hubbub_parser *setup_parser(void) { hubbub_parser *parser; hubbub_parser_optparams params; assert(hubbub_parser_create("UTF-8", false, myrealloc, NULL, &parser) == HUBBUB_OK); params.tree_handler = &tree_handler; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_TREE_HANDLER, ¶ms) == HUBBUB_OK); params.document_node = (void *)1; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_DOCUMENT_NODE, ¶ms) == HUBBUB_OK); params.enable_scripting = true; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_ENABLE_SCRIPTING, ¶ms) == HUBBUB_OK); return parser; } /*** Buffer handling bits ***/ static void buf_clear(buf_t *buf) { if (!buf || !buf->buf) return; buf->buf[0] = '\0'; buf->pos = 0; } static void buf_add(buf_t *buf, const char *str) { size_t len = strlen(str) + 1; if (!buf) { printf("%s", str); return; } if (buf->buf == NULL) { buf->len = ((len + 1024) / 1024) * 1024; buf->buf = calloc(1, buf->len); } while (buf->pos + len > buf->len) { buf->len *= 2; buf->buf = realloc(buf->buf, buf->len); } strcat(buf->buf, str); buf->pos += len; } /* States for reading in data from the tree construction file */ enum reading_state { ERASE_DATA, EXPECT_DATA, READING_DATA, READING_DATA_AFTER_FIRST, READING_ERRORS, READING_TREE }; int main(int argc, char **argv) { FILE *fp; char line[2048]; bool reprocess = false; bool passed = true; hubbub_parser *parser = NULL; enum reading_state state = EXPECT_DATA; buf_t expected = { NULL, 0, 0 }; buf_t got = { NULL, 0, 0 }; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Failed opening %s\n", argv[1]); return 1; } /* We rely on lines not being anywhere near 2048 characters... */ while (reprocess || (passed && fgets(line, sizeof line, fp) == line)) { reprocess = false; switch (state) { case ERASE_DATA: buf_clear(&got); buf_clear(&expected); hubbub_parser_destroy(parser); while (Document) { node_t *victim = Document; Document = victim->next; delete_node(victim); } Document = NULL; state = EXPECT_DATA; case EXPECT_DATA: if (strcmp(line, "#data\n") == 0) { parser = setup_parser(); state = READING_DATA; } break; case READING_DATA: case READING_DATA_AFTER_FIRST: if (strcmp(line, "#errors\n") == 0) { assert(hubbub_parser_completed(parser) == HUBBUB_OK); state = READING_ERRORS; } else { size_t len = strlen(line); if (state == READING_DATA_AFTER_FIRST) { assert(hubbub_parser_parse_chunk(parser, (uint8_t *)"\n", 1) == HUBBUB_OK); } else { state = READING_DATA_AFTER_FIRST; } printf(": %s", line); assert(hubbub_parser_parse_chunk(parser, (uint8_t *)line, len - 1) == HUBBUB_OK); } break; case READING_ERRORS: if (strcmp(line, "#document-fragment\n") == 0) { state = ERASE_DATA; reprocess = true; } if (strcmp(line, "#document\n") == 0) state = READING_TREE; else { } break; case READING_TREE: if (strcmp(line, "#data\n") == 0) { node_print(&got, Document, 0); /* Trim off the last newline */ expected.buf[strlen(expected.buf) - 1] = '\0'; passed = !strcmp(got.buf, expected.buf); if (!passed) { printf("expected:\n"); printf("%s", expected.buf); printf("got:\n"); printf("%s", got.buf); } state = ERASE_DATA; reprocess = true; } else { buf_add(&expected, line); } break; } } if (Document != NULL) { node_print(&got, Document, 0); passed = !strcmp(got.buf, expected.buf); if (!passed) { printf("expected:\n"); printf("%s", expected.buf); printf("got:\n"); printf("%s", got.buf); } hubbub_parser_destroy(parser); while (Document) { node_t *victim = Document; Document = victim->next; delete_node(victim); } } printf("%s\n", passed ? "PASS" : "FAIL"); fclose(fp); free(got.buf); free(expected.buf); return 0; } /*** Tree construction functions ***/ hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); node->type = COMMENT; node->data.content = strndup((const char *) data->ptr, data->len); node->refcnt = 1; node->refcnt = 1; *result = node; return HUBBUB_OK; } hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); node->type = DOCTYPE; node->data.doctype.name = strndup( (const char *) doctype->name.ptr, doctype->name.len); if (!doctype->public_missing) { node->data.doctype.public_id = strndup( (const char *) doctype->public_id.ptr, doctype->public_id.len); } if (!doctype->system_missing) { node->data.doctype.system_id = strndup( (const char *) doctype->system_id.ptr, doctype->system_id.len); } node->refcnt = 1; *result = node; return HUBBUB_OK; } hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result) { size_t i; node_t *node = calloc(1, sizeof *node); UNUSED(ctx); assert(tag->ns < NUM_NAMESPACES); node->type = ELEMENT; node->data.element.ns = tag->ns; node->data.element.name = strndup( (const char *) tag->name.ptr, tag->name.len); node->data.element.n_attrs = tag->n_attributes; node->data.element.attrs = calloc(node->data.element.n_attrs, sizeof *node->data.element.attrs); for (i = 0; i < tag->n_attributes; i++) { attr_t *attr = &node->data.element.attrs[i]; assert(tag->attributes[i].ns < NUM_NAMESPACES); attr->ns = tag->attributes[i].ns; attr->name = strndup( (const char *) tag->attributes[i].name.ptr, tag->attributes[i].name.len); attr->value = strndup( (const char *) tag->attributes[i].value.ptr, tag->attributes[i].value.len); } node->refcnt = 1; *result = node; return HUBBUB_OK; } hubbub_error create_text(void *ctx, const hubbub_string *data, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); node->type = CHARACTER; node->data.content = strndup((const char *) data->ptr, data->len); node->refcnt = 1; node->refcnt = 1; *result = node; return HUBBUB_OK; } hubbub_error ref_node(void *ctx, void *node) { node_t *n = node; UNUSED(ctx); if (node != (void *) 1) n->refcnt++; return HUBBUB_OK; } hubbub_error unref_node(void *ctx, void *node) { node_t *n = node; UNUSED(ctx); if (n != (void *) 1) { assert(n->refcnt > 0); n->refcnt--; printf("Unreferencing node %p (%d) [%d : %s]\n", node, n->refcnt, n->type, n->type == ELEMENT ? n->data.element.name : ""); if (n->refcnt == 0 && n->parent == NULL) { delete_node(n); } } return HUBBUB_OK; } hubbub_error append_child(void *ctx, void *parent, void *child, void **result) { node_t *tparent = parent; node_t *tchild = child; node_t *insert = NULL; tchild->next = tchild->prev = NULL; #ifndef NDEBUG printf("appending (%p):\n", (void *) tchild); node_print(NULL, tchild, 0); printf("to:\n"); if (parent != (void *)1) node_print(NULL, tparent, 0); #endif *result = child; if (parent == (void *)1) { if (Document) { insert = Document; } else { Document = tchild; } } else { if (tparent->child == NULL) { tparent->child = tchild; } else { insert = tparent->child; } } if (insert) { while (insert->next != NULL) { insert = insert->next; } if (tchild->type == CHARACTER && insert->type == CHARACTER) { insert->data.content = realloc(insert->data.content, strlen(insert->data.content) + strlen(tchild->data.content) + 1); strcat(insert->data.content, tchild->data.content); *result = insert; } else { insert->next = tchild; tchild->prev = insert; } } if (*result == child) tchild->parent = tparent; ref_node(ctx, *result); return HUBBUB_OK; } /* insert 'child' before 'ref_child', under 'parent' */ hubbub_error insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result) { node_t *tparent = parent; node_t *tchild = child; node_t *tref = ref_child; #ifndef NDEBUG printf("inserting (%p):\n", (void *) tchild); node_print(NULL, tchild, 0); printf("before:\n"); node_print(NULL, tref, 0); printf("under:\n"); if (parent != (void *)1) node_print(NULL, tparent, 0); #endif if (tchild->type == CHARACTER && tref->prev && tref->prev->type == CHARACTER) { node_t *insert = tref->prev; insert->data.content = realloc(insert->data.content, strlen(insert->data.content) + strlen(tchild->data.content) + 1); strcat(insert->data.content, tchild->data.content); *result = insert; } else { tchild->parent = parent; tchild->prev = tref->prev; tchild->next = tref; tref->prev = tchild; if (tchild->prev) tchild->prev->next = tchild; else tparent->child = tchild; *result = child; } ref_node(ctx, *result); return HUBBUB_OK; } hubbub_error remove_child(void *ctx, void *parent, void *child, void **result) { node_t *tparent = parent; node_t *tchild = child; assert(tparent->child); assert(tchild->parent == tparent); printf("Removing child %p\n", child); if (tchild->parent->child == tchild) { tchild->parent->child = tchild->next; } if (tchild->prev) tchild->prev->next = tchild->next; if (tchild->next) tchild->next->prev = tchild->prev; /* now reset all the child's pointers */ tchild->next = tchild->prev = tchild->parent = NULL; *result = child; ref_node(ctx, *result); return HUBBUB_OK; } hubbub_error clone_node(void *ctx, void *node, bool deep, void **result) { node_t *old_node = node; node_t *new_node = calloc(1, sizeof *new_node); node_t *last; node_t *child; size_t i; new_node->type = old_node->type; switch (old_node->type) { case DOCTYPE: new_node->data.doctype.name = strdup(old_node->data.doctype.name); if (old_node->data.doctype.public_id) new_node->data.doctype.public_id = strdup(old_node->data.doctype.public_id); if (old_node->data.doctype.system_id) new_node->data.doctype.system_id = strdup(old_node->data.doctype.system_id); break; case COMMENT: case CHARACTER: new_node->data.content = strdup(old_node->data.content); break; case ELEMENT: new_node->data.element.ns = old_node->data.element.ns; new_node->data.element.name = strdup(old_node->data.element.name); new_node->data.element.attrs = calloc(old_node->data.element.n_attrs, sizeof *new_node->data.element.attrs); for (i = 0; i < old_node->data.element.n_attrs; i++) { attr_t *attr = &new_node->data.element.attrs[i]; attr->ns = old_node->data.element.attrs[i].ns; attr->name = strdup(old_node->data.element.attrs[i].name); attr->value = strdup(old_node->data.element.attrs[i].value); } new_node->data.element.n_attrs = old_node->data.element.n_attrs; break; } *result = new_node; new_node->child = new_node->parent = new_node->next = new_node->prev = NULL; new_node->refcnt = 1; if (deep == false) return 0; last = NULL; for (child = old_node->child; child != NULL; child = child->next) { node_t *n; clone_node(ctx, child, true, (void **) (void *) &n); n->refcnt = 0; if (last == NULL) { new_node->child = n; } else { last->next = n; n->prev = last; } n->parent = new_node; last = n; } return HUBBUB_OK; } /* Take all of the child nodes of "node" and append them to "new_parent" */ hubbub_error reparent_children(void *ctx, void *node, void *new_parent) { node_t *parent = new_parent; node_t *old_parent = node; node_t *insert; node_t *kids; UNUSED(ctx); kids = old_parent->child; if (!kids) return 0; old_parent->child = NULL; insert = parent->child; if (!insert) { parent->child = kids; } else { while (insert->next != NULL) { insert = insert->next; } insert->next = kids; kids->prev = insert; } while (kids) { kids->parent = parent; kids = kids->next; } return HUBBUB_OK; } hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result) { UNUSED(element_only); *result = ((node_t *)node)->parent; if (*result != NULL) ref_node(ctx, *result); return HUBBUB_OK; } hubbub_error has_children(void *ctx, void *node, bool *result) { UNUSED(ctx); *result = ((node_t *)node)->child ? true : false; return HUBBUB_OK; } hubbub_error form_associate(void *ctx, void *form, void *node) { UNUSED(ctx); UNUSED(form); UNUSED(node); return HUBBUB_OK; } hubbub_error add_attributes(void *ctx, void *vnode, const hubbub_attribute *attributes, uint32_t n_attributes) { node_t *node = vnode; size_t old_elems = node->data.element.n_attrs; size_t i; UNUSED(ctx); node->data.element.n_attrs += n_attributes; node->data.element.attrs = realloc(node->data.element.attrs, node->data.element.n_attrs * sizeof *node->data.element.attrs); for (i = 0; i < n_attributes; i++) { attr_t *attr = &node->data.element.attrs[old_elems + i]; assert(attributes[i].ns < NUM_NAMESPACES); attr->ns = attributes[i].ns; attr->name = strndup( (const char *) attributes[i].name.ptr, attributes[i].name.len); attr->value = strndup( (const char *) attributes[i].value.ptr, attributes[i].value.len); } return HUBBUB_OK; } hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode) { UNUSED(ctx); UNUSED(mode); return HUBBUB_OK; } /*** Serialising bits ***/ static int compare_attrs(const void *a, const void *b) { const attr_t *first = a; const attr_t *second = b; return strcmp(first->name, second->name); } static void indent(buf_t *buf, unsigned depth) { unsigned int i; buf_add(buf, "| "); for (i = 0; i < depth; i++) { buf_add(buf, " "); } } static void print_ns(buf_t *buf, hubbub_ns ns) { if (ns_names[ns] != NULL) { buf_add(buf, ns_names[ns]); buf_add(buf, " "); } } static void node_print(buf_t *buf, node_t *node, unsigned depth) { size_t i; if (!node) return; indent(buf, depth); switch (node->type) { case DOCTYPE: buf_add(buf, "data.doctype.name); if (node->data.doctype.public_id || node->data.doctype.system_id) { if (node->data.doctype.public_id) { buf_add(buf, " \""); buf_add(buf, node->data.doctype.public_id); buf_add(buf, "\" "); } else { buf_add(buf, "\"\" "); } if (node->data.doctype.system_id) { buf_add(buf, " \""); buf_add(buf, node->data.doctype.system_id); buf_add(buf, "\""); } else { buf_add(buf, "\"\""); } } buf_add(buf, ">\n"); break; case ELEMENT: buf_add(buf, "<"); print_ns(buf, node->data.element.ns); buf_add(buf, node->data.element.name); buf_add(buf, ">\n"); qsort(node->data.element.attrs, node->data.element.n_attrs, sizeof *node->data.element.attrs, compare_attrs); for (i = 0; i < node->data.element.n_attrs; i++) { indent(buf, depth + 1); print_ns(buf, node->data.element.attrs[i].ns); buf_add(buf, node->data.element.attrs[i].name); buf_add(buf, "="); buf_add(buf, "\""); buf_add(buf, node->data.element.attrs[i].value); buf_add(buf, "\"\n"); } break; case CHARACTER: buf_add(buf, "\""); buf_add(buf, node->data.content); buf_add(buf, "\"\n"); break; case COMMENT: buf_add(buf, "\n"); break; default: printf("Unexpected node type %d\n", node->type); assert(0); } if (node->child) { node_print(buf, node->child, depth + 1); } if (node->next) { node_print(buf, node->next, depth); } } static void delete_node(node_t *node) { size_t i; node_t *c, *d; if (node == NULL) return; if (node->refcnt != 0) { printf("Node %p has non-zero refcount %d\n", (void *) node, node->refcnt); assert(0); } switch (node->type) { case DOCTYPE: free(node->data.doctype.name); free(node->data.doctype.public_id); free(node->data.doctype.system_id); break; case COMMENT: case CHARACTER: free(node->data.content); break; case ELEMENT: free(node->data.element.name); for (i = 0; i < node->data.element.n_attrs; i++) delete_attr(&node->data.element.attrs[i]); free(node->data.element.attrs); break; } for (c = node->child; c != NULL; c = d) { d = c->next; delete_node(c); } memset(node, 0xdf, sizeof(node_t)); free(node); } static void delete_attr(attr_t *attr) { if (attr == NULL) return; free(attr->name); free(attr->value); memset(attr, 0xdf, sizeof(attr_t)); } netsurf-2.9/hubbub-0.1.2/test/parser.c0000664000175000017500000001031711476512132016374 0ustar vincevince#include #include #include #include #include #include "utils/utils.h" #include "testutils.h" static hubbub_error token_handler(const hubbub_token *token, void *pw); static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } static int run_test(int argc, char **argv, unsigned int CHUNK_SIZE) { hubbub_parser *parser; hubbub_parser_optparams params; FILE *fp; size_t len, origlen; uint8_t *buf = alloca(CHUNK_SIZE); const char *charset; hubbub_charset_source cssource; UNUSED(argc); assert(hubbub_parser_create("UTF-8", false, myrealloc, NULL, &parser) == HUBBUB_OK); params.token_handler.handler = token_handler; params.token_handler.pw = NULL; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_TOKEN_HANDLER, ¶ms) == HUBBUB_OK); fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Failed opening %s\n", argv[1]); return 1; } fseek(fp, 0, SEEK_END); origlen = len = ftell(fp); fseek(fp, 0, SEEK_SET); while (len > 0) { ssize_t bytes_read = fread(buf, 1, CHUNK_SIZE, fp); if (bytes_read < 1) break; assert(hubbub_parser_parse_chunk(parser, buf, bytes_read) == HUBBUB_OK); len -= bytes_read; } assert(len == 0); fclose(fp); charset = hubbub_parser_read_charset(parser, &cssource); printf("Charset: %s (from %d)\n", charset, cssource); hubbub_parser_destroy(parser); printf("PASS\n"); return 0; } int main(int argc, char **argv) { int ret; int shift; int offset; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } #define DO_TEST(n) if ((ret = run_test(argc, argv, (n))) != 0) return ret for (shift = 0; (1 << shift) != 16384; shift++) for (offset = 0; offset < 10; offset += 3) DO_TEST((1 << shift) + offset); return 0; #undef DO_TEST } hubbub_error token_handler(const hubbub_token *token, void *pw) { static const char *token_names[] = { "DOCTYPE", "START TAG", "END TAG", "COMMENT", "CHARACTERS", "EOF" }; size_t i; UNUSED(pw); printf("%s: ", token_names[token->type]); switch (token->type) { case HUBBUB_TOKEN_DOCTYPE: printf("'%.*s' %sids:\n", (int) token->data.doctype.name.len, token->data.doctype.name.ptr, token->data.doctype.force_quirks ? "(force-quirks) " : ""); if (token->data.doctype.public_missing) printf("\tpublic: missing\n"); else printf("\tpublic: '%.*s'\n", (int) token->data.doctype.public_id.len, token->data.doctype.public_id.ptr); if (token->data.doctype.system_missing) printf("\tsystem: missing\n"); else printf("\tsystem: '%.*s'\n", (int) token->data.doctype.system_id.len, token->data.doctype.system_id.ptr); break; case HUBBUB_TOKEN_START_TAG: printf("'%.*s' %s%s\n", (int) token->data.tag.name.len, token->data.tag.name.ptr, (token->data.tag.self_closing) ? "(self-closing) " : "", (token->data.tag.n_attributes > 0) ? "attributes:" : ""); for (i = 0; i < token->data.tag.n_attributes; i++) { printf("\t'%.*s' = '%.*s'\n", (int) token->data.tag.attributes[i].name.len, token->data.tag.attributes[i].name.ptr, (int) token->data.tag.attributes[i].value.len, token->data.tag.attributes[i].value.ptr); } break; case HUBBUB_TOKEN_END_TAG: printf("'%.*s' %s%s\n", (int) token->data.tag.name.len, token->data.tag.name.ptr, (token->data.tag.self_closing) ? "(self-closing) " : "", (token->data.tag.n_attributes > 0) ? "attributes:" : ""); for (i = 0; i < token->data.tag.n_attributes; i++) { printf("\t'%.*s' = '%.*s'\n", (int) token->data.tag.attributes[i].name.len, token->data.tag.attributes[i].name.ptr, (int) token->data.tag.attributes[i].value.len, token->data.tag.attributes[i].value.ptr); } break; case HUBBUB_TOKEN_COMMENT: printf("'%.*s'\n", (int) token->data.comment.len, token->data.comment.ptr); break; case HUBBUB_TOKEN_CHARACTER: printf("'%.*s'\n", (int) token->data.character.len, token->data.character.ptr); break; case HUBBUB_TOKEN_EOF: printf("\n"); break; } return HUBBUB_OK; } netsurf-2.9/hubbub-0.1.2/test/data/0000775000175000017500000000000011734430254015644 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/test/data/html/0000775000175000017500000000000011734430254016610 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/test/data/html/isindex.html0000664000175000017500000000020010776300425021132 0ustar vincevince netsurf-2.9/hubbub-0.1.2/test/data/html/mangleme.3.html0000664000175000017500000013301411050600333021412 0ustar vincevince

#errors Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. Line: 1 Col: 20 Unexpected end tag (strong) in table context caused voodoo mode. Line: 1 Col: 20 End tag (strong) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 24 Unexpected end tag (b) in table context caused voodoo mode. Line: 1 Col: 24 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 29 Unexpected end tag (em) in table context caused voodoo mode. Line: 1 Col: 29 End tag (em) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 33 Unexpected end tag (i) in table context caused voodoo mode. Line: 1 Col: 33 End tag (i) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 37 Unexpected end tag (u) in table context caused voodoo mode. Line: 1 Col: 37 End tag (u) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 46 Unexpected end tag (strike) in table context caused voodoo mode. Line: 1 Col: 46 End tag (strike) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 50 Unexpected end tag (s) in table context caused voodoo mode. Line: 1 Col: 50 End tag (s) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 58 Unexpected end tag (blink) in table context caused voodoo mode. Line: 1 Col: 58 Unexpected end tag (blink). Ignored. Line: 1 Col: 63 Unexpected end tag (tt) in table context caused voodoo mode. Line: 1 Col: 63 End tag (tt) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 69 Unexpected end tag (pre) in table context caused voodoo mode. Line: 1 Col: 69 End tag (pre) seen too early. Expected other end tag. Line: 1 Col: 75 Unexpected end tag (big) in table context caused voodoo mode. Line: 1 Col: 75 End tag (big) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 83 Unexpected end tag (small) in table context caused voodoo mode. Line: 1 Col: 83 End tag (small) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 90 Unexpected end tag (font) in table context caused voodoo mode. Line: 1 Col: 90 End tag (font) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 99 Unexpected end tag (select) in table context caused voodoo mode. Line: 1 Col: 99 Unexpected end tag (select). Ignored. Line: 1 Col: 104 Unexpected end tag (h1) in table context caused voodoo mode. Line: 1 Col: 104 End tag (h1) seen too early. Expected other end tag. Line: 1 Col: 109 Unexpected end tag (h2) in table context caused voodoo mode. Line: 1 Col: 109 End tag (h2) seen too early. Expected other end tag. Line: 1 Col: 114 Unexpected end tag (h3) in table context caused voodoo mode. Line: 1 Col: 114 End tag (h3) seen too early. Expected other end tag. Line: 1 Col: 119 Unexpected end tag (h4) in table context caused voodoo mode. Line: 1 Col: 119 End tag (h4) seen too early. Expected other end tag. Line: 1 Col: 124 Unexpected end tag (h5) in table context caused voodoo mode. Line: 1 Col: 124 End tag (h5) seen too early. Expected other end tag. Line: 1 Col: 129 Unexpected end tag (h6) in table context caused voodoo mode. Line: 1 Col: 129 End tag (h6) seen too early. Expected other end tag. Line: 1 Col: 136 Unexpected end tag (body) in the table row phase. Ignored. Line: 1 Col: 141 Unexpected end tag (br) in table context caused voodoo mode. Line: 1 Col: 141 Unexpected end tag (br). Treated as br element. Line: 1 Col: 145 Unexpected end tag (a) in table context caused voodoo mode. Line: 1 Col: 145 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 151 Unexpected end tag (img) in table context caused voodoo mode. Line: 1 Col: 151 This element (img) has no end tag. Line: 1 Col: 159 Unexpected end tag (title) in table context caused voodoo mode. Line: 1 Col: 159 Unexpected end tag (title). Ignored. Line: 1 Col: 166 Unexpected end tag (span) in table context caused voodoo mode. Line: 1 Col: 166 Unexpected end tag (span). Ignored. Line: 1 Col: 174 Unexpected end tag (style) in table context caused voodoo mode. Line: 1 Col: 174 Unexpected end tag (style). Ignored. Line: 1 Col: 183 Unexpected end tag (script) in table context caused voodoo mode. Line: 1 Col: 183 Unexpected end tag (script). Ignored. Line: 1 Col: 196 Unexpected end tag (th). Ignored. Line: 1 Col: 201 Unexpected end tag (td). Ignored. Line: 1 Col: 206 Unexpected end tag (tr). Ignored. Line: 1 Col: 214 This element (frame) has no end tag. Line: 1 Col: 221 This element (area) has no end tag. Line: 1 Col: 228 Unexpected end tag (link). Ignored. Line: 1 Col: 236 This element (param) has no end tag. Line: 1 Col: 241 This element (hr) has no end tag. Line: 1 Col: 249 This element (input) has no end tag. Line: 1 Col: 255 Unexpected end tag (col). Ignored. Line: 1 Col: 262 Unexpected end tag (base). Ignored. Line: 1 Col: 269 Unexpected end tag (meta). Ignored. Line: 1 Col: 280 This element (basefont) has no end tag. Line: 1 Col: 290 This element (bgsound) has no end tag. Line: 1 Col: 298 This element (embed) has no end tag. Line: 1 Col: 307 This element (spacer) has no end tag. Line: 1 Col: 311 Unexpected end tag (p). Ignored. Line: 1 Col: 316 End tag (dd) seen too early. Expected other end tag. Line: 1 Col: 321 End tag (dt) seen too early. Expected other end tag. Line: 1 Col: 331 Unexpected end tag (caption). Ignored. Line: 1 Col: 342 Unexpected end tag (colgroup). Ignored. Line: 1 Col: 350 Unexpected end tag (tbody). Ignored. Line: 1 Col: 358 Unexpected end tag (tfoot). Ignored. Line: 1 Col: 366 Unexpected end tag (thead). Ignored. Line: 1 Col: 376 End tag (address) seen too early. Expected other end tag. Line: 1 Col: 389 End tag (blockquote) seen too early. Expected other end tag. Line: 1 Col: 398 End tag (center) seen too early. Expected other end tag. Line: 1 Col: 404 Unexpected end tag (dir). Ignored. Line: 1 Col: 410 End tag (div) seen too early. Expected other end tag. Line: 1 Col: 415 End tag (dl) seen too early. Expected other end tag. Line: 1 Col: 426 End tag (fieldset) seen too early. Expected other end tag. Line: 1 Col: 436 End tag (listing) seen too early. Expected other end tag. Line: 1 Col: 443 End tag (menu) seen too early. Expected other end tag. Line: 1 Col: 448 End tag (ol) seen too early. Expected other end tag. Line: 1 Col: 453 End tag (ul) seen too early. Expected other end tag. Line: 1 Col: 458 End tag (li) seen too early. Expected other end tag. Line: 1 Col: 465 End tag (nobr) violates step 1, paragraph 1 of the adoption agency algorithm. Line: 1 Col: 471 This element (wbr) has no end tag. Line: 1 Col: 487 End tag (button) seen too early. Expected other end tag. Line: 1 Col: 497 End tag (marquee) seen too early. Expected other end tag. Line: 1 Col: 506 End tag (object) seen too early. Expected other end tag. Line: 1 Col: 524 Unexpected end tag (). Ignored. Line: 1 Col: 524 Unexpected end tag (frameset). Ignored. Line: 1 Col: 531 Unexpected end tag (head). Ignored. Line: 1 Col: 540 Unexpected end tag (iframe). Ignored. Line: 1 Col: 548 This element (image) has no end tag. Line: 1 Col: 558 This element (isindex) has no end tag. Line: 1 Col: 568 Unexpected end tag (noembed). Ignored. Line: 1 Col: 579 Unexpected end tag (noframes). Ignored. Line: 1 Col: 590 Unexpected end tag (noscript). Ignored. Line: 1 Col: 601 Unexpected end tag (optgroup). Ignored. Line: 1 Col: 610 Unexpected end tag (option). Ignored. Line: 1 Col: 622 Unexpected end tag (plaintext). Ignored. Line: 1 Col: 633 Unexpected end tag (textarea). Ignored. #document | | | |
| | | |

#data #errors Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. Line: 1 Col: 10 Expected closing tag. Unexpected end of file. #document | | | netsurf-2.9/hubbub-0.1.2/test/data/tree-construction/regression.dat0000664000175000017500000000271611652212563024213 0ustar vincevince#data

X
#errors #document | | | | | | |
|
| | | "X" | |
| #encoding Windows-1252 #data #encoding iso8859-2 #data #encoding iso8859-2 #data #encoding iso8859-2 #data #encoding iso8859-2 #data

#encoding iso8859-2 #data #encoding iso8859-2 netsurf-2.9/hubbub-0.1.2/test/data/csdetect/regression.dat0000664000175000017500000000005511044347624022316 0ustar vincevince#data
#encoding windows-1252 netsurf-2.9/hubbub-0.1.2/test/data/csdetect/bom.dat0000664000175000017500000000120311047336026020704 0ustar vincevince#data Hello #encoding windows-1252 #data Hello #encoding utf-16le #data Hello #encoding utf-16be #data Hello #encoding utf-16le #data Hello #encoding utf-8 netsurf-2.9/hubbub-0.1.2/test/data/csdetect/INDEX0000664000175000017500000000065611047724627020252 0ustar vincevince# Index file for charset detection tests # # Test Description bom.dat UTF Byte Order Mark detection tests non-ascii-meta.dat Tests for meta charsets claiming to be non-ASCII test-yahoo-jp.dat Yahoo! Japan, from html5lib testcases tests1.dat Assorted tests, including edge cases, from html5lib tests2.dat Further tests from html5lib regression.dat Regression tests overrides.dat Character encoding overrides from 8.2.2.2. netsurf-2.9/hubbub-0.1.2/test/data/tokeniser2/0000775000175000017500000000000011734430254017731 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/test/data/tokeniser2/test3.test0000664000175000017500000054331011155460755021710 0ustar vincevince{"tests": [ {"description":"", "input":"", "output":[]}, {"description":"\\u0000", "input":"\u0000", "output":["ParseError", ["Character", "\uFFFD"]]}, {"description":"\\u0009", "input":"\u0009", "output":[["Character", "\u0009"]]}, {"description":"\\u000A", "input":"\u000A", "output":[["Character", "\u000A"]]}, {"description":"\\u000B", "input":"\u000B", "output":["ParseError", ["Character", "\u000B"]]}, {"description":"\\u000C", "input":"\u000C", "output":[["Character", "\u000C"]]}, {"description":" ", "input":" ", "output":[["Character", " "]]}, {"description":"!", "input":"!", "output":[["Character", "!"]]}, {"description":"\"", "input":"\"", "output":[["Character", "\""]]}, {"description":"%", "input":"%", "output":[["Character", "%"]]}, {"description":"&", "input":"&", "output":[["Character", "&"]]}, {"description":"'", "input":"'", "output":[["Character", "'"]]}, {"description":",", "input":",", "output":[["Character", ","]]}, {"description":"-", "input":"-", "output":[["Character", "-"]]}, {"description":".", "input":".", "output":[["Character", "."]]}, {"description":"/", "input":"/", "output":[["Character", "/"]]}, {"description":"0", "input":"0", "output":[["Character", "0"]]}, {"description":"1", "input":"1", "output":[["Character", "1"]]}, {"description":"9", "input":"9", "output":[["Character", "9"]]}, {"description":";", "input":";", "output":[["Character", ";"]]}, {"description":"<", "input":"<", "output":["ParseError", ["Character", "<"]]}, {"description":"<\\u0000", "input":"<\u0000", "output":["ParseError", "ParseError", ["Character", "<\uFFFD"]]}, {"description":"<\\u0009", "input":"<\u0009", "output":["ParseError", ["Character", "<\u0009"]]}, {"description":"<\\u000A", "input":"<\u000A", "output":["ParseError", ["Character", "<\u000A"]]}, {"description":"<\\u000B", "input":"<\u000B", "output":["ParseError", "ParseError", ["Character", "<\u000B"]]}, {"description":"<\\u000C", "input":"<\u000C", "output":["ParseError", ["Character", "<\u000C"]]}, {"description":"< ", "input":"< ", "output":["ParseError", ["Character", "< "]]}, {"description":"", "input":"", "input":"", "output":[["Comment", ""]]}, {"description":"", "input":"", "output":["ParseError", ["Comment", ""]]}, {"description":"", "input":"", "output":["ParseError", ["Comment", ""]]}, {"description":"", "output":[["Character", "foo"], ["EndTag", "xmp"]]}, {"description":"Bogus comment in [R]CDATA", "contentModelFlags":["RCDATA", "CDATA"], "lastStartTag":"xmp", "input":"foobaz", "output":[["Character", "foobaz"], ["EndTag", "xmp"]]}, {"description":"End tag surrounded by bogus comment in [R]CDATA", "contentModelFlags":["RCDATA", "CDATA"], "lastStartTag":"xmp", "input":"foobaz", "output":[["Character", "foo"], ["EndTag", "xmp"], "ParseError", ["Comment", ""], ["Character", "baz"], ["EndTag", "xmp"]]}, {"description":"Commented entities in RCDATA", "contentModelFlags":["RCDATA"], "lastStartTag":"xmp", "input":" & & ", "output":[["Character", " & & "], ["EndTag", "xmp"]]}, {"description":"Incorrect comment ending sequences in [R]CDATA", "contentModelFlags":["RCDATA", "CDATA"], "lastStartTag":"xmp", "input":"foox--<>", "output":[["Character", "foox--<>"]]} ]} netsurf-2.9/hubbub-0.1.2/test/data/tokeniser2/unicodeChars.test0000664000175000017500000011115711155460755023255 0ustar vincevince{"tests": [ {"description": "Invalid Unicode character U+0001", "input": "\u0001", "output": ["ParseError", ["Character", "\u0001"]]}, {"description": "Invalid Unicode character U+0002", "input": "\u0002", "output": ["ParseError", ["Character", "\u0002"]]}, {"description": "Invalid Unicode character U+0003", "input": "\u0003", "output": ["ParseError", ["Character", "\u0003"]]}, {"description": "Invalid Unicode character U+0004", "input": "\u0004", "output": ["ParseError", ["Character", "\u0004"]]}, {"description": "Invalid Unicode character U+0005", "input": "\u0005", "output": ["ParseError", ["Character", "\u0005"]]}, {"description": "Invalid Unicode character U+0006", "input": "\u0006", "output": ["ParseError", ["Character", "\u0006"]]}, {"description": "Invalid Unicode character U+0007", "input": "\u0007", "output": ["ParseError", ["Character", "\u0007"]]}, {"description": "Invalid Unicode character U+0008", "input": "\u0008", "output": ["ParseError", ["Character", "\u0008"]]}, {"description": "Invalid Unicode character U+000B", "input": "\u000B", "output": ["ParseError", ["Character", "\u000B"]]}, {"description": "Invalid Unicode character U+000E", "input": "\u000E", "output": ["ParseError", ["Character", "\u000E"]]}, {"description": "Invalid Unicode character U+000F", "input": "\u000F", "output": ["ParseError", ["Character", "\u000F"]]}, {"description": "Invalid Unicode character U+0010", "input": "\u0010", "output": ["ParseError", ["Character", "\u0010"]]}, {"description": "Invalid Unicode character U+0011", "input": "\u0011", "output": ["ParseError", ["Character", "\u0011"]]}, {"description": "Invalid Unicode character U+0012", "input": "\u0012", "output": ["ParseError", ["Character", "\u0012"]]}, {"description": "Invalid Unicode character U+0013", "input": "\u0013", "output": ["ParseError", ["Character", "\u0013"]]}, {"description": "Invalid Unicode character U+0014", "input": "\u0014", "output": ["ParseError", ["Character", "\u0014"]]}, {"description": "Invalid Unicode character U+0015", "input": "\u0015", "output": ["ParseError", ["Character", "\u0015"]]}, {"description": "Invalid Unicode character U+0016", "input": "\u0016", "output": ["ParseError", ["Character", "\u0016"]]}, {"description": "Invalid Unicode character U+0017", "input": "\u0017", "output": ["ParseError", ["Character", "\u0017"]]}, {"description": "Invalid Unicode character U+0018", "input": "\u0018", "output": ["ParseError", ["Character", "\u0018"]]}, {"description": "Invalid Unicode character U+0019", "input": "\u0019", "output": ["ParseError", ["Character", "\u0019"]]}, {"description": "Invalid Unicode character U+001A", "input": "\u001A", "output": ["ParseError", ["Character", "\u001A"]]}, {"description": "Invalid Unicode character U+001B", "input": "\u001B", "output": ["ParseError", ["Character", "\u001B"]]}, {"description": "Invalid Unicode character U+001C", "input": "\u001C", "output": ["ParseError", ["Character", "\u001C"]]}, {"description": "Invalid Unicode character U+001D", "input": "\u001D", "output": ["ParseError", ["Character", "\u001D"]]}, {"description": "Invalid Unicode character U+001E", "input": "\u001E", "output": ["ParseError", ["Character", "\u001E"]]}, {"description": "Invalid Unicode character U+001F", "input": "\u001F", "output": ["ParseError", ["Character", "\u001F"]]}, {"description": "Invalid Unicode character U+007F", "input": "\u007F", "output": ["ParseError", ["Character", "\u007F"]]}, {"description": "Invalid Unicode character U+D800", "input": "\uD800", "output": ["ParseError", ["Character", "\uD800"]]}, {"description": "Invalid Unicode character U+DFFF", "input": "\uDFFF", "output": ["ParseError", ["Character", "\uDFFF"]]}, {"description": "Invalid Unicode character U+FDD0", "input": "\uFDD0", "output": ["ParseError", ["Character", "\uFDD0"]]}, {"description": "Invalid Unicode character U+FDD1", "input": "\uFDD1", "output": ["ParseError", ["Character", "\uFDD1"]]}, {"description": "Invalid Unicode character U+FDD2", "input": "\uFDD2", "output": ["ParseError", ["Character", "\uFDD2"]]}, {"description": "Invalid Unicode character U+FDD3", "input": "\uFDD3", "output": ["ParseError", ["Character", "\uFDD3"]]}, {"description": "Invalid Unicode character U+FDD4", "input": "\uFDD4", "output": ["ParseError", ["Character", "\uFDD4"]]}, {"description": "Invalid Unicode character U+FDD5", "input": "\uFDD5", "output": ["ParseError", ["Character", "\uFDD5"]]}, {"description": "Invalid Unicode character U+FDD6", "input": "\uFDD6", "output": ["ParseError", ["Character", "\uFDD6"]]}, {"description": "Invalid Unicode character U+FDD7", "input": "\uFDD7", "output": ["ParseError", ["Character", "\uFDD7"]]}, {"description": "Invalid Unicode character U+FDD8", "input": "\uFDD8", "output": ["ParseError", ["Character", "\uFDD8"]]}, {"description": "Invalid Unicode character U+FDD9", "input": "\uFDD9", "output": ["ParseError", ["Character", "\uFDD9"]]}, {"description": "Invalid Unicode character U+FDDA", "input": "\uFDDA", "output": ["ParseError", ["Character", "\uFDDA"]]}, {"description": "Invalid Unicode character U+FDDB", "input": "\uFDDB", "output": ["ParseError", ["Character", "\uFDDB"]]}, {"description": "Invalid Unicode character U+FDDC", "input": "\uFDDC", "output": ["ParseError", ["Character", "\uFDDC"]]}, {"description": "Invalid Unicode character U+FDDD", "input": "\uFDDD", "output": ["ParseError", ["Character", "\uFDDD"]]}, {"description": "Invalid Unicode character U+FDDE", "input": "\uFDDE", "output": ["ParseError", ["Character", "\uFDDE"]]}, {"description": "Invalid Unicode character U+FDDF", "input": "\uFDDF", "output": ["ParseError", ["Character", "\uFDDF"]]}, {"description": "Invalid Unicode character U+FDE0", "input": "\uFDE0", "output": ["ParseError", ["Character", "\uFDE0"]]}, {"description": "Invalid Unicode character U+FDE1", "input": "\uFDE1", "output": ["ParseError", ["Character", "\uFDE1"]]}, {"description": "Invalid Unicode character U+FDE2", "input": "\uFDE2", "output": ["ParseError", ["Character", "\uFDE2"]]}, {"description": "Invalid Unicode character U+FDE3", "input": "\uFDE3", "output": ["ParseError", ["Character", "\uFDE3"]]}, {"description": "Invalid Unicode character U+FDE4", "input": "\uFDE4", "output": ["ParseError", ["Character", "\uFDE4"]]}, {"description": "Invalid Unicode character U+FDE5", "input": "\uFDE5", "output": ["ParseError", ["Character", "\uFDE5"]]}, {"description": "Invalid Unicode character U+FDE6", "input": "\uFDE6", "output": ["ParseError", ["Character", "\uFDE6"]]}, {"description": "Invalid Unicode character U+FDE7", "input": "\uFDE7", "output": ["ParseError", ["Character", "\uFDE7"]]}, {"description": "Invalid Unicode character U+FDE8", "input": "\uFDE8", "output": ["ParseError", ["Character", "\uFDE8"]]}, {"description": "Invalid Unicode character U+FDE9", "input": "\uFDE9", "output": ["ParseError", ["Character", "\uFDE9"]]}, {"description": "Invalid Unicode character U+FDEA", "input": "\uFDEA", "output": ["ParseError", ["Character", "\uFDEA"]]}, {"description": "Invalid Unicode character U+FDEB", "input": "\uFDEB", "output": ["ParseError", ["Character", "\uFDEB"]]}, {"description": "Invalid Unicode character U+FDEC", "input": "\uFDEC", "output": ["ParseError", ["Character", "\uFDEC"]]}, {"description": "Invalid Unicode character U+FDED", "input": "\uFDED", "output": ["ParseError", ["Character", "\uFDED"]]}, {"description": "Invalid Unicode character U+FDEE", "input": "\uFDEE", "output": ["ParseError", ["Character", "\uFDEE"]]}, {"description": "Invalid Unicode character U+FDEF", "input": "\uFDEF", "output": ["ParseError", ["Character", "\uFDEF"]]}, {"description": "Invalid Unicode character U+FFFE", "input": "\uFFFE", "output": ["ParseError", ["Character", "\uFFFE"]]}, {"description": "Invalid Unicode character U+FFFF", "input": "\uFFFF", "output": ["ParseError", ["Character", "\uFFFF"]]}, {"description": "Invalid Unicode character U+1FFFE", "input": "\uD83F\uDFFE", "output": ["ParseError", ["Character", "\uD83F\uDFFE"]]}, {"description": "Invalid Unicode character U+1FFFF", "input": "\uD83F\uDFFF", "output": ["ParseError", ["Character", "\uD83F\uDFFF"]]}, {"description": "Invalid Unicode character U+2FFFE", "input": "\uD87F\uDFFE", "output": ["ParseError", ["Character", "\uD87F\uDFFE"]]}, {"description": "Invalid Unicode character U+2FFFF", "input": "\uD87F\uDFFF", "output": ["ParseError", ["Character", "\uD87F\uDFFF"]]}, {"description": "Invalid Unicode character U+3FFFE", "input": "\uD8BF\uDFFE", "output": ["ParseError", ["Character", "\uD8BF\uDFFE"]]}, {"description": "Invalid Unicode character U+3FFFF", "input": "\uD8BF\uDFFF", "output": ["ParseError", ["Character", "\uD8BF\uDFFF"]]}, {"description": "Invalid Unicode character U+4FFFE", "input": "\uD8FF\uDFFE", "output": ["ParseError", ["Character", "\uD8FF\uDFFE"]]}, {"description": "Invalid Unicode character U+4FFFF", "input": "\uD8FF\uDFFF", "output": ["ParseError", ["Character", "\uD8FF\uDFFF"]]}, {"description": "Invalid Unicode character U+5FFFE", "input": "\uD93F\uDFFE", "output": ["ParseError", ["Character", "\uD93F\uDFFE"]]}, {"description": "Invalid Unicode character U+5FFFF", "input": "\uD93F\uDFFF", "output": ["ParseError", ["Character", "\uD93F\uDFFF"]]}, {"description": "Invalid Unicode character U+6FFFE", "input": "\uD97F\uDFFE", "output": ["ParseError", ["Character", "\uD97F\uDFFE"]]}, {"description": "Invalid Unicode character U+6FFFF", "input": "\uD97F\uDFFF", "output": ["ParseError", ["Character", "\uD97F\uDFFF"]]}, {"description": "Invalid Unicode character U+7FFFE", "input": "\uD9BF\uDFFE", "output": ["ParseError", ["Character", "\uD9BF\uDFFE"]]}, {"description": "Invalid Unicode character U+7FFFF", "input": "\uD9BF\uDFFF", "output": ["ParseError", ["Character", "\uD9BF\uDFFF"]]}, {"description": "Invalid Unicode character U+8FFFE", "input": "\uD9FF\uDFFE", "output": ["ParseError", ["Character", "\uD9FF\uDFFE"]]}, {"description": "Invalid Unicode character U+8FFFF", "input": "\uD9FF\uDFFF", "output": ["ParseError", ["Character", "\uD9FF\uDFFF"]]}, {"description": "Invalid Unicode character U+9FFFE", "input": "\uDA3F\uDFFE", "output": ["ParseError", ["Character", "\uDA3F\uDFFE"]]}, {"description": "Invalid Unicode character U+9FFFF", "input": "\uDA3F\uDFFF", "output": ["ParseError", ["Character", "\uDA3F\uDFFF"]]}, {"description": "Invalid Unicode character U+AFFFE", "input": "\uDA7F\uDFFE", "output": ["ParseError", ["Character", "\uDA7F\uDFFE"]]}, {"description": "Invalid Unicode character U+AFFFF", "input": "\uDA7F\uDFFF", "output": ["ParseError", ["Character", "\uDA7F\uDFFF"]]}, {"description": "Invalid Unicode character U+BFFFE", "input": "\uDABF\uDFFE", "output": ["ParseError", ["Character", "\uDABF\uDFFE"]]}, {"description": "Invalid Unicode character U+BFFFF", "input": "\uDABF\uDFFF", "output": ["ParseError", ["Character", "\uDABF\uDFFF"]]}, {"description": "Invalid Unicode character U+CFFFE", "input": "\uDAFF\uDFFE", "output": ["ParseError", ["Character", "\uDAFF\uDFFE"]]}, {"description": "Invalid Unicode character U+CFFFF", "input": "\uDAFF\uDFFF", "output": ["ParseError", ["Character", "\uDAFF\uDFFF"]]}, {"description": "Invalid Unicode character U+DFFFE", "input": "\uDB3F\uDFFE", "output": ["ParseError", ["Character", "\uDB3F\uDFFE"]]}, {"description": "Invalid Unicode character U+DFFFF", "input": "\uDB3F\uDFFF", "output": ["ParseError", ["Character", "\uDB3F\uDFFF"]]}, {"description": "Invalid Unicode character U+EFFFE", "input": "\uDB7F\uDFFE", "output": ["ParseError", ["Character", "\uDB7F\uDFFE"]]}, {"description": "Invalid Unicode character U+EFFFF", "input": "\uDB7F\uDFFF", "output": ["ParseError", ["Character", "\uDB7F\uDFFF"]]}, {"description": "Invalid Unicode character U+FFFFE", "input": "\uDBBF\uDFFE", "output": ["ParseError", ["Character", "\uDBBF\uDFFE"]]}, {"description": "Invalid Unicode character U+FFFFF", "input": "\uDBBF\uDFFF", "output": ["ParseError", ["Character", "\uDBBF\uDFFF"]]}, {"description": "Invalid Unicode character U+10FFFE", "input": "\uDBFF\uDFFE", "output": ["ParseError", ["Character", "\uDBFF\uDFFE"]]}, {"description": "Invalid Unicode character U+10FFFF", "input": "\uDBFF\uDFFF", "output": ["ParseError", ["Character", "\uDBFF\uDFFF"]]}, {"description": "Valid Unicode character U+0009", "input": "\u0009", "output": [["Character", "\u0009"]]}, {"description": "Valid Unicode character U+000A", "input": "\u000A", "output": [["Character", "\u000A"]]}, {"description": "Valid Unicode character U+0020", "input": "\u0020", "output": [["Character", "\u0020"]]}, {"description": "Valid Unicode character U+0021", "input": "\u0021", "output": [["Character", "\u0021"]]}, {"description": "Valid Unicode character U+0022", "input": "\u0022", "output": [["Character", "\u0022"]]}, {"description": "Valid Unicode character U+0023", "input": "\u0023", "output": [["Character", "\u0023"]]}, {"description": "Valid Unicode character U+0024", "input": "\u0024", "output": [["Character", "\u0024"]]}, {"description": "Valid Unicode character U+0025", "input": "\u0025", "output": [["Character", "\u0025"]]}, {"description": "Valid Unicode character U+0026", "input": "\u0026", "output": [["Character", "\u0026"]]}, {"description": "Valid Unicode character U+0027", "input": "\u0027", "output": [["Character", "\u0027"]]}, {"description": "Valid Unicode character U+0028", "input": "\u0028", "output": [["Character", "\u0028"]]}, {"description": "Valid Unicode character U+0029", "input": "\u0029", "output": [["Character", "\u0029"]]}, {"description": "Valid Unicode character U+002A", "input": "\u002A", "output": [["Character", "\u002A"]]}, {"description": "Valid Unicode character U+002B", "input": "\u002B", "output": [["Character", "\u002B"]]}, {"description": "Valid Unicode character U+002C", "input": "\u002C", "output": [["Character", "\u002C"]]}, {"description": "Valid Unicode character U+002D", "input": "\u002D", "output": [["Character", "\u002D"]]}, {"description": "Valid Unicode character U+002E", "input": "\u002E", "output": [["Character", "\u002E"]]}, {"description": "Valid Unicode character U+002F", "input": "\u002F", "output": [["Character", "\u002F"]]}, {"description": "Valid Unicode character U+0030", "input": "\u0030", "output": [["Character", "\u0030"]]}, {"description": "Valid Unicode character U+0031", "input": "\u0031", "output": [["Character", "\u0031"]]}, {"description": "Valid Unicode character U+0032", "input": "\u0032", "output": [["Character", "\u0032"]]}, {"description": "Valid Unicode character U+0033", "input": "\u0033", "output": [["Character", "\u0033"]]}, {"description": "Valid Unicode character U+0034", "input": "\u0034", "output": [["Character", "\u0034"]]}, {"description": "Valid Unicode character U+0035", "input": "\u0035", "output": [["Character", "\u0035"]]}, {"description": "Valid Unicode character U+0036", "input": "\u0036", "output": [["Character", "\u0036"]]}, {"description": "Valid Unicode character U+0037", "input": "\u0037", "output": [["Character", "\u0037"]]}, {"description": "Valid Unicode character U+0038", "input": "\u0038", "output": [["Character", "\u0038"]]}, {"description": "Valid Unicode character U+0039", "input": "\u0039", "output": [["Character", "\u0039"]]}, {"description": "Valid Unicode character U+003A", "input": "\u003A", "output": [["Character", "\u003A"]]}, {"description": "Valid Unicode character U+003B", "input": "\u003B", "output": [["Character", "\u003B"]]}, {"description": "Valid Unicode character U+003D", "input": "\u003D", "output": [["Character", "\u003D"]]}, {"description": "Valid Unicode character U+003E", "input": "\u003E", "output": [["Character", "\u003E"]]}, {"description": "Valid Unicode character U+003F", "input": "\u003F", "output": [["Character", "\u003F"]]}, {"description": "Valid Unicode character U+0040", "input": "\u0040", "output": [["Character", "\u0040"]]}, {"description": "Valid Unicode character U+0041", "input": "\u0041", "output": [["Character", "\u0041"]]}, {"description": "Valid Unicode character U+0042", "input": "\u0042", "output": [["Character", "\u0042"]]}, {"description": "Valid Unicode character U+0043", "input": "\u0043", "output": [["Character", "\u0043"]]}, {"description": "Valid Unicode character U+0044", "input": "\u0044", "output": [["Character", "\u0044"]]}, {"description": "Valid Unicode character U+0045", "input": "\u0045", "output": [["Character", "\u0045"]]}, {"description": "Valid Unicode character U+0046", "input": "\u0046", "output": [["Character", "\u0046"]]}, {"description": "Valid Unicode character U+0047", "input": "\u0047", "output": [["Character", "\u0047"]]}, {"description": "Valid Unicode character U+0048", "input": "\u0048", "output": [["Character", "\u0048"]]}, {"description": "Valid Unicode character U+0049", "input": "\u0049", "output": [["Character", "\u0049"]]}, {"description": "Valid Unicode character U+004A", "input": "\u004A", "output": [["Character", "\u004A"]]}, {"description": "Valid Unicode character U+004B", "input": "\u004B", "output": [["Character", "\u004B"]]}, {"description": "Valid Unicode character U+004C", "input": "\u004C", "output": [["Character", "\u004C"]]}, {"description": "Valid Unicode character U+004D", "input": "\u004D", "output": [["Character", "\u004D"]]}, {"description": "Valid Unicode character U+004E", "input": "\u004E", "output": [["Character", "\u004E"]]}, {"description": "Valid Unicode character U+004F", "input": "\u004F", "output": [["Character", "\u004F"]]}, {"description": "Valid Unicode character U+0050", "input": "\u0050", "output": [["Character", "\u0050"]]}, {"description": "Valid Unicode character U+0051", "input": "\u0051", "output": [["Character", "\u0051"]]}, {"description": "Valid Unicode character U+0052", "input": "\u0052", "output": [["Character", "\u0052"]]}, {"description": "Valid Unicode character U+0053", "input": "\u0053", "output": [["Character", "\u0053"]]}, {"description": "Valid Unicode character U+0054", "input": "\u0054", "output": [["Character", "\u0054"]]}, {"description": "Valid Unicode character U+0055", "input": "\u0055", "output": [["Character", "\u0055"]]}, {"description": "Valid Unicode character U+0056", "input": "\u0056", "output": [["Character", "\u0056"]]}, {"description": "Valid Unicode character U+0057", "input": "\u0057", "output": [["Character", "\u0057"]]}, {"description": "Valid Unicode character U+0058", "input": "\u0058", "output": [["Character", "\u0058"]]}, {"description": "Valid Unicode character U+0059", "input": "\u0059", "output": [["Character", "\u0059"]]}, {"description": "Valid Unicode character U+005A", "input": "\u005A", "output": [["Character", "\u005A"]]}, {"description": "Valid Unicode character U+005B", "input": "\u005B", "output": [["Character", "\u005B"]]}, {"description": "Valid Unicode character U+005C", "input": "\u005C", "output": [["Character", "\u005C"]]}, {"description": "Valid Unicode character U+005D", "input": "\u005D", "output": [["Character", "\u005D"]]}, {"description": "Valid Unicode character U+005E", "input": "\u005E", "output": [["Character", "\u005E"]]}, {"description": "Valid Unicode character U+005F", "input": "\u005F", "output": [["Character", "\u005F"]]}, {"description": "Valid Unicode character U+0060", "input": "\u0060", "output": [["Character", "\u0060"]]}, {"description": "Valid Unicode character U+0061", "input": "\u0061", "output": [["Character", "\u0061"]]}, {"description": "Valid Unicode character U+0062", "input": "\u0062", "output": [["Character", "\u0062"]]}, {"description": "Valid Unicode character U+0063", "input": "\u0063", "output": [["Character", "\u0063"]]}, {"description": "Valid Unicode character U+0064", "input": "\u0064", "output": [["Character", "\u0064"]]}, {"description": "Valid Unicode character U+0065", "input": "\u0065", "output": [["Character", "\u0065"]]}, {"description": "Valid Unicode character U+0066", "input": "\u0066", "output": [["Character", "\u0066"]]}, {"description": "Valid Unicode character U+0067", "input": "\u0067", "output": [["Character", "\u0067"]]}, {"description": "Valid Unicode character U+0068", "input": "\u0068", "output": [["Character", "\u0068"]]}, {"description": "Valid Unicode character U+0069", "input": "\u0069", "output": [["Character", "\u0069"]]}, {"description": "Valid Unicode character U+006A", "input": "\u006A", "output": [["Character", "\u006A"]]}, {"description": "Valid Unicode character U+006B", "input": "\u006B", "output": [["Character", "\u006B"]]}, {"description": "Valid Unicode character U+006C", "input": "\u006C", "output": [["Character", "\u006C"]]}, {"description": "Valid Unicode character U+006D", "input": "\u006D", "output": [["Character", "\u006D"]]}, {"description": "Valid Unicode character U+006E", "input": "\u006E", "output": [["Character", "\u006E"]]}, {"description": "Valid Unicode character U+006F", "input": "\u006F", "output": [["Character", "\u006F"]]}, {"description": "Valid Unicode character U+0070", "input": "\u0070", "output": [["Character", "\u0070"]]}, {"description": "Valid Unicode character U+0071", "input": "\u0071", "output": [["Character", "\u0071"]]}, {"description": "Valid Unicode character U+0072", "input": "\u0072", "output": [["Character", "\u0072"]]}, {"description": "Valid Unicode character U+0073", "input": "\u0073", "output": [["Character", "\u0073"]]}, {"description": "Valid Unicode character U+0074", "input": "\u0074", "output": [["Character", "\u0074"]]}, {"description": "Valid Unicode character U+0075", "input": "\u0075", "output": [["Character", "\u0075"]]}, {"description": "Valid Unicode character U+0076", "input": "\u0076", "output": [["Character", "\u0076"]]}, {"description": "Valid Unicode character U+0077", "input": "\u0077", "output": [["Character", "\u0077"]]}, {"description": "Valid Unicode character U+0078", "input": "\u0078", "output": [["Character", "\u0078"]]}, {"description": "Valid Unicode character U+0079", "input": "\u0079", "output": [["Character", "\u0079"]]}, {"description": "Valid Unicode character U+007A", "input": "\u007A", "output": [["Character", "\u007A"]]}, {"description": "Valid Unicode character U+007B", "input": "\u007B", "output": [["Character", "\u007B"]]}, {"description": "Valid Unicode character U+007C", "input": "\u007C", "output": [["Character", "\u007C"]]}, {"description": "Valid Unicode character U+007D", "input": "\u007D", "output": [["Character", "\u007D"]]}, {"description": "Valid Unicode character U+007E", "input": "\u007E", "output": [["Character", "\u007E"]]}, {"description": "Valid Unicode character U+00A0", "input": "\u00A0", "output": [["Character", "\u00A0"]]}, {"description": "Valid Unicode character U+00A1", "input": "\u00A1", "output": [["Character", "\u00A1"]]}, {"description": "Valid Unicode character U+00A2", "input": "\u00A2", "output": [["Character", "\u00A2"]]}, {"description": "Valid Unicode character U+00A3", "input": "\u00A3", "output": [["Character", "\u00A3"]]}, {"description": "Valid Unicode character U+00A4", "input": "\u00A4", "output": [["Character", "\u00A4"]]}, {"description": "Valid Unicode character U+00A5", "input": "\u00A5", "output": [["Character", "\u00A5"]]}, {"description": "Valid Unicode character U+00A6", "input": "\u00A6", "output": [["Character", "\u00A6"]]}, {"description": "Valid Unicode character U+00A7", "input": "\u00A7", "output": [["Character", "\u00A7"]]}, {"description": "Valid Unicode character U+00A8", "input": "\u00A8", "output": [["Character", "\u00A8"]]}, {"description": "Valid Unicode character U+00A9", "input": "\u00A9", "output": [["Character", "\u00A9"]]}, {"description": "Valid Unicode character U+00AA", "input": "\u00AA", "output": [["Character", "\u00AA"]]}, {"description": "Valid Unicode character U+00AB", "input": "\u00AB", "output": [["Character", "\u00AB"]]}, {"description": "Valid Unicode character U+00AC", "input": "\u00AC", "output": [["Character", "\u00AC"]]}, {"description": "Valid Unicode character U+00AD", "input": "\u00AD", "output": [["Character", "\u00AD"]]}, {"description": "Valid Unicode character U+00AE", "input": "\u00AE", "output": [["Character", "\u00AE"]]}, {"description": "Valid Unicode character U+00AF", "input": "\u00AF", "output": [["Character", "\u00AF"]]}, {"description": "Valid Unicode character U+00B0", "input": "\u00B0", "output": [["Character", "\u00B0"]]}, {"description": "Valid Unicode character U+00B1", "input": "\u00B1", "output": [["Character", "\u00B1"]]}, {"description": "Valid Unicode character U+00B2", "input": "\u00B2", "output": [["Character", "\u00B2"]]}, {"description": "Valid Unicode character U+00B3", "input": "\u00B3", "output": [["Character", "\u00B3"]]}, {"description": "Valid Unicode character U+00B4", "input": "\u00B4", "output": [["Character", "\u00B4"]]}, {"description": "Valid Unicode character U+00B5", "input": "\u00B5", "output": [["Character", "\u00B5"]]}, {"description": "Valid Unicode character U+00B6", "input": "\u00B6", "output": [["Character", "\u00B6"]]}, {"description": "Valid Unicode character U+00B7", "input": "\u00B7", "output": [["Character", "\u00B7"]]}, {"description": "Valid Unicode character U+00B8", "input": "\u00B8", "output": [["Character", "\u00B8"]]}, {"description": "Valid Unicode character U+00B9", "input": "\u00B9", "output": [["Character", "\u00B9"]]}, {"description": "Valid Unicode character U+00BA", "input": "\u00BA", "output": [["Character", "\u00BA"]]}, {"description": "Valid Unicode character U+00BB", "input": "\u00BB", "output": [["Character", "\u00BB"]]}, {"description": "Valid Unicode character U+00BC", "input": "\u00BC", "output": [["Character", "\u00BC"]]}, {"description": "Valid Unicode character U+00BD", "input": "\u00BD", "output": [["Character", "\u00BD"]]}, {"description": "Valid Unicode character U+00BE", "input": "\u00BE", "output": [["Character", "\u00BE"]]}, {"description": "Valid Unicode character U+00BF", "input": "\u00BF", "output": [["Character", "\u00BF"]]}, {"description": "Valid Unicode character U+00C0", "input": "\u00C0", "output": [["Character", "\u00C0"]]}, {"description": "Valid Unicode character U+00C1", "input": "\u00C1", "output": [["Character", "\u00C1"]]}, {"description": "Valid Unicode character U+00C2", "input": "\u00C2", "output": [["Character", "\u00C2"]]}, {"description": "Valid Unicode character U+00C3", "input": "\u00C3", "output": [["Character", "\u00C3"]]}, {"description": "Valid Unicode character U+00C4", "input": "\u00C4", "output": [["Character", "\u00C4"]]}, {"description": "Valid Unicode character U+00C5", "input": "\u00C5", "output": [["Character", "\u00C5"]]}, {"description": "Valid Unicode character U+00C6", "input": "\u00C6", "output": [["Character", "\u00C6"]]}, {"description": "Valid Unicode character U+00C7", "input": "\u00C7", "output": [["Character", "\u00C7"]]}, {"description": "Valid Unicode character U+00C8", "input": "\u00C8", "output": [["Character", "\u00C8"]]}, {"description": "Valid Unicode character U+00C9", "input": "\u00C9", "output": [["Character", "\u00C9"]]}, {"description": "Valid Unicode character U+00CA", "input": "\u00CA", "output": [["Character", "\u00CA"]]}, {"description": "Valid Unicode character U+00CB", "input": "\u00CB", "output": [["Character", "\u00CB"]]}, {"description": "Valid Unicode character U+00CC", "input": "\u00CC", "output": [["Character", "\u00CC"]]}, {"description": "Valid Unicode character U+00CD", "input": "\u00CD", "output": [["Character", "\u00CD"]]}, {"description": "Valid Unicode character U+00CE", "input": "\u00CE", "output": [["Character", "\u00CE"]]}, {"description": "Valid Unicode character U+00CF", "input": "\u00CF", "output": [["Character", "\u00CF"]]}, {"description": "Valid Unicode character U+00D0", "input": "\u00D0", "output": [["Character", "\u00D0"]]}, {"description": "Valid Unicode character U+00D1", "input": "\u00D1", "output": [["Character", "\u00D1"]]}, {"description": "Valid Unicode character U+00D2", "input": "\u00D2", "output": [["Character", "\u00D2"]]}, {"description": "Valid Unicode character U+00D3", "input": "\u00D3", "output": [["Character", "\u00D3"]]}, {"description": "Valid Unicode character U+00D4", "input": "\u00D4", "output": [["Character", "\u00D4"]]}, {"description": "Valid Unicode character U+00D5", "input": "\u00D5", "output": [["Character", "\u00D5"]]}, {"description": "Valid Unicode character U+00D6", "input": "\u00D6", "output": [["Character", "\u00D6"]]}, {"description": "Valid Unicode character U+00D7", "input": "\u00D7", "output": [["Character", "\u00D7"]]}, {"description": "Valid Unicode character U+00D8", "input": "\u00D8", "output": [["Character", "\u00D8"]]}, {"description": "Valid Unicode character U+00D9", "input": "\u00D9", "output": [["Character", "\u00D9"]]}, {"description": "Valid Unicode character U+00DA", "input": "\u00DA", "output": [["Character", "\u00DA"]]}, {"description": "Valid Unicode character U+00DB", "input": "\u00DB", "output": [["Character", "\u00DB"]]}, {"description": "Valid Unicode character U+00DC", "input": "\u00DC", "output": [["Character", "\u00DC"]]}, {"description": "Valid Unicode character U+00DD", "input": "\u00DD", "output": [["Character", "\u00DD"]]}, {"description": "Valid Unicode character U+00DE", "input": "\u00DE", "output": [["Character", "\u00DE"]]}, {"description": "Valid Unicode character U+00DF", "input": "\u00DF", "output": [["Character", "\u00DF"]]}, {"description": "Valid Unicode character U+00E0", "input": "\u00E0", "output": [["Character", "\u00E0"]]}, {"description": "Valid Unicode character U+00E1", "input": "\u00E1", "output": [["Character", "\u00E1"]]}, {"description": "Valid Unicode character U+00E2", "input": "\u00E2", "output": [["Character", "\u00E2"]]}, {"description": "Valid Unicode character U+00E3", "input": "\u00E3", "output": [["Character", "\u00E3"]]}, {"description": "Valid Unicode character U+00E4", "input": "\u00E4", "output": [["Character", "\u00E4"]]}, {"description": "Valid Unicode character U+00E5", "input": "\u00E5", "output": [["Character", "\u00E5"]]}, {"description": "Valid Unicode character U+00E6", "input": "\u00E6", "output": [["Character", "\u00E6"]]}, {"description": "Valid Unicode character U+00E7", "input": "\u00E7", "output": [["Character", "\u00E7"]]}, {"description": "Valid Unicode character U+00E8", "input": "\u00E8", "output": [["Character", "\u00E8"]]}, {"description": "Valid Unicode character U+00E9", "input": "\u00E9", "output": [["Character", "\u00E9"]]}, {"description": "Valid Unicode character U+00EA", "input": "\u00EA", "output": [["Character", "\u00EA"]]}, {"description": "Valid Unicode character U+00EB", "input": "\u00EB", "output": [["Character", "\u00EB"]]}, {"description": "Valid Unicode character U+00EC", "input": "\u00EC", "output": [["Character", "\u00EC"]]}, {"description": "Valid Unicode character U+00ED", "input": "\u00ED", "output": [["Character", "\u00ED"]]}, {"description": "Valid Unicode character U+00EE", "input": "\u00EE", "output": [["Character", "\u00EE"]]}, {"description": "Valid Unicode character U+00EF", "input": "\u00EF", "output": [["Character", "\u00EF"]]}, {"description": "Valid Unicode character U+00F0", "input": "\u00F0", "output": [["Character", "\u00F0"]]}, {"description": "Valid Unicode character U+00F1", "input": "\u00F1", "output": [["Character", "\u00F1"]]}, {"description": "Valid Unicode character U+00F2", "input": "\u00F2", "output": [["Character", "\u00F2"]]}, {"description": "Valid Unicode character U+00F3", "input": "\u00F3", "output": [["Character", "\u00F3"]]}, {"description": "Valid Unicode character U+00F4", "input": "\u00F4", "output": [["Character", "\u00F4"]]}, {"description": "Valid Unicode character U+00F5", "input": "\u00F5", "output": [["Character", "\u00F5"]]}, {"description": "Valid Unicode character U+00F6", "input": "\u00F6", "output": [["Character", "\u00F6"]]}, {"description": "Valid Unicode character U+00F7", "input": "\u00F7", "output": [["Character", "\u00F7"]]}, {"description": "Valid Unicode character U+00F8", "input": "\u00F8", "output": [["Character", "\u00F8"]]}, {"description": "Valid Unicode character U+00F9", "input": "\u00F9", "output": [["Character", "\u00F9"]]}, {"description": "Valid Unicode character U+00FA", "input": "\u00FA", "output": [["Character", "\u00FA"]]}, {"description": "Valid Unicode character U+00FB", "input": "\u00FB", "output": [["Character", "\u00FB"]]}, {"description": "Valid Unicode character U+00FC", "input": "\u00FC", "output": [["Character", "\u00FC"]]}, {"description": "Valid Unicode character U+00FD", "input": "\u00FD", "output": [["Character", "\u00FD"]]}, {"description": "Valid Unicode character U+00FE", "input": "\u00FE", "output": [["Character", "\u00FE"]]}, {"description": "Valid Unicode character U+00FF", "input": "\u00FF", "output": [["Character", "\u00FF"]]}, {"description": "Valid Unicode character U+D7FF", "input": "\uD7FF", "output": [["Character", "\uD7FF"]]}, {"description": "Valid Unicode character U+E000", "input": "\uE000", "output": [["Character", "\uE000"]]}, {"description": "Valid Unicode character U+FDCF", "input": "\uFDCF", "output": [["Character", "\uFDCF"]]}, {"description": "Valid Unicode character U+FDF0", "input": "\uFDF0", "output": [["Character", "\uFDF0"]]}, {"description": "Valid Unicode character U+FFFD", "input": "\uFFFD", "output": [["Character", "\uFFFD"]]}, {"description": "Valid Unicode character U+10000", "input": "\uD800\uDC00", "output": [["Character", "\uD800\uDC00"]]}, {"description": "Valid Unicode character U+1FFFD", "input": "\uD83F\uDFFD", "output": [["Character", "\uD83F\uDFFD"]]}, {"description": "Valid Unicode character U+20000", "input": "\uD840\uDC00", "output": [["Character", "\uD840\uDC00"]]}, {"description": "Valid Unicode character U+2FFFD", "input": "\uD87F\uDFFD", "output": [["Character", "\uD87F\uDFFD"]]}, {"description": "Valid Unicode character U+30000", "input": "\uD880\uDC00", "output": [["Character", "\uD880\uDC00"]]}, {"description": "Valid Unicode character U+3FFFD", "input": "\uD8BF\uDFFD", "output": [["Character", "\uD8BF\uDFFD"]]}, {"description": "Valid Unicode character U+40000", "input": "\uD8C0\uDC00", "output": [["Character", "\uD8C0\uDC00"]]}, {"description": "Valid Unicode character U+4FFFD", "input": "\uD8FF\uDFFD", "output": [["Character", "\uD8FF\uDFFD"]]}, {"description": "Valid Unicode character U+50000", "input": "\uD900\uDC00", "output": [["Character", "\uD900\uDC00"]]}, {"description": "Valid Unicode character U+5FFFD", "input": "\uD93F\uDFFD", "output": [["Character", "\uD93F\uDFFD"]]}, {"description": "Valid Unicode character U+60000", "input": "\uD940\uDC00", "output": [["Character", "\uD940\uDC00"]]}, {"description": "Valid Unicode character U+6FFFD", "input": "\uD97F\uDFFD", "output": [["Character", "\uD97F\uDFFD"]]}, {"description": "Valid Unicode character U+70000", "input": "\uD980\uDC00", "output": [["Character", "\uD980\uDC00"]]}, {"description": "Valid Unicode character U+7FFFD", "input": "\uD9BF\uDFFD", "output": [["Character", "\uD9BF\uDFFD"]]}, {"description": "Valid Unicode character U+80000", "input": "\uD9C0\uDC00", "output": [["Character", "\uD9C0\uDC00"]]}, {"description": "Valid Unicode character U+8FFFD", "input": "\uD9FF\uDFFD", "output": [["Character", "\uD9FF\uDFFD"]]}, {"description": "Valid Unicode character U+90000", "input": "\uDA00\uDC00", "output": [["Character", "\uDA00\uDC00"]]}, {"description": "Valid Unicode character U+9FFFD", "input": "\uDA3F\uDFFD", "output": [["Character", "\uDA3F\uDFFD"]]}, {"description": "Valid Unicode character U+A0000", "input": "\uDA40\uDC00", "output": [["Character", "\uDA40\uDC00"]]}, {"description": "Valid Unicode character U+AFFFD", "input": "\uDA7F\uDFFD", "output": [["Character", "\uDA7F\uDFFD"]]}, {"description": "Valid Unicode character U+B0000", "input": "\uDA80\uDC00", "output": [["Character", "\uDA80\uDC00"]]}, {"description": "Valid Unicode character U+BFFFD", "input": "\uDABF\uDFFD", "output": [["Character", "\uDABF\uDFFD"]]}, {"description": "Valid Unicode character U+C0000", "input": "\uDAC0\uDC00", "output": [["Character", "\uDAC0\uDC00"]]}, {"description": "Valid Unicode character U+CFFFD", "input": "\uDAFF\uDFFD", "output": [["Character", "\uDAFF\uDFFD"]]}, {"description": "Valid Unicode character U+D0000", "input": "\uDB00\uDC00", "output": [["Character", "\uDB00\uDC00"]]}, {"description": "Valid Unicode character U+DFFFD", "input": "\uDB3F\uDFFD", "output": [["Character", "\uDB3F\uDFFD"]]}, {"description": "Valid Unicode character U+E0000", "input": "\uDB40\uDC00", "output": [["Character", "\uDB40\uDC00"]]}, {"description": "Valid Unicode character U+EFFFD", "input": "\uDB7F\uDFFD", "output": [["Character", "\uDB7F\uDFFD"]]}, {"description": "Valid Unicode character U+F0000", "input": "\uDB80\uDC00", "output": [["Character", "\uDB80\uDC00"]]}, {"description": "Valid Unicode character U+FFFFD", "input": "\uDBBF\uDFFD", "output": [["Character", "\uDBBF\uDFFD"]]}, {"description": "Valid Unicode character U+100000", "input": "\uDBC0\uDC00", "output": [["Character", "\uDBC0\uDC00"]]}, {"description": "Valid Unicode character U+10FFFD", "input": "\uDBFF\uDFFD", "output": [["Character", "\uDBFF\uDFFD"]]} ]} netsurf-2.9/hubbub-0.1.2/test/data/tokeniser2/test2.test0000664000175000017500000001321211155460755021700 0ustar vincevince{"tests": [ {"description":"DOCTYPE without name", "input":"", "output":["ParseError", "ParseError", ["DOCTYPE", "", null, null, false]]}, {"description":"DOCTYPE without space before name", "input":"", "output":["ParseError", ["DOCTYPE", "html", null, null, true]]}, {"description":"Incorrect DOCTYPE without a space before name", "input":"", "output":["ParseError", ["DOCTYPE", "foo", null, null, true]]}, {"description":"DOCTYPE with publicId", "input":"", "output":[["DOCTYPE", "html", "-//W3C//DTD HTML Transitional 4.01//EN", null, true]]}, {"description":"DOCTYPE with EOF after PUBLIC", "input":"", "output":[["DOCTYPE", "html", null, "-//W3C//DTD HTML Transitional 4.01//EN", true]]}, {"description":"DOCTYPE with publicId and systemId", "input":"", "output":[["DOCTYPE", "html", "-//W3C//DTD HTML Transitional 4.01//EN", "-//W3C//DTD HTML Transitional 4.01//EN", true]]}, {"description":"DOCTYPE with > in double-quoted publicId", "input":"x", "output":["ParseError", ["DOCTYPE", "html", "", null, false], ["Character", "x"]]}, {"description":"DOCTYPE with > in single-quoted publicId", "input":"x", "output":["ParseError", ["DOCTYPE", "html", "", null, false], ["Character", "x"]]}, {"description":"DOCTYPE with > in double-quoted systemId", "input":"x", "output":["ParseError", ["DOCTYPE", "html", "foo", "", false], ["Character", "x"]]}, {"description":"DOCTYPE with > in single-quoted systemId", "input":"x", "output":["ParseError", ["DOCTYPE", "html", "foo", "", false], ["Character", "x"]]}, {"description":"Incomplete doctype", "input":"", "output":[["StartTag", "h", { "a":"&" }]]}, {"description":"StartTag containing <", "input":"", "output":[["StartTag", "a", "output":[["StartTag","h",{},true]]}, {"description":"Void element with permitted slash", "input":"
", "output":[["StartTag","br",{},true]]}, {"description":"Void element with permitted slash (with attribute)", "input":"
", "output":[["StartTag","br",{"foo":"bar"},true]]}, {"description":"StartTag containing /", "input":"", "output":["ParseError", ["StartTag", "h", { "a":"b" }]]}, {"description":"Double-quoted attribute value", "input":"", "output":[["StartTag", "h", { "a":"b" }]]}, {"description":"Unescaped ", "output":["ParseError", ["Comment", "1"]]}, {"description":"Simili processing instruction", "input":"", "output":["ParseError", ["Comment", "?namespace"]]}, {"description":"A bogus comment stops at >, even if preceeded by two dashes", "input":"", "output":["ParseError", ["Comment", "?foo--"]]}, {"description":"Unescaped <", "input":"foo < bar", "output":[["Character", "foo "], "ParseError", ["Character", "< bar"]]}, {"description":"Null Byte Replacement", "input":"\u0000", "output":["ParseError", ["Character", "\ufffd"]]}, {"description":"Comment with dash", "input":"", "output":[["Comment", "\n\u2022xyz"]]}, {"description":"CR in CDATA section", "processCDATA":true, "input":"", "output":[["Character", "\n\u2022xyz"]]}, ]} netsurf-2.9/hubbub-0.1.2/test/data/tokeniser2/entities.test0000664000175000017500000022060511025376002022454 0ustar vincevince{"tests": [ {"description": "Undefined named entity in attribute value ending in semicolon and whose name starts with a known entity name.", "input":"", "output": ["ParseError", ["StartTag", "h", {"a": "¬i;"}]]}, {"description": "Named entity: AElig with a semi-colon.", "input":"Æ", "output": [["Character", "\u00C6"]]}, {"description": "Named entity: AElig without a semi-colon.", "input":"Æ", "output": ["ParseError", ["Character", "\u00C6"]]}, {"description": "Named entity: AMP with a semi-colon.", "input":"&", "output": [["Character", "\u0026"]]}, {"description": "Named entity: AMP without a semi-colon.", "input":"&", "output": ["ParseError", ["Character", "\u0026"]]}, {"description": "Named entity: Aacute with a semi-colon.", "input":"Á", "output": [["Character", "\u00C1"]]}, {"description": "Named entity: Aacute without a semi-colon.", "input":"Á", "output": ["ParseError", ["Character", "\u00C1"]]}, {"description": "Named entity: Acirc with a semi-colon.", "input":"Â", "output": [["Character", "\u00C2"]]}, {"description": "Named entity: Acirc without a semi-colon.", "input":"Â", "output": ["ParseError", ["Character", "\u00C2"]]}, {"description": "Named entity: Agrave with a semi-colon.", "input":"À", "output": [["Character", "\u00C0"]]}, {"description": "Named entity: Agrave without a semi-colon.", "input":"À", "output": ["ParseError", ["Character", "\u00C0"]]}, {"description": "Named entity: Alpha with a semi-colon.", "input":"Α", "output": [["Character", "\u0391"]]}, {"description": "Named entity: Aring with a semi-colon.", "input":"Å", "output": [["Character", "\u00C5"]]}, {"description": "Named entity: Aring without a semi-colon.", "input":"Å", "output": ["ParseError", ["Character", "\u00C5"]]}, {"description": "Named entity: Atilde with a semi-colon.", "input":"Ã", "output": [["Character", "\u00C3"]]}, {"description": "Named entity: Atilde without a semi-colon.", "input":"Ã", "output": ["ParseError", ["Character", "\u00C3"]]}, {"description": "Named entity: Auml with a semi-colon.", "input":"Ä", "output": [["Character", "\u00C4"]]}, {"description": "Named entity: Auml without a semi-colon.", "input":"Ä", "output": ["ParseError", ["Character", "\u00C4"]]}, {"description": "Named entity: Beta with a semi-colon.", "input":"Β", "output": [["Character", "\u0392"]]}, {"description": "Named entity: COPY with a semi-colon.", "input":"©", "output": [["Character", "\u00A9"]]}, {"description": "Named entity: COPY without a semi-colon.", "input":"©", "output": ["ParseError", ["Character", "\u00A9"]]}, {"description": "Named entity: Ccedil with a semi-colon.", "input":"Ç", "output": [["Character", "\u00C7"]]}, {"description": "Named entity: Ccedil without a semi-colon.", "input":"Ç", "output": ["ParseError", ["Character", "\u00C7"]]}, {"description": "Named entity: Chi with a semi-colon.", "input":"Χ", "output": [["Character", "\u03A7"]]}, {"description": "Named entity: Dagger with a semi-colon.", "input":"‡", "output": [["Character", "\u2021"]]}, {"description": "Named entity: Delta with a semi-colon.", "input":"Δ", "output": [["Character", "\u0394"]]}, {"description": "Named entity: ETH with a semi-colon.", "input":"Ð", "output": [["Character", "\u00D0"]]}, {"description": "Named entity: ETH without a semi-colon.", "input":"Ð", "output": ["ParseError", ["Character", "\u00D0"]]}, {"description": "Named entity: Eacute with a semi-colon.", "input":"É", "output": [["Character", "\u00C9"]]}, {"description": "Named entity: Eacute without a semi-colon.", "input":"É", "output": ["ParseError", ["Character", "\u00C9"]]}, {"description": "Named entity: Ecirc with a semi-colon.", "input":"Ê", "output": [["Character", "\u00CA"]]}, {"description": "Named entity: Ecirc without a semi-colon.", "input":"Ê", "output": ["ParseError", ["Character", "\u00CA"]]}, {"description": "Named entity: Egrave with a semi-colon.", "input":"È", "output": [["Character", "\u00C8"]]}, {"description": "Named entity: Egrave without a semi-colon.", "input":"È", "output": ["ParseError", ["Character", "\u00C8"]]}, {"description": "Named entity: Epsilon with a semi-colon.", "input":"Ε", "output": [["Character", "\u0395"]]}, {"description": "Named entity: Eta with a semi-colon.", "input":"Η", "output": [["Character", "\u0397"]]}, {"description": "Named entity: Euml with a semi-colon.", "input":"Ë", "output": [["Character", "\u00CB"]]}, {"description": "Named entity: Euml without a semi-colon.", "input":"Ë", "output": ["ParseError", ["Character", "\u00CB"]]}, {"description": "Named entity: GT with a semi-colon.", "input":">", "output": [["Character", "\u003E"]]}, {"description": "Named entity: GT without a semi-colon.", "input":">", "output": ["ParseError", ["Character", "\u003E"]]}, {"description": "Named entity: Gamma with a semi-colon.", "input":"Γ", "output": [["Character", "\u0393"]]}, {"description": "Named entity: Iacute with a semi-colon.", "input":"Í", "output": [["Character", "\u00CD"]]}, {"description": "Named entity: Iacute without a semi-colon.", "input":"Í", "output": ["ParseError", ["Character", "\u00CD"]]}, {"description": "Named entity: Icirc with a semi-colon.", "input":"Î", "output": [["Character", "\u00CE"]]}, {"description": "Named entity: Icirc without a semi-colon.", "input":"Î", "output": ["ParseError", ["Character", "\u00CE"]]}, {"description": "Named entity: Igrave with a semi-colon.", "input":"Ì", "output": [["Character", "\u00CC"]]}, {"description": "Named entity: Igrave without a semi-colon.", "input":"Ì", "output": ["ParseError", ["Character", "\u00CC"]]}, {"description": "Named entity: Iota with a semi-colon.", "input":"Ι", "output": [["Character", "\u0399"]]}, {"description": "Named entity: Iuml with a semi-colon.", "input":"Ï", "output": [["Character", "\u00CF"]]}, {"description": "Named entity: Iuml without a semi-colon.", "input":"Ï", "output": ["ParseError", ["Character", "\u00CF"]]}, {"description": "Named entity: Kappa with a semi-colon.", "input":"Κ", "output": [["Character", "\u039A"]]}, {"description": "Named entity: LT with a semi-colon.", "input":"<", "output": [["Character", "\u003C"]]}, {"description": "Named entity: LT without a semi-colon.", "input":"<", "output": ["ParseError", ["Character", "\u003C"]]}, {"description": "Named entity: Lambda with a semi-colon.", "input":"Λ", "output": [["Character", "\u039B"]]}, {"description": "Named entity: Mu with a semi-colon.", "input":"Μ", "output": [["Character", "\u039C"]]}, {"description": "Named entity: Ntilde with a semi-colon.", "input":"Ñ", "output": [["Character", "\u00D1"]]}, {"description": "Named entity: Ntilde without a semi-colon.", "input":"Ñ", "output": ["ParseError", ["Character", "\u00D1"]]}, {"description": "Named entity: Nu with a semi-colon.", "input":"Ν", "output": [["Character", "\u039D"]]}, {"description": "Named entity: OElig with a semi-colon.", "input":"Œ", "output": [["Character", "\u0152"]]}, {"description": "Named entity: Oacute with a semi-colon.", "input":"Ó", "output": [["Character", "\u00D3"]]}, {"description": "Named entity: Oacute without a semi-colon.", "input":"Ó", "output": ["ParseError", ["Character", "\u00D3"]]}, {"description": "Named entity: Ocirc with a semi-colon.", "input":"Ô", "output": [["Character", "\u00D4"]]}, {"description": "Named entity: Ocirc without a semi-colon.", "input":"Ô", "output": ["ParseError", ["Character", "\u00D4"]]}, {"description": "Named entity: Ograve with a semi-colon.", "input":"Ò", "output": [["Character", "\u00D2"]]}, {"description": "Named entity: Ograve without a semi-colon.", "input":"Ò", "output": ["ParseError", ["Character", "\u00D2"]]}, {"description": "Named entity: Omega with a semi-colon.", "input":"Ω", "output": [["Character", "\u03A9"]]}, {"description": "Named entity: Omicron with a semi-colon.", "input":"Ο", "output": [["Character", "\u039F"]]}, {"description": "Named entity: Oslash with a semi-colon.", "input":"Ø", "output": [["Character", "\u00D8"]]}, {"description": "Named entity: Oslash without a semi-colon.", "input":"Ø", "output": ["ParseError", ["Character", "\u00D8"]]}, {"description": "Named entity: Otilde with a semi-colon.", "input":"Õ", "output": [["Character", "\u00D5"]]}, {"description": "Named entity: Otilde without a semi-colon.", "input":"Õ", "output": ["ParseError", ["Character", "\u00D5"]]}, {"description": "Named entity: Ouml with a semi-colon.", "input":"Ö", "output": [["Character", "\u00D6"]]}, {"description": "Named entity: Ouml without a semi-colon.", "input":"Ö", "output": ["ParseError", ["Character", "\u00D6"]]}, {"description": "Named entity: Phi with a semi-colon.", "input":"Φ", "output": [["Character", "\u03A6"]]}, {"description": "Named entity: Pi with a semi-colon.", "input":"Π", "output": [["Character", "\u03A0"]]}, {"description": "Named entity: Prime with a semi-colon.", "input":"″", "output": [["Character", "\u2033"]]}, {"description": "Named entity: Psi with a semi-colon.", "input":"Ψ", "output": [["Character", "\u03A8"]]}, {"description": "Named entity: QUOT with a semi-colon.", "input":""", "output": [["Character", "\u0022"]]}, {"description": "Named entity: QUOT without a semi-colon.", "input":""", "output": ["ParseError", ["Character", "\u0022"]]}, {"description": "Named entity: REG with a semi-colon.", "input":"®", "output": [["Character", "\u00AE"]]}, {"description": "Named entity: REG without a semi-colon.", "input":"®", "output": ["ParseError", ["Character", "\u00AE"]]}, {"description": "Named entity: Rho with a semi-colon.", "input":"Ρ", "output": [["Character", "\u03A1"]]}, {"description": "Named entity: Scaron with a semi-colon.", "input":"Š", "output": [["Character", "\u0160"]]}, {"description": "Named entity: Sigma with a semi-colon.", "input":"Σ", "output": [["Character", "\u03A3"]]}, {"description": "Named entity: THORN with a semi-colon.", "input":"Þ", "output": [["Character", "\u00DE"]]}, {"description": "Named entity: THORN without a semi-colon.", "input":"Þ", "output": ["ParseError", ["Character", "\u00DE"]]}, {"description": "Named entity: TRADE with a semi-colon.", "input":"™", "output": [["Character", "\u2122"]]}, {"description": "Named entity: Tau with a semi-colon.", "input":"Τ", "output": [["Character", "\u03A4"]]}, {"description": "Named entity: Theta with a semi-colon.", "input":"Θ", "output": [["Character", "\u0398"]]}, {"description": "Named entity: Uacute with a semi-colon.", "input":"Ú", "output": [["Character", "\u00DA"]]}, {"description": "Named entity: Uacute without a semi-colon.", "input":"Ú", "output": ["ParseError", ["Character", "\u00DA"]]}, {"description": "Named entity: Ucirc with a semi-colon.", "input":"Û", "output": [["Character", "\u00DB"]]}, {"description": "Named entity: Ucirc without a semi-colon.", "input":"Û", "output": ["ParseError", ["Character", "\u00DB"]]}, {"description": "Named entity: Ugrave with a semi-colon.", "input":"Ù", "output": [["Character", "\u00D9"]]}, {"description": "Named entity: Ugrave without a semi-colon.", "input":"Ù", "output": ["ParseError", ["Character", "\u00D9"]]}, {"description": "Named entity: Upsilon with a semi-colon.", "input":"Υ", "output": [["Character", "\u03A5"]]}, {"description": "Named entity: Uuml with a semi-colon.", "input":"Ü", "output": [["Character", "\u00DC"]]}, {"description": "Named entity: Uuml without a semi-colon.", "input":"Ü", "output": ["ParseError", ["Character", "\u00DC"]]}, {"description": "Named entity: Xi with a semi-colon.", "input":"Ξ", "output": [["Character", "\u039E"]]}, {"description": "Named entity: Yacute with a semi-colon.", "input":"Ý", "output": [["Character", "\u00DD"]]}, {"description": "Named entity: Yacute without a semi-colon.", "input":"Ý", "output": ["ParseError", ["Character", "\u00DD"]]}, {"description": "Named entity: Yuml with a semi-colon.", "input":"Ÿ", "output": [["Character", "\u0178"]]}, {"description": "Named entity: Zeta with a semi-colon.", "input":"Ζ", "output": [["Character", "\u0396"]]}, {"description": "Named entity: aacute with a semi-colon.", "input":"á", "output": [["Character", "\u00E1"]]}, {"description": "Named entity: aacute without a semi-colon.", "input":"á", "output": ["ParseError", ["Character", "\u00E1"]]}, {"description": "Named entity: acirc with a semi-colon.", "input":"â", "output": [["Character", "\u00E2"]]}, {"description": "Named entity: acirc without a semi-colon.", "input":"â", "output": ["ParseError", ["Character", "\u00E2"]]}, {"description": "Named entity: acute with a semi-colon.", "input":"´", "output": [["Character", "\u00B4"]]}, {"description": "Named entity: acute without a semi-colon.", "input":"´", "output": ["ParseError", ["Character", "\u00B4"]]}, {"description": "Named entity: aelig with a semi-colon.", "input":"æ", "output": [["Character", "\u00E6"]]}, {"description": "Named entity: aelig without a semi-colon.", "input":"æ", "output": ["ParseError", ["Character", "\u00E6"]]}, {"description": "Named entity: agrave with a semi-colon.", "input":"à", "output": [["Character", "\u00E0"]]}, {"description": "Named entity: agrave without a semi-colon.", "input":"à", "output": ["ParseError", ["Character", "\u00E0"]]}, {"description": "Named entity: alefsym with a semi-colon.", "input":"ℵ", "output": [["Character", "\u2135"]]}, {"description": "Named entity: alpha with a semi-colon.", "input":"α", "output": [["Character", "\u03B1"]]}, {"description": "Named entity: amp with a semi-colon.", "input":"&", "output": [["Character", "\u0026"]]}, {"description": "Named entity: amp without a semi-colon.", "input":"&", "output": ["ParseError", ["Character", "\u0026"]]}, {"description": "Named entity: and with a semi-colon.", "input":"∧", "output": [["Character", "\u2227"]]}, {"description": "Named entity: ang with a semi-colon.", "input":"∠", "output": [["Character", "\u2220"]]}, {"description": "Named entity: apos with a semi-colon.", "input":"'", "output": [["Character", "\u0027"]]}, {"description": "Named entity: aring with a semi-colon.", "input":"å", "output": [["Character", "\u00E5"]]}, {"description": "Named entity: aring without a semi-colon.", "input":"å", "output": ["ParseError", ["Character", "\u00E5"]]}, {"description": "Named entity: asymp with a semi-colon.", "input":"≈", "output": [["Character", "\u2248"]]}, {"description": "Named entity: atilde with a semi-colon.", "input":"ã", "output": [["Character", "\u00E3"]]}, {"description": "Named entity: atilde without a semi-colon.", "input":"ã", "output": ["ParseError", ["Character", "\u00E3"]]}, {"description": "Named entity: auml with a semi-colon.", "input":"ä", "output": [["Character", "\u00E4"]]}, {"description": "Named entity: auml without a semi-colon.", "input":"ä", "output": ["ParseError", ["Character", "\u00E4"]]}, {"description": "Named entity: bdquo with a semi-colon.", "input":"„", "output": [["Character", "\u201E"]]}, {"description": "Named entity: beta with a semi-colon.", "input":"β", "output": [["Character", "\u03B2"]]}, {"description": "Named entity: brvbar with a semi-colon.", "input":"¦", "output": [["Character", "\u00A6"]]}, {"description": "Named entity: brvbar without a semi-colon.", "input":"¦", "output": ["ParseError", ["Character", "\u00A6"]]}, {"description": "Named entity: bull with a semi-colon.", "input":"•", "output": [["Character", "\u2022"]]}, {"description": "Named entity: cap with a semi-colon.", "input":"∩", "output": [["Character", "\u2229"]]}, {"description": "Named entity: ccedil with a semi-colon.", "input":"ç", "output": [["Character", "\u00E7"]]}, {"description": "Named entity: ccedil without a semi-colon.", "input":"ç", "output": ["ParseError", ["Character", "\u00E7"]]}, {"description": "Named entity: cedil with a semi-colon.", "input":"¸", "output": [["Character", "\u00B8"]]}, {"description": "Named entity: cedil without a semi-colon.", "input":"¸", "output": ["ParseError", ["Character", "\u00B8"]]}, {"description": "Named entity: cent with a semi-colon.", "input":"¢", "output": [["Character", "\u00A2"]]}, {"description": "Named entity: cent without a semi-colon.", "input":"¢", "output": ["ParseError", ["Character", "\u00A2"]]}, {"description": "Named entity: chi with a semi-colon.", "input":"χ", "output": [["Character", "\u03C7"]]}, {"description": "Named entity: circ with a semi-colon.", "input":"ˆ", "output": [["Character", "\u02C6"]]}, {"description": "Named entity: clubs with a semi-colon.", "input":"♣", "output": [["Character", "\u2663"]]}, {"description": "Named entity: cong with a semi-colon.", "input":"≅", "output": [["Character", "\u2245"]]}, {"description": "Named entity: copy with a semi-colon.", "input":"©", "output": [["Character", "\u00A9"]]}, {"description": "Named entity: copy without a semi-colon.", "input":"©", "output": ["ParseError", ["Character", "\u00A9"]]}, {"description": "Named entity: crarr with a semi-colon.", "input":"↵", "output": [["Character", "\u21B5"]]}, {"description": "Named entity: cup with a semi-colon.", "input":"∪", "output": [["Character", "\u222A"]]}, {"description": "Named entity: curren with a semi-colon.", "input":"¤", "output": [["Character", "\u00A4"]]}, {"description": "Named entity: curren without a semi-colon.", "input":"¤", "output": ["ParseError", ["Character", "\u00A4"]]}, {"description": "Named entity: dArr with a semi-colon.", "input":"⇓", "output": [["Character", "\u21D3"]]}, {"description": "Named entity: dagger with a semi-colon.", "input":"†", "output": [["Character", "\u2020"]]}, {"description": "Named entity: darr with a semi-colon.", "input":"↓", "output": [["Character", "\u2193"]]}, {"description": "Named entity: deg with a semi-colon.", "input":"°", "output": [["Character", "\u00B0"]]}, {"description": "Named entity: deg without a semi-colon.", "input":"°", "output": ["ParseError", ["Character", "\u00B0"]]}, {"description": "Named entity: delta with a semi-colon.", "input":"δ", "output": [["Character", "\u03B4"]]}, {"description": "Named entity: diams with a semi-colon.", "input":"♦", "output": [["Character", "\u2666"]]}, {"description": "Named entity: divide with a semi-colon.", "input":"÷", "output": [["Character", "\u00F7"]]}, {"description": "Named entity: divide without a semi-colon.", "input":"÷", "output": ["ParseError", ["Character", "\u00F7"]]}, {"description": "Named entity: eacute with a semi-colon.", "input":"é", "output": [["Character", "\u00E9"]]}, {"description": "Named entity: eacute without a semi-colon.", "input":"é", "output": ["ParseError", ["Character", "\u00E9"]]}, {"description": "Named entity: ecirc with a semi-colon.", "input":"ê", "output": [["Character", "\u00EA"]]}, {"description": "Named entity: ecirc without a semi-colon.", "input":"ê", "output": ["ParseError", ["Character", "\u00EA"]]}, {"description": "Named entity: egrave with a semi-colon.", "input":"è", "output": [["Character", "\u00E8"]]}, {"description": "Named entity: egrave without a semi-colon.", "input":"è", "output": ["ParseError", ["Character", "\u00E8"]]}, {"description": "Named entity: empty with a semi-colon.", "input":"∅", "output": [["Character", "\u2205"]]}, {"description": "Named entity: emsp with a semi-colon.", "input":" ", "output": [["Character", "\u2003"]]}, {"description": "Named entity: ensp with a semi-colon.", "input":" ", "output": [["Character", "\u2002"]]}, {"description": "Named entity: epsilon with a semi-colon.", "input":"ε", "output": [["Character", "\u03B5"]]}, {"description": "Named entity: equiv with a semi-colon.", "input":"≡", "output": [["Character", "\u2261"]]}, {"description": "Named entity: eta with a semi-colon.", "input":"η", "output": [["Character", "\u03B7"]]}, {"description": "Named entity: eth with a semi-colon.", "input":"ð", "output": [["Character", "\u00F0"]]}, {"description": "Named entity: eth without a semi-colon.", "input":"ð", "output": ["ParseError", ["Character", "\u00F0"]]}, {"description": "Named entity: euml with a semi-colon.", "input":"ë", "output": [["Character", "\u00EB"]]}, {"description": "Named entity: euml without a semi-colon.", "input":"ë", "output": ["ParseError", ["Character", "\u00EB"]]}, {"description": "Named entity: euro with a semi-colon.", "input":"€", "output": [["Character", "\u20AC"]]}, {"description": "Named entity: exist with a semi-colon.", "input":"∃", "output": [["Character", "\u2203"]]}, {"description": "Named entity: fnof with a semi-colon.", "input":"ƒ", "output": [["Character", "\u0192"]]}, {"description": "Named entity: forall with a semi-colon.", "input":"∀", "output": [["Character", "\u2200"]]}, {"description": "Named entity: frac12 with a semi-colon.", "input":"½", "output": [["Character", "\u00BD"]]}, {"description": "Named entity: frac12 without a semi-colon.", "input":"½", "output": ["ParseError", ["Character", "\u00BD"]]}, {"description": "Named entity: frac14 with a semi-colon.", "input":"¼", "output": [["Character", "\u00BC"]]}, {"description": "Named entity: frac14 without a semi-colon.", "input":"¼", "output": ["ParseError", ["Character", "\u00BC"]]}, {"description": "Named entity: frac34 with a semi-colon.", "input":"¾", "output": [["Character", "\u00BE"]]}, {"description": "Named entity: frac34 without a semi-colon.", "input":"¾", "output": ["ParseError", ["Character", "\u00BE"]]}, {"description": "Named entity: frasl with a semi-colon.", "input":"⁄", "output": [["Character", "\u2044"]]}, {"description": "Named entity: gamma with a semi-colon.", "input":"γ", "output": [["Character", "\u03B3"]]}, {"description": "Named entity: ge with a semi-colon.", "input":"≥", "output": [["Character", "\u2265"]]}, {"description": "Named entity: gt with a semi-colon.", "input":">", "output": [["Character", "\u003E"]]}, {"description": "Named entity: gt without a semi-colon.", "input":">", "output": ["ParseError", ["Character", "\u003E"]]}, {"description": "Named entity: hArr with a semi-colon.", "input":"⇔", "output": [["Character", "\u21D4"]]}, {"description": "Named entity: harr with a semi-colon.", "input":"↔", "output": [["Character", "\u2194"]]}, {"description": "Named entity: hearts with a semi-colon.", "input":"♥", "output": [["Character", "\u2665"]]}, {"description": "Named entity: hellip with a semi-colon.", "input":"…", "output": [["Character", "\u2026"]]}, {"description": "Named entity: iacute with a semi-colon.", "input":"í", "output": [["Character", "\u00ED"]]}, {"description": "Named entity: iacute without a semi-colon.", "input":"í", "output": ["ParseError", ["Character", "\u00ED"]]}, {"description": "Named entity: icirc with a semi-colon.", "input":"î", "output": [["Character", "\u00EE"]]}, {"description": "Named entity: icirc without a semi-colon.", "input":"î", "output": ["ParseError", ["Character", "\u00EE"]]}, {"description": "Named entity: iexcl with a semi-colon.", "input":"¡", "output": [["Character", "\u00A1"]]}, {"description": "Named entity: iexcl without a semi-colon.", "input":"¡", "output": ["ParseError", ["Character", "\u00A1"]]}, {"description": "Named entity: igrave with a semi-colon.", "input":"ì", "output": [["Character", "\u00EC"]]}, {"description": "Named entity: igrave without a semi-colon.", "input":"ì", "output": ["ParseError", ["Character", "\u00EC"]]}, {"description": "Named entity: image with a semi-colon.", "input":"ℑ", "output": [["Character", "\u2111"]]}, {"description": "Named entity: infin with a semi-colon.", "input":"∞", "output": [["Character", "\u221E"]]}, {"description": "Named entity: int with a semi-colon.", "input":"∫", "output": [["Character", "\u222B"]]}, {"description": "Named entity: iota with a semi-colon.", "input":"ι", "output": [["Character", "\u03B9"]]}, {"description": "Named entity: iquest with a semi-colon.", "input":"¿", "output": [["Character", "\u00BF"]]}, {"description": "Named entity: iquest without a semi-colon.", "input":"¿", "output": ["ParseError", ["Character", "\u00BF"]]}, {"description": "Named entity: isin with a semi-colon.", "input":"∈", "output": [["Character", "\u2208"]]}, {"description": "Named entity: iuml with a semi-colon.", "input":"ï", "output": [["Character", "\u00EF"]]}, {"description": "Named entity: iuml without a semi-colon.", "input":"ï", "output": ["ParseError", ["Character", "\u00EF"]]}, {"description": "Named entity: kappa with a semi-colon.", "input":"κ", "output": [["Character", "\u03BA"]]}, {"description": "Named entity: lArr with a semi-colon.", "input":"⇐", "output": [["Character", "\u21D0"]]}, {"description": "Named entity: lambda with a semi-colon.", "input":"λ", "output": [["Character", "\u03BB"]]}, {"description": "Named entity: lang with a semi-colon.", "input":"⟨", "output": [["Character", "\u27E8"]]}, {"description": "Named entity: laquo with a semi-colon.", "input":"«", "output": [["Character", "\u00AB"]]}, {"description": "Named entity: laquo without a semi-colon.", "input":"«", "output": ["ParseError", ["Character", "\u00AB"]]}, {"description": "Named entity: larr with a semi-colon.", "input":"←", "output": [["Character", "\u2190"]]}, {"description": "Named entity: lceil with a semi-colon.", "input":"⌈", "output": [["Character", "\u2308"]]}, {"description": "Named entity: ldquo with a semi-colon.", "input":"“", "output": [["Character", "\u201C"]]}, {"description": "Named entity: le with a semi-colon.", "input":"≤", "output": [["Character", "\u2264"]]}, {"description": "Named entity: lfloor with a semi-colon.", "input":"⌊", "output": [["Character", "\u230A"]]}, {"description": "Named entity: lowast with a semi-colon.", "input":"∗", "output": [["Character", "\u2217"]]}, {"description": "Named entity: loz with a semi-colon.", "input":"◊", "output": [["Character", "\u25CA"]]}, {"description": "Named entity: lrm with a semi-colon.", "input":"‎", "output": [["Character", "\u200E"]]}, {"description": "Named entity: lsaquo with a semi-colon.", "input":"‹", "output": [["Character", "\u2039"]]}, {"description": "Named entity: lsquo with a semi-colon.", "input":"‘", "output": [["Character", "\u2018"]]}, {"description": "Named entity: lt with a semi-colon.", "input":"<", "output": [["Character", "\u003C"]]}, {"description": "Named entity: lt without a semi-colon.", "input":"<", "output": ["ParseError", ["Character", "\u003C"]]}, {"description": "Named entity: macr with a semi-colon.", "input":"¯", "output": [["Character", "\u00AF"]]}, {"description": "Named entity: macr without a semi-colon.", "input":"¯", "output": ["ParseError", ["Character", "\u00AF"]]}, {"description": "Named entity: mdash with a semi-colon.", "input":"—", "output": [["Character", "\u2014"]]}, {"description": "Named entity: micro with a semi-colon.", "input":"µ", "output": [["Character", "\u00B5"]]}, {"description": "Named entity: micro without a semi-colon.", "input":"µ", "output": ["ParseError", ["Character", "\u00B5"]]}, {"description": "Named entity: middot with a semi-colon.", "input":"·", "output": [["Character", "\u00B7"]]}, {"description": "Named entity: middot without a semi-colon.", "input":"·", "output": ["ParseError", ["Character", "\u00B7"]]}, {"description": "Named entity: minus with a semi-colon.", "input":"−", "output": [["Character", "\u2212"]]}, {"description": "Named entity: mu with a semi-colon.", "input":"μ", "output": [["Character", "\u03BC"]]}, {"description": "Named entity: nabla with a semi-colon.", "input":"∇", "output": [["Character", "\u2207"]]}, {"description": "Named entity: nbsp with a semi-colon.", "input":" ", "output": [["Character", "\u00A0"]]}, {"description": "Named entity: nbsp without a semi-colon.", "input":" ", "output": ["ParseError", ["Character", "\u00A0"]]}, {"description": "Named entity: ndash with a semi-colon.", "input":"–", "output": [["Character", "\u2013"]]}, {"description": "Named entity: ne with a semi-colon.", "input":"≠", "output": [["Character", "\u2260"]]}, {"description": "Named entity: ni with a semi-colon.", "input":"∋", "output": [["Character", "\u220B"]]}, {"description": "Named entity: not with a semi-colon.", "input":"¬", "output": [["Character", "\u00AC"]]}, {"description": "Named entity: not without a semi-colon.", "input":"¬", "output": ["ParseError", ["Character", "\u00AC"]]}, {"description": "Named entity: notin with a semi-colon.", "input":"∉", "output": [["Character", "\u2209"]]}, {"description": "Named entity: nsub with a semi-colon.", "input":"⊄", "output": [["Character", "\u2284"]]}, {"description": "Named entity: ntilde with a semi-colon.", "input":"ñ", "output": [["Character", "\u00F1"]]}, {"description": "Named entity: ntilde without a semi-colon.", "input":"ñ", "output": ["ParseError", ["Character", "\u00F1"]]}, {"description": "Named entity: nu with a semi-colon.", "input":"ν", "output": [["Character", "\u03BD"]]}, {"description": "Named entity: oacute with a semi-colon.", "input":"ó", "output": [["Character", "\u00F3"]]}, {"description": "Named entity: oacute without a semi-colon.", "input":"ó", "output": ["ParseError", ["Character", "\u00F3"]]}, {"description": "Named entity: ocirc with a semi-colon.", "input":"ô", "output": [["Character", "\u00F4"]]}, {"description": "Named entity: ocirc without a semi-colon.", "input":"ô", "output": ["ParseError", ["Character", "\u00F4"]]}, {"description": "Named entity: oelig with a semi-colon.", "input":"œ", "output": [["Character", "\u0153"]]}, {"description": "Named entity: ograve with a semi-colon.", "input":"ò", "output": [["Character", "\u00F2"]]}, {"description": "Named entity: ograve without a semi-colon.", "input":"ò", "output": ["ParseError", ["Character", "\u00F2"]]}, {"description": "Named entity: oline with a semi-colon.", "input":"‾", "output": [["Character", "\u203E"]]}, {"description": "Named entity: omega with a semi-colon.", "input":"ω", "output": [["Character", "\u03C9"]]}, {"description": "Named entity: omicron with a semi-colon.", "input":"ο", "output": [["Character", "\u03BF"]]}, {"description": "Named entity: oplus with a semi-colon.", "input":"⊕", "output": [["Character", "\u2295"]]}, {"description": "Named entity: or with a semi-colon.", "input":"∨", "output": [["Character", "\u2228"]]}, {"description": "Named entity: ordf with a semi-colon.", "input":"ª", "output": [["Character", "\u00AA"]]}, {"description": "Named entity: ordf without a semi-colon.", "input":"ª", "output": ["ParseError", ["Character", "\u00AA"]]}, {"description": "Named entity: ordm with a semi-colon.", "input":"º", "output": [["Character", "\u00BA"]]}, {"description": "Named entity: ordm without a semi-colon.", "input":"º", "output": ["ParseError", ["Character", "\u00BA"]]}, {"description": "Named entity: oslash with a semi-colon.", "input":"ø", "output": [["Character", "\u00F8"]]}, {"description": "Named entity: oslash without a semi-colon.", "input":"ø", "output": ["ParseError", ["Character", "\u00F8"]]}, {"description": "Named entity: otilde with a semi-colon.", "input":"õ", "output": [["Character", "\u00F5"]]}, {"description": "Named entity: otilde without a semi-colon.", "input":"õ", "output": ["ParseError", ["Character", "\u00F5"]]}, {"description": "Named entity: otimes with a semi-colon.", "input":"⊗", "output": [["Character", "\u2297"]]}, {"description": "Named entity: ouml with a semi-colon.", "input":"ö", "output": [["Character", "\u00F6"]]}, {"description": "Named entity: ouml without a semi-colon.", "input":"ö", "output": ["ParseError", ["Character", "\u00F6"]]}, {"description": "Named entity: para with a semi-colon.", "input":"¶", "output": [["Character", "\u00B6"]]}, {"description": "Named entity: para without a semi-colon.", "input":"¶", "output": ["ParseError", ["Character", "\u00B6"]]}, {"description": "Named entity: part with a semi-colon.", "input":"∂", "output": [["Character", "\u2202"]]}, {"description": "Named entity: permil with a semi-colon.", "input":"‰", "output": [["Character", "\u2030"]]}, {"description": "Named entity: perp with a semi-colon.", "input":"⊥", "output": [["Character", "\u22A5"]]}, {"description": "Named entity: phi with a semi-colon.", "input":"φ", "output": [["Character", "\u03C6"]]}, {"description": "Named entity: pi with a semi-colon.", "input":"π", "output": [["Character", "\u03C0"]]}, {"description": "Named entity: piv with a semi-colon.", "input":"ϖ", "output": [["Character", "\u03D6"]]}, {"description": "Named entity: plusmn with a semi-colon.", "input":"±", "output": [["Character", "\u00B1"]]}, {"description": "Named entity: plusmn without a semi-colon.", "input":"±", "output": ["ParseError", ["Character", "\u00B1"]]}, {"description": "Named entity: pound with a semi-colon.", "input":"£", "output": [["Character", "\u00A3"]]}, {"description": "Named entity: pound without a semi-colon.", "input":"£", "output": ["ParseError", ["Character", "\u00A3"]]}, {"description": "Named entity: prime with a semi-colon.", "input":"′", "output": [["Character", "\u2032"]]}, {"description": "Named entity: prod with a semi-colon.", "input":"∏", "output": [["Character", "\u220F"]]}, {"description": "Named entity: prop with a semi-colon.", "input":"∝", "output": [["Character", "\u221D"]]}, {"description": "Named entity: psi with a semi-colon.", "input":"ψ", "output": [["Character", "\u03C8"]]}, {"description": "Named entity: quot with a semi-colon.", "input":""", "output": [["Character", "\u0022"]]}, {"description": "Named entity: quot without a semi-colon.", "input":""", "output": ["ParseError", ["Character", "\u0022"]]}, {"description": "Named entity: rArr with a semi-colon.", "input":"⇒", "output": [["Character", "\u21D2"]]}, {"description": "Named entity: radic with a semi-colon.", "input":"√", "output": [["Character", "\u221A"]]}, {"description": "Named entity: rang with a semi-colon.", "input":"⟩", "output": [["Character", "\u27E9"]]}, {"description": "Named entity: raquo with a semi-colon.", "input":"»", "output": [["Character", "\u00BB"]]}, {"description": "Named entity: raquo without a semi-colon.", "input":"»", "output": ["ParseError", ["Character", "\u00BB"]]}, {"description": "Named entity: rarr with a semi-colon.", "input":"→", "output": [["Character", "\u2192"]]}, {"description": "Named entity: rceil with a semi-colon.", "input":"⌉", "output": [["Character", "\u2309"]]}, {"description": "Named entity: rdquo with a semi-colon.", "input":"”", "output": [["Character", "\u201D"]]}, {"description": "Named entity: real with a semi-colon.", "input":"ℜ", "output": [["Character", "\u211C"]]}, {"description": "Named entity: reg with a semi-colon.", "input":"®", "output": [["Character", "\u00AE"]]}, {"description": "Named entity: reg without a semi-colon.", "input":"®", "output": ["ParseError", ["Character", "\u00AE"]]}, {"description": "Named entity: rfloor with a semi-colon.", "input":"⌋", "output": [["Character", "\u230B"]]}, {"description": "Named entity: rho with a semi-colon.", "input":"ρ", "output": [["Character", "\u03C1"]]}, {"description": "Named entity: rlm with a semi-colon.", "input":"‏", "output": [["Character", "\u200F"]]}, {"description": "Named entity: rsaquo with a semi-colon.", "input":"›", "output": [["Character", "\u203A"]]}, {"description": "Named entity: rsquo with a semi-colon.", "input":"’", "output": [["Character", "\u2019"]]}, {"description": "Named entity: sbquo with a semi-colon.", "input":"‚", "output": [["Character", "\u201A"]]}, {"description": "Named entity: scaron with a semi-colon.", "input":"š", "output": [["Character", "\u0161"]]}, {"description": "Named entity: sdot with a semi-colon.", "input":"⋅", "output": [["Character", "\u22C5"]]}, {"description": "Named entity: sect with a semi-colon.", "input":"§", "output": [["Character", "\u00A7"]]}, {"description": "Named entity: sect without a semi-colon.", "input":"§", "output": ["ParseError", ["Character", "\u00A7"]]}, {"description": "Named entity: shy with a semi-colon.", "input":"­", "output": [["Character", "\u00AD"]]}, {"description": "Named entity: shy without a semi-colon.", "input":"­", "output": ["ParseError", ["Character", "\u00AD"]]}, {"description": "Named entity: sigma with a semi-colon.", "input":"σ", "output": [["Character", "\u03C3"]]}, {"description": "Named entity: sigmaf with a semi-colon.", "input":"ς", "output": [["Character", "\u03C2"]]}, {"description": "Named entity: sim with a semi-colon.", "input":"∼", "output": [["Character", "\u223C"]]}, {"description": "Named entity: spades with a semi-colon.", "input":"♠", "output": [["Character", "\u2660"]]}, {"description": "Named entity: sub with a semi-colon.", "input":"⊂", "output": [["Character", "\u2282"]]}, {"description": "Named entity: sube with a semi-colon.", "input":"⊆", "output": [["Character", "\u2286"]]}, {"description": "Named entity: sum with a semi-colon.", "input":"∑", "output": [["Character", "\u2211"]]}, {"description": "Named entity: sup1 with a semi-colon.", "input":"¹", "output": [["Character", "\u00B9"]]}, {"description": "Named entity: sup1 without a semi-colon.", "input":"¹", "output": ["ParseError", ["Character", "\u00B9"]]}, {"description": "Named entity: sup2 with a semi-colon.", "input":"²", "output": [["Character", "\u00B2"]]}, {"description": "Named entity: sup2 without a semi-colon.", "input":"²", "output": ["ParseError", ["Character", "\u00B2"]]}, {"description": "Named entity: sup3 with a semi-colon.", "input":"³", "output": [["Character", "\u00B3"]]}, {"description": "Named entity: sup3 without a semi-colon.", "input":"³", "output": ["ParseError", ["Character", "\u00B3"]]}, {"description": "Named entity: sup with a semi-colon.", "input":"⊃", "output": [["Character", "\u2283"]]}, {"description": "Named entity: supe with a semi-colon.", "input":"⊇", "output": [["Character", "\u2287"]]}, {"description": "Named entity: szlig with a semi-colon.", "input":"ß", "output": [["Character", "\u00DF"]]}, {"description": "Named entity: szlig without a semi-colon.", "input":"ß", "output": ["ParseError", ["Character", "\u00DF"]]}, {"description": "Named entity: tau with a semi-colon.", "input":"τ", "output": [["Character", "\u03C4"]]}, {"description": "Named entity: there4 with a semi-colon.", "input":"∴", "output": [["Character", "\u2234"]]}, {"description": "Named entity: theta with a semi-colon.", "input":"θ", "output": [["Character", "\u03B8"]]}, {"description": "Named entity: thetasym with a semi-colon.", "input":"ϑ", "output": [["Character", "\u03D1"]]}, {"description": "Named entity: thinsp with a semi-colon.", "input":" ", "output": [["Character", "\u2009"]]}, {"description": "Named entity: thorn with a semi-colon.", "input":"þ", "output": [["Character", "\u00FE"]]}, {"description": "Named entity: thorn without a semi-colon.", "input":"þ", "output": ["ParseError", ["Character", "\u00FE"]]}, {"description": "Named entity: tilde with a semi-colon.", "input":"˜", "output": [["Character", "\u02DC"]]}, {"description": "Named entity: times with a semi-colon.", "input":"×", "output": [["Character", "\u00D7"]]}, {"description": "Named entity: times without a semi-colon.", "input":"×", "output": ["ParseError", ["Character", "\u00D7"]]}, {"description": "Named entity: trade with a semi-colon.", "input":"™", "output": [["Character", "\u2122"]]}, {"description": "Named entity: uArr with a semi-colon.", "input":"⇑", "output": [["Character", "\u21D1"]]}, {"description": "Named entity: uacute with a semi-colon.", "input":"ú", "output": [["Character", "\u00FA"]]}, {"description": "Named entity: uacute without a semi-colon.", "input":"ú", "output": ["ParseError", ["Character", "\u00FA"]]}, {"description": "Named entity: uarr with a semi-colon.", "input":"↑", "output": [["Character", "\u2191"]]}, {"description": "Named entity: ucirc with a semi-colon.", "input":"û", "output": [["Character", "\u00FB"]]}, {"description": "Named entity: ucirc without a semi-colon.", "input":"û", "output": ["ParseError", ["Character", "\u00FB"]]}, {"description": "Named entity: ugrave with a semi-colon.", "input":"ù", "output": [["Character", "\u00F9"]]}, {"description": "Named entity: ugrave without a semi-colon.", "input":"ù", "output": ["ParseError", ["Character", "\u00F9"]]}, {"description": "Named entity: uml with a semi-colon.", "input":"¨", "output": [["Character", "\u00A8"]]}, {"description": "Named entity: uml without a semi-colon.", "input":"¨", "output": ["ParseError", ["Character", "\u00A8"]]}, {"description": "Named entity: upsih with a semi-colon.", "input":"ϒ", "output": [["Character", "\u03D2"]]}, {"description": "Named entity: upsilon with a semi-colon.", "input":"υ", "output": [["Character", "\u03C5"]]}, {"description": "Named entity: uuml with a semi-colon.", "input":"ü", "output": [["Character", "\u00FC"]]}, {"description": "Named entity: uuml without a semi-colon.", "input":"ü", "output": ["ParseError", ["Character", "\u00FC"]]}, {"description": "Named entity: weierp with a semi-colon.", "input":"℘", "output": [["Character", "\u2118"]]}, {"description": "Named entity: xi with a semi-colon.", "input":"ξ", "output": [["Character", "\u03BE"]]}, {"description": "Named entity: yacute with a semi-colon.", "input":"ý", "output": [["Character", "\u00FD"]]}, {"description": "Named entity: yacute without a semi-colon.", "input":"ý", "output": ["ParseError", ["Character", "\u00FD"]]}, {"description": "Named entity: yen with a semi-colon.", "input":"¥", "output": [["Character", "\u00A5"]]}, {"description": "Named entity: yen without a semi-colon.", "input":"¥", "output": ["ParseError", ["Character", "\u00A5"]]}, {"description": "Named entity: yuml with a semi-colon.", "input":"ÿ", "output": [["Character", "\u00FF"]]}, {"description": "Named entity: yuml without a semi-colon.", "input":"ÿ", "output": ["ParseError", ["Character", "\u00FF"]]}, {"description": "Named entity: zeta with a semi-colon.", "input":"ζ", "output": [["Character", "\u03B6"]]}, {"description": "Named entity: zwj with a semi-colon.", "input":"‍", "output": [["Character", "\u200D"]]}, {"description": "Named entity: zwnj with a semi-colon.", "input":"‌", "output": [["Character", "\u200C"]]}, {"description": "Bad named entity: Alpha without a semi-colon.", "input":"&Alpha", "output": ["ParseError", ["Character", "&Alpha"]]}, {"description": "Bad named entity: alpha without a semi-colon.", "input":"&alpha", "output": ["ParseError", ["Character", "&alpha"]]}, {"description": "Bad named entity: and without a semi-colon.", "input":"&and", "output": ["ParseError", ["Character", "&and"]]}, {"description": "Bad named entity: ang without a semi-colon.", "input":"&ang", "output": ["ParseError", ["Character", "&ang"]]}, {"description": "Bad named entity: apos without a semi-colon.", "input":"&apos", "output": ["ParseError", ["Character", "&apos"]]}, {"description": "Bad named entity: asymp without a semi-colon.", "input":"&asymp", "output": ["ParseError", ["Character", "&asymp"]]}, {"description": "Bad named entity: bdquo without a semi-colon.", "input":"&bdquo", "output": ["ParseError", ["Character", "&bdquo"]]}, {"description": "Bad named entity: Beta without a semi-colon.", "input":"&Beta", "output": ["ParseError", ["Character", "&Beta"]]}, {"description": "Bad named entity: beta without a semi-colon.", "input":"&beta", "output": ["ParseError", ["Character", "&beta"]]}, {"description": "Bad named entity: bull without a semi-colon.", "input":"&bull", "output": ["ParseError", ["Character", "&bull"]]}, {"description": "Bad named entity: cap without a semi-colon.", "input":"&cap", "output": ["ParseError", ["Character", "&cap"]]}, {"description": "Bad named entity: Chi without a semi-colon.", "input":"&Chi", "output": ["ParseError", ["Character", "&Chi"]]}, {"description": "Bad named entity: chi without a semi-colon.", "input":"&chi", "output": ["ParseError", ["Character", "&chi"]]}, {"description": "Bad named entity: circ without a semi-colon.", "input":"&circ", "output": ["ParseError", ["Character", "&circ"]]}, {"description": "Bad named entity: clubs without a semi-colon.", "input":"&clubs", "output": ["ParseError", ["Character", "&clubs"]]}, {"description": "Bad named entity: cong without a semi-colon.", "input":"&cong", "output": ["ParseError", ["Character", "&cong"]]}, {"description": "Bad named entity: crarr without a semi-colon.", "input":"&crarr", "output": ["ParseError", ["Character", "&crarr"]]}, {"description": "Bad named entity: cup without a semi-colon.", "input":"&cup", "output": ["ParseError", ["Character", "&cup"]]}, {"description": "Bad named entity: dagger without a semi-colon.", "input":"&dagger", "output": ["ParseError", ["Character", "&dagger"]]}, {"description": "Bad named entity: dagger without a semi-colon.", "input":"&dagger", "output": ["ParseError", ["Character", "&dagger"]]}, {"description": "Bad named entity: darr without a semi-colon.", "input":"&darr", "output": ["ParseError", ["Character", "&darr"]]}, {"description": "Bad named entity: darr without a semi-colon.", "input":"&darr", "output": ["ParseError", ["Character", "&darr"]]}, {"description": "Bad named entity: Delta without a semi-colon.", "input":"&Delta", "output": ["ParseError", ["Character", "&Delta"]]}, {"description": "Bad named entity: delta without a semi-colon.", "input":"&delta", "output": ["ParseError", ["Character", "&delta"]]}, {"description": "Bad named entity: diams without a semi-colon.", "input":"&diams", "output": ["ParseError", ["Character", "&diams"]]}, {"description": "Bad named entity: empty without a semi-colon.", "input":"&empty", "output": ["ParseError", ["Character", "&empty"]]}, {"description": "Bad named entity: emsp without a semi-colon.", "input":"&emsp", "output": ["ParseError", ["Character", "&emsp"]]}, {"description": "Bad named entity: ensp without a semi-colon.", "input":"&ensp", "output": ["ParseError", ["Character", "&ensp"]]}, {"description": "Bad named entity: Epsilon without a semi-colon.", "input":"&Epsilon", "output": ["ParseError", ["Character", "&Epsilon"]]}, {"description": "Bad named entity: epsilon without a semi-colon.", "input":"&epsilon", "output": ["ParseError", ["Character", "&epsilon"]]}, {"description": "Bad named entity: equiv without a semi-colon.", "input":"&equiv", "output": ["ParseError", ["Character", "&equiv"]]}, {"description": "Bad named entity: Eta without a semi-colon.", "input":"&Eta", "output": ["ParseError", ["Character", "&Eta"]]}, {"description": "Bad named entity: eta without a semi-colon.", "input":"&eta", "output": ["ParseError", ["Character", "&eta"]]}, {"description": "Bad named entity: euro without a semi-colon.", "input":"&euro", "output": ["ParseError", ["Character", "&euro"]]}, {"description": "Bad named entity: exist without a semi-colon.", "input":"&exist", "output": ["ParseError", ["Character", "&exist"]]}, {"description": "Bad named entity: fnof without a semi-colon.", "input":"&fnof", "output": ["ParseError", ["Character", "&fnof"]]}, {"description": "Bad named entity: forall without a semi-colon.", "input":"&forall", "output": ["ParseError", ["Character", "&forall"]]}, {"description": "Bad named entity: frasl without a semi-colon.", "input":"&frasl", "output": ["ParseError", ["Character", "&frasl"]]}, {"description": "Bad named entity: Gamma without a semi-colon.", "input":"&Gamma", "output": ["ParseError", ["Character", "&Gamma"]]}, {"description": "Bad named entity: gamma without a semi-colon.", "input":"&gamma", "output": ["ParseError", ["Character", "&gamma"]]}, {"description": "Bad named entity: ge without a semi-colon.", "input":"&ge", "output": ["ParseError", ["Character", "&ge"]]}, {"description": "Bad named entity: harr without a semi-colon.", "input":"&harr", "output": ["ParseError", ["Character", "&harr"]]}, {"description": "Bad named entity: harr without a semi-colon.", "input":"&harr", "output": ["ParseError", ["Character", "&harr"]]}, {"description": "Bad named entity: hearts without a semi-colon.", "input":"&hearts", "output": ["ParseError", ["Character", "&hearts"]]}, {"description": "Bad named entity: hellip without a semi-colon.", "input":"&hellip", "output": ["ParseError", ["Character", "&hellip"]]}, {"description": "Bad named entity: image without a semi-colon.", "input":"&image", "output": ["ParseError", ["Character", "&image"]]}, {"description": "Bad named entity: infin without a semi-colon.", "input":"&infin", "output": ["ParseError", ["Character", "&infin"]]}, {"description": "Bad named entity: int without a semi-colon.", "input":"&int", "output": ["ParseError", ["Character", "&int"]]}, {"description": "Bad named entity: Iota without a semi-colon.", "input":"&Iota", "output": ["ParseError", ["Character", "&Iota"]]}, {"description": "Bad named entity: iota without a semi-colon.", "input":"&iota", "output": ["ParseError", ["Character", "&iota"]]}, {"description": "Bad named entity: isin without a semi-colon.", "input":"&isin", "output": ["ParseError", ["Character", "&isin"]]}, {"description": "Bad named entity: Kappa without a semi-colon.", "input":"&Kappa", "output": ["ParseError", ["Character", "&Kappa"]]}, {"description": "Bad named entity: kappa without a semi-colon.", "input":"&kappa", "output": ["ParseError", ["Character", "&kappa"]]}, {"description": "Bad named entity: Lambda without a semi-colon.", "input":"&Lambda", "output": ["ParseError", ["Character", "&Lambda"]]}, {"description": "Bad named entity: lambda without a semi-colon.", "input":"&lambda", "output": ["ParseError", ["Character", "&lambda"]]}, {"description": "Bad named entity: lang without a semi-colon.", "input":"&lang", "output": ["ParseError", ["Character", "&lang"]]}, {"description": "Bad named entity: larr without a semi-colon.", "input":"&larr", "output": ["ParseError", ["Character", "&larr"]]}, {"description": "Bad named entity: larr without a semi-colon.", "input":"&larr", "output": ["ParseError", ["Character", "&larr"]]}, {"description": "Bad named entity: lceil without a semi-colon.", "input":"&lceil", "output": ["ParseError", ["Character", "&lceil"]]}, {"description": "Bad named entity: ldquo without a semi-colon.", "input":"&ldquo", "output": ["ParseError", ["Character", "&ldquo"]]}, {"description": "Bad named entity: le without a semi-colon.", "input":"&le", "output": ["ParseError", ["Character", "&le"]]}, {"description": "Bad named entity: lfloor without a semi-colon.", "input":"&lfloor", "output": ["ParseError", ["Character", "&lfloor"]]}, {"description": "Bad named entity: lowast without a semi-colon.", "input":"&lowast", "output": ["ParseError", ["Character", "&lowast"]]}, {"description": "Bad named entity: loz without a semi-colon.", "input":"&loz", "output": ["ParseError", ["Character", "&loz"]]}, {"description": "Bad named entity: lrm without a semi-colon.", "input":"&lrm", "output": ["ParseError", ["Character", "&lrm"]]}, {"description": "Bad named entity: lsaquo without a semi-colon.", "input":"&lsaquo", "output": ["ParseError", ["Character", "&lsaquo"]]}, {"description": "Bad named entity: lsquo without a semi-colon.", "input":"&lsquo", "output": ["ParseError", ["Character", "&lsquo"]]}, {"description": "Bad named entity: mdash without a semi-colon.", "input":"&mdash", "output": ["ParseError", ["Character", "&mdash"]]}, {"description": "Bad named entity: minus without a semi-colon.", "input":"&minus", "output": ["ParseError", ["Character", "&minus"]]}, {"description": "Bad named entity: Mu without a semi-colon.", "input":"&Mu", "output": ["ParseError", ["Character", "&Mu"]]}, {"description": "Bad named entity: mu without a semi-colon.", "input":"&mu", "output": ["ParseError", ["Character", "&mu"]]}, {"description": "Bad named entity: nabla without a semi-colon.", "input":"&nabla", "output": ["ParseError", ["Character", "&nabla"]]}, {"description": "Bad named entity: ndash without a semi-colon.", "input":"&ndash", "output": ["ParseError", ["Character", "&ndash"]]}, {"description": "Bad named entity: ne without a semi-colon.", "input":"&ne", "output": ["ParseError", ["Character", "&ne"]]}, {"description": "Bad named entity: ni without a semi-colon.", "input":"&ni", "output": ["ParseError", ["Character", "&ni"]]}, {"description": "Bad named entity: notin without a semi-colon.", "input":"¬in", "output": ["ParseError", ["Character", "\u00ACin"]]}, {"description": "Bad named entity: nsub without a semi-colon.", "input":"&nsub", "output": ["ParseError", ["Character", "&nsub"]]}, {"description": "Bad named entity: Nu without a semi-colon.", "input":"&Nu", "output": ["ParseError", ["Character", "&Nu"]]}, {"description": "Bad named entity: nu without a semi-colon.", "input":"&nu", "output": ["ParseError", ["Character", "&nu"]]}, {"description": "Bad named entity: OElig without a semi-colon.", "input":"&OElig", "output": ["ParseError", ["Character", "&OElig"]]}, {"description": "Bad named entity: oelig without a semi-colon.", "input":"&oelig", "output": ["ParseError", ["Character", "&oelig"]]}, {"description": "Bad named entity: oline without a semi-colon.", "input":"&oline", "output": ["ParseError", ["Character", "&oline"]]}, {"description": "Bad named entity: Omega without a semi-colon.", "input":"&Omega", "output": ["ParseError", ["Character", "&Omega"]]}, {"description": "Bad named entity: omega without a semi-colon.", "input":"&omega", "output": ["ParseError", ["Character", "&omega"]]}, {"description": "Bad named entity: Omicron without a semi-colon.", "input":"&Omicron", "output": ["ParseError", ["Character", "&Omicron"]]}, {"description": "Bad named entity: omicron without a semi-colon.", "input":"&omicron", "output": ["ParseError", ["Character", "&omicron"]]}, {"description": "Bad named entity: oplus without a semi-colon.", "input":"&oplus", "output": ["ParseError", ["Character", "&oplus"]]}, {"description": "Bad named entity: or without a semi-colon.", "input":"&or", "output": ["ParseError", ["Character", "&or"]]}, {"description": "Bad named entity: otimes without a semi-colon.", "input":"&otimes", "output": ["ParseError", ["Character", "&otimes"]]}, {"description": "Bad named entity: part without a semi-colon.", "input":"&part", "output": ["ParseError", ["Character", "&part"]]}, {"description": "Bad named entity: permil without a semi-colon.", "input":"&permil", "output": ["ParseError", ["Character", "&permil"]]}, {"description": "Bad named entity: perp without a semi-colon.", "input":"&perp", "output": ["ParseError", ["Character", "&perp"]]}, {"description": "Bad named entity: Phi without a semi-colon.", "input":"&Phi", "output": ["ParseError", ["Character", "&Phi"]]}, {"description": "Bad named entity: phi without a semi-colon.", "input":"&phi", "output": ["ParseError", ["Character", "&phi"]]}, {"description": "Bad named entity: Pi without a semi-colon.", "input":"&Pi", "output": ["ParseError", ["Character", "&Pi"]]}, {"description": "Bad named entity: pi without a semi-colon.", "input":"&pi", "output": ["ParseError", ["Character", "&pi"]]}, {"description": "Bad named entity: piv without a semi-colon.", "input":"&piv", "output": ["ParseError", ["Character", "&piv"]]}, {"description": "Bad named entity: prime without a semi-colon.", "input":"&prime", "output": ["ParseError", ["Character", "&prime"]]}, {"description": "Bad named entity: prime without a semi-colon.", "input":"&prime", "output": ["ParseError", ["Character", "&prime"]]}, {"description": "Bad named entity: prod without a semi-colon.", "input":"&prod", "output": ["ParseError", ["Character", "&prod"]]}, {"description": "Bad named entity: prop without a semi-colon.", "input":"&prop", "output": ["ParseError", ["Character", "&prop"]]}, {"description": "Bad named entity: Psi without a semi-colon.", "input":"&Psi", "output": ["ParseError", ["Character", "&Psi"]]}, {"description": "Bad named entity: psi without a semi-colon.", "input":"&psi", "output": ["ParseError", ["Character", "&psi"]]}, {"description": "Bad named entity: radic without a semi-colon.", "input":"&radic", "output": ["ParseError", ["Character", "&radic"]]}, {"description": "Bad named entity: rang without a semi-colon.", "input":"&rang", "output": ["ParseError", ["Character", "&rang"]]}, {"description": "Bad named entity: rarr without a semi-colon.", "input":"&rarr", "output": ["ParseError", ["Character", "&rarr"]]}, {"description": "Bad named entity: rarr without a semi-colon.", "input":"&rarr", "output": ["ParseError", ["Character", "&rarr"]]}, {"description": "Bad named entity: rceil without a semi-colon.", "input":"&rceil", "output": ["ParseError", ["Character", "&rceil"]]}, {"description": "Bad named entity: rdquo without a semi-colon.", "input":"&rdquo", "output": ["ParseError", ["Character", "&rdquo"]]}, {"description": "Bad named entity: real without a semi-colon.", "input":"&real", "output": ["ParseError", ["Character", "&real"]]}, {"description": "Bad named entity: rfloor without a semi-colon.", "input":"&rfloor", "output": ["ParseError", ["Character", "&rfloor"]]}, {"description": "Bad named entity: Rho without a semi-colon.", "input":"&Rho", "output": ["ParseError", ["Character", "&Rho"]]}, {"description": "Bad named entity: rho without a semi-colon.", "input":"&rho", "output": ["ParseError", ["Character", "&rho"]]}, {"description": "Bad named entity: rlm without a semi-colon.", "input":"&rlm", "output": ["ParseError", ["Character", "&rlm"]]}, {"description": "Bad named entity: rsaquo without a semi-colon.", "input":"&rsaquo", "output": ["ParseError", ["Character", "&rsaquo"]]}, {"description": "Bad named entity: rsquo without a semi-colon.", "input":"&rsquo", "output": ["ParseError", ["Character", "&rsquo"]]}, {"description": "Bad named entity: sbquo without a semi-colon.", "input":"&sbquo", "output": ["ParseError", ["Character", "&sbquo"]]}, {"description": "Bad named entity: Scaron without a semi-colon.", "input":"&Scaron", "output": ["ParseError", ["Character", "&Scaron"]]}, {"description": "Bad named entity: scaron without a semi-colon.", "input":"&scaron", "output": ["ParseError", ["Character", "&scaron"]]}, {"description": "Bad named entity: sdot without a semi-colon.", "input":"&sdot", "output": ["ParseError", ["Character", "&sdot"]]}, {"description": "Bad named entity: Sigma without a semi-colon.", "input":"&Sigma", "output": ["ParseError", ["Character", "&Sigma"]]}, {"description": "Bad named entity: sigma without a semi-colon.", "input":"&sigma", "output": ["ParseError", ["Character", "&sigma"]]}, {"description": "Bad named entity: sigmaf without a semi-colon.", "input":"&sigmaf", "output": ["ParseError", ["Character", "&sigmaf"]]}, {"description": "Bad named entity: sim without a semi-colon.", "input":"&sim", "output": ["ParseError", ["Character", "&sim"]]}, {"description": "Bad named entity: spades without a semi-colon.", "input":"&spades", "output": ["ParseError", ["Character", "&spades"]]}, {"description": "Bad named entity: sub without a semi-colon.", "input":"&sub", "output": ["ParseError", ["Character", "&sub"]]}, {"description": "Bad named entity: sube without a semi-colon.", "input":"&sube", "output": ["ParseError", ["Character", "&sube"]]}, {"description": "Bad named entity: sum without a semi-colon.", "input":"&sum", "output": ["ParseError", ["Character", "&sum"]]}, {"description": "Bad named entity: sup without a semi-colon.", "input":"&sup", "output": ["ParseError", ["Character", "&sup"]]}, {"description": "Bad named entity: supe without a semi-colon.", "input":"&supe", "output": ["ParseError", ["Character", "&supe"]]}, {"description": "Bad named entity: Tau without a semi-colon.", "input":"&Tau", "output": ["ParseError", ["Character", "&Tau"]]}, {"description": "Bad named entity: tau without a semi-colon.", "input":"&tau", "output": ["ParseError", ["Character", "&tau"]]}, {"description": "Bad named entity: there4 without a semi-colon.", "input":"&there4", "output": ["ParseError", ["Character", "&there4"]]}, {"description": "Bad named entity: Theta without a semi-colon.", "input":"&Theta", "output": ["ParseError", ["Character", "&Theta"]]}, {"description": "Bad named entity: theta without a semi-colon.", "input":"&theta", "output": ["ParseError", ["Character", "&theta"]]}, {"description": "Bad named entity: thetasym without a semi-colon.", "input":"&thetasym", "output": ["ParseError", ["Character", "&thetasym"]]}, {"description": "Bad named entity: thinsp without a semi-colon.", "input":"&thinsp", "output": ["ParseError", ["Character", "&thinsp"]]}, {"description": "Bad named entity: tilde without a semi-colon.", "input":"&tilde", "output": ["ParseError", ["Character", "&tilde"]]}, {"description": "Bad named entity: trade without a semi-colon.", "input":"&trade", "output": ["ParseError", ["Character", "&trade"]]}, {"description": "Bad named entity: uarr without a semi-colon.", "input":"&uarr", "output": ["ParseError", ["Character", "&uarr"]]}, {"description": "Bad named entity: uarr without a semi-colon.", "input":"&uarr", "output": ["ParseError", ["Character", "&uarr"]]}, {"description": "Bad named entity: upsih without a semi-colon.", "input":"&upsih", "output": ["ParseError", ["Character", "&upsih"]]}, {"description": "Bad named entity: Upsilon without a semi-colon.", "input":"&Upsilon", "output": ["ParseError", ["Character", "&Upsilon"]]}, {"description": "Bad named entity: upsilon without a semi-colon.", "input":"&upsilon", "output": ["ParseError", ["Character", "&upsilon"]]}, {"description": "Bad named entity: weierp without a semi-colon.", "input":"&weierp", "output": ["ParseError", ["Character", "&weierp"]]}, {"description": "Bad named entity: Xi without a semi-colon.", "input":"&Xi", "output": ["ParseError", ["Character", "&Xi"]]}, {"description": "Bad named entity: xi without a semi-colon.", "input":"&xi", "output": ["ParseError", ["Character", "&xi"]]}, {"description": "Bad named entity: Yuml without a semi-colon.", "input":"&Yuml", "output": ["ParseError", ["Character", "&Yuml"]]}, {"description": "Bad named entity: Zeta without a semi-colon.", "input":"&Zeta", "output": ["ParseError", ["Character", "&Zeta"]]}, {"description": "Bad named entity: zeta without a semi-colon.", "input":"&zeta", "output": ["ParseError", ["Character", "&zeta"]]}, {"description": "Bad named entity: zwj without a semi-colon.", "input":"&zwj", "output": ["ParseError", ["Character", "&zwj"]]}, {"description": "Bad named entity: zwnj without a semi-colon.", "input":"&zwnj", "output": ["ParseError", ["Character", "&zwnj"]]}, {"description": "Bad named entity: zwnj without a semi-colon.", "input":"&zwnj", "output": ["ParseError", ["Character", "&zwnj"]]}, {"description": "CR as numeric entity", "input":" ", "output": ["ParseError", ["Character", "\n"]]}, {"description": "CR as hexadecimal numeric entity", "input":" ", "output": ["ParseError", ["Character", "\n"]]}, {"description": "Windows-1252 EURO SIGN numeric entity.", "input":"€", "output": ["ParseError", ["Character", "\u20AC"]]}, {"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 SINGLE LOW-9 QUOTATION MARK numeric entity.", "input":"‚", "output": ["ParseError", ["Character", "\u201A"]]}, {"description": "Windows-1252 LATIN SMALL LETTER F WITH HOOK numeric entity.", "input":"ƒ", "output": ["ParseError", ["Character", "\u0192"]]}, {"description": "Windows-1252 DOUBLE LOW-9 QUOTATION MARK numeric entity.", "input":"„", "output": ["ParseError", ["Character", "\u201E"]]}, {"description": "Windows-1252 HORIZONTAL ELLIPSIS numeric entity.", "input":"…", "output": ["ParseError", ["Character", "\u2026"]]}, {"description": "Windows-1252 DAGGER numeric entity.", "input":"†", "output": ["ParseError", ["Character", "\u2020"]]}, {"description": "Windows-1252 DOUBLE DAGGER numeric entity.", "input":"‡", "output": ["ParseError", ["Character", "\u2021"]]}, {"description": "Windows-1252 MODIFIER LETTER CIRCUMFLEX ACCENT numeric entity.", "input":"ˆ", "output": ["ParseError", ["Character", "\u02C6"]]}, {"description": "Windows-1252 PER MILLE SIGN numeric entity.", "input":"‰", "output": ["ParseError", ["Character", "\u2030"]]}, {"description": "Windows-1252 LATIN CAPITAL LETTER S WITH CARON numeric entity.", "input":"Š", "output": ["ParseError", ["Character", "\u0160"]]}, {"description": "Windows-1252 SINGLE LEFT-POINTING ANGLE QUOTATION MARK numeric entity.", "input":"‹", "output": ["ParseError", ["Character", "\u2039"]]}, {"description": "Windows-1252 LATIN CAPITAL LIGATURE OE numeric entity.", "input":"Œ", "output": ["ParseError", ["Character", "\u0152"]]}, {"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 LATIN CAPITAL LETTER Z WITH CARON numeric entity.", "input":"Ž", "output": ["ParseError", ["Character", "\u017D"]]}, {"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 LEFT SINGLE QUOTATION MARK numeric entity.", "input":"‘", "output": ["ParseError", ["Character", "\u2018"]]}, {"description": "Windows-1252 RIGHT SINGLE QUOTATION MARK numeric entity.", "input":"’", "output": ["ParseError", ["Character", "\u2019"]]}, {"description": "Windows-1252 LEFT DOUBLE QUOTATION MARK numeric entity.", "input":"“", "output": ["ParseError", ["Character", "\u201C"]]}, {"description": "Windows-1252 RIGHT DOUBLE QUOTATION MARK numeric entity.", "input":"”", "output": ["ParseError", ["Character", "\u201D"]]}, {"description": "Windows-1252 BULLET numeric entity.", "input":"•", "output": ["ParseError", ["Character", "\u2022"]]}, {"description": "Windows-1252 EN DASH numeric entity.", "input":"–", "output": ["ParseError", ["Character", "\u2013"]]}, {"description": "Windows-1252 EM DASH numeric entity.", "input":"—", "output": ["ParseError", ["Character", "\u2014"]]}, {"description": "Windows-1252 SMALL TILDE numeric entity.", "input":"˜", "output": ["ParseError", ["Character", "\u02DC"]]}, {"description": "Windows-1252 TRADE MARK SIGN numeric entity.", "input":"™", "output": ["ParseError", ["Character", "\u2122"]]}, {"description": "Windows-1252 LATIN SMALL LETTER S WITH CARON numeric entity.", "input":"š", "output": ["ParseError", ["Character", "\u0161"]]}, {"description": "Windows-1252 SINGLE RIGHT-POINTING ANGLE QUOTATION MARK numeric entity.", "input":"›", "output": ["ParseError", ["Character", "\u203A"]]}, {"description": "Windows-1252 LATIN SMALL LIGATURE OE numeric entity.", "input":"œ", "output": ["ParseError", ["Character", "\u0153"]]}, {"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 EURO SIGN hexadecimal numeric entity.", "input":"€", "output": ["ParseError", ["Character", "\u20AC"]]}, {"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 SINGLE LOW-9 QUOTATION MARK hexadecimal numeric entity.", "input":"‚", "output": ["ParseError", ["Character", "\u201A"]]}, {"description": "Windows-1252 LATIN SMALL LETTER F WITH HOOK hexadecimal numeric entity.", "input":"ƒ", "output": ["ParseError", ["Character", "\u0192"]]}, {"description": "Windows-1252 DOUBLE LOW-9 QUOTATION MARK hexadecimal numeric entity.", "input":"„", "output": ["ParseError", ["Character", "\u201E"]]}, {"description": "Windows-1252 HORIZONTAL ELLIPSIS hexadecimal numeric entity.", "input":"…", "output": ["ParseError", ["Character", "\u2026"]]}, {"description": "Windows-1252 DAGGER hexadecimal numeric entity.", "input":"†", "output": ["ParseError", ["Character", "\u2020"]]}, {"description": "Windows-1252 DOUBLE DAGGER hexadecimal numeric entity.", "input":"‡", "output": ["ParseError", ["Character", "\u2021"]]}, {"description": "Windows-1252 MODIFIER LETTER CIRCUMFLEX ACCENT hexadecimal numeric entity.", "input":"ˆ", "output": ["ParseError", ["Character", "\u02C6"]]}, {"description": "Windows-1252 PER MILLE SIGN hexadecimal numeric entity.", "input":"‰", "output": ["ParseError", ["Character", "\u2030"]]}, {"description": "Windows-1252 LATIN CAPITAL LETTER S WITH CARON hexadecimal numeric entity.", "input":"Š", "output": ["ParseError", ["Character", "\u0160"]]}, {"description": "Windows-1252 SINGLE LEFT-POINTING ANGLE QUOTATION MARK hexadecimal numeric entity.", "input":"‹", "output": ["ParseError", ["Character", "\u2039"]]}, {"description": "Windows-1252 LATIN CAPITAL LIGATURE OE hexadecimal numeric entity.", "input":"Œ", "output": ["ParseError", ["Character", "\u0152"]]}, {"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 LATIN CAPITAL LETTER Z WITH CARON hexadecimal numeric entity.", "input":"Ž", "output": ["ParseError", ["Character", "\u017D"]]}, {"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 LEFT SINGLE QUOTATION MARK hexadecimal numeric entity.", "input":"‘", "output": ["ParseError", ["Character", "\u2018"]]}, {"description": "Windows-1252 RIGHT SINGLE QUOTATION MARK hexadecimal numeric entity.", "input":"’", "output": ["ParseError", ["Character", "\u2019"]]}, {"description": "Windows-1252 LEFT DOUBLE QUOTATION MARK hexadecimal numeric entity.", "input":"“", "output": ["ParseError", ["Character", "\u201C"]]}, {"description": "Windows-1252 RIGHT DOUBLE QUOTATION MARK hexadecimal numeric entity.", "input":"”", "output": ["ParseError", ["Character", "\u201D"]]}, {"description": "Windows-1252 BULLET hexadecimal numeric entity.", "input":"•", "output": ["ParseError", ["Character", "\u2022"]]}, {"description": "Windows-1252 EN DASH hexadecimal numeric entity.", "input":"–", "output": ["ParseError", ["Character", "\u2013"]]}, {"description": "Windows-1252 EM DASH hexadecimal numeric entity.", "input":"—", "output": ["ParseError", ["Character", "\u2014"]]}, {"description": "Windows-1252 SMALL TILDE hexadecimal numeric entity.", "input":"˜", "output": ["ParseError", ["Character", "\u02DC"]]}, {"description": "Windows-1252 TRADE MARK SIGN hexadecimal numeric entity.", "input":"™", "output": ["ParseError", ["Character", "\u2122"]]}, {"description": "Windows-1252 LATIN SMALL LETTER S WITH CARON hexadecimal numeric entity.", "input":"š", "output": ["ParseError", ["Character", "\u0161"]]}, {"description": "Windows-1252 SINGLE RIGHT-POINTING ANGLE QUOTATION MARK hexadecimal numeric entity.", "input":"›", "output": ["ParseError", ["Character", "\u203A"]]}, {"description": "Windows-1252 LATIN SMALL LIGATURE OE hexadecimal numeric entity.", "input":"œ", "output": ["ParseError", ["Character", "\u0153"]]}, {"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", "input":"", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Windows-1252 LATIN SMALL LETTER Z WITH CARON hexadecimal numeric entity.", "input":"ž", "output": ["ParseError", ["Character", "\u017E"]]}, {"description": "Windows-1252 LATIN CAPITAL LETTER Y WITH DIAERESIS hexadecimal numeric entity.", "input":"Ÿ", "output": ["ParseError", ["Character", "\u0178"]]} ]} netsurf-2.9/hubbub-0.1.2/test/data/tokeniser2/cdata.test0000664000175000017500000000077511026335416021715 0ustar vincevince{"tests": [ {"description":"Basic CDATA test", "processCDATA":true, "input":"", "output":[["Character", "test"]]}, {"description":"Unfinished CDATA test", "processCDATA":true, "input":"", "output":[["DOCTYPE", "html", null, null, true]]}, {"description":"Correct Doctype uppercase", "input":"", "output":[["DOCTYPE", "html", null, null, true]]}, {"description":"Correct Doctype mixed case", "input":"", "output":[["DOCTYPE", "html", null, null, true]]}, {"description":"Correct Doctype case with EOF", "input":"", "output":["ParseError", ["Comment", "DOC"]]}, {"description":"Doctype in error", "input":"", "output":[["DOCTYPE", "foo", null, null, true]]}, {"description":"Single Start Tag", "input":"", "output":[["StartTag", "h", {}]]}, {"description":"Empty end tag", "input":"", "output":["ParseError"]}, {"description":"Empty start tag", "input":"<>", "output":["ParseError", ["Character", "<>"]]}, {"description":"Start Tag w/attribute", "input":"", "output":[["StartTag", "h", {"a":"b"}]]}, {"description":"Start Tag w/attribute no quotes", "input":"", "output":[["StartTag", "h", {"a":"b"}]]}, {"description":"Start/End Tag", "input":"", "output":[["StartTag", "h", {}], ["EndTag", "h"]]}, {"description":"Two unclosed start tags", "input":"

One

Two", "output":[["StartTag", "p", {}], ["Character", "One"], ["StartTag", "p", {}], ["Character", "Two"]]}, {"description":"End Tag w/attribute", "input":"", "output":[["StartTag", "h", {}], "ParseError", ["EndTag", "h"]]}, {"description":"Multiple atts", "input":"", "output":[["StartTag", "h", {"a":"b", "c":"d"}]]}, {"description":"Multiple atts no space", "input":"", "output":["ParseError", ["StartTag", "h", {"a":"b", "c":"d"}]]}, {"description":"Repeated attr", "input":"", "output":["ParseError", ["StartTag", "h", {"a":"b"}]]}, {"description":"Simple comment", "input":"", "output":[["Comment", "comment"]]}, {"description":"Comment, Central dash no space", "input":"", "output":["ParseError", ["Comment", "-"]]}, {"description":"Comment, two central dashes", "input":"", "output":["ParseError", ["Comment", " --comment "]]}, {"description":"Unfinished comment", "input":"", "output":["ParseError", ["Comment", ""]]}, {"description":"Short comment two", "input":"", "output":["ParseError", ["Comment", ""]]}, {"description":"Short comment three", "input":"", "output":[["Comment", ""]]}, {"description":"Ampersand EOF", "input":"&", "output":[["Character", "&"]]}, {"description":"Ampersand ampersand EOF", "input":"&&", "output":[["Character", "&&"]]}, {"description":"Ampersand space EOF", "input":"& ", "output":[["Character", "& "]]}, {"description":"Unfinished entity", "input":"&f", "output":["ParseError", ["Character", "&f"]]}, {"description":"Ampersand, number sign", "input":"&#", "output":["ParseError", ["Character", "&#"]]}, {"description":"Unfinished numeric entity", "input":"&#x", "output":["ParseError", ["Character", "&#x"]]}, {"description":"Entity with trailing semicolon (1)", "input":"I'm ¬it", "output":[["Character","I'm \u00ACit"]]}, {"description":"Entity with trailing semicolon (2)", "input":"I'm ∉", "output":[["Character","I'm \u2209"]]}, {"description":"Entity without trailing semicolon (1)", "input":"I'm ¬it", "output":[["Character","I'm "], "ParseError", ["Character", "\u00ACit"]]}, {"description":"Entity without trailing semicolon (2)", "input":"I'm ¬in", "output":[["Character","I'm "], "ParseError", ["Character", "\u00ACin"]]}, {"description":"Partial entity match at end of file", "input":"I'm &no", "output":[["Character","I'm "], "ParseError", ["Character", "&no"]]}, {"description":"Non-ASCII character reference name", "input":"&\u00AC;", "output":["ParseError", ["Character", "&\u00AC;"]]}, {"description":"ASCII decimal entity", "input":"$", "output":[["Character","$"]]}, {"description":"ASCII hexadecimal entity", "input":"?", "output":[["Character","?"]]}, {"description":"Hexadecimal entity in attribute", "input":"", "output":[["StartTag", "h", {"a":"?"}], ["EndTag", "h"]]}, {"description":"Entity in attribute without semicolon ending in x", "input":"", "output":["ParseError", ["StartTag", "h", {"a":"¬x"}]]}, {"description":"Entity in attribute without semicolon ending in 1", "input":"", "output":["ParseError", ["StartTag", "h", {"a":"¬1"}]]}, {"description":"Entity in attribute without semicolon ending in i", "input":"", "output":["ParseError", ["StartTag", "h", {"a":"¬i"}]]}, {"description":"Entity in attribute without semicolon", "input":"", "output":["ParseError", ["StartTag", "h", {"a":"\u00A9"}]]}, {"description":"Unquoted attribute ending in ampersand", "input":"&body;", "output":[["Character", "&body;"]]}, {"description":"End tag closing RCDATA or CDATA", "contentModelFlags":["RCDATA", "CDATA"], "lastStartTag":"xmp", "input":"foo", "output":[["Character", "foo"], ["EndTag", "xmp"]]}, {"description":"End tag closing RCDATA or CDATA (case-insensitivity)", "contentModelFlags":["RCDATA", "CDATA"], "lastStartTag":"xmp", "input":"foo", "output":[["Character", "foo"], ["EndTag", "xmp"]]}, {"description":"End tag closing RCDATA or CDATA (ending with space)", "contentModelFlags":["RCDATA", "CDATA"], "lastStartTag":"xmp", "input":"foobar", "output":[["Character", "bar"], ["EndTag", "xmp"]]}, {"description":"End tag with incorrect name in RCDATA or CDATA (starting like correct name)", "contentModelFlags":["RCDATA", "CDATA"], "lastStartTag":"xmp", "input":"bar", "output":[["Character", "bar"]]}, {"description":"End tag closing RCDATA or CDATA, switching back to PCDATA", "contentModelFlags":["RCDATA", "CDATA"], "lastStartTag":"xmp", "input":"foo", "output":[["Character", "foo"], ["EndTag", "xmp"], ["EndTag", "baz"]]}, {"description":"CDATA w/ something looking like an entity", "contentModelFlags":["CDATA"], "lastStartTag":"xmp", "input":"&foo;", "output":[["Character", "&foo;"]]}, {"description":"RCDATA w/ an entity", "contentModelFlags":["RCDATA"], "lastStartTag":"textarea", "input":"<", "output":[["Character", "<"]]} ]} netsurf-2.9/hubbub-0.1.2/test/data/tokeniser2/numericEntities.test0000664000175000017500000011633211155460755024015 0ustar vincevince{"tests": [ {"description": "Invalid numeric entity character U+0000", "input": "�", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0001", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0002", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0003", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0004", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0005", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0006", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0007", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0008", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+000B", "input": " ", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+000E", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+000F", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0010", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0011", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0012", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0013", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0014", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0015", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0016", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0017", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0018", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+0019", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+001A", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+001B", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+001C", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+001D", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+001E", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+001F", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+007F", "input": "", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+D800", "input": "�", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+DFFF", "input": "�", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD0", "input": "﷐", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD1", "input": "﷑", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD2", "input": "﷒", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD3", "input": "﷓", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD4", "input": "﷔", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD5", "input": "﷕", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD6", "input": "﷖", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD7", "input": "﷗", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD8", "input": "﷘", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDD9", "input": "﷙", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDDA", "input": "﷚", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDDB", "input": "﷛", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDDC", "input": "﷜", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDDD", "input": "﷝", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDDE", "input": "﷞", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDDF", "input": "﷟", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE0", "input": "﷠", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE1", "input": "﷡", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE2", "input": "﷢", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE3", "input": "﷣", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE4", "input": "﷤", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE5", "input": "﷥", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE6", "input": "﷦", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE7", "input": "﷧", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE8", "input": "﷨", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDE9", "input": "﷩", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDEA", "input": "﷪", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDEB", "input": "﷫", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDEC", "input": "﷬", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDED", "input": "﷭", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDEE", "input": "﷮", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FDEF", "input": "﷯", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FFFE", "input": "￾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FFFF", "input": "￿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+1FFFE", "input": "🿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+1FFFF", "input": "🿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+2FFFE", "input": "𯿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+2FFFF", "input": "𯿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+3FFFE", "input": "𿿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+3FFFF", "input": "𿿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+4FFFE", "input": "񏿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+4FFFF", "input": "񏿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+5FFFE", "input": "񟿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+5FFFF", "input": "񟿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+6FFFE", "input": "񯿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+6FFFF", "input": "񯿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+7FFFE", "input": "񿿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+7FFFF", "input": "񿿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+8FFFE", "input": "򏿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+8FFFF", "input": "򏿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+9FFFE", "input": "򟿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+9FFFF", "input": "򟿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+AFFFE", "input": "򯿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+AFFFF", "input": "򯿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+BFFFE", "input": "򿿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+BFFFF", "input": "򿿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+CFFFE", "input": "󏿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+CFFFF", "input": "󏿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+DFFFE", "input": "󟿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+DFFFF", "input": "󟿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+EFFFE", "input": "󯿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+EFFFF", "input": "󯿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FFFFE", "input": "󿿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+FFFFF", "input": "󿿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+10FFFE", "input": "􏿾", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Invalid numeric entity character U+10FFFF", "input": "􏿿", "output": ["ParseError", ["Character", "\uFFFD"]]}, {"description": "Valid numeric entity character U+0009", "input": " ", "output": [["Character", "\u0009"]]}, {"description": "Valid numeric entity character U+000A", "input": " ", "output": [["Character", "\u000A"]]}, {"description": "Valid numeric entity character U+0020", "input": " ", "output": [["Character", "\u0020"]]}, {"description": "Valid numeric entity character U+0021", "input": "!", "output": [["Character", "\u0021"]]}, {"description": "Valid numeric entity character U+0022", "input": """, "output": [["Character", "\u0022"]]}, {"description": "Valid numeric entity character U+0023", "input": "#", "output": [["Character", "\u0023"]]}, {"description": "Valid numeric entity character U+0024", "input": "$", "output": [["Character", "\u0024"]]}, {"description": "Valid numeric entity character U+0025", "input": "%", "output": [["Character", "\u0025"]]}, {"description": "Valid numeric entity character U+0026", "input": "&", "output": [["Character", "\u0026"]]}, {"description": "Valid numeric entity character U+0027", "input": "'", "output": [["Character", "\u0027"]]}, {"description": "Valid numeric entity character U+0028", "input": "(", "output": [["Character", "\u0028"]]}, {"description": "Valid numeric entity character U+0029", "input": ")", "output": [["Character", "\u0029"]]}, {"description": "Valid numeric entity character U+002A", "input": "*", "output": [["Character", "\u002A"]]}, {"description": "Valid numeric entity character U+002B", "input": "+", "output": [["Character", "\u002B"]]}, {"description": "Valid numeric entity character U+002C", "input": ",", "output": [["Character", "\u002C"]]}, {"description": "Valid numeric entity character U+002D", "input": "-", "output": [["Character", "\u002D"]]}, {"description": "Valid numeric entity character U+002E", "input": ".", "output": [["Character", "\u002E"]]}, {"description": "Valid numeric entity character U+002F", "input": "/", "output": [["Character", "\u002F"]]}, {"description": "Valid numeric entity character U+0030", "input": "0", "output": [["Character", "\u0030"]]}, {"description": "Valid numeric entity character U+0031", "input": "1", "output": [["Character", "\u0031"]]}, {"description": "Valid numeric entity character U+0032", "input": "2", "output": [["Character", "\u0032"]]}, {"description": "Valid numeric entity character U+0033", "input": "3", "output": [["Character", "\u0033"]]}, {"description": "Valid numeric entity character U+0034", "input": "4", "output": [["Character", "\u0034"]]}, {"description": "Valid numeric entity character U+0035", "input": "5", "output": [["Character", "\u0035"]]}, {"description": "Valid numeric entity character U+0036", "input": "6", "output": [["Character", "\u0036"]]}, {"description": "Valid numeric entity character U+0037", "input": "7", "output": [["Character", "\u0037"]]}, {"description": "Valid numeric entity character U+0038", "input": "8", "output": [["Character", "\u0038"]]}, {"description": "Valid numeric entity character U+0039", "input": "9", "output": [["Character", "\u0039"]]}, {"description": "Valid numeric entity character U+003A", "input": ":", "output": [["Character", "\u003A"]]}, {"description": "Valid numeric entity character U+003B", "input": ";", "output": [["Character", "\u003B"]]}, {"description": "Valid numeric entity character U+003C", "input": "<", "output": [["Character", "\u003C"]]}, {"description": "Valid numeric entity character U+003D", "input": "=", "output": [["Character", "\u003D"]]}, {"description": "Valid numeric entity character U+003E", "input": ">", "output": [["Character", "\u003E"]]}, {"description": "Valid numeric entity character U+003F", "input": "?", "output": [["Character", "\u003F"]]}, {"description": "Valid numeric entity character U+0040", "input": "@", "output": [["Character", "\u0040"]]}, {"description": "Valid numeric entity character U+0041", "input": "A", "output": [["Character", "\u0041"]]}, {"description": "Valid numeric entity character U+0042", "input": "B", "output": [["Character", "\u0042"]]}, {"description": "Valid numeric entity character U+0043", "input": "C", "output": [["Character", "\u0043"]]}, {"description": "Valid numeric entity character U+0044", "input": "D", "output": [["Character", "\u0044"]]}, {"description": "Valid numeric entity character U+0045", "input": "E", "output": [["Character", "\u0045"]]}, {"description": "Valid numeric entity character U+0046", "input": "F", "output": [["Character", "\u0046"]]}, {"description": "Valid numeric entity character U+0047", "input": "G", "output": [["Character", "\u0047"]]}, {"description": "Valid numeric entity character U+0048", "input": "H", "output": [["Character", "\u0048"]]}, {"description": "Valid numeric entity character U+0049", "input": "I", "output": [["Character", "\u0049"]]}, {"description": "Valid numeric entity character U+004A", "input": "J", "output": [["Character", "\u004A"]]}, {"description": "Valid numeric entity character U+004B", "input": "K", "output": [["Character", "\u004B"]]}, {"description": "Valid numeric entity character U+004C", "input": "L", "output": [["Character", "\u004C"]]}, {"description": "Valid numeric entity character U+004D", "input": "M", "output": [["Character", "\u004D"]]}, {"description": "Valid numeric entity character U+004E", "input": "N", "output": [["Character", "\u004E"]]}, {"description": "Valid numeric entity character U+004F", "input": "O", "output": [["Character", "\u004F"]]}, {"description": "Valid numeric entity character U+0050", "input": "P", "output": [["Character", "\u0050"]]}, {"description": "Valid numeric entity character U+0051", "input": "Q", "output": [["Character", "\u0051"]]}, {"description": "Valid numeric entity character U+0052", "input": "R", "output": [["Character", "\u0052"]]}, {"description": "Valid numeric entity character U+0053", "input": "S", "output": [["Character", "\u0053"]]}, {"description": "Valid numeric entity character U+0054", "input": "T", "output": [["Character", "\u0054"]]}, {"description": "Valid numeric entity character U+0055", "input": "U", "output": [["Character", "\u0055"]]}, {"description": "Valid numeric entity character U+0056", "input": "V", "output": [["Character", "\u0056"]]}, {"description": "Valid numeric entity character U+0057", "input": "W", "output": [["Character", "\u0057"]]}, {"description": "Valid numeric entity character U+0058", "input": "X", "output": [["Character", "\u0058"]]}, {"description": "Valid numeric entity character U+0059", "input": "Y", "output": [["Character", "\u0059"]]}, {"description": "Valid numeric entity character U+005A", "input": "Z", "output": [["Character", "\u005A"]]}, {"description": "Valid numeric entity character U+005B", "input": "[", "output": [["Character", "\u005B"]]}, {"description": "Valid numeric entity character U+005C", "input": "\", "output": [["Character", "\u005C"]]}, {"description": "Valid numeric entity character U+005D", "input": "]", "output": [["Character", "\u005D"]]}, {"description": "Valid numeric entity character U+005E", "input": "^", "output": [["Character", "\u005E"]]}, {"description": "Valid numeric entity character U+005F", "input": "_", "output": [["Character", "\u005F"]]}, {"description": "Valid numeric entity character U+0060", "input": "`", "output": [["Character", "\u0060"]]}, {"description": "Valid numeric entity character U+0061", "input": "a", "output": [["Character", "\u0061"]]}, {"description": "Valid numeric entity character U+0062", "input": "b", "output": [["Character", "\u0062"]]}, {"description": "Valid numeric entity character U+0063", "input": "c", "output": [["Character", "\u0063"]]}, {"description": "Valid numeric entity character U+0064", "input": "d", "output": [["Character", "\u0064"]]}, {"description": "Valid numeric entity character U+0065", "input": "e", "output": [["Character", "\u0065"]]}, {"description": "Valid numeric entity character U+0066", "input": "f", "output": [["Character", "\u0066"]]}, {"description": "Valid numeric entity character U+0067", "input": "g", "output": [["Character", "\u0067"]]}, {"description": "Valid numeric entity character U+0068", "input": "h", "output": [["Character", "\u0068"]]}, {"description": "Valid numeric entity character U+0069", "input": "i", "output": [["Character", "\u0069"]]}, {"description": "Valid numeric entity character U+006A", "input": "j", "output": [["Character", "\u006A"]]}, {"description": "Valid numeric entity character U+006B", "input": "k", "output": [["Character", "\u006B"]]}, {"description": "Valid numeric entity character U+006C", "input": "l", "output": [["Character", "\u006C"]]}, {"description": "Valid numeric entity character U+006D", "input": "m", "output": [["Character", "\u006D"]]}, {"description": "Valid numeric entity character U+006E", "input": "n", "output": [["Character", "\u006E"]]}, {"description": "Valid numeric entity character U+006F", "input": "o", "output": [["Character", "\u006F"]]}, {"description": "Valid numeric entity character U+0070", "input": "p", "output": [["Character", "\u0070"]]}, {"description": "Valid numeric entity character U+0071", "input": "q", "output": [["Character", "\u0071"]]}, {"description": "Valid numeric entity character U+0072", "input": "r", "output": [["Character", "\u0072"]]}, {"description": "Valid numeric entity character U+0073", "input": "s", "output": [["Character", "\u0073"]]}, {"description": "Valid numeric entity character U+0074", "input": "t", "output": [["Character", "\u0074"]]}, {"description": "Valid numeric entity character U+0075", "input": "u", "output": [["Character", "\u0075"]]}, {"description": "Valid numeric entity character U+0076", "input": "v", "output": [["Character", "\u0076"]]}, {"description": "Valid numeric entity character U+0077", "input": "w", "output": [["Character", "\u0077"]]}, {"description": "Valid numeric entity character U+0078", "input": "x", "output": [["Character", "\u0078"]]}, {"description": "Valid numeric entity character U+0079", "input": "y", "output": [["Character", "\u0079"]]}, {"description": "Valid numeric entity character U+007A", "input": "z", "output": [["Character", "\u007A"]]}, {"description": "Valid numeric entity character U+007B", "input": "{", "output": [["Character", "\u007B"]]}, {"description": "Valid numeric entity character U+007C", "input": "|", "output": [["Character", "\u007C"]]}, {"description": "Valid numeric entity character U+007D", "input": "}", "output": [["Character", "\u007D"]]}, {"description": "Valid numeric entity character U+007E", "input": "~", "output": [["Character", "\u007E"]]}, {"description": "Valid numeric entity character U+00A0", "input": " ", "output": [["Character", "\u00A0"]]}, {"description": "Valid numeric entity character U+00A1", "input": "¡", "output": [["Character", "\u00A1"]]}, {"description": "Valid numeric entity character U+00A2", "input": "¢", "output": [["Character", "\u00A2"]]}, {"description": "Valid numeric entity character U+00A3", "input": "£", "output": [["Character", "\u00A3"]]}, {"description": "Valid numeric entity character U+00A4", "input": "¤", "output": [["Character", "\u00A4"]]}, {"description": "Valid numeric entity character U+00A5", "input": "¥", "output": [["Character", "\u00A5"]]}, {"description": "Valid numeric entity character U+00A6", "input": "¦", "output": [["Character", "\u00A6"]]}, {"description": "Valid numeric entity character U+00A7", "input": "§", "output": [["Character", "\u00A7"]]}, {"description": "Valid numeric entity character U+00A8", "input": "¨", "output": [["Character", "\u00A8"]]}, {"description": "Valid numeric entity character U+00A9", "input": "©", "output": [["Character", "\u00A9"]]}, {"description": "Valid numeric entity character U+00AA", "input": "ª", "output": [["Character", "\u00AA"]]}, {"description": "Valid numeric entity character U+00AB", "input": "«", "output": [["Character", "\u00AB"]]}, {"description": "Valid numeric entity character U+00AC", "input": "¬", "output": [["Character", "\u00AC"]]}, {"description": "Valid numeric entity character U+00AD", "input": "­", "output": [["Character", "\u00AD"]]}, {"description": "Valid numeric entity character U+00AE", "input": "®", "output": [["Character", "\u00AE"]]}, {"description": "Valid numeric entity character U+00AF", "input": "¯", "output": [["Character", "\u00AF"]]}, {"description": "Valid numeric entity character U+00B0", "input": "°", "output": [["Character", "\u00B0"]]}, {"description": "Valid numeric entity character U+00B1", "input": "±", "output": [["Character", "\u00B1"]]}, {"description": "Valid numeric entity character U+00B2", "input": "²", "output": [["Character", "\u00B2"]]}, {"description": "Valid numeric entity character U+00B3", "input": "³", "output": [["Character", "\u00B3"]]}, {"description": "Valid numeric entity character U+00B4", "input": "´", "output": [["Character", "\u00B4"]]}, {"description": "Valid numeric entity character U+00B5", "input": "µ", "output": [["Character", "\u00B5"]]}, {"description": "Valid numeric entity character U+00B6", "input": "¶", "output": [["Character", "\u00B6"]]}, {"description": "Valid numeric entity character U+00B7", "input": "·", "output": [["Character", "\u00B7"]]}, {"description": "Valid numeric entity character U+00B8", "input": "¸", "output": [["Character", "\u00B8"]]}, {"description": "Valid numeric entity character U+00B9", "input": "¹", "output": [["Character", "\u00B9"]]}, {"description": "Valid numeric entity character U+00BA", "input": "º", "output": [["Character", "\u00BA"]]}, {"description": "Valid numeric entity character U+00BB", "input": "»", "output": [["Character", "\u00BB"]]}, {"description": "Valid numeric entity character U+00BC", "input": "¼", "output": [["Character", "\u00BC"]]}, {"description": "Valid numeric entity character U+00BD", "input": "½", "output": [["Character", "\u00BD"]]}, {"description": "Valid numeric entity character U+00BE", "input": "¾", "output": [["Character", "\u00BE"]]}, {"description": "Valid numeric entity character U+00BF", "input": "¿", "output": [["Character", "\u00BF"]]}, {"description": "Valid numeric entity character U+00C0", "input": "À", "output": [["Character", "\u00C0"]]}, {"description": "Valid numeric entity character U+00C1", "input": "Á", "output": [["Character", "\u00C1"]]}, {"description": "Valid numeric entity character U+00C2", "input": "Â", "output": [["Character", "\u00C2"]]}, {"description": "Valid numeric entity character U+00C3", "input": "Ã", "output": [["Character", "\u00C3"]]}, {"description": "Valid numeric entity character U+00C4", "input": "Ä", "output": [["Character", "\u00C4"]]}, {"description": "Valid numeric entity character U+00C5", "input": "Å", "output": [["Character", "\u00C5"]]}, {"description": "Valid numeric entity character U+00C6", "input": "Æ", "output": [["Character", "\u00C6"]]}, {"description": "Valid numeric entity character U+00C7", "input": "Ç", "output": [["Character", "\u00C7"]]}, {"description": "Valid numeric entity character U+00C8", "input": "È", "output": [["Character", "\u00C8"]]}, {"description": "Valid numeric entity character U+00C9", "input": "É", "output": [["Character", "\u00C9"]]}, {"description": "Valid numeric entity character U+00CA", "input": "Ê", "output": [["Character", "\u00CA"]]}, {"description": "Valid numeric entity character U+00CB", "input": "Ë", "output": [["Character", "\u00CB"]]}, {"description": "Valid numeric entity character U+00CC", "input": "Ì", "output": [["Character", "\u00CC"]]}, {"description": "Valid numeric entity character U+00CD", "input": "Í", "output": [["Character", "\u00CD"]]}, {"description": "Valid numeric entity character U+00CE", "input": "Î", "output": [["Character", "\u00CE"]]}, {"description": "Valid numeric entity character U+00CF", "input": "Ï", "output": [["Character", "\u00CF"]]}, {"description": "Valid numeric entity character U+00D0", "input": "Ð", "output": [["Character", "\u00D0"]]}, {"description": "Valid numeric entity character U+00D1", "input": "Ñ", "output": [["Character", "\u00D1"]]}, {"description": "Valid numeric entity character U+00D2", "input": "Ò", "output": [["Character", "\u00D2"]]}, {"description": "Valid numeric entity character U+00D3", "input": "Ó", "output": [["Character", "\u00D3"]]}, {"description": "Valid numeric entity character U+00D4", "input": "Ô", "output": [["Character", "\u00D4"]]}, {"description": "Valid numeric entity character U+00D5", "input": "Õ", "output": [["Character", "\u00D5"]]}, {"description": "Valid numeric entity character U+00D6", "input": "Ö", "output": [["Character", "\u00D6"]]}, {"description": "Valid numeric entity character U+00D7", "input": "×", "output": [["Character", "\u00D7"]]}, {"description": "Valid numeric entity character U+00D8", "input": "Ø", "output": [["Character", "\u00D8"]]}, {"description": "Valid numeric entity character U+00D9", "input": "Ù", "output": [["Character", "\u00D9"]]}, {"description": "Valid numeric entity character U+00DA", "input": "Ú", "output": [["Character", "\u00DA"]]}, {"description": "Valid numeric entity character U+00DB", "input": "Û", "output": [["Character", "\u00DB"]]}, {"description": "Valid numeric entity character U+00DC", "input": "Ü", "output": [["Character", "\u00DC"]]}, {"description": "Valid numeric entity character U+00DD", "input": "Ý", "output": [["Character", "\u00DD"]]}, {"description": "Valid numeric entity character U+00DE", "input": "Þ", "output": [["Character", "\u00DE"]]}, {"description": "Valid numeric entity character U+00DF", "input": "ß", "output": [["Character", "\u00DF"]]}, {"description": "Valid numeric entity character U+00E0", "input": "à", "output": [["Character", "\u00E0"]]}, {"description": "Valid numeric entity character U+00E1", "input": "á", "output": [["Character", "\u00E1"]]}, {"description": "Valid numeric entity character U+00E2", "input": "â", "output": [["Character", "\u00E2"]]}, {"description": "Valid numeric entity character U+00E3", "input": "ã", "output": [["Character", "\u00E3"]]}, {"description": "Valid numeric entity character U+00E4", "input": "ä", "output": [["Character", "\u00E4"]]}, {"description": "Valid numeric entity character U+00E5", "input": "å", "output": [["Character", "\u00E5"]]}, {"description": "Valid numeric entity character U+00E6", "input": "æ", "output": [["Character", "\u00E6"]]}, {"description": "Valid numeric entity character U+00E7", "input": "ç", "output": [["Character", "\u00E7"]]}, {"description": "Valid numeric entity character U+00E8", "input": "è", "output": [["Character", "\u00E8"]]}, {"description": "Valid numeric entity character U+00E9", "input": "é", "output": [["Character", "\u00E9"]]}, {"description": "Valid numeric entity character U+00EA", "input": "ê", "output": [["Character", "\u00EA"]]}, {"description": "Valid numeric entity character U+00EB", "input": "ë", "output": [["Character", "\u00EB"]]}, {"description": "Valid numeric entity character U+00EC", "input": "ì", "output": [["Character", "\u00EC"]]}, {"description": "Valid numeric entity character U+00ED", "input": "í", "output": [["Character", "\u00ED"]]}, {"description": "Valid numeric entity character U+00EE", "input": "î", "output": [["Character", "\u00EE"]]}, {"description": "Valid numeric entity character U+00EF", "input": "ï", "output": [["Character", "\u00EF"]]}, {"description": "Valid numeric entity character U+00F0", "input": "ð", "output": [["Character", "\u00F0"]]}, {"description": "Valid numeric entity character U+00F1", "input": "ñ", "output": [["Character", "\u00F1"]]}, {"description": "Valid numeric entity character U+00F2", "input": "ò", "output": [["Character", "\u00F2"]]}, {"description": "Valid numeric entity character U+00F3", "input": "ó", "output": [["Character", "\u00F3"]]}, {"description": "Valid numeric entity character U+00F4", "input": "ô", "output": [["Character", "\u00F4"]]}, {"description": "Valid numeric entity character U+00F5", "input": "õ", "output": [["Character", "\u00F5"]]}, {"description": "Valid numeric entity character U+00F6", "input": "ö", "output": [["Character", "\u00F6"]]}, {"description": "Valid numeric entity character U+00F7", "input": "÷", "output": [["Character", "\u00F7"]]}, {"description": "Valid numeric entity character U+00F8", "input": "ø", "output": [["Character", "\u00F8"]]}, {"description": "Valid numeric entity character U+00F9", "input": "ù", "output": [["Character", "\u00F9"]]}, {"description": "Valid numeric entity character U+00FA", "input": "ú", "output": [["Character", "\u00FA"]]}, {"description": "Valid numeric entity character U+00FB", "input": "û", "output": [["Character", "\u00FB"]]}, {"description": "Valid numeric entity character U+00FC", "input": "ü", "output": [["Character", "\u00FC"]]}, {"description": "Valid numeric entity character U+00FD", "input": "ý", "output": [["Character", "\u00FD"]]}, {"description": "Valid numeric entity character U+00FE", "input": "þ", "output": [["Character", "\u00FE"]]}, {"description": "Valid numeric entity character U+00FF", "input": "ÿ", "output": [["Character", "\u00FF"]]}, {"description": "Valid numeric entity character U+D7FF", "input": "퟿", "output": [["Character", "\uD7FF"]]}, {"description": "Valid numeric entity character U+E000", "input": "", "output": [["Character", "\uE000"]]}, {"description": "Valid numeric entity character U+FDCF", "input": "﷏", "output": [["Character", "\uFDCF"]]}, {"description": "Valid numeric entity character U+FDF0", "input": "ﷰ", "output": [["Character", "\uFDF0"]]}, {"description": "Valid numeric entity character U+FFFD", "input": "�", "output": [["Character", "\uFFFD"]]}, {"description": "Valid numeric entity character U+10000", "input": "𐀀", "output": [["Character", "\uD800\uDC00"]]}, {"description": "Valid numeric entity character U+1FFFD", "input": "🿽", "output": [["Character", "\uD83F\uDFFD"]]}, {"description": "Valid numeric entity character U+20000", "input": "𠀀", "output": [["Character", "\uD840\uDC00"]]}, {"description": "Valid numeric entity character U+2FFFD", "input": "𯿽", "output": [["Character", "\uD87F\uDFFD"]]}, {"description": "Valid numeric entity character U+30000", "input": "𰀀", "output": [["Character", "\uD880\uDC00"]]}, {"description": "Valid numeric entity character U+3FFFD", "input": "𿿽", "output": [["Character", "\uD8BF\uDFFD"]]}, {"description": "Valid numeric entity character U+40000", "input": "񀀀", "output": [["Character", "\uD8C0\uDC00"]]}, {"description": "Valid numeric entity character U+4FFFD", "input": "񏿽", "output": [["Character", "\uD8FF\uDFFD"]]}, {"description": "Valid numeric entity character U+50000", "input": "񐀀", "output": [["Character", "\uD900\uDC00"]]}, {"description": "Valid numeric entity character U+5FFFD", "input": "񟿽", "output": [["Character", "\uD93F\uDFFD"]]}, {"description": "Valid numeric entity character U+60000", "input": "񠀀", "output": [["Character", "\uD940\uDC00"]]}, {"description": "Valid numeric entity character U+6FFFD", "input": "񯿽", "output": [["Character", "\uD97F\uDFFD"]]}, {"description": "Valid numeric entity character U+70000", "input": "񰀀", "output": [["Character", "\uD980\uDC00"]]}, {"description": "Valid numeric entity character U+7FFFD", "input": "񿿽", "output": [["Character", "\uD9BF\uDFFD"]]}, {"description": "Valid numeric entity character U+80000", "input": "򀀀", "output": [["Character", "\uD9C0\uDC00"]]}, {"description": "Valid numeric entity character U+8FFFD", "input": "򏿽", "output": [["Character", "\uD9FF\uDFFD"]]}, {"description": "Valid numeric entity character U+90000", "input": "򐀀", "output": [["Character", "\uDA00\uDC00"]]}, {"description": "Valid numeric entity character U+9FFFD", "input": "򟿽", "output": [["Character", "\uDA3F\uDFFD"]]}, {"description": "Valid numeric entity character U+A0000", "input": "򠀀", "output": [["Character", "\uDA40\uDC00"]]}, {"description": "Valid numeric entity character U+AFFFD", "input": "򯿽", "output": [["Character", "\uDA7F\uDFFD"]]}, {"description": "Valid numeric entity character U+B0000", "input": "򰀀", "output": [["Character", "\uDA80\uDC00"]]}, {"description": "Valid numeric entity character U+BFFFD", "input": "򿿽", "output": [["Character", "\uDABF\uDFFD"]]}, {"description": "Valid numeric entity character U+C0000", "input": "󀀀", "output": [["Character", "\uDAC0\uDC00"]]}, {"description": "Valid numeric entity character U+CFFFD", "input": "󏿽", "output": [["Character", "\uDAFF\uDFFD"]]}, {"description": "Valid numeric entity character U+D0000", "input": "󐀀", "output": [["Character", "\uDB00\uDC00"]]}, {"description": "Valid numeric entity character U+DFFFD", "input": "󟿽", "output": [["Character", "\uDB3F\uDFFD"]]}, {"description": "Valid numeric entity character U+E0000", "input": "󠀀", "output": [["Character", "\uDB40\uDC00"]]}, {"description": "Valid numeric entity character U+EFFFD", "input": "󯿽", "output": [["Character", "\uDB7F\uDFFD"]]}, {"description": "Valid numeric entity character U+F0000", "input": "󰀀", "output": [["Character", "\uDB80\uDC00"]]}, {"description": "Valid numeric entity character U+FFFFD", "input": "󿿽", "output": [["Character", "\uDBBF\uDFFD"]]}, {"description": "Valid numeric entity character U+100000", "input": "􀀀", "output": [["Character", "\uDBC0\uDC00"]]}, {"description": "Valid numeric entity character U+10FFFD", "input": "􏿽", "output": [["Character", "\uDBFF\uDFFD"]]} ]} netsurf-2.9/hubbub-0.1.2/test/tokeniser2.c0000664000175000017500000003052011476512132017163 0ustar vincevince#include #include #include #include #include #include #include "utils/utils.h" #include "tokeniser/tokeniser.h" #include "testutils.h" typedef struct context { const uint8_t *pbuffer; const uint8_t *input; size_t input_len; struct array_list *output; int output_index; size_t char_off; const char *last_start_tag; struct array_list *content_model; bool process_cdata; } context; static void run_test(context *ctx); static hubbub_error token_handler(const hubbub_token *token, void *pw); static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { struct json_object *json; struct array_list *tests; struct lh_entry *entry; char *key; struct json_object *val; int i; context ctx; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } json = json_object_from_file(argv[1]); assert(!is_error(json)); assert(strcmp((char *) ((json_object_get_object(json)->head)->k), "tests") == 0); /* Get array of tests */ tests = json_object_get_array((struct json_object *) (json_object_get_object(json)->head)->v); for (i = 0; i < array_list_length(tests); i++) { /* Get test */ struct json_object *test = (struct json_object *) array_list_get_idx(tests, i); ctx.last_start_tag = NULL; ctx.content_model = NULL; ctx.process_cdata = false; /* Extract settings */ for (entry = json_object_get_object(test)->head; entry; entry = entry->next) { key = (char *) entry->k; val = (struct json_object *) entry->v; if (strcmp(key, "description") == 0) { printf("Test: %s\n", json_object_get_string(val)); } else if (strcmp(key, "input") == 0) { int len; ctx.input = (const uint8_t *) json_object_get_string_len(val, &len); ctx.input_len = len; } else if (strcmp(key, "output") == 0) { ctx.output = json_object_get_array(val); ctx.output_index = 0; ctx.char_off = 0; } else if (strcmp(key, "lastStartTag") == 0) { ctx.last_start_tag = (const char *) json_object_get_string(val); } else if (strcmp(key, "contentModelFlags") == 0) { ctx.content_model = json_object_get_array(val); } else if (strcmp(key, "processCDATA") == 0) { ctx.process_cdata = json_object_get_boolean(val); } } /* And run the test */ run_test(&ctx); } json_object_put(json); printf("PASS\n"); return 0; } void run_test(context *ctx) { parserutils_inputstream *stream; hubbub_tokeniser *tok; hubbub_tokeniser_optparams params; int i, max_i; struct array_list *outputsave = ctx->output; if (ctx->content_model == NULL) { max_i = 1; } else { max_i = array_list_length(ctx->content_model); } /* We test for each of the content models specified */ for (i = 0; i < max_i; i++) { /* Reset expected output */ ctx->output = outputsave; ctx->output_index = 0; ctx->char_off = 0; assert(parserutils_inputstream_create("UTF-8", 0, NULL, myrealloc, NULL, &stream) == PARSERUTILS_OK); assert(hubbub_tokeniser_create(stream, myrealloc, NULL, &tok) == HUBBUB_OK); if (ctx->last_start_tag != NULL) { /* Fake up a start tag, in PCDATA state */ size_t len = strlen(ctx->last_start_tag) + 3; uint8_t *buf = alloca(len); snprintf((char *) buf, len, "<%s>", ctx->last_start_tag); assert(parserutils_inputstream_append(stream, buf, len - 1) == HUBBUB_OK); assert(hubbub_tokeniser_run(tok) == HUBBUB_OK); } if (ctx->process_cdata) { params.process_cdata = ctx->process_cdata; assert(hubbub_tokeniser_setopt(tok, HUBBUB_TOKENISER_PROCESS_CDATA, ¶ms) == HUBBUB_OK); } params.token_handler.handler = token_handler; params.token_handler.pw = ctx; assert(hubbub_tokeniser_setopt(tok, HUBBUB_TOKENISER_TOKEN_HANDLER, ¶ms) == HUBBUB_OK); if (ctx->content_model == NULL) { params.content_model.model = HUBBUB_CONTENT_MODEL_PCDATA; } else { char *cm = json_object_get_string( (struct json_object *) array_list_get_idx(ctx->content_model, i)); if (strcmp(cm, "PCDATA") == 0) { params.content_model.model = HUBBUB_CONTENT_MODEL_PCDATA; } else if (strcmp(cm, "RCDATA") == 0) { params.content_model.model = HUBBUB_CONTENT_MODEL_RCDATA; } else if (strcmp(cm, "CDATA") == 0) { params.content_model.model = HUBBUB_CONTENT_MODEL_CDATA; } else { params.content_model.model = HUBBUB_CONTENT_MODEL_PLAINTEXT; } } assert(hubbub_tokeniser_setopt(tok, HUBBUB_TOKENISER_CONTENT_MODEL, ¶ms) == HUBBUB_OK); assert(parserutils_inputstream_append(stream, ctx->input, ctx->input_len) == HUBBUB_OK); assert(parserutils_inputstream_append(stream, NULL, 0) == HUBBUB_OK); printf("Input: '%.*s' (%d)\n", (int) ctx->input_len, (const char *) ctx->input, (int) ctx->input_len); assert(hubbub_tokeniser_run(tok) == HUBBUB_OK); hubbub_tokeniser_destroy(tok); parserutils_inputstream_destroy(stream); } } hubbub_error token_handler(const hubbub_token *token, void *pw) { static const char *token_names[] = { "DOCTYPE", "StartTag", "EndTag", "Comment", "Character", "EOF" }; size_t i; context *ctx = (context *) pw; struct json_object *obj = NULL; struct array_list *items; for (; ctx->output_index < array_list_length(ctx->output); ctx->output_index++) { /* Get object for index */ obj = (struct json_object *) array_list_get_idx(ctx->output, ctx->output_index); /* If it's not a string, we've found the expected output */ if (json_object_get_type(obj) != json_type_string) break; /* Otherwise, it must be a parse error */ assert(strcmp(json_object_get_string(obj), "ParseError") == 0); } /* If we've run off the end, this is an error -- the tokeniser has * produced more tokens than expected. We allow for the generation * of a terminating EOF token, however. */ assert("too many tokens" && (ctx->output_index < array_list_length(ctx->output) || token->type == HUBBUB_TOKEN_EOF)); /* Got a terminating EOF -- no error */ if (ctx->output_index >= array_list_length(ctx->output)) return HUBBUB_OK; /* Now increment the output index so we don't re-expect this token */ ctx->output_index++; /* Expected output must be an array */ assert(json_object_get_type(obj) == json_type_array); items = json_object_get_array(obj); printf("got %s: expected %s\n", token_names[token->type], json_object_get_string((struct json_object *) array_list_get_idx(items, 0))); /* Make sure we got the token we expected */ assert(strcmp(token_names[token->type], json_object_get_string((struct json_object *) array_list_get_idx(items, 0))) == 0); switch (token->type) { case HUBBUB_TOKEN_DOCTYPE: { char *expname = json_object_get_string( array_list_get_idx(items, 1)); char *exppub = json_object_get_string( array_list_get_idx(items, 2)); char *expsys = json_object_get_string( array_list_get_idx(items, 3)); bool expquirks = !json_object_get_boolean( array_list_get_idx(items, 4)); const char *gotname = (const char *)token->data.doctype.name.ptr; const char *gotpub, *gotsys; printf("'%.*s' %sids:\n", (int) token->data.doctype.name.len, gotname, token->data.doctype.force_quirks ? "(force-quirks) " : ""); if (token->data.doctype.public_missing) { gotpub = NULL; printf("\tpublic: missing\n"); } else { gotpub = (const char *) token->data.doctype.public_id.ptr; printf("\tpublic: '%.*s' (%d)\n", (int) token->data.doctype.public_id.len, gotpub, (int) token->data.doctype.public_id.len); } if (token->data.doctype.system_missing) { gotsys = NULL; printf("\tsystem: missing\n"); } else { gotsys = (const char *) token->data.doctype.system_id.ptr; printf("\tsystem: '%.*s' (%d)\n", (int) token->data.doctype.system_id.len, gotsys, (int) token->data.doctype.system_id.len); } assert(token->data.doctype.name.len == strlen(expname)); assert(strncmp(gotname, expname, strlen(expname)) == 0); assert((exppub == NULL) == (token->data.doctype.public_missing == true)); if (exppub) { assert(token->data.doctype.public_id.len == strlen(exppub)); assert(strncmp(gotpub, exppub, strlen(exppub)) == 0); } assert((expsys == NULL) == (token->data.doctype.system_missing == true)); if (gotsys) { assert(token->data.doctype.system_id.len == strlen(expsys)); assert(strncmp(gotsys, expsys, strlen(expsys)) == 0); } assert(expquirks == token->data.doctype.force_quirks); } break; case HUBBUB_TOKEN_START_TAG: { char *expname = json_object_get_string( array_list_get_idx(items, 1)); struct lh_entry *expattrs = json_object_get_object( array_list_get_idx(items, 2))->head; bool self_closing = json_object_get_boolean( array_list_get_idx(items, 3)); const char *tagname = (const char *) token->data.tag.name.ptr; printf("expected: '%s' %s\n", expname, (self_closing) ? "(self-closing) " : ""); printf(" got: '%.*s' %s\n", (int) token->data.tag.name.len, tagname, (token->data.tag.self_closing) ? "(self-closing) " : ""); if (token->data.tag.n_attributes > 0) { printf("attributes:\n"); } assert(token->data.tag.name.len == strlen(expname)); assert(strncmp(tagname, expname, strlen(expname)) == 0); assert((token->data.tag.n_attributes == 0) == (expattrs == NULL)); assert(self_closing == token->data.tag.self_closing); for (i = 0; i < token->data.tag.n_attributes; i++) { char *expname = (char *) expattrs->k; char *expval = json_object_get_string( (struct json_object *) expattrs->v); const char *gotname = (const char *) token->data.tag.attributes[i].name.ptr; size_t namelen = token->data.tag.attributes[i].name.len; const char *gotval = (const char *) token->data.tag.attributes[i].value.ptr; size_t vallen = token->data.tag.attributes[i].value.len; printf("\t'%.*s' = '%.*s'\n", (int) namelen, gotname, (int) vallen, gotval); assert(namelen == strlen(expname)); assert(strncmp(gotname, expname, strlen(expname)) == 0); assert(vallen == strlen(expval)); assert(strncmp(gotval, expval, strlen(expval)) == 0); expattrs = expattrs->next; } assert(expattrs == NULL); } break; case HUBBUB_TOKEN_END_TAG: { char *expname = json_object_get_string( array_list_get_idx(items, 1)); const char *tagname = (const char *) token->data.tag.name.ptr; printf("'%.*s' %s\n", (int) token->data.tag.name.len, tagname, (token->data.tag.n_attributes > 0) ? "attributes:" : ""); assert(token->data.tag.name.len == strlen(expname)); assert(strncmp(tagname, expname, strlen(expname)) == 0); } break; case HUBBUB_TOKEN_COMMENT: { char *expstr = json_object_get_string( array_list_get_idx(items, 1)); const char *gotstr = (const char *) token->data.comment.ptr; printf("expected: '%s'\n", expstr); printf(" got: '%.*s'\n", (int) token->data.comment.len, gotstr); assert(token->data.comment.len == strlen(expstr)); assert(strncmp(gotstr, expstr, strlen(expstr)) == 0); } break; case HUBBUB_TOKEN_CHARACTER: { int expstrlen; char *expstr = json_object_get_string_len( array_list_get_idx(items, 1), &expstrlen); const char *gotstr = (const char *) token->data.character.ptr; size_t len = min(token->data.character.len, expstrlen - ctx->char_off); printf("expected: '%.*s'\n", (int) len, expstr + ctx->char_off); printf(" got: '%.*s'\n", (int) token->data.character.len, gotstr); assert(memcmp(gotstr, expstr + ctx->char_off, len) == 0); if (len < token->data.character.len) { /* Expected token only contained part of the data * Calculate how much is left, then try again with * the next expected token */ hubbub_token t; t.type = HUBBUB_TOKEN_CHARACTER; t.data.character.ptr += len; t.data.character.len -= len; ctx->char_off = 0; token_handler(&t, pw); } else if (strlen(expstr + ctx->char_off) > token->data.character.len) { /* Tokeniser output only contained part of the data * in the expected token; calculate the offset into * the token and process the remainder next time */ ctx->char_off += len; ctx->output_index--; } else { /* Exact match - clear offset */ ctx->char_off = 0; } } break; case HUBBUB_TOKEN_EOF: printf("\n"); break; } return HUBBUB_OK; } netsurf-2.9/hubbub-0.1.2/test/tree.c0000664000175000017500000002313611476512132016042 0ustar vincevince#include #include #include #include #include #include #include #include "utils/utils.h" #include "testutils.h" #define NODE_REF_CHUNK 8192 static uint16_t *node_ref; static uintptr_t node_ref_alloc; static uintptr_t node_counter; #define GROW_REF \ if (node_counter >= node_ref_alloc) { \ uint16_t *temp = realloc(node_ref, \ (node_ref_alloc + NODE_REF_CHUNK) * \ sizeof(uint16_t)); \ if (temp == NULL) { \ printf("FAIL - no memory\n"); \ exit(1); \ } \ node_ref = temp; \ node_ref_alloc += NODE_REF_CHUNK; \ } static hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result); static hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, void **result); static hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result); static hubbub_error create_text(void *ctx, const hubbub_string *data, void **result); static hubbub_error ref_node(void *ctx, void *node); static hubbub_error unref_node(void *ctx, void *node); static hubbub_error append_child(void *ctx, void *parent, void *child, void **result); static hubbub_error insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result); static hubbub_error remove_child(void *ctx, void *parent, void *child, void **result); static hubbub_error clone_node(void *ctx, void *node, bool deep, void **result); static hubbub_error reparent_children(void *ctx, void *node, void *new_parent); static hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result); static hubbub_error has_children(void *ctx, void *node, bool *result); static hubbub_error form_associate(void *ctx, void *form, void *node); static hubbub_error add_attributes(void *ctx, void *node, const hubbub_attribute *attributes, uint32_t n_attributes); static hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode); static hubbub_tree_handler tree_handler = { create_comment, create_doctype, create_element, create_text, ref_node, unref_node, append_child, insert_before, remove_child, clone_node, reparent_children, get_parent, has_children, form_associate, add_attributes, set_quirks_mode, NULL, NULL }; static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } static int run_test(int argc, char **argv, unsigned int CHUNK_SIZE) { hubbub_parser *parser; hubbub_parser_optparams params; FILE *fp; size_t len, origlen; uint8_t *buf = alloca(CHUNK_SIZE); const char *charset; hubbub_charset_source cssource; bool passed = true; uintptr_t n; UNUSED(argc); node_ref = calloc(NODE_REF_CHUNK, sizeof(uint16_t)); if (node_ref == NULL) { printf("Failed allocating node_ref\n"); return 1; } node_ref_alloc = NODE_REF_CHUNK; assert(hubbub_parser_create("UTF-8", false, myrealloc, NULL, &parser) == HUBBUB_OK); params.tree_handler = &tree_handler; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_TREE_HANDLER, ¶ms) == HUBBUB_OK); params.document_node = (void *) ++node_counter; ref_node(NULL, (void *) node_counter); assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_DOCUMENT_NODE, ¶ms) == HUBBUB_OK); fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Failed opening %s\n", argv[1]); return 1; } fseek(fp, 0, SEEK_END); origlen = len = ftell(fp); fseek(fp, 0, SEEK_SET); while (len > 0) { ssize_t bytes_read = fread(buf, 1, CHUNK_SIZE, fp); if (bytes_read < 1) break; assert(hubbub_parser_parse_chunk(parser, buf, bytes_read) == HUBBUB_OK); len -= bytes_read; } assert(len == 0); fclose(fp); charset = hubbub_parser_read_charset(parser, &cssource); printf("Charset: %s (from %d)\n", charset, cssource); hubbub_parser_destroy(parser); /* Ensure that all nodes have been released by the treebuilder */ for (n = 1; n <= node_counter; n++) { if (node_ref[n] != 0) { printf("%" PRIuPTR " still referenced (=%u)\n", n, node_ref[n]); passed = false; } } free(node_ref); node_counter = 0; printf("%s\n", passed ? "PASS" : "FAIL"); return passed ? 0 : 1; } int main(int argc, char **argv) { int ret; int shift; int offset; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } #define DO_TEST(n) if ((ret = run_test(argc, argv, (n))) != 0) return ret for (shift = 0; (1 << shift) != 16384; shift++) for (offset = 0; offset < 10; offset += 3) DO_TEST((1 << shift) + offset); return 0; #undef DO_TEST } hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result) { printf("Creating (%" PRIuPTR ") [comment '%.*s']\n", ++node_counter, (int) data->len, data->ptr); assert(memchr(data->ptr, 0xff, data->len) == NULL); GROW_REF node_ref[node_counter] = 0; ref_node(ctx, (void *) node_counter); *result = (void *) node_counter; return HUBBUB_OK; } hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, void **result) { printf("Creating (%" PRIuPTR ") [doctype '%.*s']\n", ++node_counter, (int) doctype->name.len, doctype->name.ptr); assert(memchr(doctype->name.ptr, 0xff, doctype->name.len) == NULL); if (doctype->public_missing == false) { assert(memchr(doctype->public_id.ptr, 0xff, doctype->public_id.len) == NULL); } if (doctype->system_missing == false) { assert(memchr(doctype->system_id.ptr, 0xff, doctype->system_id.len) == NULL); } GROW_REF node_ref[node_counter] = 0; ref_node(ctx, (void *) node_counter); *result = (void *) node_counter; return HUBBUB_OK; } hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result) { uint32_t i; printf("Creating (%" PRIuPTR ") [element '%.*s']\n", ++node_counter, (int) tag->name.len, tag->name.ptr); assert(memchr(tag->name.ptr, 0xff, tag->name.len) == NULL); for (i = 0; i < tag->n_attributes; i++) { hubbub_attribute *attr = &tag->attributes[i]; assert(memchr(attr->name.ptr, 0xff, attr->name.len) == NULL); assert(memchr(attr->value.ptr, 0xff, attr->value.len) == NULL); } GROW_REF node_ref[node_counter] = 0; ref_node(ctx, (void *) node_counter); *result = (void *) node_counter; return HUBBUB_OK; } hubbub_error create_text(void *ctx, const hubbub_string *data, void **result) { printf("Creating (%" PRIuPTR ") [text '%.*s']\n", ++node_counter, (int) data->len, data->ptr); assert(memchr(data->ptr, 0xff, data->len) == NULL); GROW_REF node_ref[node_counter] = 0; ref_node(ctx, (void *) node_counter); *result = (void *) node_counter; return HUBBUB_OK; } hubbub_error ref_node(void *ctx, void *node) { UNUSED(ctx); printf("Referencing %" PRIuPTR " (=%u)\n", (uintptr_t) node, ++node_ref[(uintptr_t) node]); return HUBBUB_OK; } hubbub_error unref_node(void *ctx, void *node) { UNUSED(ctx); printf("Unreferencing %" PRIuPTR " (=%u)\n", (uintptr_t) node, --node_ref[(uintptr_t) node]); return HUBBUB_OK; } hubbub_error append_child(void *ctx, void *parent, void *child, void **result) { printf("Appending %" PRIuPTR " to %" PRIuPTR "\n", (uintptr_t) child, (uintptr_t) parent); ref_node(ctx, child); *result = (void *) child; return HUBBUB_OK; } hubbub_error insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result) { printf("Inserting %" PRIuPTR " in %" PRIuPTR " before %" PRIuPTR "\n", (uintptr_t) child, (uintptr_t) parent, (uintptr_t) ref_child); ref_node(ctx, child); *result = (void *) child; return HUBBUB_OK; } hubbub_error remove_child(void *ctx, void *parent, void *child, void **result) { printf("Removing %" PRIuPTR " from %" PRIuPTR "\n", (uintptr_t) child, (uintptr_t) parent); ref_node(ctx, child); *result = (void *) child; return HUBBUB_OK; } hubbub_error clone_node(void *ctx, void *node, bool deep, void **result) { printf("%sCloning %" PRIuPTR " -> %" PRIuPTR "\n", deep ? "Deep-" : "", (uintptr_t) node, ++node_counter); GROW_REF node_ref[node_counter] = 0; ref_node(ctx, (void *) node_counter); *result = (void *) node_counter; return HUBBUB_OK; } hubbub_error reparent_children(void *ctx, void *node, void *new_parent) { UNUSED(ctx); printf("Reparenting children of %" PRIuPTR " to %" PRIuPTR "\n", (uintptr_t) node, (uintptr_t) new_parent); return HUBBUB_OK; } hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result) { printf("Retrieving parent of %" PRIuPTR " (%s)\n", (uintptr_t) node, element_only ? "element only" : ""); ref_node(ctx, (void *) 1); *result = (void *) 1; return HUBBUB_OK; } hubbub_error has_children(void *ctx, void *node, bool *result) { UNUSED(ctx); printf("Want children for %" PRIuPTR "\n", (uintptr_t) node); *result = false; return HUBBUB_OK; } hubbub_error form_associate(void *ctx, void *form, void *node) { UNUSED(ctx); printf("Associating %" PRIuPTR " with form %" PRIuPTR "\n", (uintptr_t) node, (uintptr_t) form); return HUBBUB_OK; } hubbub_error add_attributes(void *ctx, void *node, const hubbub_attribute *attributes, uint32_t n_attributes) { uint32_t i; UNUSED(ctx); UNUSED(attributes); UNUSED(n_attributes); printf("Adding attributes to %" PRIuPTR "\n", (uintptr_t) node); for (i = 0; i < n_attributes; i++) { const hubbub_attribute *attr = &attributes[i]; assert(memchr(attr->name.ptr, 0xff, attr->name.len) == NULL); assert(memchr(attr->value.ptr, 0xff, attr->value.len) == NULL); } return HUBBUB_OK; } hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode) { UNUSED(ctx); printf("Quirks mode = %u\n", mode); return HUBBUB_OK; } netsurf-2.9/hubbub-0.1.2/test/Makefile0000664000175000017500000000037011476510167016400 0ustar vincevince# Tests DIR_TEST_ITEMS := csdetect:csdetect.c entities:entities.c \ parser:parser.c tokeniser:tokeniser.c \ tokeniser2:tokeniser2.c tokeniser3:tokeniser3.c tree:tree.c \ tree2:tree2.c tree-buf:tree-buf.c include build/makefiles/Makefile.subdir netsurf-2.9/hubbub-0.1.2/test/csdetect.c0000664000175000017500000000504311476512132016676 0ustar vincevince#include #include #include #include #include #include #include #include "charset/detect.h" #include "utils/utils.h" #include "testutils.h" typedef struct line_ctx { size_t buflen; size_t bufused; uint8_t *buf; char enc[64]; bool indata; bool inenc; } line_ctx; static bool handle_line(const char *data, size_t datalen, void *pw); static void run_test(const uint8_t *data, size_t len, char *expected); int main(int argc, char **argv) { line_ctx ctx; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } ctx.buflen = parse_filesize(argv[1]); if (ctx.buflen == 0) return 1; ctx.buf = malloc(ctx.buflen); if (ctx.buf == NULL) { printf("Failed allocating %u bytes\n", (unsigned int) ctx.buflen); return 1; } ctx.buf[0] = '\0'; ctx.enc[0] = '\0'; ctx.bufused = 0; ctx.indata = false; ctx.inenc = false; assert(parse_testfile(argv[1], handle_line, &ctx) == true); /* and run final test */ if (ctx.bufused > 0 && ctx.buf[ctx.bufused - 1] == '\n') ctx.bufused -= 1; run_test(ctx.buf, ctx.bufused, ctx.enc); free(ctx.buf); printf("PASS\n"); return 0; } bool handle_line(const char *data, size_t datalen, void *pw) { line_ctx *ctx = (line_ctx *) pw; if (data[0] == '#') { if (ctx->inenc) { /* This marks end of testcase, so run it */ if (ctx->buf[ctx->bufused - 1] == '\n') ctx->bufused -= 1; run_test(ctx->buf, ctx->bufused, ctx->enc); ctx->buf[0] = '\0'; ctx->enc[0] = '\0'; ctx->bufused = 0; } ctx->indata = (strncasecmp(data+1, "data", 4) == 0); ctx->inenc = (strncasecmp(data+1, "encoding", 8) == 0); } else { if (ctx->indata) { memcpy(ctx->buf + ctx->bufused, data, datalen); ctx->bufused += datalen; } if (ctx->inenc) { strcpy(ctx->enc, data); if (ctx->enc[strlen(ctx->enc) - 1] == '\n') ctx->enc[strlen(ctx->enc) - 1] = '\0'; } } return true; } void run_test(const uint8_t *data, size_t len, char *expected) { uint16_t mibenum = 0; hubbub_charset_source source = HUBBUB_CHARSET_UNKNOWN; static int testnum; assert(hubbub_charset_extract(data, len, &mibenum, &source) == HUBBUB_OK); assert(mibenum != 0); printf("%d: Detected charset %s (%d) Source %d Expected %s (%d)\n", ++testnum, parserutils_charset_mibenum_to_name(mibenum), mibenum, source, expected, parserutils_charset_mibenum_from_name( expected, strlen(expected))); assert(mibenum == parserutils_charset_mibenum_from_name( expected, strlen(expected))); } netsurf-2.9/hubbub-0.1.2/test/tokeniser.c0000664000175000017500000000767011476512132017113 0ustar vincevince#include #include #include #include #include "utils/utils.h" #include "tokeniser/tokeniser.h" #include "testutils.h" static hubbub_error token_handler(const hubbub_token *token, void *pw); static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_inputstream *stream; hubbub_tokeniser *tok; hubbub_tokeniser_optparams params; FILE *fp; size_t len, origlen; #define CHUNK_SIZE (4096) uint8_t buf[CHUNK_SIZE]; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } assert(parserutils_inputstream_create("UTF-8", 0, NULL, myrealloc, NULL, &stream) == PARSERUTILS_OK); assert(hubbub_tokeniser_create(stream, myrealloc, NULL, &tok) == HUBBUB_OK); params.token_handler.handler = token_handler; params.token_handler.pw = NULL; assert(hubbub_tokeniser_setopt(tok, HUBBUB_TOKENISER_TOKEN_HANDLER, ¶ms) == HUBBUB_OK); fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Failed opening %s\n", argv[1]); return 1; } fseek(fp, 0, SEEK_END); origlen = len = ftell(fp); fseek(fp, 0, SEEK_SET); while (len > 0) { ssize_t bytes_read = fread(buf, 1, CHUNK_SIZE, fp); if (bytes_read < 1) break; assert(parserutils_inputstream_append(stream, buf, bytes_read) == HUBBUB_OK); len -= bytes_read; assert(hubbub_tokeniser_run(tok) == HUBBUB_OK); } assert(len == 0); fclose(fp); hubbub_tokeniser_destroy(tok); parserutils_inputstream_destroy(stream); printf("PASS\n"); return 0; } hubbub_error token_handler(const hubbub_token *token, void *pw) { static const char *token_names[] = { "DOCTYPE", "START TAG", "END TAG", "COMMENT", "CHARACTERS", "EOF" }; size_t i; UNUSED(pw); printf("%s: ", token_names[token->type]); switch (token->type) { case HUBBUB_TOKEN_DOCTYPE: printf("'%.*s' %sids:\n", (int) token->data.doctype.name.len, token->data.doctype.name.ptr, token->data.doctype.force_quirks ? "(force-quirks) " : ""); if (token->data.doctype.public_missing) printf("\tpublic: missing\n"); else printf("\tpublic: '%.*s'\n", (int) token->data.doctype.public_id.len, token->data.doctype.public_id.ptr); if (token->data.doctype.system_missing) printf("\tsystem: missing\n"); else printf("\tsystem: '%.*s'\n", (int) token->data.doctype.system_id.len, token->data.doctype.system_id.ptr); break; case HUBBUB_TOKEN_START_TAG: printf("'%.*s' %s%s\n", (int) token->data.tag.name.len, token->data.tag.name.ptr, (token->data.tag.self_closing) ? "(self-closing) " : "", (token->data.tag.n_attributes > 0) ? "attributes:" : ""); for (i = 0; i < token->data.tag.n_attributes; i++) { printf("\t'%.*s' = '%.*s'\n", (int) token->data.tag.attributes[i].name.len, token->data.tag.attributes[i].name.ptr, (int) token->data.tag.attributes[i].value.len, token->data.tag.attributes[i].value.ptr); } break; case HUBBUB_TOKEN_END_TAG: printf("'%.*s' %s%s\n", (int) token->data.tag.name.len, token->data.tag.name.ptr, (token->data.tag.self_closing) ? "(self-closing) " : "", (token->data.tag.n_attributes > 0) ? "attributes:" : ""); for (i = 0; i < token->data.tag.n_attributes; i++) { printf("\t'%.*s' = '%.*s'\n", (int) token->data.tag.attributes[i].name.len, token->data.tag.attributes[i].name.ptr, (int) token->data.tag.attributes[i].value.len, token->data.tag.attributes[i].value.ptr); } break; case HUBBUB_TOKEN_COMMENT: printf("'%.*s'\n", (int) token->data.comment.len, token->data.comment.ptr); break; case HUBBUB_TOKEN_CHARACTER: printf("'%.*s'\n", (int) token->data.character.len, token->data.character.ptr); break; case HUBBUB_TOKEN_EOF: printf("\n"); break; } return HUBBUB_OK; } netsurf-2.9/hubbub-0.1.2/test/INDEX0000664000175000017500000000065611476510167015541 0ustar vincevince# Index for libhubbub testcases # # Test Description DataDir entities Named entity dictionary csdetect Charset detection csdetect parser Public parser API html tokeniser HTML tokeniser html tokeniser2 HTML tokeniser (again) tokeniser2 tokeniser3 HTML tokeniser (byte-by-byte) tokeniser2 tree Treebuilding API html tree2 Treebuilding API tree-construction tree-buf Treebuilder (specified chunks) tree-chunks netsurf-2.9/hubbub-0.1.2/test/tree-buf.c0000664000175000017500000004350311476512132016614 0ustar vincevince/* * Tree construction tester. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "utils/utils.h" #include "testutils.h" typedef struct attr_t attr_t; typedef struct node_t node_t; typedef struct buf_t buf_t; struct attr_t { hubbub_ns ns; char *name; char *value; }; struct node_t { enum { DOCTYPE, COMMENT, ELEMENT, CHARACTER } type; union { struct { char *name; char *public_id; char *system_id; } doctype; struct { hubbub_ns ns; char *name; attr_t *attrs; size_t n_attrs; } element; char *content; /**< For comments, characters **/ } data; node_t *next; node_t *prev; node_t *child; node_t *parent; uint32_t refcnt; }; struct buf_t { char *buf; size_t len; size_t pos; }; #define NUM_NAMESPACES 7 const char * const ns_names[NUM_NAMESPACES] = { NULL, NULL /*html*/, "math", "svg", "xlink", "xml", "xmlns" }; node_t *Document; static void node_print(buf_t *buf, node_t *node, unsigned depth); static hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result); static hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, void **result); static hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result); static hubbub_error create_text(void *ctx, const hubbub_string *data, void **result); static hubbub_error ref_node(void *ctx, void *node); static hubbub_error unref_node(void *ctx, void *node); static hubbub_error append_child(void *ctx, void *parent, void *child, void **result); static hubbub_error insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result); static hubbub_error remove_child(void *ctx, void *parent, void *child, void **result); static hubbub_error clone_node(void *ctx, void *node, bool deep, void **result); static hubbub_error reparent_children(void *ctx, void *node, void *new_parent); static hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result); static hubbub_error has_children(void *ctx, void *node, bool *result); static hubbub_error form_associate(void *ctx, void *form, void *node); static hubbub_error add_attributes(void *ctx, void *node, const hubbub_attribute *attributes, uint32_t n_attributes); static hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode); static void delete_node(node_t *node); static void delete_attr(attr_t *attr); static hubbub_tree_handler tree_handler = { create_comment, create_doctype, create_element, create_text, ref_node, unref_node, append_child, insert_before, remove_child, clone_node, reparent_children, get_parent, has_children, form_associate, add_attributes, set_quirks_mode, NULL, NULL }; static void *myrealloc(void *ptr, size_t len, void *pw) { void *ret; UNUSED(pw); /* A half-arsed attempt at filling freshly allocated space with junk. */ if (ptr == NULL) { ret = malloc(len); if (ret != NULL) memset(ret, 0xdf, len); } else { ret = realloc(ptr, len); } return ret; } /* * Create, initialise, and return, a parser instance. */ static hubbub_parser *setup_parser(void) { hubbub_parser *parser; hubbub_parser_optparams params; assert(hubbub_parser_create("UTF-8", false, myrealloc, NULL, &parser) == HUBBUB_OK); params.tree_handler = &tree_handler; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_TREE_HANDLER, ¶ms) == HUBBUB_OK); params.document_node = (void *)1; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_DOCUMENT_NODE, ¶ms) == HUBBUB_OK); /* Don't enable scripting -- we want the same behaviour as NetSurf. params.enable_scripting = true; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_ENABLE_SCRIPTING, ¶ms) == HUBBUB_OK); */ return parser; } /*** Buffer handling bits ***/ static void buf_add(buf_t *buf, const char *str) { size_t len = strlen(str) + 1; if (!buf) { printf("%s", str); return; } if (buf->buf == NULL) { buf->len = ((len + 1024) / 1024) * 1024; buf->buf = calloc(1, buf->len); } while (buf->pos + len > buf->len) { buf->len *= 2; buf->buf = realloc(buf->buf, buf->len); } strcat(buf->buf, str); buf->pos += len; } int main(int argc, char **argv) { FILE *fp; char buf[4096]; size_t *chunks; size_t n_chunks; hubbub_parser *parser; uint32_t i; buf_t got = { NULL, 0, 0 }; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Failed opening %s\n", argv[1]); return 1; } /* Format: * #chunks * lines * #data * */ assert(fgets(buf, sizeof(buf), fp) != NULL); assert(strncmp(buf, "#chunks ", sizeof("#chunks ") - 1) == 0); n_chunks = atoi(buf + sizeof("#chunks ") - 1); chunks = malloc(n_chunks * sizeof(size_t)); assert(chunks != NULL); for (i = 0; i < n_chunks; i++) { assert(fgets(buf, sizeof(buf), fp) != NULL); chunks[i] = atoi(buf); } assert(fgets(buf, sizeof(buf), fp) != NULL); assert(strcmp(buf, "#data\n") == 0); parser = setup_parser(); for (i = 0; i < n_chunks; i++) { ssize_t bytes_read; assert(chunks[i] <= sizeof(buf)); bytes_read = fread(buf, 1, chunks[i], fp); assert((size_t)(bytes_read) == chunks[i]); assert(hubbub_parser_parse_chunk(parser, (uint8_t *) buf, chunks[i]) == HUBBUB_OK); } assert(hubbub_parser_completed(parser) == HUBBUB_OK); node_print(&got, Document, 0); printf("%s", got.buf); hubbub_parser_destroy(parser); while (Document) { node_t *victim = Document; Document = victim->next; delete_node(victim); } Document = NULL; printf("PASS\n"); fclose(fp); free(got.buf); return 0; } /*** Tree construction functions ***/ hubbub_error create_comment(void *ctx, const hubbub_string *data, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); node->type = COMMENT; node->data.content = strndup((const char *) data->ptr, data->len); node->refcnt = 1; node->refcnt = 1; *result = node; return HUBBUB_OK; } hubbub_error create_doctype(void *ctx, const hubbub_doctype *doctype, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); node->type = DOCTYPE; node->data.doctype.name = strndup( (const char *) doctype->name.ptr, doctype->name.len); if (!doctype->public_missing) { node->data.doctype.public_id = strndup( (const char *) doctype->public_id.ptr, doctype->public_id.len); } if (!doctype->system_missing) { node->data.doctype.system_id = strndup( (const char *) doctype->system_id.ptr, doctype->system_id.len); } node->refcnt = 1; *result = node; return HUBBUB_OK; } hubbub_error create_element(void *ctx, const hubbub_tag *tag, void **result) { node_t *node = calloc(1, sizeof *node); size_t i; UNUSED(ctx); assert(tag->ns < NUM_NAMESPACES); node->type = ELEMENT; node->data.element.ns = tag->ns; node->data.element.name = strndup( (const char *) tag->name.ptr, tag->name.len); node->data.element.n_attrs = tag->n_attributes; node->data.element.attrs = calloc(node->data.element.n_attrs, sizeof *node->data.element.attrs); for (i = 0; i < tag->n_attributes; i++) { attr_t *attr = &node->data.element.attrs[i]; assert(tag->attributes[i].ns < NUM_NAMESPACES); attr->ns = tag->attributes[i].ns; attr->name = strndup( (const char *) tag->attributes[i].name.ptr, tag->attributes[i].name.len); attr->value = strndup( (const char *) tag->attributes[i].value.ptr, tag->attributes[i].value.len); } node->refcnt = 1; *result = node; return HUBBUB_OK; } hubbub_error create_text(void *ctx, const hubbub_string *data, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); node->type = CHARACTER; node->data.content = strndup((const char *) data->ptr, data->len); node->refcnt = 1; node->refcnt = 1; *result = node; return HUBBUB_OK; } hubbub_error ref_node(void *ctx, void *node) { node_t *n = node; UNUSED(ctx); if (node != (void *) 1) n->refcnt++; return HUBBUB_OK; } hubbub_error unref_node(void *ctx, void *node) { node_t *n = node; UNUSED(ctx); if (n != (void *) 1) { assert(n->refcnt > 0); n->refcnt--; printf("Unreferencing node %p (%d)\n", node, n->refcnt); if (n->refcnt == 0 && n->parent == NULL) { delete_node(n); } } return HUBBUB_OK; } hubbub_error append_child(void *ctx, void *parent, void *child, void **result) { node_t *tparent = parent; node_t *tchild = child; node_t *insert = NULL; tchild->next = tchild->prev = NULL; #ifndef NDEBUG printf("appending (%p):\n", (void *) tchild); node_print(NULL, tchild, 0); printf("to:\n"); if (parent != (void *)1) node_print(NULL, tparent, 0); #endif *result = child; if (parent == (void *)1) { if (Document) { insert = Document; } else { Document = tchild; } } else { if (tparent->child == NULL) { tparent->child = tchild; } else { insert = tparent->child; } } if (insert) { while (insert->next != NULL) { insert = insert->next; } if (tchild->type == CHARACTER && insert->type == CHARACTER) { insert->data.content = realloc(insert->data.content, strlen(insert->data.content) + strlen(tchild->data.content) + 1); strcat(insert->data.content, tchild->data.content); *result = insert; } else { insert->next = tchild; tchild->prev = insert; } } if (*result == child) tchild->parent = tparent; ref_node(ctx, *result); return HUBBUB_OK; } /* insert 'child' before 'ref_child', under 'parent' */ hubbub_error insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result) { node_t *tparent = parent; node_t *tchild = child; node_t *tref = ref_child; #ifndef NDEBUG printf("inserting (%p):\n", (void *) tchild); node_print(NULL, tchild, 0); printf("before:\n"); node_print(NULL, tref, 0); printf("under:\n"); if (parent != (void *)1) node_print(NULL, tparent, 0); #endif if (tchild->type == CHARACTER && tref->prev && tref->prev->type == CHARACTER) { node_t *insert = tref->prev; insert->data.content = realloc(insert->data.content, strlen(insert->data.content) + strlen(tchild->data.content) + 1); strcat(insert->data.content, tchild->data.content); *result = insert; } else { tchild->parent = parent; tchild->prev = tref->prev; tchild->next = tref; tref->prev = tchild; if (tchild->prev) tchild->prev->next = tchild; else tparent->child = tchild; *result = child; } ref_node(ctx, *result); return HUBBUB_OK; } hubbub_error remove_child(void *ctx, void *parent, void *child, void **result) { node_t *tparent = parent; node_t *tchild = child; assert(tparent->child); assert(tchild->parent == tparent); printf("Removing child %p\n", child); if (tchild->parent->child == tchild) { tchild->parent->child = tchild->next; } if (tchild->prev) tchild->prev->next = tchild->next; if (tchild->next) tchild->next->prev = tchild->prev; /* now reset all the child's pointers */ tchild->next = tchild->prev = tchild->parent = NULL; *result = child; ref_node(ctx, *result); return HUBBUB_OK; } hubbub_error clone_node(void *ctx, void *node, bool deep, void **result) { node_t *old_node = node; node_t *new_node = calloc(1, sizeof *new_node); node_t *last; node_t *child; size_t i; new_node->type = old_node->type; switch (old_node->type) { case DOCTYPE: new_node->data.doctype.name = strdup(old_node->data.doctype.name); if (old_node->data.doctype.public_id) new_node->data.doctype.public_id = strdup(old_node->data.doctype.public_id); if (old_node->data.doctype.system_id) new_node->data.doctype.system_id = strdup(old_node->data.doctype.system_id); break; case COMMENT: case CHARACTER: new_node->data.content = strdup(old_node->data.content); break; case ELEMENT: new_node->data.element.ns = old_node->data.element.ns; new_node->data.element.name = strdup(old_node->data.element.name); new_node->data.element.attrs = calloc(old_node->data.element.n_attrs, sizeof *new_node->data.element.attrs); for (i = 0; i < old_node->data.element.n_attrs; i++) { attr_t *attr = &new_node->data.element.attrs[i]; attr->ns = old_node->data.element.attrs[i].ns; attr->name = strdup(old_node->data.element.attrs[i].name); attr->value = strdup(old_node->data.element.attrs[i].value); } new_node->data.element.n_attrs = old_node->data.element.n_attrs; break; } *result = new_node; new_node->child = new_node->parent = new_node->next = new_node->prev = NULL; new_node->refcnt = 1; if (deep == false) return 0; last = NULL; for (child = old_node->child; child != NULL; child = child->next) { node_t *n; clone_node(ctx, child, true, (void **) (void *) &n); n->refcnt = 0; if (last == NULL) { new_node->child = n; } else { last->next = n; n->prev = last; } n->parent = new_node; last = n; } return HUBBUB_OK; } /* Take all of the child nodes of "node" and append them to "new_parent" */ hubbub_error reparent_children(void *ctx, void *node, void *new_parent) { node_t *parent = new_parent; node_t *old_parent = node; node_t *insert; node_t *kids; UNUSED(ctx); kids = old_parent->child; if (!kids) return 0; old_parent->child = NULL; insert = parent->child; if (!insert) { parent->child = kids; } else { while (insert->next != NULL) { insert = insert->next; } insert->next = kids; kids->prev = insert; } while (kids) { kids->parent = parent; kids = kids->next; } return HUBBUB_OK; } hubbub_error get_parent(void *ctx, void *node, bool element_only, void **result) { UNUSED(element_only); *result = ((node_t *)node)->parent; if (*result != NULL) ref_node(ctx, *result); return HUBBUB_OK; } hubbub_error has_children(void *ctx, void *node, bool *result) { UNUSED(ctx); *result = ((node_t *)node)->child ? true : false; return HUBBUB_OK; } hubbub_error form_associate(void *ctx, void *form, void *node) { UNUSED(ctx); UNUSED(form); UNUSED(node); return HUBBUB_OK; } hubbub_error add_attributes(void *ctx, void *vnode, const hubbub_attribute *attributes, uint32_t n_attributes) { node_t *node = vnode; size_t old_elems = node->data.element.n_attrs; size_t i; UNUSED(ctx); node->data.element.n_attrs += n_attributes; node->data.element.attrs = realloc(node->data.element.attrs, node->data.element.n_attrs * sizeof *node->data.element.attrs); for (i = 0; i < n_attributes; i++) { attr_t *attr = &node->data.element.attrs[old_elems + i]; assert(attributes[i].ns < NUM_NAMESPACES); attr->ns = attributes[i].ns; attr->name = strndup( (const char *) attributes[i].name.ptr, attributes[i].name.len); attr->value = strndup( (const char *) attributes[i].value.ptr, attributes[i].value.len); } return HUBBUB_OK; } hubbub_error set_quirks_mode(void *ctx, hubbub_quirks_mode mode) { UNUSED(ctx); UNUSED(mode); return HUBBUB_OK; } /*** Serialising bits ***/ static int compare_attrs(const void *a, const void *b) { const attr_t *first = a; const attr_t *second = b; return strcmp(first->name, second->name); } static void indent(buf_t *buf, unsigned depth) { unsigned int i; buf_add(buf, "| "); for (i = 0; i < depth; i++) { buf_add(buf, " "); } } static void print_ns(buf_t *buf, hubbub_ns ns) { if (ns_names[ns] != NULL) { buf_add(buf, ns_names[ns]); buf_add(buf, " "); } } static void node_print(buf_t *buf, node_t *node, unsigned depth) { size_t i; if (!node) return; indent(buf, depth); switch (node->type) { case DOCTYPE: buf_add(buf, "data.doctype.name); if (node->data.doctype.public_id || node->data.doctype.system_id) { if (node->data.doctype.public_id) { buf_add(buf, " \""); buf_add(buf, node->data.doctype.public_id); buf_add(buf, "\" "); } else { buf_add(buf, "\"\" "); } if (node->data.doctype.system_id) { buf_add(buf, " \""); buf_add(buf, node->data.doctype.system_id); buf_add(buf, "\""); } else { buf_add(buf, "\"\""); } } buf_add(buf, ">\n"); break; case ELEMENT: buf_add(buf, "<"); print_ns(buf, node->data.element.ns); buf_add(buf, node->data.element.name); buf_add(buf, ">\n"); qsort(node->data.element.attrs, node->data.element.n_attrs, sizeof *node->data.element.attrs, compare_attrs); for (i = 0; i < node->data.element.n_attrs; i++) { indent(buf, depth + 1); print_ns(buf, node->data.element.attrs[i].ns); buf_add(buf, node->data.element.attrs[i].name); buf_add(buf, "="); buf_add(buf, "\""); buf_add(buf, node->data.element.attrs[i].value); buf_add(buf, "\"\n"); } break; case CHARACTER: buf_add(buf, "\""); buf_add(buf, node->data.content); buf_add(buf, "\"\n"); break; case COMMENT: buf_add(buf, "\n"); break; default: printf("Unexpected node type %d\n", node->type); assert(0); } if (node->child) { node_print(buf, node->child, depth + 1); } if (node->next) { node_print(buf, node->next, depth); } } static void delete_node(node_t *node) { size_t i; node_t *c, *d; if (node == NULL) return; if (node->refcnt != 0) { printf("Node %p has non-zero refcount %d\n", (void *) node, node->refcnt); assert(0); } switch (node->type) { case DOCTYPE: free(node->data.doctype.name); free(node->data.doctype.public_id); free(node->data.doctype.system_id); break; case COMMENT: case CHARACTER: free(node->data.content); break; case ELEMENT: free(node->data.element.name); for (i = 0; i < node->data.element.n_attrs; i++) delete_attr(&node->data.element.attrs[i]); free(node->data.element.attrs); break; } for (c = node->child; c != NULL; c = d) { d = c->next; delete_node(c); } memset(node, 0xdf, sizeof(node_t)); free(node); } static void delete_attr(attr_t *attr) { if (attr == NULL) return; free(attr->name); free(attr->value); memset(attr, 0xdf, sizeof(attr_t)); } netsurf-2.9/hubbub-0.1.2/test/testutils.h0000664000175000017500000000711111165524766017156 0ustar vincevince#ifndef hubbub_test_testutils_h_ #define hubbub_test_testutils_h_ #include #include #include #include #ifndef UNUSED #define UNUSED(x) ((x) = (x)) #endif /* Redefine assert, so we can simply use the standard assert mechanism * within testcases and exit with the right output for the testrunner * to do the right thing. */ void __assert2(const char *expr, const char *function, const char *file, int line); void __assert2(const char *expr, const char *function, const char *file, int line) { UNUSED(function); UNUSED(file); printf("FAIL - %s at line %d\n", expr, line); exit(EXIT_FAILURE); } #define assert(expr) \ ((void) ((expr) || (__assert2 (#expr, __func__, __FILE__, __LINE__), 0))) /** * Convert a string representation of an error name to a hubbub error code * * \param str String containing error name * \param len Length of string (bytes) * \return Hubbub error code, or HUBBUB_OK if unknown */ hubbub_error hubbub_error_from_string(const char *str, size_t len); hubbub_error hubbub_error_from_string(const char *str, size_t len) { if (strncmp(str, "HUBBUB_OK", len) == 0) { return HUBBUB_OK; } else if (strncmp(str, "HUBBUB_NOMEM", len) == 0) { return HUBBUB_NOMEM; } else if (strncmp(str, "HUBBUB_BADPARM", len) == 0) { return HUBBUB_BADPARM; } else if (strncmp(str, "HUBBUB_INVALID", len) == 0) { return HUBBUB_INVALID; } else if (strncmp(str, "HUBBUB_FILENOTFOUND", len) == 0) { return HUBBUB_FILENOTFOUND; } else if (strncmp(str, "HUBBUB_NEEDDATA", len) == 0) { return HUBBUB_NEEDDATA; } return HUBBUB_OK; } typedef bool (*line_func)(const char *data, size_t datalen, void *pw); static size_t parse_strlen(const char *str, size_t limit); bool parse_testfile(const char *filename, line_func callback, void *pw); size_t parse_filesize(const char *filename); /** * Testcase datafile parser driver * * \param filename Name of file to parse * \param callback Pointer to function to handle each line of input data * \param pw Pointer to client-specific private data * \return true on success, false otherwise. */ bool parse_testfile(const char *filename, line_func callback, void *pw) { FILE *fp; char buf[300]; fp = fopen(filename, "rb"); if (fp == NULL) { printf("Failed opening %s\n", filename); return false; } while (fgets(buf, sizeof buf, fp)) { if (buf[0] == '\n') continue; if (!callback(buf, parse_strlen(buf, sizeof buf - 1), pw)) { fclose(fp); return false; } } fclose(fp); return true; } /** * Utility string length measurer; assumes strings are '\n' terminated * * \param str String to measure length of * \param limit Upper bound on string length * \return String length */ size_t parse_strlen(const char *str, size_t limit) { size_t len = 0; if (str == NULL) return 0; while (len < limit - 1 && *str != '\n') { len++; str++; } len++; return len; } /** * Read the size of a file * * \param filename Name of file to read size of * \return File size (in bytes), or 0 on error */ size_t parse_filesize(const char *filename) { FILE *fp; size_t len = 0; fp = fopen(filename, "rb"); if (fp == NULL) { printf("Failed opening %s\n", filename); return 0; } fseek(fp, 0, SEEK_END); len = ftell(fp); fclose(fp); return len; } #ifndef strndup char *my_strndup(const char *s, size_t n); char *my_strndup(const char *s, size_t n) { size_t len; char *s2; for (len = 0; len != n && s[len]; len++) ; s2 = malloc(len + 1); if (!s2) return NULL; memcpy(s2, s, len); s2[len] = '\0'; return s2; } #define strndup my_strndup #endif #endif netsurf-2.9/hubbub-0.1.2/libhubbub.pc.in0000664000175000017500000000035411173433231016640 0ustar vincevinceprefix=PREFIX exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: libhubbub Description: HTML5 parsing library Version: VERSION Requires: libparserutils Libs: -L${libdir} -lhubbub Cflags: -I${includedir} netsurf-2.9/hubbub-0.1.2/Makefile0000664000175000017500000000431511722663035015421 0ustar vincevince# Component settings COMPONENT := hubbub COMPONENT_VERSION := 0.1.2 # Default to a static library COMPONENT_TYPE ?= lib-static # Setup the tooling include build/makefiles/Makefile.tools TESTRUNNER := $(PERL) build/testtools/testrunner.pl # Toolchain flags WARNFLAGS := -Wall -W -Wundef -Wpointer-arith -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ -Wmissing-declarations -Wnested-externs -pedantic # BeOS/Haiku/AmigaOS have standard library errors that issue warnings. ifneq ($(TARGET),beos) ifneq ($(TARGET),amiga) WARNFLAGS := $(WARNFLAGS) -Werror endif endif CFLAGS := -D_BSD_SOURCE -I$(CURDIR)/include/ \ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS) ifneq ($(GCCVER),2) CFLAGS := $(CFLAGS) -std=c99 else # __inline__ is a GCCism CFLAGS := $(CFLAGS) -Dinline="__inline__" endif # Parserutils ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) ifneq ($(PKGCONFIG),) CFLAGS := $(CFLAGS) $(shell $(PKGCONFIG) libparserutils --cflags) LDFLAGS := $(LDFLAGS) $(shell $(PKGCONFIG) libparserutils --libs) else CFLAGS := $(CFLAGS) -I$(PREFIX)/include LDFLAGS := $(LDFLAGS) -lparserutils endif endif include build/makefiles/Makefile.top ifeq ($(WANT_TEST),yes) # We require the presence of libjson -- http://oss.metaparadigm.com/json-c/ ifneq ($(PKGCONFIG),) TESTCFLAGS := $(TESTCFLAGS) \ $(shell $(PKGCONFIG) $(PKGCONFIGFLAGS) --cflags json) TESTLDFLAGS := $(TESTLDFLAGS) \ $(shell $(PKGCONFIG) $(PKGCONFIGFLAGS) --libs json) else TESTCFLAGS := $(TESTCFLAGS) -I$(PREFIX)/include/json TESTLDFLAGS := $(TESTLDFLAGS) -ljson endif ifneq ($(GCCVER),2) TESTCFLAGS := $(TESTCFLAGS) -Wno-unused-parameter endif endif # Extra installation rules I := /include/hubbub INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/hubbub/errors.h INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/hubbub/functypes.h INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/hubbub/hubbub.h INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/hubbub/parser.h INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/hubbub/tree.h INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/hubbub/types.h INSTALL_ITEMS := $(INSTALL_ITEMS) /lib/pkgconfig:lib$(COMPONENT).pc.in INSTALL_ITEMS := $(INSTALL_ITEMS) /lib:$(OUTPUT) netsurf-2.9/hubbub-0.1.2/perf/0000775000175000017500000000000011734430254014710 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/perf/hubbub.c0000664000175000017500000002450411155615652016334 0ustar vincevince#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #define UNUSED(x) ((x) = (x)) typedef struct attr_t attr_t; typedef struct node_t node_t; typedef struct buf_t buf_t; struct attr_t { hubbub_ns ns; char *name; char *value; }; struct node_t { enum { DOCTYPE, COMMENT, ELEMENT, CHARACTER } type; union { struct { char *name; char *public_id; char *system_id; } doctype; struct { hubbub_ns ns; char *name; attr_t *attrs; size_t n_attrs; } element; char *content; /**< For comments, characters **/ } data; node_t *next; node_t *prev; node_t *child; node_t *parent; }; struct buf_t { char *buf; size_t len; size_t pos; }; #define NUM_NAMESPACES 7 const char const *ns_names[NUM_NAMESPACES] = { NULL, NULL /*html*/, "math", "svg", "xlink", "xml", "xmlns" }; node_t *Document; static int create_comment(void *ctx, const hubbub_string *data, void **result); static int create_doctype(void *ctx, const hubbub_doctype *doctype, void **result); static int create_element(void *ctx, const hubbub_tag *tag, void **result); static int create_text(void *ctx, const hubbub_string *data, void **result); static int ref_node(void *ctx, void *node); static int unref_node(void *ctx, void *node); static int append_child(void *ctx, void *parent, void *child, void **result); static int insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result); static int remove_child(void *ctx, void *parent, void *child, void **result); static int clone_node(void *ctx, void *node, bool deep, void **result); static int reparent_children(void *ctx, void *node, void *new_parent); static int get_parent(void *ctx, void *node, bool element_only, void **result); static int has_children(void *ctx, void *node, bool *result); static int form_associate(void *ctx, void *form, void *node); static int add_attributes(void *ctx, void *node, const hubbub_attribute *attributes, uint32_t n_attributes); static int set_quirks_mode(void *ctx, hubbub_quirks_mode mode); static hubbub_tree_handler tree_handler = { create_comment, create_doctype, create_element, create_text, ref_node, unref_node, append_child, insert_before, remove_child, clone_node, reparent_children, get_parent, has_children, form_associate, add_attributes, set_quirks_mode, NULL, NULL }; static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { hubbub_parser *parser; hubbub_parser_optparams params; struct stat info; int fd; uint8_t *file; if (argc != 3) { printf("Usage: %s \n", argv[0]); return 1; } /* Initialise library */ assert(hubbub_initialise(argv[1], myrealloc, NULL) == HUBBUB_OK); assert(hubbub_parser_create("UTF-8", false, myrealloc, NULL, &parser) == HUBBUB_OK); params.tree_handler = &tree_handler; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_TREE_HANDLER, ¶ms) == HUBBUB_OK); params.document_node = (void *)1; assert(hubbub_parser_setopt(parser, HUBBUB_PARSER_DOCUMENT_NODE, ¶ms) == HUBBUB_OK); stat(argv[2], &info); fd = open(argv[2], 0); file = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0); assert(hubbub_parser_parse_chunk(parser, file, info.st_size) == HUBBUB_OK); assert(hubbub_finalise(myrealloc, NULL) == HUBBUB_OK); return 0; } /*** Tree construction functions ***/ int create_comment(void *ctx, const hubbub_string *data, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); node->type = COMMENT; node->data.content = strndup((const char *) data->ptr, data->len); *result = node; return 0; } int create_doctype(void *ctx, const hubbub_doctype *doctype, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); node->type = DOCTYPE; node->data.doctype.name = strndup( (const char *) doctype->name.ptr, doctype->name.len); if (!doctype->public_missing) { node->data.doctype.public_id = strndup( (const char *) doctype->public_id.ptr, doctype->public_id.len); } if (!doctype->system_missing) { node->data.doctype.system_id = strndup( (const char *) doctype->system_id.ptr, doctype->system_id.len); } *result = node; return 0; } int create_element(void *ctx, const hubbub_tag *tag, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); assert(tag->ns < NUM_NAMESPACES); node->type = ELEMENT; node->data.element.ns = tag->ns; node->data.element.name = strndup( (const char *) tag->name.ptr, tag->name.len); node->data.element.n_attrs = tag->n_attributes; node->data.element.attrs = calloc(node->data.element.n_attrs, sizeof *node->data.element.attrs); for (size_t i = 0; i < tag->n_attributes; i++) { attr_t *attr = &node->data.element.attrs[i]; assert(tag->attributes[i].ns < NUM_NAMESPACES); attr->ns = tag->attributes[i].ns; attr->name = strndup( (const char *) tag->attributes[i].name.ptr, tag->attributes[i].name.len); attr->value = strndup( (const char *) tag->attributes[i].value.ptr, tag->attributes[i].value.len); } *result = node; return 0; } int create_text(void *ctx, const hubbub_string *data, void **result) { node_t *node = calloc(1, sizeof *node); UNUSED(ctx); node->type = CHARACTER; node->data.content = strndup((const char *) data->ptr, data->len); *result = node; return 0; } int ref_node(void *ctx, void *node) { UNUSED(ctx); UNUSED(node); return 0; } int unref_node(void *ctx, void *node) { UNUSED(ctx); UNUSED(node); return 0; } int append_child(void *ctx, void *parent, void *child, void **result) { node_t *tparent = parent; node_t *tchild = child; UNUSED(ctx); node_t *insert = NULL; tchild->parent = tparent; tchild->next = tchild->prev = NULL; *result = child; if (parent == (void *)1) { if (Document) { insert = Document; } else { Document = tchild; } } else { if (tparent->child == NULL) { tparent->child = tchild; } else { insert = tparent->child; } } if (insert) { while (insert->next != NULL) { insert = insert->next; } if (tchild->type == CHARACTER && insert->type == CHARACTER) { insert->data.content = realloc(insert->data.content, strlen(insert->data.content) + strlen(tchild->data.content) + 1); strcat(insert->data.content, tchild->data.content); *result = insert; } else { insert->next = tchild; tchild->prev = insert; } } return 0; } /* insert 'child' before 'ref_child', under 'parent' */ int insert_before(void *ctx, void *parent, void *child, void *ref_child, void **result) { node_t *tparent = parent; node_t *tchild = child; node_t *tref = ref_child; UNUSED(ctx); if (tchild->type == CHARACTER && tref->prev && tref->prev->type == CHARACTER) { node_t *insert = tref->prev; insert->data.content = realloc(insert->data.content, strlen(insert->data.content) + strlen(tchild->data.content) + 1); strcat(insert->data.content, tchild->data.content); *result = insert; } else { tchild->parent = parent; tchild->prev = tref->prev; tchild->next = tref; tref->prev = tchild; if (tchild->prev) tchild->prev->next = tchild; else tparent->child = tchild; *result = child; } return 0; } int remove_child(void *ctx, void *parent, void *child, void **result) { node_t *tparent = parent; node_t *tchild = child; UNUSED(ctx); assert(tparent->child); assert(tchild->parent == tparent); if (tchild->parent->child == tchild) { tchild->parent->child = tchild->next; } if (tchild->prev) tchild->prev->next = tchild->next; if (tchild->next) tchild->next->prev = tchild->prev; /* now reset all the child's pointers */ tchild->next = tchild->prev = tchild->parent = NULL; *result = child; return 0; } int clone_node(void *ctx, void *node, bool deep, void **result) { node_t *old_node = node; node_t *new_node = calloc(1, sizeof *new_node); UNUSED(ctx); *new_node = *old_node; *result = new_node; new_node->child = new_node->parent = new_node->next = new_node->prev = NULL; if (deep == false) return 0; if (old_node->next) { void *n; clone_node(ctx, old_node->next, true, &n); new_node->next = n; new_node->next->prev = new_node; } if (old_node->child) { void *n; clone_node(ctx, old_node->child, true, &n); new_node->child = n; new_node->child->parent = new_node; } return 0; } /* Take all of the child nodes of "node" and append them to "new_parent" */ int reparent_children(void *ctx, void *node, void *new_parent) { node_t *parent = new_parent; node_t *old_parent = node; node_t *insert; node_t *kids; UNUSED(ctx); kids = old_parent->child; if (!kids) return 0; old_parent->child = NULL; insert = parent->child; if (!insert) { parent->child = kids; } else { while (insert->next != NULL) { insert = insert->next; } insert->next = kids; kids->prev = insert; } while (kids) { kids->parent = parent; kids = kids->next; } return 0; } int get_parent(void *ctx, void *node, bool element_only, void **result) { UNUSED(ctx); UNUSED(element_only); *result = ((node_t *)node)->parent; return 0; } int has_children(void *ctx, void *node, bool *result) { UNUSED(ctx); *result = ((node_t *)node)->child ? true : false; return 0; } int form_associate(void *ctx, void *form, void *node) { UNUSED(ctx); UNUSED(form); UNUSED(node); return 0; } int add_attributes(void *ctx, void *vnode, const hubbub_attribute *attributes, uint32_t n_attributes) { node_t *node = vnode; size_t old_elems = node->data.element.n_attrs; UNUSED(ctx); node->data.element.n_attrs += n_attributes; node->data.element.attrs = realloc(node->data.element.attrs, node->data.element.n_attrs * sizeof *node->data.element.attrs); for (size_t i = 0; i < n_attributes; i++) { attr_t *attr = &node->data.element.attrs[old_elems + i]; assert(attributes[i].ns < NUM_NAMESPACES); attr->ns = attributes[i].ns; attr->name = strndup( (const char *) attributes[i].name.ptr, attributes[i].name.len); attr->value = strndup( (const char *) attributes[i].value.ptr, attributes[i].value.len); } return 0; } int set_quirks_mode(void *ctx, hubbub_quirks_mode mode) { UNUSED(ctx); UNUSED(mode); return 0; } netsurf-2.9/hubbub-0.1.2/perf/libxml2.c0000664000175000017500000000156311044353020016417 0ustar vincevince#include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { htmlDocPtr doc; struct stat info; int fd; char *file; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } /* libxml hack */ LIBXML_TEST_VERSION stat(argv[1], &info); fd = open(argv[1], 0); file = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd, 0); doc = htmlReadMemory(file, info.st_size, NULL, NULL, HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING); #if 0 doc = htmlReadFile(argv[1], NULL, HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING); #endif if (!doc) { printf("FAIL\n"); return 1; } xmlFreeDoc(doc); xmlCleanupParser(); return 0; } netsurf-2.9/hubbub-0.1.2/perf/README0000664000175000017500000000137511044353020015563 0ustar vincevinceThis directory contains some very basic cobbled-together performance tests. A makefile is provided for generating the executables from the .c files. html5libtest.py --------------- This tests the Python html5lib project, obtained from: http://code.google.com/p/html5lib/ This is generally quite a slow parser. :) libxml2.c --------- This tests the GNOME libxml2 HTML parser, using mmap(). It doesn't do anything with the resulting tree, just generates one. hubbub.c -------- This tests hubbub, using mmap(), and a modified version of the test treebuilder. It could certainly be made more efficient (it's based on an old version of the tree construction testrunner) so should not be compared too harshly against the libxml2 results. netsurf-2.9/hubbub-0.1.2/perf/makefile0000664000175000017500000000070011044353020016372 0ustar vincevinceall: libxml2 hubbub CC = gcc CFLAGS = -W -Wall --std=c99 LIBXML2_OBJS = libxml2.o libxml2: libxml2.c libxml2: CFLAGS += `pkg-config libxml-2.0 --cflags` libxml2: $(LIBXML2_OBJS) gcc -o libxml2 $(LIBXML2_OBJS) `pkg-config libxml-2.0 --libs` HUBBUB_OBJS = hubbub.o hubbub: hubbub.c hubbub: CFLAGS += `pkg-config --cflags libparserutils libhubbub` hubbub: $(HUBBUB_OBJS) gcc -o hubbub $(HUBBUB_OBJS) `pkg-config --libs libhubbub libparserutils` netsurf-2.9/hubbub-0.1.2/perf/html5libtest.py0000775000175000017500000000031411044353020017670 0ustar vincevince#!/usr/bin/python import sys import html5lib if len(sys.argv) != 2: print "Usage: %s " % sys.argv[0] sys.exit(1) f = open(sys.argv[1]) parser = html5lib.HTMLParser() document = parser.parse(f) netsurf-2.9/hubbub-0.1.2/COPYING0000664000175000017500000000204510637320531015005 0ustar vincevinceCopyright (C) 2007 J-M Bell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. netsurf-2.9/hubbub-0.1.2/build/0000775000175000017500000000000011734430260015050 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/build/make-entities.pl0000664000175000017500000000636411476510167020165 0ustar vincevince#!/usr/bin/perl -w # This file is part of Hubbub. # Licensed under the MIT License, # http://www.opensource.org/licenses/mit-license.php # Copyright 2010 Daniel Silverstone # John-Mark Bell use strict; use constant ENTITIES_FILE => 'build/Entities'; use constant ENTITIES_INC => 'src/tokeniser/entities.inc'; open(INFILE, "<", ENTITIES_FILE) || die "Unable to open " . ENTITIES_FILE; my %entities; while (my $line = ) { last unless (defined $line); next if ($line =~ /^#/); chomp $line; next if ($line eq ''); my @elements = split /\s+/, $line; my $entity = shift @elements; my $code = shift @elements; $entities{$entity} = $code; } close(INFILE); my $output = <<'EOH'; /* * This file is part of Hubbub. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2010 The NetSurf Project. * * Note: This file is automatically generated by make-entities.pl * * Do not edit file file, changes will be overwritten during build. */ EOH # Build a Trie of the entities my $heapindex = 0; my @nodelist; sub insert_node { my ($parent, $key, $code) = @_; my ($pivot, $tail); if (length($key) == 0) { $pivot = ''; $tail = ''; } elsif (length($key) == 1) { $pivot = $key; $tail = ''; } else { $pivot = substr($key, 0, 1); $tail = substr($key, 1); } unless (defined($parent)) { $parent = { pivot => $pivot, heapindex => $heapindex }; push @nodelist, $parent; $heapindex++; } if ($pivot lt $parent->{pivot}) { $parent->{lt} = insert_node($parent->{lt}, $key, $code); } elsif ($pivot eq $parent->{pivot}) { if ($pivot eq '') { $parent->{value} = $code; } elsif (substr($tail, 0, 1) eq '') { $parent->{value} = $code; $parent->{eq} = insert_node($parent->{eq}, $tail, $code); } else { $parent->{eq} = insert_node($parent->{eq}, $tail, $code); } } else { $parent->{gt} = insert_node($parent->{gt}, $key, $code); } return $parent; } my $trie; foreach my $key (keys %entities) { $trie = insert_node($trie, $key, $entities{$key}); } # Serialise the Trie to the output string $output .= "static hubbub_entity_node dict[] = {\n"; foreach my $node (@nodelist) { my $split = $node->{pivot}; my $lt = $node->{lt}; my $eq = $node->{eq}; my $gt = $node->{gt}; my $value = $node->{value}; $lt = $lt->{heapindex} if defined($lt); $lt = "-1" unless defined($lt); $eq = $eq->{heapindex} if defined($eq); $eq = "-1" unless defined($eq); $gt = $gt->{heapindex} if defined($gt); $gt = "-1" unless defined($gt); $split = ord($split) if ($split ne ''); $split = 0 if ($split eq ''); $value = "0" unless defined($value); $output .= "\t{ $split, $lt, $eq, $gt, $value },\n"; } $output .= "};\n\n"; $output .= "static int32_t dict_root = " . $trie->{heapindex} . ";\n"; # Write file out if (open(EXISTING, "<", ENTITIES_INC)) { local $/ = undef(); my $now = ; undef($output) if ($output eq $now); close(EXISTING); } if (defined($output)) { open(OUTF, ">", ENTITIES_INC); print OUTF $output; close(OUTF); } netsurf-2.9/hubbub-0.1.2/build/makefiles/0000775000175000017500000000000011734430256017015 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/build/makefiles/Makefile.top0000664000175000017500000004232311537116272021262 0ustar vincevince# Top-level Makefile fragment # # Expected inputs: # # BUILD Type of build to perform: # release - Release build # debug - Debug build # COMPONENT Name of the component (sans leading "lib" iff a library) # COMPONENT_VERSION Component version number (x.y.z) # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # TARGET Target platform identifier # # Optional inputs: # # BUILDDIR Directory to build into (defaults to # build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE)) # CC_CAN_BUILD_AND_DEP Flag whether $(CC) is capable of calculating dependency # information at the same time as compiling sources. # Set to "yes" if it can. # DESTDIR Sandboxed FS root (e.g. for packaging) # HOST Host platform identifier # REQUIRED_PKGS List of required pkg-config packages # # The client may also override all toolchain settings, including: # # ARFLAGS Archiver flags for the current compilation # CFLAGS C compiler flags for the current compilation # CXXFLAGS C++ compiler flags for the current compilation # LDFLAGS Linker flags for the current compilation # # TESTCFLAGS Any test-specific CFLAGS # TESTCXXFLAGS Any test-specific CXXFLAGS # TESTLDFLAGS Any test-specific LDFLAGS # # TESTRUNNER Test runner invocation command # The test runner takes a command line in the form # # # Targets provided: # # all Default target. Builds component using current settings # test Build and run test suite, using current settings. # coverage Determine test suite coverage (requires lcov) # profile Build with profiling support enabled (requires gprof) # docs Produce documentation (requires doxygen) # clean Clean the build # distclean Remove distribution files, too # install Install component into prefix. # uninstall Remove component from prefix. # # Variables provided: # # major-version Extracts the major version (x) from COMPONENT_VERSION # minor-version Extracts the minor version (y) from COMPONENT_VERSION # patch-version Extracts the patch version (z) from COMPONENT_VERSION # OUTPUT Path + filename of build target ############################################################################### # Sanity checks ############################################################################### # Name of component must be defined by client ifeq ($(COMPONENT),) $(error COMPONENT not defined) endif # As must the version ifeq ($(COMPONENT_VERSION),) $(error COMPONENT_VERSION not defined) endif # As must the component type ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not defined) endif # Target platform must be defined by the client ifeq ($(TARGET),) $(error TARGET not defined) endif # Build type, too ifeq ($(BUILD),) $(error BUILD not defined) endif ############################################################################## # Makefile variables ############################################################################## Q ?= @ VQ ?= @ ############################################################################## # Exported variables (also OUTPUT, further down) ############################################################################## major-version := $(word 1,$(subst ., ,$(COMPONENT_VERSION))) minor-version := $(word 2,$(subst ., ,$(COMPONENT_VERSION))) patch-version := $(word 3,$(subst ., ,$(COMPONENT_VERSION))) ############################################################################## # Build environment ############################################################################## # Build directory BUILDDIR ?= build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE) # Build tree subdirs COVERAGEDIR := $(BUILDDIR)/coverage DOCDIR := $(BUILDDIR)/docs # Determine if we want to build testcases ifeq ($(MAKECMDGOALS),test) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),profile) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),coverage) WANT_TEST := yes else WANT_TEST := no endif # List of items to delete on clean CLEAN_ITEMS := # List of items to delete on distclean DISTCLEAN_ITEMS := # List of items to build for testing TEST_ITEMS := # List of targets to run for testing TEST_TARGETS := # List of targets which are prerequisites for running tests TEST_PREREQS := # List of items to (un)install INSTALL_ITEMS := # List of targets to run before building $(OBJECT) PRE_TARGETS := # List of targets to run after building $(OBJECT) POST_TARGETS := # Source files SOURCES := # Include configuration Makefile fragment -include Makefile.config # Set the default target (before including any children) __default: all # Include Makefile fragments in subdirectories define do_include DIR := $$(dir $(1)) include $(1) endef MAKE_INCLUDES := $(wildcard */Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Calculate objects to build OBJECTS := $(addprefix $(BUILDDIR)/,$(filter %.o, \ $(subst /,_,$(subst .c,.o,$(SOURCES))) \ $(subst /,_,$(subst .cpp,.o,$(SOURCES))) \ $(subst /,_,$(subst .cmhg,.o,$(SOURCES))) \ $(subst /,_,$(subst .s,.o,$(SOURCES))))) bin_for_test = $(addprefix $(BUILDDIR)/,$(firstword $(subst :, ,$(ITEM)))) TEST_BINARIES := $(foreach ITEM,$(TEST_ITEMS),$(bin_for_test)) # Determine if we're building any C++ sources ifneq ($(filter %.cpp,$(SOURCES)),) CXX_IN_BUILD := yes else CXX_IN_BUILD := no endif # Determine the output filename ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) ifeq ($(findstring lib-shared,$(COMPONENT_TYPE)),lib-shared) SHAREDLIBNAME := lib$(COMPONENT)$(LIBEXT) SONAME := $(SHAREDLIBNAME).$(major-version) OUTPUT := $(BUILDDIR)/$(SHAREDLIBNAME).$(COMPONENT_VERSION) else OUTPUT := $(BUILDDIR)/lib$(COMPONENT)$(LIBEXT) endif else OUTPUT := $(BUILDDIR)/$(COMPONENT)$(EXEEXT) endif ############################################################################### # Build targets ############################################################################### .PHONY: all test coverage profile docs clean distclean install uninstall \ __default __precov __partial_clean __postshared ifeq ($(COMPONENT_TYPE),lib-shared) POST_TARGETS := __postshared $(POST_TARGETS) __postshared: $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SONAME) $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SHAREDLIBNAME) endif # Default target all: $(PRE_TARGETS) $(OUTPUT) $(POST_TARGETS) # Build and execute testsuite test: all $(TEST_PREREQS) $(TEST_BINARIES) $(TEST_TARGETS) $(VQ)$(ECHO) $(ECHOFLAGS) " TEST: Testing complete" # Compute coverage __precov: __partial_clean $(Q)$(LCOV) --directory . --zerocounters coverage: __precov test $(Q)$(LCOV) --directory $(BUILDDIR) --base-directory $(CURDIR) \ --capture --output-file $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(LCOV) --extract $(COVERAGEDIR)/$(COMPONENT)_tmp.info \ "$(CURDIR)/src*" -o $(COVERAGEDIR)/$(COMPONENT).info $(Q)$(RM) $(RMFLAGS) $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(GENHTML) -o $(COVERAGEDIR) --num-spaces 2 \ $(COVERAGEDIR)/$(COMPONENT).info # Build for profiling profile: __partial_clean test # Compile documentation docs: $(BUILDDIR)/stamp $(Q)$(DOXYGEN) build/Doxyfile # Clean build tree __partial_clean: -$(Q)$(RM) $(RMFLAGS) $(CLEAN_ITEMS) -$(Q)$(RM) $(RMFLAGS) gmon.out -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.d) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcda) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcno) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.o) clean: __partial_clean -$(Q)$(RM) $(RMFLAGS) -r build/docs -$(Q)$(RM) $(RMFLAGS) -r $(BUILDDIR) # Remove auto-generated non-build-tree items distclean: clean -$(Q)$(RM) $(RMFLAGS) $(DISTCLEAN_ITEMS) # The installation target, and associated canned command sequences. # For reference, the syntax of INSTALL_ITEMS is: # # :[';']* # # We also permit a trailing ';' in the file list. __comma := , __empty := __space := $(empty) $(empty) __required = $(if $(REQUIRED_PKGS),Requires: $(subst $(__space),$(__comma) ,$(strip $(REQUIRED_PKGS))),) # Install a pkg-config control file ($1) to the specified location ($2) define install_pkgconfig $(Q)$(ECHO) $(ECHOFLAGS) "sed -e... $1 >$(BUILDDIR)/$(1:.in=)" $(Q)$(SED) \ -e 's#PREFIX#$(PREFIX)#' \ -e 's#MAJOR#$(major-version)#' \ -e 's#MINOR#$(minor-version)#' \ -e 's#PATCH#$(patch-version)#' \ -e 's#VERSION#$(COMPONENT_VERSION)#' \ -e 's#REQUIRED#$(__required)#' \ $1 >$(BUILDDIR)/$(1:.in=) $(INSTALL) $(INSTALLFLAGS) -m 644 $(BUILDDIR)/$(1:.in=) \ $2/$(1:.in=) endef # TODO: Is this scheme portable? define install_shared_lib $(INSTALL) $(INSTALLFLAGS) -m 755 $1 $2/$(notdir $1) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SONAME) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SHAREDLIBNAME) endef # Install a file ($1) to the specified location ($2) define install_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(call install_pkgconfig,$1,$2), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call install_shared_lib,$1,$2), \ $(INSTALL) $(INSTALLFLAGS) -m 644 $1 $2))) endef # Install a list of files ($2) to the specified location ($1) # We create the installation location if it doesn't already exist define install_to_dest $(Q)$(MKDIR) $(MKDIRFLAGS) $(DESTDIR)$(PREFIX)$1 $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call install_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef install: all $(foreach ITEM,$(INSTALL_ITEMS), \ $(call install_to_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) # Uninstallation # TODO: Work out how to safely remove symlinks define uninstall_shared_lib $(RM) $(RMFLAGS) $2/$(notdir $1).$(COMPONENT_VERSION) endef # Uninstall a file ($1) from the specified location ($2) define uninstall_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(RM) $(RMFLAGS) $2/$(1:.pc.in=.pc), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call uninstall_shared_lib,$1,$2), \ $(RM) $(RMFLAGS) $2/$(notdir $1)))) endef # Uninstall a list of files ($2) from the specified location ($1) # TODO: Come up with a safe way of removing directories, too define uninstall_from_dest $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call uninstall_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef uninstall: $(foreach ITEM,$(INSTALL_ITEMS), \ $(call uninstall_from_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) ############################################################################### # Actual rules ############################################################################### $(BUILDDIR)/stamp: $(Q)$(MKDIR) $(MKDIRFLAGS) $(BUILDDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(COVERAGEDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(DOCDIR) $(Q)$(TOUCH) $(TOUCHFLAGS) $(BUILDDIR)/stamp $(OUTPUT): $(BUILDDIR)/stamp $(OBJECTS) ifeq ($(COMPONENT_TYPE),lib-static) $(VQ)$(ECHO) $(ECHOFLAGS) " AR: $@" $(Q)$(RM) $(RMFLAGS) $@ $(Q)$(AR) $(ARFLAGS) $@ $(OBJECTS) else $(VQ)$(ECHO) $(ECHOFLAGS) " LINK: $@" ifeq ($(CXX_IN_BUILD),yes) $(Q)$(CXX) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) else $(Q)$(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) endif endif ############################################################################### # Autogenerated, implied rules ############################################################################### DEPFILES := BUILDFILES := ifeq ($(CC_CAN_BUILD_AND_DEP),yes) # C compiler can compile and dep simultaneously define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else ifeq ($(CC_CANNOT_DEP),yes) # C compiler cannot calculate dependencies define dep_c endef define dep_cxx endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else # C compiler must calculate dependencies first, then compile (default) define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CC) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CXX) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef endif endif define build_cmhg ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " CMHG: $1" $$(Q)$$(CMHG) $$(CMHGFLAGS) $1 -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_s ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) "ASSEMBLE: $1" $$(Q)$$(CC) $$($3) $1 -c -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef BUILDCFLAGS = $(CFLAGS) $(SHAREDCFLAGS) BUILDCXXFLAGS = $(CXXFLAGS) $(SHAREDCXXFLAGS) BUILDASFLAGS = $(ASFLAGS) $(SHAREDCFLAGS) # Generate dependency rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),BUILDCXXFLAGS))) # Generate compilation rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),BUILDCXXFLAGS))) $(eval $(foreach SOURCE,$(filter %.cmhg,$(SOURCES)), \ $(call build_cmhg,$(SOURCE),$(subst /,_,$(SOURCE:.cmhg=.o))))) $(eval $(foreach SOURCE,$(filter %.s,$(SOURCES)), \ $(call build_s,$(SOURCE),$(subst /,_,$(SOURCE:.s=.o)),BUILDASFLAGS))) # Similarly for test sources ifeq ($(WANT_TEST),yes) ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) TESTLIB := $(OUTPUT) TESTLDFLAGS += -L$(BUILDDIR)/ -l$(COMPONENT) endif TESTCFLAGS := $(CFLAGS) $(TESTCFLAGS) TESTCXXFLAGS += $(CXXFLAGS) TESTLDFLAGS += $(LDFLAGS) define link_test $2: $($3) $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " LINK: $2" ifeq ($$(CXX_IN_BUILD),yes) $$(Q)$$(CXX) -o $$@ $1 $$($4) else $$(Q)$$(CC) -o $$@ $1 $$($4) endif endef srcs_for_test = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) objs_for_test = $(addprefix $(BUILDDIR)/, \ $(subst /,_,$(addsuffix .o,$(basename $(srcs_for_test))))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(call link_test,$(objs_for_test),$(bin_for_test),TESTLIB,TESTLDFLAGS))) endif # Include dependency makefiles ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) -include $(sort $(DEPFILES)) endif netsurf-2.9/hubbub-0.1.2/build/makefiles/Makefile.clang0000664000175000017500000000232611545435603021544 0ustar vincevince# Clang-specific toolchain setup # We assume that we're using a standard GCC/binutils environment, as well # as clang being mostly GCC-compatible on the command line CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### CC_CAN_BUILD_AND_DEP ?= yes netsurf-2.9/hubbub-0.1.2/build/makefiles/Makefile.norcroft0000664000175000017500000000220311545435603022306 0ustar vincevince# Norcroft specific toolchain setup CCDEF := -D CCOPT := -Otime CCNOOPT := CCDBG := -g CCINC := -I CCLIB := -L # TODO: Norcroft CC cannot do assembler as C CCAS := CCSHR := CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g LDSHR := ARFLG := -c # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) $(error Coverage is not supported with Norcroft) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) $(error Profile is not supported with Norcroft) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -zM CXXFLAGS := $(CXXFLAGS) -zM LDFLAGS := $(LDFLAGS) -zM endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. CC_CANNOT_DEP := yes netsurf-2.9/hubbub-0.1.2/build/makefiles/Makefile.gcc0000664000175000017500000000457011545435603021217 0ustar vincevince# GCC specific toolchain setup # We assume that we're using a standard GCC/binutils environment CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions for various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="__attribute__((aligned))" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) COVCFLAGS ?= -fprofile-arcs -ftest-coverage COVCXXFLAGS ?= -fprofile-arcs -ftest-coverage COVLDFLAGS ?= -lgcov CFLAGS := $(CFLAGS) $(COVCFLAGS) CXXFLAGS := $(CXXFLAGS) $(COVCXXFLAGS) LDFLAGS := $(LDFLAGS) $(COVLDFLAGS) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) PROFCFLAGS ?= -pg PROFCXXFLAGS ?= -pg PROFLDFLAGS ?= -pg CFLAGS := $(CFLAGS) $(PROFCFLAGS) CXXFLAGS := $(CXXFLAGS) $(PROFCXXFLAGS) LDFLAGS := $(LDFLAGS) $(PROFLDFLAGS) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -mmodule CXXFLAGS := $(CXXFLAGS) -mmodule LDFLAGS := $(LDFLAGS) -mmodule endif ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CC_CAN_BUILD_AND_DEP := no CC_CANNOT_DEP := yes CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. ccvsn := $(shell $(CC) -dumpversion) # ccvsn = x.y.z GCCVER := $(word 1,$(subst ., ,$(ccvsn))) # GCCVER = x # If the major version (x, above) is not 2, then assume build & dep. # This will break if using a version of GCC < 2, but that's unlikely. ifneq ($(GCCVER),2) CC_CAN_BUILD_AND_DEP ?= yes endif netsurf-2.9/hubbub-0.1.2/build/makefiles/Makefile.pkgconfig0000664000175000017500000000426511476474557022451 0ustar vincevince# General purpose pkg-config macros # Determine if a package is available # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_available ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package availability) endif ifeq ($$(shell $$(PKGCONFIG) --exists $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Retrieve the version of a package # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif $(1) := $$(shell $$(PKGCONFIG) --version $(2)) endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number define pkg_config_package_min_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number # 4: Highest accepted version number define pkg_config_package_compare_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) ifeq ($$(shell $$(PKGCONFIG) --max-version=$(4) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif else $(1) := no endif endef # Add package to compiler/linker flags # 1: Name of package to add details of # 2: CFLAGS variable to extend, or none # 3: LDFLAGS variable to extend, or none define pkg_config_package_add_flags ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifneq ($(2),) $(2) := $$($(2)) $$(shell $$(PKGCONFIG) --cflags $(1)) endif ifneq ($(3),) $(3) := $$($(3)) $$(shell $$(PKGCONFIG) --libs $(1)) endif endef netsurf-2.9/hubbub-0.1.2/build/makefiles/Makefile.subdir0000664000175000017500000000741711165262413021751 0ustar vincevince# Child makefile fragment # # Inputs (reset on exit) # # DIR_SOURCES List of source files in this directory # DIR_TEST_ITEMS List of test items in this directory # DIR_INSTALL_ITEMS Items to install in form :; # # Toolchain is provided by top-level makefile # # Variables provided by top-level makefile # # BUILDDIR The location of the build tree root # COMPONENT The name of the component # CURDIR The location of the source tree root # EXPORTDIR The location of the export directory # WANT_TEST Whether to build testcases # # do_include Canned command sequence to include a child makefile # # Variables provided by parent makefile: # # DIR The name of the directory we're in, relative to CURDIR # # Variables we can manipulate: # # CLEAN_ITEMS The list of items to remove for "make clean" # DISTCLEAN_ITEMS The list of items to remove for "make distclean" # TEST_ITEMS The list of items to build for "make test" # TEST_TARGETS The list of target names to run for "make test" # INSTALL_ITEMS The list of items to (un)install # # SOURCES The list of sources to build for $(COMPONENT) # # Plus anything from the toolchain # Push parent directory onto the directory stack sp := $(sp).x dirstack_$(sp) := $(d) d := $(DIR) # Sources SRCS_$(d) := $(DIR_SOURCES) TEST_ITEMS_$(d) := INSTALL_ITEMS_$(d) := # Append to sources for component SOURCES := $(SOURCES) $(addprefix $(d), $(SRCS_$(d))) # Test sources ifeq ($(WANT_TEST),yes) ifneq ($(DIR_TEST_ITEMS),) # Extract the binary name from the ITEM binary = $(subst /,_,$(addprefix $(d),$(firstword $(subst :, ,$(ITEM))))) # Extract the list of sources from the ITEM sources = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) # We can't simply use the output of foreach here, # as it space separates its output, which kinda defeats the point. define append_test_src TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d))$1; endef define append_test TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d)) $1: $$(eval $$(foreach TSRC,$2, \ $$(call append_test_src,$$(addprefix $$(d),$$(TSRC))))) endef # Append test items, prepending $(d) to each source file $(eval $(foreach ITEM,$(DIR_TEST_ITEMS), \ $(call append_test,$(binary),$(sources)))) TEST_ITEMS := $(TEST_ITEMS) $(TEST_ITEMS_$(d)) TEST_TARGETS := $(TEST_TARGETS) test_$(d) # Extract the binary name from the TEST binary_name = $(firstword $(subst :, ,$(TEST))) # Target for tests in this directory test_$(d): $(d) $(addprefix $(BUILDDIR)/, \ $(foreach TEST,$(TEST_ITEMS_$(d)),$(binary_name))) $(Q)$(SHAREDLDPATH) $(TESTRUNNER) $(BUILDDIR) \ $(CURDIR)/$< $(subst /,_,$<) $(EXEEXT) endif endif # Install items ifneq ($(DIR_INSTALL_ITEMS),) # Extract the destination directory from the variable dest_dir = $(firstword $(subst :, ,$(ITEM))) # Extract the list of files to install files = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) define append_install_file INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d))$1; endef define append_install_item INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d)) $1: $$(eval $$(foreach FILE,$2, \ $$(call append_install_file,$$(addprefix $$(d),$$(FILE))))) endef # Append items to install (along with install location), prepending $(d) # to each item in the file list $(eval $(foreach ITEM,$(DIR_INSTALL_ITEMS), \ $(call append_install_item,$(dest_dir),$(files)))) INSTALL_ITEMS := $(INSTALL_ITEMS) $(INSTALL_ITEMS_$(d)) endif # Reset the inputs DIR_SOURCES := DIR_TEST_ITEMS := DIR_INSTALL_ITEMS := # Now include any children we may have MAKE_INCLUDES := $(wildcard $(d)*/Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Pop off the directory stack d := $(dirstack_$(sp)) sp := $(basename $(sp)) netsurf-2.9/hubbub-0.1.2/build/makefiles/Makefile.tools0000664000175000017500000003224511711241331021607 0ustar vincevince# Tools Makefile fragment # # Expected inputs: # # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # # Optional inputs: # # BUILD Type of build to perform: # release - Release build (default) # debug - Debug build # OPTCFLAGS Optional C compiler flags for $(BUILD) # OPTCXXFLAGS Optional C++ compiler flags for $(BUILD) # OPTLDFLAGS Optional linker flags for $(BUILD) # TARGET Target platform (defaults to host) # PREFIX Absolute installation path prefix # (defaults to /usr/local) # ############################################################################### # Sanity checks ############################################################################### ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not set) endif # Default build to release ifeq ($(BUILD),) BUILD := release endif ############################################################################### # Host/target platform detection ############################################################################### # Autodetect host if necessary ifeq ($(HOST),) HOST := $(shell uname -s) endif # Simple host sanitisation ifeq ($(HOST),) # Don't ask HOST := riscos else ifeq ($(HOST),RISC OS) HOST := riscos endif ifeq ($(HOST),BeOS) HOST := beos endif ifeq ($(HOST),Haiku) HOST := haiku endif ifeq ($(HOST),AmigaOS) HOST := amiga endif ifeq ($(findstring MINGW,$(HOST)),MINGW) HOST := windows endif endif ifeq ($(TARGET),) # Default target to host. Please add exceptions as required. TARGET := $(HOST) ifeq ($(HOST),haiku) # This isn't necessarily correct -- they have differences. However, in the # general case, this will work. If there are differences that are actually # important wrt the target platform (as opposed to the build host) then # we'll just have to introduce a haiku target, too. TARGET := beos endif endif # Sanitise HOST and TARGET # TODO: Ideally, we want the equivalent of s/[^A-Za-z0-9]/_/g here HOST := $(subst .,_,$(subst -,_,$(subst /,_,$(HOST)))) TARGET := $(subst .,_,$(subst -,_,$(subst /,_,$(TARGET)))) # Now setup our tooling ifeq ($(TARGET),riscos) ifeq ($(HOST),riscos) # Building on native RISC OS GCCSDK_INSTALL_ENV ?= CC__ := gcc CXX__ := g++ CMHG ?= cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= # On certain versions of RISC OS (<>4 || kernel < 8.75), # the kernel will clean up the current redirection on # OS_Exit, including closing the associated file handles. # This is problematic for UnixLib, as it's invariably using # those filehandles in a pipe between parent and child processes. # This affects us as, anywhere where we shell out and want to # capture the output of the child process may fail. # Fortunately, if we know the child process is built against # UnixLib, then we also know that it won't call OS_Exit when it # exits, instead returning directly to our exit handler (and thus # preserving the redirection). This only works, however, if the # child application is specified using its absolute path, or # found in Run$Path. In the case of Perl, it does not appear in # Run$Path, so we must invoke it using its absolute path so that # the SharedUnixLibrary successfully detects it as a child process. PERL ?= .bin.perl # This is nasty, but needed because $(CURDIR) will # contain colons, and thus confuse make mightily $(shell SetMacro Alias$$$(COMPONENT)pwd Set %0 :|$$CSD>|mUnset Alias$$$(COMPONENT)pwd) $(shell $(COMPONENT)pwd $(COMPONENT)$$Dir) CURDIR := <$(COMPONENT)$$Dir> else # Cross compiling for RISC OS ifeq ($(origin GCCSDK_INSTALL_ENV),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/env),) GCCSDK_INSTALL_ENV := /opt/netsurf/arm-unknown-riscos/env else GCCSDK_INSTALL_ENV := /home/riscos/env endif endif ifeq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/cross/bin),) GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-unknown-riscos/cross/bin else GCCSDK_INSTALL_CROSSBIN := /home/riscos/cross/bin endif endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) CMHG ?= PATH="$(GCCSDK_INSTALL_CROSSBIN):$(PATH)" $(GCCSDK_INSTALL_CROSSBIN)/cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/share/pkgconfig" pkg-config ifneq ($(COMPONENT_TYPE),riscos-module) ifeq ($(origin CC),default) ifneq ($(findstring arm-unknown-riscos-gcc,$(CC__)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif else ifneq ($(findstring arm-unknown-riscos-gcc,$(CC)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif endif else EXEEXT := ,ffa endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib CMHGFLAGS := -p -tgcc -32bit -apcs 3/32/nonreent/fpe2/noswst/nofpr/nofp # Default prefix PREFIX ?= $(GCCSDK_INSTALL_ENV) endif # BeOS-like targets ifeq ($(TARGET),beos) ifeq ($(HOST),beos) # Building on BeOS CC__ := gcc # No pkg-config PKGCONFIG ?= # Default prefix BEOS_INSTALL_ENV ?= /boot/home/config else ifeq ($(HOST),haiku) # Building on Haiku # Default prefix BEOS_INSTALL_ENV ?= /boot/common else # TODO: more sensible default BEOS_INSTALL_ENV ?= /home/jmb/haiku/env BEOS_INSTALL_CROSSBIN ?= /home/jmb/haiku/haiku/generated/cross-tools/bin CC__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*g++) AR__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*ar) PKGCONFIG := PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/share/pkgconfig" pkg-config endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -I$(BEOS_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -I$(BEOS_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(BEOS_INSTALL_ENV)/lib PREFIX ?= $(BEOS_INSTALL_ENV) endif # Windows ifeq ($(TARGET),windows) ifeq ($(HOST),windows) # Building on Windows CC__ := gcc CXX__ := g++ AR__ := ar PKGCONFIG ?= else # Cross compiling for Windows -- assumes mingw toolchain MINGW_INSTALL_ENV ?= /usr/local/mingw CC__ := i586-mingw32msvc-gcc CXX__ := i586-mingw32msvc-g++ AR__ := i586-mingw32msvc-ar PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(MINGW_INSTALL_ENV)/lib # Default prefix PREFIX ?= $(MINGW_INSTALL_ENV) endif # AmigaOS (3/4; m68k/ppc: we can treat them identically) ifeq ($(findstring amiga,$(TARGET)),amiga) ifeq ($(findstring amiga,$(HOST)),amiga) # Building on AmigaOS # Nothing to do, as we assume the default tooling works else # Cross compiling for AmigaOS ifeq ($(TARGET),amigaos3) GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-unknown-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-unknown-amigaos/cross/bin else GCCSDK_INSTALL_ENV ?= /opt/netsurf/ppc-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/ppc-amigaos/cross/bin endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib PREFIX ?= $(GCCSDK_INSTALL_ENV) endif endif # Default prefix PREFIX ?= /usr/local ############################################################################### # Tool defaults ############################################################################### CP ?= cp DOXYGEN ?= doxygen ECHO ?= echo GENHTML ?= genhtml ifeq ($(HOST),$(TARGET)) HOST_CC ?= $(CC) HOST_CXX ?= $(CXX) else HOST_CC ?= cc HOST_CXX ?= c++ endif INSTALL ?= install LCOV ?= lcov LN ?= ln MAKE ?= make MKDIR ?= mkdir MKDIRFLAGS ?= -p MV ?= mv PERL ?= perl PKGCONFIG ?= PKG_CONFIG_PATH="$(PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)" pkg-config GREP ?= grep SED ?= sed TOUCH ?= touch XSLTPROC ?= xsltproc ############################################################################### # Override defaulted tools ############################################################################### # CC ifeq ($(findstring ccc-analyzer,$(CC)),ccc-analyzer) # We're being invoked by scan-build, so export # the compiler we would have used such that # scan-build works with cross-compilation. # There's no need to do this if we would have # used the default compiler. ifdef CC__ export CCC_CC := $(CC__) endif else # Only set CC if it's not already set in the # environment and we have a value for it. # Otherwise, leave it to be defaulted. ifeq ($(origin CC),default) ifdef CC__ CC := $(CC__) endif endif endif # CXX ifeq ($(origin CXX),default) ifdef CXX__ CXX := $(CXX__) endif endif # AR ifeq ($(origin AR),default) ifdef AR__ AR := $(AR__) endif endif ############################################################################### # Auto-detect the toolchain ############################################################################### # Check for GCC first, as that's most likely # TODO: Using shell redirection like this probably hurts portability ccspecs := $(shell $(CC) -dumpspecs 2>&1) ifeq ($(findstring libgcc,$(ccspecs)),libgcc) # Looks like GCC toolchain := gcc else # Not GCC, so enquire further ccvsn := $(shell $(CC) --version 2>&1) ifeq ($(ccvsn),) # Version string is blank ifeq ($(HOST),riscos) # For some reason we never see the output of SCL apps, so might be # Norcroft. However it might also be a GCC linked against a buggy # UnixLib. # TODO: Something more useful than blindly assuming GCC. ccvsn := GCC # ccvsn := Norcroft endif endif # "Norcroft ..." ifeq ($(word 1,$(ccvsn)),Norcroft) toolchain := norcroft endif # "GCC ..." ifeq ($(word 1,$(ccvsn)),GCC) toolchain := gcc endif # "clang ..." ifeq ($(word 1,$(ccvsn)),clang) toolchain := clang endif ifeq ($(word 1,$(ccvsn)),Apple) ifeq ($(word 2,$(ccvsn)),clang) # Apple clang toolchain := clang endif endif endif ifeq ($(toolchain),) $(error Unable to detect toolchain) endif # TODO: It would be nice to avoid this hard-coded path include build/makefiles/Makefile.$(toolchain) ############################################################################### # Default assembler/compiler/linker/archiver flags ############################################################################### ifeq ($(BUILD),release) OPTCFLAGS ?= $(CCDEF)NDEBUG $(CCOPT) OPTCXXFLAGS ?= $(CXXDEF)NDEBUG $(CXXOPT) else OPTCFLAGS ?= $(CCDBG) $(CCNOOPT) $(CCDEF)DEBUG OPTCXXFLAGS ?= $(CXXDBG) $(CXXNOOPT) $(CXXDEF)DEBUG OPTLDFLAGS ?= $(LDDBG) endif ifeq ($(origin ARFLAGS),default) ARFLAGS := $(ARFLG) endif # TODO: This assumes that the C compiler can cope with assembler ASFLAGS ?= $(CCAS) CFLAGS := $(CFLAGS) $(OPTCFLAGS) $(CCDEF)BUILD_TARGET_$(TARGET) $(CCDEF)BUILD_HOST_$(HOST) CXXFLAGS := $(CXXFLAGS) $(OPTCXXFLAGS) \ $(CXXDEF)BUILD_TARGET_$(TARGET) $(CXXDEF)BUILD_HOST_$(HOST) ASFLAGS := $(ASFLAGS) $(CFLAGS) LDFLAGS := $(LDFLAGS) $(OPTLDFLAGS) ############################################################################### # lib-shared defaults ############################################################################### # Default library extension ifeq ($(COMPONENT_TYPE),lib-static) LIBEXT ?= .a else LIBEXT ?= .so endif # If we're building a shared library, modify the flags appropriately ifeq ($(COMPONENT_TYPE),lib-shared) # Default CFLAGS/LDFLAGS for shared libraries SHAREDCFLAGS ?= $(CCSHR) $(CCDEF)PIC SHAREDCXXFLAGS ?= $(CXXSHR) $(CCDEF)PIC SHAREDLDFLAGS ?= $(LDSHR) SHAREDLDPATH ?= LD_LIBRARY_PATH="$(BUILDDIR):$(LD_LIBRARY_PATH)" endif ################################################################################ # Package config macros ################################################################################ include build/makefiles/Makefile.pkgconfig netsurf-2.9/hubbub-0.1.2/build/get-entities/0000775000175000017500000000000011734430252017452 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/build/get-entities/entities.xslt0000664000175000017500000000063411013065654022215 0ustar vincevince { "", 0x}, netsurf-2.9/hubbub-0.1.2/build/get-entities/get_entities0000775000175000017500000000066511013065654022072 0ustar vincevince#!/bin/bash # Get entities from the whatwg.org SVN repository. (rm -f *.inc entities.xml) || exit 1 (wget http://svn.whatwg.org/webapps/entities-legacy.inc && wget http://svn.whatwg.org/webapps/entities-unicode.inc) || (echo "Failed to get entities" && exit 1) (echo "

" && cat entities-legacy.inc && cat entities-unicode.inc && echo "
") > entities.xml (xsltproc entities.xslt entities.xml | sort -d) > entities.inc netsurf-2.9/hubbub-0.1.2/build/testtools/0000775000175000017500000000000011734430260017110 5ustar vincevincenetsurf-2.9/hubbub-0.1.2/build/testtools/testrunner.pl0000664000175000017500000001275111476511774021701 0ustar vincevince#!/bin/perl # # Testcase runner for libhubbub # # Usage: testrunner [] # # Operates upon INDEX files described in the README. # Locates and executes testcases, feeding data files to programs # as appropriate. # Logs testcase output to file. # Aborts test sequence on detection of error. # use warnings; use strict; use File::Spec; use IO::Select; use IPC::Open3; use Symbol; if (@ARGV < 3) { print "Usage: testrunner.pl []\n"; exit; } # Get directories my $builddir = shift @ARGV; my $directory = shift @ARGV; my $prefix = shift @ARGV; # Get EXE extension (if any) my $exeext = ""; $exeext = shift @ARGV if (@ARGV > 0); # Open log file and /dev/null open(LOG, ">$builddir/testlog") or die "Failed opening test log"; open(NULL, "+<", File::Spec->devnull) or die "Failed opening /dev/null"; # Open testcase index open(TINDEX, "<$directory/INDEX") or die "Failed opening test INDEX"; # Parse testcase index, looking for testcases while (my $line = ) { next if ($line =~ /^(#.*)?$/); # Found one; decompose (my $test, my $desc, my $data) = split /\t+/, $line; # Strip whitespace $test =~ s/^\s+|\s+$//g; $desc =~ s/^\s+|\s+$//g; $data =~ s/^\s+|\s+$//g if ($data); # Append prefix & EXE extension to binary name $test = $prefix . $test . $exeext; print "Test: $desc\n"; if ($data) { # Testcase has external data files # Open datafile index open(DINDEX, "<$directory/data/$data/INDEX") or die "Failed opening $directory/data/$data/INDEX"; # Parse datafile index, looking for datafiles while (my $dentry = ) { next if ($dentry =~ /^(#.*)?$/); # Found one; decompose (my $dtest, my $ddesc) = split /\t+/, $dentry; # Strip whitespace $dtest =~ s/^\s+|\s+$//g; $ddesc =~ s/^\s+|\s+$//g; print LOG "Running $builddir/$test " . "$directory/data/$data/$dtest\n"; # Make message fit on an 80 column terminal my $msg = " ==> $test [$data/$dtest]"; $msg = $msg . "." x (80 - length($msg) - 8); print $msg; # Run testcase run_test("$builddir/$test", "$directory/data/$data/$dtest"); } close(DINDEX); } else { # Testcase has no external data files print LOG "Running $builddir/$test\n"; # Make message fit on an 80 column terminal my $msg = " ==> $test"; $msg = $msg . "." x (80 - length($msg) - 8); print $msg; # Run testcase run_test("$builddir/$test"); } print "\n"; } # Clean up close(TINDEX); close(NULL); close(LOG); sub run_test { my @errors; # Handles for communicating with the child my ($out, $err); $err = gensym(); # Apparently, this is required my $pid; # Invoke child eval { $pid = open3("&new(); $selector->add($out, $err); my $last = "FAIL"; my $outcont = 0; my $errcont = 0; # Marshal testcase output to log file while (my @ready = $selector->can_read) { foreach my $fh (@ready) { my $input; # Read up to 4096 bytes from handle my $len = sysread($fh, $input, 4096); if (!defined $len) { die "Error reading from child: $!\n"; } elsif ($len == 0) { # EOF, so remove handle $selector->remove($fh); next; } else { # Split into lines my @lines = split('\n', $input); # Grab the last character of the input my $lastchar = substr($input, -1, 1); if ($fh == $out) { # Child's stdout foreach my $l (@lines) { # Last line of previous read # was incomplete, and this is # the first line of this read # Simply contatenate. if ($outcont == 1 && $l eq $lines[0]) { print LOG "$l\n"; $last .= $l; # Last char of this read was # not '\n', so don't terminate # line in log. } elsif ($lastchar ne '\n' && $l eq $lines[-1]) { print LOG " $l"; $last = $l; # Normal behaviour, just print # the line to the log. } else { print LOG " $l\n"; $last = $l; } } # Flag whether last line was incomplete # for next time. if ($lastchar ne '\n') { $outcont = 1; } else { $outcont = 0; } } elsif ($fh == $err) { # Child's stderr if ($errcont == 1) { # Continuation required, # concatenate first line of # this read with last of # previous, then append the # rest from this read. $errors[-1] .= $lines[0]; push(@errors, @lines[1 .. -1]); } else { # Normal behaviour, just append push(@errors, @lines); } # Flag need for continuation if ($lastchar ne '\n') { $errcont = 1; } else { $errcont = 0; } } else { die "Unexpected file handle\n"; } } } } # Last line of child's output may not be terminated, so ensure it # is in the log, for readability. print LOG "\n"; # Reap child waitpid($pid, 0); # Catch non-zero exit status and turn it into failure if ($? != 0) { my $status = $? & 127; if ($status != 0) { print LOG " FAIL: Exit status $status\n"; } $last = "FAIL"; } # Only interested in first 4 characters of last line $last = substr($last, 0, 4); # Convert all non-pass to fail if ($last ne "PASS") { $last = "FAIL"; } print "$last\n"; # Bail, noisily, on failure if ($last eq "FAIL") { # Write any stderr output to the log foreach my $error (@errors) { print LOG " $error\n"; } print "\n\nFailure detected: consult log file\n\n\n"; exit(1); } } netsurf-2.9/hubbub-0.1.2/build/Doxyfile0000664000175000017500000014371211131456147016571 0ustar vincevince# Doxyfile 1.4.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = Hubbub # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = build/docs # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = include src # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py FILE_PATTERNS = *.c *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */.svn/* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that a graph may be further truncated if the graph's # image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH # and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), # the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO netsurf-2.9/hubbub-0.1.2/build/Entities0000664000175000017500000011110411476510167016565 0ustar vincevince# Entities for HTML5 # Note, some entities are allowed to omit their trailing semicolon, which is # why most entities here have semicolons after them. # Entity Code Aacute; 0x000C1 Aacute 0x000C1 aacute; 0x000E1 aacute 0x000E1 Abreve; 0x00102 abreve; 0x00103 ac; 0x0223E acd; 0x0223F Acirc; 0x000C2 Acirc 0x000C2 acirc; 0x000E2 acirc 0x000E2 acute; 0x000B4 acute 0x000B4 Acy; 0x00410 acy; 0x00430 AElig; 0x000C6 AElig 0x000C6 aelig; 0x000E6 aelig 0x000E6 af; 0x02061 Afr; 0x1D504 afr; 0x1D51E Agrave; 0x000C0 Agrave 0x000C0 agrave; 0x000E0 agrave 0x000E0 alefsym; 0x02135 aleph; 0x02135 Alpha; 0x00391 alpha; 0x003B1 Amacr; 0x00100 amacr; 0x00101 amalg; 0x02A3F amp; 0x00026 amp 0x00026 AMP; 0x00026 AMP 0x00026 and; 0x02227 And; 0x02A53 andand; 0x02A55 andd; 0x02A5C andslope; 0x02A58 andv; 0x02A5A ang; 0x02220 ange; 0x029A4 angle; 0x02220 angmsd; 0x02221 angmsdaa; 0x029A8 angmsdab; 0x029A9 angmsdac; 0x029AA angmsdad; 0x029AB angmsdae; 0x029AC angmsdaf; 0x029AD angmsdag; 0x029AE angmsdah; 0x029AF angrt; 0x0221F angrtvb; 0x022BE angrtvbd; 0x0299D angsph; 0x02222 angst; 0x0212B angzarr; 0x0237C Aogon; 0x00104 aogon; 0x00105 Aopf; 0x1D538 aopf; 0x1D552 ap; 0x02248 apacir; 0x02A6F ape; 0x0224A apE; 0x02A70 apid; 0x0224B apos; 0x00027 ApplyFunction; 0x02061 approx; 0x02248 approxeq; 0x0224A Aring; 0x000C5 Aring 0x000C5 aring; 0x000E5 aring 0x000E5 Ascr; 0x1D49C ascr; 0x1D4B6 Assign; 0x02254 ast; 0x0002A asymp; 0x02248 asympeq; 0x0224D Atilde; 0x000C3 Atilde 0x000C3 atilde; 0x000E3 atilde 0x000E3 Auml; 0x000C4 Auml 0x000C4 auml; 0x000E4 auml 0x000E4 awconint; 0x02233 awint; 0x02A11 backcong; 0x0224C backepsilon; 0x003F6 backprime; 0x02035 backsim; 0x0223D backsimeq; 0x022CD Backslash; 0x02216 Barv; 0x02AE7 barvee; 0x022BD barwed; 0x02305 Barwed; 0x02306 barwedge; 0x02305 bbrk; 0x023B5 bbrktbrk; 0x023B6 bcong; 0x0224C Bcy; 0x00411 bcy; 0x00431 bdquo; 0x0201E becaus; 0x02235 because; 0x02235 Because; 0x02235 bemptyv; 0x029B0 bepsi; 0x003F6 bernou; 0x0212C Bernoullis; 0x0212C Beta; 0x00392 beta; 0x003B2 beth; 0x02136 between; 0x0226C Bfr; 0x1D505 bfr; 0x1D51F bigcap; 0x022C2 bigcirc; 0x025EF bigcup; 0x022C3 bigodot; 0x02A00 bigoplus; 0x02A01 bigotimes; 0x02A02 bigsqcup; 0x02A06 bigstar; 0x02605 bigtriangledown; 0x025BD bigtriangleup; 0x025B3 biguplus; 0x02A04 bigvee; 0x022C1 bigwedge; 0x022C0 bkarow; 0x0290D blacklozenge; 0x029EB blacksquare; 0x025AA blacktriangle; 0x025B4 blacktriangledown; 0x025BE blacktriangleleft; 0x025C2 blacktriangleright; 0x025B8 blank; 0x02423 blk12; 0x02592 blk14; 0x02591 blk34; 0x02593 block; 0x02588 bnot; 0x02310 bNot; 0x02AED Bopf; 0x1D539 bopf; 0x1D553 bot; 0x022A5 bottom; 0x022A5 bowtie; 0x022C8 boxbox; 0x029C9 boxdl; 0x02510 boxdL; 0x02555 boxDl; 0x02556 boxDL; 0x02557 boxdr; 0x0250C boxdR; 0x02552 boxDr; 0x02553 boxDR; 0x02554 boxh; 0x02500 boxH; 0x02550 boxhd; 0x0252C boxHd; 0x02564 boxhD; 0x02565 boxHD; 0x02566 boxhu; 0x02534 boxHu; 0x02567 boxhU; 0x02568 boxHU; 0x02569 boxminus; 0x0229F boxplus; 0x0229E boxtimes; 0x022A0 boxul; 0x02518 boxuL; 0x0255B boxUl; 0x0255C boxUL; 0x0255D boxur; 0x02514 boxuR; 0x02558 boxUr; 0x02559 boxUR; 0x0255A boxv; 0x02502 boxV; 0x02551 boxvh; 0x0253C boxvH; 0x0256A boxVh; 0x0256B boxVH; 0x0256C boxvl; 0x02524 boxvL; 0x02561 boxVl; 0x02562 boxVL; 0x02563 boxvr; 0x0251C boxvR; 0x0255E boxVr; 0x0255F boxVR; 0x02560 bprime; 0x02035 breve; 0x002D8 Breve; 0x002D8 brvbar; 0x000A6 brvbar 0x000A6 Bscr; 0x0212C bscr; 0x1D4B7 bsemi; 0x0204F bsim; 0x0223D bsime; 0x022CD bsol; 0x0005C bsolb; 0x029C5 bull; 0x02022 bullet; 0x02022 bump; 0x0224E bumpe; 0x0224F bumpE; 0x02AAE Bumpeq; 0x0224E bumpeq; 0x0224F Cacute; 0x00106 cacute; 0x00107 cap; 0x02229 Cap; 0x022D2 capand; 0x02A44 capbrcup; 0x02A49 capcap; 0x02A4B capcup; 0x02A47 capdot; 0x02A40 CapitalDifferentialD; 0x02145 caret; 0x02041 caron; 0x002C7 Cayleys; 0x0212D ccaps; 0x02A4D Ccaron; 0x0010C ccaron; 0x0010D Ccedil; 0x000C7 Ccedil 0x000C7 ccedil; 0x000E7 ccedil 0x000E7 Ccirc; 0x00108 ccirc; 0x00109 Cconint; 0x02230 ccups; 0x02A4C ccupssm; 0x02A50 Cdot; 0x0010A cdot; 0x0010B cedil; 0x000B8 cedil 0x000B8 Cedilla; 0x000B8 cemptyv; 0x029B2 cent; 0x000A2 cent 0x000A2 centerdot; 0x000B7 CenterDot; 0x000B7 Cfr; 0x0212D cfr; 0x1D520 CHcy; 0x00427 chcy; 0x00447 check; 0x02713 checkmark; 0x02713 Chi; 0x003A7 chi; 0x003C7 cir; 0x025CB circ; 0x002C6 circeq; 0x02257 circlearrowleft; 0x021BA circlearrowright; 0x021BB circledast; 0x0229B circledcirc; 0x0229A circleddash; 0x0229D CircleDot; 0x02299 circledR; 0x000AE circledS; 0x024C8 CircleMinus; 0x02296 CirclePlus; 0x02295 CircleTimes; 0x02297 cire; 0x02257 cirE; 0x029C3 cirfnint; 0x02A10 cirmid; 0x02AEF cirscir; 0x029C2 ClockwiseContourIntegral; 0x02232 CloseCurlyDoubleQuote; 0x0201D CloseCurlyQuote; 0x02019 clubs; 0x02663 clubsuit; 0x02663 colon; 0x0003A Colon; 0x02237 colone; 0x02254 Colone; 0x02A74 coloneq; 0x02254 comma; 0x0002C commat; 0x00040 comp; 0x02201 compfn; 0x02218 complement; 0x02201 complexes; 0x02102 cong; 0x02245 congdot; 0x02A6D Congruent; 0x02261 conint; 0x0222E Conint; 0x0222F ContourIntegral; 0x0222E Copf; 0x02102 copf; 0x1D554 coprod; 0x02210 Coproduct; 0x02210 copy; 0x000A9 copy 0x000A9 COPY; 0x000A9 COPY 0x000A9 copysr; 0x02117 CounterClockwiseContourIntegral; 0x02233 crarr; 0x021B5 cross; 0x02717 Cross; 0x02A2F Cscr; 0x1D49E cscr; 0x1D4B8 csub; 0x02ACF csube; 0x02AD1 csup; 0x02AD0 csupe; 0x02AD2 ctdot; 0x022EF cudarrl; 0x02938 cudarrr; 0x02935 cuepr; 0x022DE cuesc; 0x022DF cularr; 0x021B6 cularrp; 0x0293D cup; 0x0222A Cup; 0x022D3 cupbrcap; 0x02A48 CupCap; 0x0224D cupcap; 0x02A46 cupcup; 0x02A4A cupdot; 0x0228D cupor; 0x02A45 curarr; 0x021B7 curarrm; 0x0293C curlyeqprec; 0x022DE curlyeqsucc; 0x022DF curlyvee; 0x022CE curlywedge; 0x022CF curren; 0x000A4 curren 0x000A4 curvearrowleft; 0x021B6 curvearrowright; 0x021B7 cuvee; 0x022CE cuwed; 0x022CF cwconint; 0x02232 cwint; 0x02231 cylcty; 0x0232D dagger; 0x02020 Dagger; 0x02021 daleth; 0x02138 darr; 0x02193 Darr; 0x021A1 dArr; 0x021D3 dash; 0x02010 dashv; 0x022A3 Dashv; 0x02AE4 dbkarow; 0x0290F dblac; 0x002DD Dcaron; 0x0010E dcaron; 0x0010F Dcy; 0x00414 dcy; 0x00434 DD; 0x02145 dd; 0x02146 ddagger; 0x02021 ddarr; 0x021CA DDotrahd; 0x02911 ddotseq; 0x02A77 deg; 0x000B0 deg 0x000B0 Del; 0x02207 Delta; 0x00394 delta; 0x003B4 demptyv; 0x029B1 dfisht; 0x0297F Dfr; 0x1D507 dfr; 0x1D521 dHar; 0x02965 dharl; 0x021C3 dharr; 0x021C2 DiacriticalAcute; 0x000B4 DiacriticalDot; 0x002D9 DiacriticalDoubleAcute; 0x002DD DiacriticalGrave; 0x00060 DiacriticalTilde; 0x002DC diam; 0x022C4 diamond; 0x022C4 Diamond; 0x022C4 diamondsuit; 0x02666 diams; 0x02666 die; 0x000A8 DifferentialD; 0x02146 digamma; 0x003DD disin; 0x022F2 div; 0x000F7 divide; 0x000F7 divide 0x000F7 divideontimes; 0x022C7 divonx; 0x022C7 DJcy; 0x00402 djcy; 0x00452 dlcorn; 0x0231E dlcrop; 0x0230D dollar; 0x00024 Dopf; 0x1D53B dopf; 0x1D555 Dot; 0x000A8 dot; 0x002D9 DotDot; 0x020DC doteq; 0x02250 doteqdot; 0x02251 DotEqual; 0x02250 dotminus; 0x02238 dotplus; 0x02214 dotsquare; 0x022A1 doublebarwedge; 0x02306 DoubleContourIntegral; 0x0222F DoubleDot; 0x000A8 DoubleDownArrow; 0x021D3 DoubleLeftArrow; 0x021D0 DoubleLeftRightArrow; 0x021D4 DoubleLeftTee; 0x02AE4 DoubleLongLeftArrow; 0x027F8 DoubleLongLeftRightArrow; 0x027FA DoubleLongRightArrow; 0x027F9 DoubleRightArrow; 0x021D2 DoubleRightTee; 0x022A8 DoubleUpArrow; 0x021D1 DoubleUpDownArrow; 0x021D5 DoubleVerticalBar; 0x02225 downarrow; 0x02193 DownArrow; 0x02193 Downarrow; 0x021D3 DownArrowBar; 0x02913 DownArrowUpArrow; 0x021F5 DownBreve; 0x00311 downdownarrows; 0x021CA downharpoonleft; 0x021C3 downharpoonright; 0x021C2 DownLeftRightVector; 0x02950 DownLeftTeeVector; 0x0295E DownLeftVector; 0x021BD DownLeftVectorBar; 0x02956 DownRightTeeVector; 0x0295F DownRightVector; 0x021C1 DownRightVectorBar; 0x02957 DownTee; 0x022A4 DownTeeArrow; 0x021A7 drbkarow; 0x02910 drcorn; 0x0231F drcrop; 0x0230C Dscr; 0x1D49F dscr; 0x1D4B9 DScy; 0x00405 dscy; 0x00455 dsol; 0x029F6 Dstrok; 0x00110 dstrok; 0x00111 dtdot; 0x022F1 dtri; 0x025BF dtrif; 0x025BE duarr; 0x021F5 duhar; 0x0296F dwangle; 0x029A6 DZcy; 0x0040F dzcy; 0x0045F dzigrarr; 0x027FF Eacute; 0x000C9 Eacute 0x000C9 eacute; 0x000E9 eacute 0x000E9 easter; 0x02A6E Ecaron; 0x0011A ecaron; 0x0011B ecir; 0x02256 Ecirc; 0x000CA Ecirc 0x000CA ecirc; 0x000EA ecirc 0x000EA ecolon; 0x02255 Ecy; 0x0042D ecy; 0x0044D eDDot; 0x02A77 Edot; 0x00116 edot; 0x00117 eDot; 0x02251 ee; 0x02147 efDot; 0x02252 Efr; 0x1D508 efr; 0x1D522 eg; 0x02A9A Egrave; 0x000C8 Egrave 0x000C8 egrave; 0x000E8 egrave 0x000E8 egs; 0x02A96 egsdot; 0x02A98 el; 0x02A99 Element; 0x02208 elinters; 0x023E7 ell; 0x02113 els; 0x02A95 elsdot; 0x02A97 Emacr; 0x00112 emacr; 0x00113 empty; 0x02205 emptyset; 0x02205 EmptySmallSquare; 0x025FB emptyv; 0x02205 EmptyVerySmallSquare; 0x025AB emsp; 0x02003 emsp13; 0x02004 emsp14; 0x02005 ENG; 0x0014A eng; 0x0014B ensp; 0x02002 Eogon; 0x00118 eogon; 0x00119 Eopf; 0x1D53C eopf; 0x1D556 epar; 0x022D5 eparsl; 0x029E3 eplus; 0x02A71 epsi; 0x003F5 Epsilon; 0x00395 epsilon; 0x003B5 epsiv; 0x003B5 eqcirc; 0x02256 eqcolon; 0x02255 eqsim; 0x02242 eqslantgtr; 0x02A96 eqslantless; 0x02A95 Equal; 0x02A75 equals; 0x0003D EqualTilde; 0x02242 equest; 0x0225F Equilibrium; 0x021CC equiv; 0x02261 equivDD; 0x02A78 eqvparsl; 0x029E5 erarr; 0x02971 erDot; 0x02253 escr; 0x0212F Escr; 0x02130 esdot; 0x02250 esim; 0x02242 Esim; 0x02A73 Eta; 0x00397 eta; 0x003B7 ETH; 0x000D0 ETH 0x000D0 eth; 0x000F0 eth 0x000F0 Euml; 0x000CB Euml 0x000CB euml; 0x000EB euml 0x000EB euro; 0x020AC excl; 0x00021 exist; 0x02203 Exists; 0x02203 expectation; 0x02130 exponentiale; 0x02147 ExponentialE; 0x02147 fallingdotseq; 0x02252 Fcy; 0x00424 fcy; 0x00444 female; 0x02640 ffilig; 0x0FB03 fflig; 0x0FB00 ffllig; 0x0FB04 Ffr; 0x1D509 ffr; 0x1D523 filig; 0x0FB01 FilledSmallSquare; 0x025FC FilledVerySmallSquare; 0x025AA flat; 0x0266D fllig; 0x0FB02 fltns; 0x025B1 fnof; 0x00192 Fopf; 0x1D53D fopf; 0x1D557 forall; 0x02200 ForAll; 0x02200 fork; 0x022D4 forkv; 0x02AD9 Fouriertrf; 0x02131 fpartint; 0x02A0D frac12; 0x000BD frac12 0x000BD frac13; 0x02153 frac14; 0x000BC frac14 0x000BC frac15; 0x02155 frac16; 0x02159 frac18; 0x0215B frac23; 0x02154 frac25; 0x02156 frac34; 0x000BE frac34 0x000BE frac35; 0x02157 frac38; 0x0215C frac45; 0x02158 frac56; 0x0215A frac58; 0x0215D frac78; 0x0215E frasl; 0x02044 frown; 0x02322 Fscr; 0x02131 fscr; 0x1D4BB gacute; 0x001F5 Gamma; 0x00393 gamma; 0x003B3 Gammad; 0x003DC gammad; 0x003DD gap; 0x02A86 Gbreve; 0x0011E gbreve; 0x0011F Gcedil; 0x00122 Gcirc; 0x0011C gcirc; 0x0011D Gcy; 0x00413 gcy; 0x00433 Gdot; 0x00120 gdot; 0x00121 ge; 0x02265 gE; 0x02267 gel; 0x022DB gEl; 0x02A8C geq; 0x02265 geqq; 0x02267 geqslant; 0x02A7E ges; 0x02A7E gescc; 0x02AA9 gesdot; 0x02A80 gesdoto; 0x02A82 gesdotol; 0x02A84 gesles; 0x02A94 Gfr; 0x1D50A gfr; 0x1D524 gg; 0x0226B Gg; 0x022D9 ggg; 0x022D9 gimel; 0x02137 GJcy; 0x00403 gjcy; 0x00453 gl; 0x02277 gla; 0x02AA5 glE; 0x02A92 glj; 0x02AA4 gnap; 0x02A8A gnapprox; 0x02A8A gnE; 0x02269 gne; 0x02A88 gneq; 0x02A88 gneqq; 0x02269 gnsim; 0x022E7 Gopf; 0x1D53E gopf; 0x1D558 grave; 0x00060 GreaterEqual; 0x02265 GreaterEqualLess; 0x022DB GreaterFullEqual; 0x02267 GreaterGreater; 0x02AA2 GreaterLess; 0x02277 GreaterSlantEqual; 0x02A7E GreaterTilde; 0x02273 gscr; 0x0210A Gscr; 0x1D4A2 gsim; 0x02273 gsime; 0x02A8E gsiml; 0x02A90 gt; 0x0003E gt 0x0003E GT; 0x0003E GT 0x0003E Gt; 0x0226B gtcc; 0x02AA7 gtcir; 0x02A7A gtdot; 0x022D7 gtlPar; 0x02995 gtquest; 0x02A7C gtrapprox; 0x02A86 gtrarr; 0x02978 gtrdot; 0x022D7 gtreqless; 0x022DB gtreqqless; 0x02A8C gtrless; 0x02277 gtrsim; 0x02273 Hacek; 0x002C7 hairsp; 0x0200A half; 0x000BD hamilt; 0x0210B HARDcy; 0x0042A hardcy; 0x0044A harr; 0x02194 hArr; 0x021D4 harrcir; 0x02948 harrw; 0x021AD Hat; 0x0005E hbar; 0x0210F Hcirc; 0x00124 hcirc; 0x00125 hearts; 0x02665 heartsuit; 0x02665 hellip; 0x02026 hercon; 0x022B9 Hfr; 0x0210C hfr; 0x1D525 HilbertSpace; 0x0210B hksearow; 0x02925 hkswarow; 0x02926 hoarr; 0x021FF homtht; 0x0223B hookleftarrow; 0x021A9 hookrightarrow; 0x021AA Hopf; 0x0210D hopf; 0x1D559 horbar; 0x02015 HorizontalLine; 0x02500 Hscr; 0x0210B hscr; 0x1D4BD hslash; 0x0210F Hstrok; 0x00126 hstrok; 0x00127 HumpDownHump; 0x0224E HumpEqual; 0x0224F hybull; 0x02043 hyphen; 0x02010 Iacute; 0x000CD Iacute 0x000CD iacute; 0x000ED iacute 0x000ED ic; 0x02063 Icirc; 0x000CE Icirc 0x000CE icirc; 0x000EE icirc 0x000EE Icy; 0x00418 icy; 0x00438 Idot; 0x00130 IEcy; 0x00415 iecy; 0x00435 iexcl; 0x000A1 iexcl 0x000A1 iff; 0x021D4 Ifr; 0x02111 ifr; 0x1D526 Igrave; 0x000CC Igrave 0x000CC igrave; 0x000EC igrave 0x000EC ii; 0x02148 iiiint; 0x02A0C iiint; 0x0222D iinfin; 0x029DC iiota; 0x02129 IJlig; 0x00132 ijlig; 0x00133 Im; 0x02111 Imacr; 0x0012A imacr; 0x0012B image; 0x02111 ImaginaryI; 0x02148 imagline; 0x02110 imagpart; 0x02111 imath; 0x00131 imof; 0x022B7 imped; 0x001B5 Implies; 0x021D2 in; 0x02208 incare; 0x02105 infin; 0x0221E infintie; 0x029DD inodot; 0x00131 int; 0x0222B Int; 0x0222C intcal; 0x022BA integers; 0x02124 Integral; 0x0222B intercal; 0x022BA Intersection; 0x022C2 intlarhk; 0x02A17 intprod; 0x02A3C InvisibleComma; 0x02063 InvisibleTimes; 0x02062 IOcy; 0x00401 iocy; 0x00451 Iogon; 0x0012E iogon; 0x0012F Iopf; 0x1D540 iopf; 0x1D55A Iota; 0x00399 iota; 0x003B9 iprod; 0x02A3C iquest; 0x000BF iquest 0x000BF Iscr; 0x02110 iscr; 0x1D4BE isin; 0x02208 isindot; 0x022F5 isinE; 0x022F9 isins; 0x022F4 isinsv; 0x022F3 isinv; 0x02208 it; 0x02062 Itilde; 0x00128 itilde; 0x00129 Iukcy; 0x00406 iukcy; 0x00456 Iuml; 0x000CF Iuml 0x000CF iuml; 0x000EF iuml 0x000EF Jcirc; 0x00134 jcirc; 0x00135 Jcy; 0x00419 jcy; 0x00439 Jfr; 0x1D50D jfr; 0x1D527 jmath; 0x00237 Jopf; 0x1D541 jopf; 0x1D55B Jscr; 0x1D4A5 jscr; 0x1D4BF Jsercy; 0x00408 jsercy; 0x00458 Jukcy; 0x00404 jukcy; 0x00454 Kappa; 0x0039A kappa; 0x003BA kappav; 0x003F0 Kcedil; 0x00136 kcedil; 0x00137 Kcy; 0x0041A kcy; 0x0043A Kfr; 0x1D50E kfr; 0x1D528 kgreen; 0x00138 KHcy; 0x00425 khcy; 0x00445 KJcy; 0x0040C kjcy; 0x0045C Kopf; 0x1D542 kopf; 0x1D55C Kscr; 0x1D4A6 kscr; 0x1D4C0 lAarr; 0x021DA Lacute; 0x00139 lacute; 0x0013A laemptyv; 0x029B4 lagran; 0x02112 Lambda; 0x0039B lambda; 0x003BB lang; 0x027E8 Lang; 0x027EA langd; 0x02991 langle; 0x027E8 lap; 0x02A85 Laplacetrf; 0x02112 laquo; 0x000AB laquo 0x000AB larr; 0x02190 Larr; 0x0219E lArr; 0x021D0 larrb; 0x021E4 larrbfs; 0x0291F larrfs; 0x0291D larrhk; 0x021A9 larrlp; 0x021AB larrpl; 0x02939 larrsim; 0x02973 larrtl; 0x021A2 lat; 0x02AAB latail; 0x02919 lAtail; 0x0291B late; 0x02AAD lbarr; 0x0290C lBarr; 0x0290E lbbrk; 0x02772 lbrace; 0x0007B lbrack; 0x0005B lbrke; 0x0298B lbrksld; 0x0298F lbrkslu; 0x0298D Lcaron; 0x0013D lcaron; 0x0013E Lcedil; 0x0013B lcedil; 0x0013C lceil; 0x02308 lcub; 0x0007B Lcy; 0x0041B lcy; 0x0043B ldca; 0x02936 ldquo; 0x0201C ldquor; 0x0201E ldrdhar; 0x02967 ldrushar; 0x0294B ldsh; 0x021B2 le; 0x02264 lE; 0x02266 LeftAngleBracket; 0x027E8 leftarrow; 0x02190 LeftArrow; 0x02190 Leftarrow; 0x021D0 LeftArrowBar; 0x021E4 LeftArrowRightArrow; 0x021C6 leftarrowtail; 0x021A2 LeftCeiling; 0x02308 LeftDoubleBracket; 0x027E6 LeftDownTeeVector; 0x02961 LeftDownVector; 0x021C3 LeftDownVectorBar; 0x02959 LeftFloor; 0x0230A leftharpoondown; 0x021BD leftharpoonup; 0x021BC leftleftarrows; 0x021C7 leftrightarrow; 0x02194 LeftRightArrow; 0x02194 Leftrightarrow; 0x021D4 leftrightarrows; 0x021C6 leftrightharpoons; 0x021CB leftrightsquigarrow; 0x021AD LeftRightVector; 0x0294E LeftTee; 0x022A3 LeftTeeArrow; 0x021A4 LeftTeeVector; 0x0295A leftthreetimes; 0x022CB LeftTriangle; 0x022B2 LeftTriangleBar; 0x029CF LeftTriangleEqual; 0x022B4 LeftUpDownVector; 0x02951 LeftUpTeeVector; 0x02960 LeftUpVector; 0x021BF LeftUpVectorBar; 0x02958 LeftVector; 0x021BC LeftVectorBar; 0x02952 leg; 0x022DA lEg; 0x02A8B leq; 0x02264 leqq; 0x02266 leqslant; 0x02A7D les; 0x02A7D lescc; 0x02AA8 lesdot; 0x02A7F lesdoto; 0x02A81 lesdotor; 0x02A83 lesges; 0x02A93 lessapprox; 0x02A85 lessdot; 0x022D6 lesseqgtr; 0x022DA lesseqqgtr; 0x02A8B LessEqualGreater; 0x022DA LessFullEqual; 0x02266 LessGreater; 0x02276 lessgtr; 0x02276 LessLess; 0x02AA1 lesssim; 0x02272 LessSlantEqual; 0x02A7D LessTilde; 0x02272 lfisht; 0x0297C lfloor; 0x0230A Lfr; 0x1D50F lfr; 0x1D529 lg; 0x02276 lgE; 0x02A91 lHar; 0x02962 lhard; 0x021BD lharu; 0x021BC lharul; 0x0296A lhblk; 0x02584 LJcy; 0x00409 ljcy; 0x00459 ll; 0x0226A Ll; 0x022D8 llarr; 0x021C7 llcorner; 0x0231E Lleftarrow; 0x021DA llhard; 0x0296B lltri; 0x025FA Lmidot; 0x0013F lmidot; 0x00140 lmoust; 0x023B0 lmoustache; 0x023B0 lnap; 0x02A89 lnapprox; 0x02A89 lnE; 0x02268 lne; 0x02A87 lneq; 0x02A87 lneqq; 0x02268 lnsim; 0x022E6 loang; 0x027EC loarr; 0x021FD lobrk; 0x027E6 longleftarrow; 0x027F5 LongLeftArrow; 0x027F5 Longleftarrow; 0x027F8 longleftrightarrow; 0x027F7 LongLeftRightArrow; 0x027F7 Longleftrightarrow; 0x027FA longmapsto; 0x027FC longrightarrow; 0x027F6 LongRightArrow; 0x027F6 Longrightarrow; 0x027F9 looparrowleft; 0x021AB looparrowright; 0x021AC lopar; 0x02985 Lopf; 0x1D543 lopf; 0x1D55D loplus; 0x02A2D lotimes; 0x02A34 lowast; 0x02217 lowbar; 0x0005F LowerLeftArrow; 0x02199 LowerRightArrow; 0x02198 loz; 0x025CA lozenge; 0x025CA lozf; 0x029EB lpar; 0x00028 lparlt; 0x02993 lrarr; 0x021C6 lrcorner; 0x0231F lrhar; 0x021CB lrhard; 0x0296D lrm; 0x0200E lrtri; 0x022BF lsaquo; 0x02039 Lscr; 0x02112 lscr; 0x1D4C1 lsh; 0x021B0 Lsh; 0x021B0 lsim; 0x02272 lsime; 0x02A8D lsimg; 0x02A8F lsqb; 0x0005B lsquo; 0x02018 lsquor; 0x0201A Lstrok; 0x00141 lstrok; 0x00142 lt; 0x0003C lt 0x0003C LT; 0x0003C LT 0x0003C Lt; 0x0226A ltcc; 0x02AA6 ltcir; 0x02A79 ltdot; 0x022D6 lthree; 0x022CB ltimes; 0x022C9 ltlarr; 0x02976 ltquest; 0x02A7B ltri; 0x025C3 ltrie; 0x022B4 ltrif; 0x025C2 ltrPar; 0x02996 lurdshar; 0x0294A luruhar; 0x02966 macr; 0x000AF macr 0x000AF male; 0x02642 malt; 0x02720 maltese; 0x02720 map; 0x021A6 Map; 0x02905 mapsto; 0x021A6 mapstodown; 0x021A7 mapstoleft; 0x021A4 mapstoup; 0x021A5 marker; 0x025AE mcomma; 0x02A29 Mcy; 0x0041C mcy; 0x0043C mdash; 0x02014 mDDot; 0x0223A measuredangle; 0x02221 MediumSpace; 0x0205F Mellintrf; 0x02133 Mfr; 0x1D510 mfr; 0x1D52A mho; 0x02127 micro; 0x000B5 micro 0x000B5 mid; 0x02223 midast; 0x0002A midcir; 0x02AF0 middot; 0x000B7 middot 0x000B7 minus; 0x02212 minusb; 0x0229F minusd; 0x02238 minusdu; 0x02A2A MinusPlus; 0x02213 mlcp; 0x02ADB mldr; 0x02026 mnplus; 0x02213 models; 0x022A7 Mopf; 0x1D544 mopf; 0x1D55E mp; 0x02213 Mscr; 0x02133 mscr; 0x1D4C2 mstpos; 0x0223E Mu; 0x0039C mu; 0x003BC multimap; 0x022B8 mumap; 0x022B8 nabla; 0x02207 Nacute; 0x00143 nacute; 0x00144 nap; 0x02249 napos; 0x00149 napprox; 0x02249 natur; 0x0266E natural; 0x0266E naturals; 0x02115 nbsp; 0x000A0 nbsp 0x000A0 ncap; 0x02A43 Ncaron; 0x00147 ncaron; 0x00148 Ncedil; 0x00145 ncedil; 0x00146 ncong; 0x02247 ncup; 0x02A42 Ncy; 0x0041D ncy; 0x0043D ndash; 0x02013 ne; 0x02260 nearhk; 0x02924 nearr; 0x02197 neArr; 0x021D7 nearrow; 0x02197 NegativeMediumSpace; 0x0200B NegativeThickSpace; 0x0200B NegativeThinSpace; 0x0200B NegativeVeryThinSpace; 0x0200B nequiv; 0x02262 nesear; 0x02928 NestedGreaterGreater; 0x0226B NestedLessLess; 0x0226A NewLine; 0x0000A nexist; 0x02204 nexists; 0x02204 Nfr; 0x1D511 nfr; 0x1D52B nge; 0x02271 ngeq; 0x02271 ngsim; 0x02275 ngt; 0x0226F ngtr; 0x0226F nharr; 0x021AE nhArr; 0x021CE nhpar; 0x02AF2 ni; 0x0220B nis; 0x022FC nisd; 0x022FA niv; 0x0220B NJcy; 0x0040A njcy; 0x0045A nlarr; 0x0219A nlArr; 0x021CD nldr; 0x02025 nle; 0x02270 nleftarrow; 0x0219A nLeftarrow; 0x021CD nleftrightarrow; 0x021AE nLeftrightarrow; 0x021CE nleq; 0x02270 nless; 0x0226E nlsim; 0x02274 nlt; 0x0226E nltri; 0x022EA nltrie; 0x022EC nmid; 0x02224 NoBreak; 0x02060 NonBreakingSpace; 0x000A0 Nopf; 0x02115 nopf; 0x1D55F not; 0x000AC not 0x000AC Not; 0x02AEC NotCongruent; 0x02262 NotCupCap; 0x0226D NotDoubleVerticalBar; 0x02226 NotElement; 0x02209 NotEqual; 0x02260 NotExists; 0x02204 NotGreater; 0x0226F NotGreaterEqual; 0x02271 NotGreaterLess; 0x02279 NotGreaterTilde; 0x02275 notin; 0x02209 notinva; 0x02209 notinvb; 0x022F7 notinvc; 0x022F6 NotLeftTriangle; 0x022EA NotLeftTriangleEqual; 0x022EC NotLess; 0x0226E NotLessEqual; 0x02270 NotLessGreater; 0x02278 NotLessTilde; 0x02274 notni; 0x0220C notniva; 0x0220C notnivb; 0x022FE notnivc; 0x022FD NotPrecedes; 0x02280 NotPrecedesSlantEqual; 0x022E0 NotReverseElement; 0x0220C NotRightTriangle; 0x022EB NotRightTriangleEqual; 0x022ED NotSquareSubsetEqual; 0x022E2 NotSquareSupersetEqual; 0x022E3 NotSubsetEqual; 0x02288 NotSucceeds; 0x02281 NotSucceedsSlantEqual; 0x022E1 NotSupersetEqual; 0x02289 NotTilde; 0x02241 NotTildeEqual; 0x02244 NotTildeFullEqual; 0x02247 NotTildeTilde; 0x02249 NotVerticalBar; 0x02224 npar; 0x02226 nparallel; 0x02226 npolint; 0x02A14 npr; 0x02280 nprcue; 0x022E0 nprec; 0x02280 nrarr; 0x0219B nrArr; 0x021CF nrightarrow; 0x0219B nRightarrow; 0x021CF nrtri; 0x022EB nrtrie; 0x022ED nsc; 0x02281 nsccue; 0x022E1 Nscr; 0x1D4A9 nscr; 0x1D4C3 nshortmid; 0x02224 nshortparallel; 0x02226 nsim; 0x02241 nsime; 0x02244 nsimeq; 0x02244 nsmid; 0x02224 nspar; 0x02226 nsqsube; 0x022E2 nsqsupe; 0x022E3 nsub; 0x02284 nsube; 0x02288 nsubseteq; 0x02288 nsucc; 0x02281 nsup; 0x02285 nsupe; 0x02289 nsupseteq; 0x02289 ntgl; 0x02279 Ntilde; 0x000D1 Ntilde 0x000D1 ntilde; 0x000F1 ntilde 0x000F1 ntlg; 0x02278 ntriangleleft; 0x022EA ntrianglelefteq; 0x022EC ntriangleright; 0x022EB ntrianglerighteq; 0x022ED Nu; 0x0039D nu; 0x003BD num; 0x00023 numero; 0x02116 numsp; 0x02007 nvdash; 0x022AC nvDash; 0x022AD nVdash; 0x022AE nVDash; 0x022AF nvHarr; 0x02904 nvinfin; 0x029DE nvlArr; 0x02902 nvrArr; 0x02903 nwarhk; 0x02923 nwarr; 0x02196 nwArr; 0x021D6 nwarrow; 0x02196 nwnear; 0x02927 Oacute; 0x000D3 Oacute 0x000D3 oacute; 0x000F3 oacute 0x000F3 oast; 0x0229B ocir; 0x0229A Ocirc; 0x000D4 Ocirc 0x000D4 ocirc; 0x000F4 ocirc 0x000F4 Ocy; 0x0041E ocy; 0x0043E odash; 0x0229D Odblac; 0x00150 odblac; 0x00151 odiv; 0x02A38 odot; 0x02299 odsold; 0x029BC OElig; 0x00152 oelig; 0x00153 ofcir; 0x029BF Ofr; 0x1D512 ofr; 0x1D52C ogon; 0x002DB Ograve; 0x000D2 Ograve 0x000D2 ograve; 0x000F2 ograve 0x000F2 ogt; 0x029C1 ohbar; 0x029B5 ohm; 0x02126 oint; 0x0222E olarr; 0x021BA olcir; 0x029BE olcross; 0x029BB oline; 0x0203E olt; 0x029C0 Omacr; 0x0014C omacr; 0x0014D Omega; 0x003A9 omega; 0x003C9 Omicron; 0x0039F omicron; 0x003BF omid; 0x029B6 ominus; 0x02296 Oopf; 0x1D546 oopf; 0x1D560 opar; 0x029B7 OpenCurlyDoubleQuote; 0x0201C OpenCurlyQuote; 0x02018 operp; 0x029B9 oplus; 0x02295 or; 0x02228 Or; 0x02A54 orarr; 0x021BB ord; 0x02A5D order; 0x02134 orderof; 0x02134 ordf; 0x000AA ordf 0x000AA ordm; 0x000BA ordm 0x000BA origof; 0x022B6 oror; 0x02A56 orslope; 0x02A57 orv; 0x02A5B oS; 0x024C8 oscr; 0x02134 Oscr; 0x1D4AA Oslash; 0x000D8 Oslash 0x000D8 oslash; 0x000F8 oslash 0x000F8 osol; 0x02298 Otilde; 0x000D5 Otilde 0x000D5 otilde; 0x000F5 otilde 0x000F5 otimes; 0x02297 Otimes; 0x02A37 otimesas; 0x02A36 Ouml; 0x000D6 Ouml 0x000D6 ouml; 0x000F6 ouml 0x000F6 ovbar; 0x0233D OverBar; 0x000AF OverBrace; 0x023DE OverBracket; 0x023B4 OverParenthesis; 0x023DC par; 0x02225 para; 0x000B6 para 0x000B6 parallel; 0x02225 parsim; 0x02AF3 parsl; 0x02AFD part; 0x02202 PartialD; 0x02202 Pcy; 0x0041F pcy; 0x0043F percnt; 0x00025 period; 0x0002E permil; 0x02030 perp; 0x022A5 pertenk; 0x02031 Pfr; 0x1D513 pfr; 0x1D52D Phi; 0x003A6 phi; 0x003C6 phiv; 0x003C6 phmmat; 0x02133 phone; 0x0260E Pi; 0x003A0 pi; 0x003C0 pitchfork; 0x022D4 piv; 0x003D6 planck; 0x0210F planckh; 0x0210E plankv; 0x0210F plus; 0x0002B plusacir; 0x02A23 plusb; 0x0229E pluscir; 0x02A22 plusdo; 0x02214 plusdu; 0x02A25 pluse; 0x02A72 PlusMinus; 0x000B1 plusmn; 0x000B1 plusmn 0x000B1 plussim; 0x02A26 plustwo; 0x02A27 pm; 0x000B1 Poincareplane; 0x0210C pointint; 0x02A15 Popf; 0x02119 popf; 0x1D561 pound; 0x000A3 pound 0x000A3 pr; 0x0227A Pr; 0x02ABB prap; 0x02AB7 prcue; 0x0227C pre; 0x02AAF prE; 0x02AB3 prec; 0x0227A precapprox; 0x02AB7 preccurlyeq; 0x0227C Precedes; 0x0227A PrecedesEqual; 0x02AAF PrecedesSlantEqual; 0x0227C PrecedesTilde; 0x0227E preceq; 0x02AAF precnapprox; 0x02AB9 precneqq; 0x02AB5 precnsim; 0x022E8 precsim; 0x0227E prime; 0x02032 Prime; 0x02033 primes; 0x02119 prnap; 0x02AB9 prnE; 0x02AB5 prnsim; 0x022E8 prod; 0x0220F Product; 0x0220F profalar; 0x0232E profline; 0x02312 profsurf; 0x02313 prop; 0x0221D Proportion; 0x02237 Proportional; 0x0221D propto; 0x0221D prsim; 0x0227E prurel; 0x022B0 Pscr; 0x1D4AB pscr; 0x1D4C5 Psi; 0x003A8 psi; 0x003C8 puncsp; 0x02008 Qfr; 0x1D514 qfr; 0x1D52E qint; 0x02A0C Qopf; 0x0211A qopf; 0x1D562 qprime; 0x02057 Qscr; 0x1D4AC qscr; 0x1D4C6 quaternions; 0x0210D quatint; 0x02A16 quest; 0x0003F questeq; 0x0225F quot; 0x00022 quot 0x00022 QUOT; 0x00022 QUOT 0x00022 rAarr; 0x021DB race; 0x029DA Racute; 0x00154 racute; 0x00155 radic; 0x0221A raemptyv; 0x029B3 rang; 0x027E9 Rang; 0x027EB rangd; 0x02992 range; 0x029A5 rangle; 0x027E9 raquo; 0x000BB raquo 0x000BB rarr; 0x02192 Rarr; 0x021A0 rArr; 0x021D2 rarrap; 0x02975 rarrb; 0x021E5 rarrbfs; 0x02920 rarrc; 0x02933 rarrfs; 0x0291E rarrhk; 0x021AA rarrlp; 0x021AC rarrpl; 0x02945 rarrsim; 0x02974 rarrtl; 0x021A3 Rarrtl; 0x02916 rarrw; 0x0219D ratail; 0x0291A rAtail; 0x0291C ratio; 0x02236 rationals; 0x0211A rbarr; 0x0290D rBarr; 0x0290F RBarr; 0x02910 rbbrk; 0x02773 rbrace; 0x0007D rbrack; 0x0005D rbrke; 0x0298C rbrksld; 0x0298E rbrkslu; 0x02990 Rcaron; 0x00158 rcaron; 0x00159 Rcedil; 0x00156 rcedil; 0x00157 rceil; 0x02309 rcub; 0x0007D Rcy; 0x00420 rcy; 0x00440 rdca; 0x02937 rdldhar; 0x02969 rdquo; 0x0201D rdquor; 0x0201D rdsh; 0x021B3 Re; 0x0211C real; 0x0211C realine; 0x0211B realpart; 0x0211C reals; 0x0211D rect; 0x025AD reg; 0x000AE reg 0x000AE REG; 0x000AE REG 0x000AE ReverseElement; 0x0220B ReverseEquilibrium; 0x021CB ReverseUpEquilibrium; 0x0296F rfisht; 0x0297D rfloor; 0x0230B Rfr; 0x0211C rfr; 0x1D52F rHar; 0x02964 rhard; 0x021C1 rharu; 0x021C0 rharul; 0x0296C Rho; 0x003A1 rho; 0x003C1 rhov; 0x003F1 RightAngleBracket; 0x027E9 rightarrow; 0x02192 RightArrow; 0x02192 Rightarrow; 0x021D2 RightArrowBar; 0x021E5 RightArrowLeftArrow; 0x021C4 rightarrowtail; 0x021A3 RightCeiling; 0x02309 RightDoubleBracket; 0x027E7 RightDownTeeVector; 0x0295D RightDownVector; 0x021C2 RightDownVectorBar; 0x02955 RightFloor; 0x0230B rightharpoondown; 0x021C1 rightharpoonup; 0x021C0 rightleftarrows; 0x021C4 rightleftharpoons; 0x021CC rightrightarrows; 0x021C9 rightsquigarrow; 0x0219D RightTee; 0x022A2 RightTeeArrow; 0x021A6 RightTeeVector; 0x0295B rightthreetimes; 0x022CC RightTriangle; 0x022B3 RightTriangleBar; 0x029D0 RightTriangleEqual; 0x022B5 RightUpDownVector; 0x0294F RightUpTeeVector; 0x0295C RightUpVector; 0x021BE RightUpVectorBar; 0x02954 RightVector; 0x021C0 RightVectorBar; 0x02953 ring; 0x002DA risingdotseq; 0x02253 rlarr; 0x021C4 rlhar; 0x021CC rlm; 0x0200F rmoust; 0x023B1 rmoustache; 0x023B1 rnmid; 0x02AEE roang; 0x027ED roarr; 0x021FE robrk; 0x027E7 ropar; 0x02986 Ropf; 0x0211D ropf; 0x1D563 roplus; 0x02A2E rotimes; 0x02A35 RoundImplies; 0x02970 rpar; 0x00029 rpargt; 0x02994 rppolint; 0x02A12 rrarr; 0x021C9 Rrightarrow; 0x021DB rsaquo; 0x0203A Rscr; 0x0211B rscr; 0x1D4C7 rsh; 0x021B1 Rsh; 0x021B1 rsqb; 0x0005D rsquo; 0x02019 rsquor; 0x02019 rthree; 0x022CC rtimes; 0x022CA rtri; 0x025B9 rtrie; 0x022B5 rtrif; 0x025B8 rtriltri; 0x029CE RuleDelayed; 0x029F4 ruluhar; 0x02968 rx; 0x0211E Sacute; 0x0015A sacute; 0x0015B sbquo; 0x0201A sc; 0x0227B Sc; 0x02ABC scap; 0x02AB8 Scaron; 0x00160 scaron; 0x00161 sccue; 0x0227D sce; 0x02AB0 scE; 0x02AB4 Scedil; 0x0015E scedil; 0x0015F Scirc; 0x0015C scirc; 0x0015D scnap; 0x02ABA scnE; 0x02AB6 scnsim; 0x022E9 scpolint; 0x02A13 scsim; 0x0227F Scy; 0x00421 scy; 0x00441 sdot; 0x022C5 sdotb; 0x022A1 sdote; 0x02A66 searhk; 0x02925 searr; 0x02198 seArr; 0x021D8 searrow; 0x02198 sect; 0x000A7 sect 0x000A7 semi; 0x0003B seswar; 0x02929 setminus; 0x02216 setmn; 0x02216 sext; 0x02736 Sfr; 0x1D516 sfr; 0x1D530 sfrown; 0x02322 sharp; 0x0266F SHCHcy; 0x00429 shchcy; 0x00449 SHcy; 0x00428 shcy; 0x00448 ShortDownArrow; 0x02193 ShortLeftArrow; 0x02190 shortmid; 0x02223 shortparallel; 0x02225 ShortRightArrow; 0x02192 ShortUpArrow; 0x02191 shy; 0x000AD shy 0x000AD Sigma; 0x003A3 sigma; 0x003C3 sigmaf; 0x003C2 sigmav; 0x003C2 sim; 0x0223C simdot; 0x02A6A sime; 0x02243 simeq; 0x02243 simg; 0x02A9E simgE; 0x02AA0 siml; 0x02A9D simlE; 0x02A9F simne; 0x02246 simplus; 0x02A24 simrarr; 0x02972 slarr; 0x02190 SmallCircle; 0x02218 smallsetminus; 0x02216 smashp; 0x02A33 smeparsl; 0x029E4 smid; 0x02223 smile; 0x02323 smt; 0x02AAA smte; 0x02AAC SOFTcy; 0x0042C softcy; 0x0044C sol; 0x0002F solb; 0x029C4 solbar; 0x0233F Sopf; 0x1D54A sopf; 0x1D564 spades; 0x02660 spadesuit; 0x02660 spar; 0x02225 sqcap; 0x02293 sqcup; 0x02294 Sqrt; 0x0221A sqsub; 0x0228F sqsube; 0x02291 sqsubset; 0x0228F sqsubseteq; 0x02291 sqsup; 0x02290 sqsupe; 0x02292 sqsupset; 0x02290 sqsupseteq; 0x02292 squ; 0x025A1 square; 0x025A1 Square; 0x025A1 SquareIntersection; 0x02293 SquareSubset; 0x0228F SquareSubsetEqual; 0x02291 SquareSuperset; 0x02290 SquareSupersetEqual; 0x02292 SquareUnion; 0x02294 squarf; 0x025AA squf; 0x025AA srarr; 0x02192 Sscr; 0x1D4AE sscr; 0x1D4C8 ssetmn; 0x02216 ssmile; 0x02323 sstarf; 0x022C6 Star; 0x022C6 star; 0x02606 starf; 0x02605 straightepsilon; 0x003F5 straightphi; 0x003D5 strns; 0x000AF sub; 0x02282 Sub; 0x022D0 subdot; 0x02ABD sube; 0x02286 subE; 0x02AC5 subedot; 0x02AC3 submult; 0x02AC1 subne; 0x0228A subnE; 0x02ACB subplus; 0x02ABF subrarr; 0x02979 subset; 0x02282 Subset; 0x022D0 subseteq; 0x02286 subseteqq; 0x02AC5 SubsetEqual; 0x02286 subsetneq; 0x0228A subsetneqq; 0x02ACB subsim; 0x02AC7 subsub; 0x02AD5 subsup; 0x02AD3 succ; 0x0227B succapprox; 0x02AB8 succcurlyeq; 0x0227D Succeeds; 0x0227B SucceedsEqual; 0x02AB0 SucceedsSlantEqual; 0x0227D SucceedsTilde; 0x0227F succeq; 0x02AB0 succnapprox; 0x02ABA succneqq; 0x02AB6 succnsim; 0x022E9 succsim; 0x0227F SuchThat; 0x0220B sum; 0x02211 Sum; 0x02211 sung; 0x0266A sup; 0x02283 Sup; 0x022D1 sup1; 0x000B9 sup1 0x000B9 sup2; 0x000B2 sup2 0x000B2 sup3; 0x000B3 sup3 0x000B3 supdot; 0x02ABE supdsub; 0x02AD8 supe; 0x02287 supE; 0x02AC6 supedot; 0x02AC4 Superset; 0x02283 SupersetEqual; 0x02287 suphsub; 0x02AD7 suplarr; 0x0297B supmult; 0x02AC2 supne; 0x0228B supnE; 0x02ACC supplus; 0x02AC0 supset; 0x02283 Supset; 0x022D1 supseteq; 0x02287 supseteqq; 0x02AC6 supsetneq; 0x0228B supsetneqq; 0x02ACC supsim; 0x02AC8 supsub; 0x02AD4 supsup; 0x02AD6 swarhk; 0x02926 swarr; 0x02199 swArr; 0x021D9 swarrow; 0x02199 swnwar; 0x0292A szlig; 0x000DF szlig 0x000DF Tab; 0x00009 target; 0x02316 Tau; 0x003A4 tau; 0x003C4 tbrk; 0x023B4 Tcaron; 0x00164 tcaron; 0x00165 Tcedil; 0x00162 tcedil; 0x00163 Tcy; 0x00422 tcy; 0x00442 tdot; 0x020DB telrec; 0x02315 Tfr; 0x1D517 tfr; 0x1D531 there4; 0x02234 therefore; 0x02234 Therefore; 0x02234 Theta; 0x00398 theta; 0x003B8 thetasym; 0x003D1 thetav; 0x003D1 thickapprox; 0x02248 thicksim; 0x0223C thinsp; 0x02009 ThinSpace; 0x02009 thkap; 0x02248 thksim; 0x0223C THORN; 0x000DE THORN 0x000DE thorn; 0x000FE thorn 0x000FE tilde; 0x002DC Tilde; 0x0223C TildeEqual; 0x02243 TildeFullEqual; 0x02245 TildeTilde; 0x02248 times; 0x000D7 times 0x000D7 timesb; 0x022A0 timesbar; 0x02A31 timesd; 0x02A30 tint; 0x0222D toea; 0x02928 top; 0x022A4 topbot; 0x02336 topcir; 0x02AF1 Topf; 0x1D54B topf; 0x1D565 topfork; 0x02ADA tosa; 0x02929 tprime; 0x02034 trade; 0x02122 TRADE; 0x02122 triangle; 0x025B5 triangledown; 0x025BF triangleleft; 0x025C3 trianglelefteq; 0x022B4 triangleq; 0x0225C triangleright; 0x025B9 trianglerighteq; 0x022B5 tridot; 0x025EC trie; 0x0225C triminus; 0x02A3A TripleDot; 0x020DB triplus; 0x02A39 trisb; 0x029CD tritime; 0x02A3B trpezium; 0x023E2 Tscr; 0x1D4AF tscr; 0x1D4C9 TScy; 0x00426 tscy; 0x00446 TSHcy; 0x0040B tshcy; 0x0045B Tstrok; 0x00166 tstrok; 0x00167 twixt; 0x0226C twoheadleftarrow; 0x0219E twoheadrightarrow; 0x021A0 Uacute; 0x000DA Uacute 0x000DA uacute; 0x000FA uacute 0x000FA uarr; 0x02191 Uarr; 0x0219F uArr; 0x021D1 Uarrocir; 0x02949 Ubrcy; 0x0040E ubrcy; 0x0045E Ubreve; 0x0016C ubreve; 0x0016D Ucirc; 0x000DB Ucirc 0x000DB ucirc; 0x000FB ucirc 0x000FB Ucy; 0x00423 ucy; 0x00443 udarr; 0x021C5 Udblac; 0x00170 udblac; 0x00171 udhar; 0x0296E ufisht; 0x0297E Ufr; 0x1D518 ufr; 0x1D532 Ugrave; 0x000D9 Ugrave 0x000D9 ugrave; 0x000F9 ugrave 0x000F9 uHar; 0x02963 uharl; 0x021BF uharr; 0x021BE uhblk; 0x02580 ulcorn; 0x0231C ulcorner; 0x0231C ulcrop; 0x0230F ultri; 0x025F8 Umacr; 0x0016A umacr; 0x0016B uml; 0x000A8 uml 0x000A8 UnderBar; 0x00332 UnderBrace; 0x023DF UnderBracket; 0x023B5 UnderParenthesis; 0x023DD Union; 0x022C3 UnionPlus; 0x0228E Uogon; 0x00172 uogon; 0x00173 Uopf; 0x1D54C uopf; 0x1D566 uparrow; 0x02191 UpArrow; 0x02191 Uparrow; 0x021D1 UpArrowBar; 0x02912 UpArrowDownArrow; 0x021C5 updownarrow; 0x02195 UpDownArrow; 0x02195 Updownarrow; 0x021D5 UpEquilibrium; 0x0296E upharpoonleft; 0x021BF upharpoonright; 0x021BE uplus; 0x0228E UpperLeftArrow; 0x02196 UpperRightArrow; 0x02197 upsi; 0x003C5 Upsi; 0x003D2 upsih; 0x003D2 Upsilon; 0x003A5 upsilon; 0x003C5 UpTee; 0x022A5 UpTeeArrow; 0x021A5 upuparrows; 0x021C8 urcorn; 0x0231D urcorner; 0x0231D urcrop; 0x0230E Uring; 0x0016E uring; 0x0016F urtri; 0x025F9 Uscr; 0x1D4B0 uscr; 0x1D4CA utdot; 0x022F0 Utilde; 0x00168 utilde; 0x00169 utri; 0x025B5 utrif; 0x025B4 uuarr; 0x021C8 Uuml; 0x000DC Uuml 0x000DC uuml; 0x000FC uuml 0x000FC uwangle; 0x029A7 vangrt; 0x0299C varepsilon; 0x003B5 varkappa; 0x003F0 varnothing; 0x02205 varphi; 0x003C6 varpi; 0x003D6 varpropto; 0x0221D varr; 0x02195 vArr; 0x021D5 varrho; 0x003F1 varsigma; 0x003C2 vartheta; 0x003D1 vartriangleleft; 0x022B2 vartriangleright; 0x022B3 vBar; 0x02AE8 Vbar; 0x02AEB vBarv; 0x02AE9 Vcy; 0x00412 vcy; 0x00432 vdash; 0x022A2 vDash; 0x022A8 Vdash; 0x022A9 VDash; 0x022AB Vdashl; 0x02AE6 vee; 0x02228 Vee; 0x022C1 veebar; 0x022BB veeeq; 0x0225A vellip; 0x022EE verbar; 0x0007C Verbar; 0x02016 vert; 0x0007C Vert; 0x02016 VerticalBar; 0x02223 VerticalLine; 0x0007C VerticalSeparator; 0x02758 VerticalTilde; 0x02240 VeryThinSpace; 0x0200A Vfr; 0x1D519 vfr; 0x1D533 vltri; 0x022B2 Vopf; 0x1D54D vopf; 0x1D567 vprop; 0x0221D vrtri; 0x022B3 Vscr; 0x1D4B1 vscr; 0x1D4CB Vvdash; 0x022AA vzigzag; 0x0299A Wcirc; 0x00174 wcirc; 0x00175 wedbar; 0x02A5F wedge; 0x02227 Wedge; 0x022C0 wedgeq; 0x02259 weierp; 0x02118 Wfr; 0x1D51A wfr; 0x1D534 Wopf; 0x1D54E wopf; 0x1D568 wp; 0x02118 wr; 0x02240 wreath; 0x02240 Wscr; 0x1D4B2 wscr; 0x1D4CC xcap; 0x022C2 xcirc; 0x025EF xcup; 0x022C3 xdtri; 0x025BD Xfr; 0x1D51B xfr; 0x1D535 xharr; 0x027F7 xhArr; 0x027FA Xi; 0x0039E xi; 0x003BE xlarr; 0x027F5 xlArr; 0x027F8 xmap; 0x027FC xnis; 0x022FB xodot; 0x02A00 Xopf; 0x1D54F xopf; 0x1D569 xoplus; 0x02A01 xotime; 0x02A02 xrarr; 0x027F6 xrArr; 0x027F9 Xscr; 0x1D4B3 xscr; 0x1D4CD xsqcup; 0x02A06 xuplus; 0x02A04 xutri; 0x025B3 xvee; 0x022C1 xwedge; 0x022C0 Yacute; 0x000DD Yacute 0x000DD yacute; 0x000FD yacute 0x000FD YAcy; 0x0042F yacy; 0x0044F Ycirc; 0x00176 ycirc; 0x00177 Ycy; 0x0042B ycy; 0x0044B yen; 0x000A5 yen 0x000A5 Yfr; 0x1D51C yfr; 0x1D536 YIcy; 0x00407 yicy; 0x00457 Yopf; 0x1D550 yopf; 0x1D56A Yscr; 0x1D4B4 yscr; 0x1D4CE YUcy; 0x0042E yucy; 0x0044E yuml; 0x000FF yuml 0x000FF Yuml; 0x00178 Zacute; 0x00179 zacute; 0x0017A Zcaron; 0x0017D zcaron; 0x0017E Zcy; 0x00417 zcy; 0x00437 Zdot; 0x0017B zdot; 0x0017C zeetrf; 0x02128 ZeroWidthSpace; 0x0200B Zeta; 0x00396 zeta; 0x003B6 Zfr; 0x02128 zfr; 0x1D537 ZHcy; 0x00416 zhcy; 0x00436 zigrarr; 0x021DD Zopf; 0x02124 zopf; 0x1D56B Zscr; 0x1D4B5 zscr; 0x1D4CF zwj; 0x0200D zwnj; 0x0200C netsurf-2.9/hubbub-0.1.2/Makefile.config0000664000175000017500000000015511200410021016633 0ustar vincevince# Configuration Makefile fragment # Cater for local configuration changes -include Makefile.config.override netsurf-2.9/librosprite-0.0.2/0000775000175000017500000000000011734430307015041 5ustar vincevincenetsurf-2.9/librosprite-0.0.2/palette2c.c0000664000175000017500000000176610774251070017103 0ustar vincevince/* * This file is part of librosprite. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 James Shaw */ #include #include #include "librosprite.h" int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: palette2c palettefile\n"); exit(EXIT_FAILURE); } char* filename = argv[1]; FILE* f = fopen(filename, "rb"); if (f == NULL) { printf("Can't load palettefile %s\n", filename); exit(EXIT_FAILURE); } struct rosprite_file_context* ctx; if (rosprite_create_file_context(f, &ctx) != ROSPRITE_OK) { exit(EXIT_FAILURE); } struct rosprite_palette* palette; if (rosprite_load_palette(rosprite_file_reader, ctx, &palette) != ROSPRITE_OK) { exit(EXIT_FAILURE); } for (uint32_t i = 0; i < palette->size; i++) { printf("0x%x, ", palette->palette[i]); } fclose(f); rosprite_destroy_file_context(ctx); rosprite_destroy_palette(palette); return EXIT_SUCCESS; } netsurf-2.9/librosprite-0.0.2/test-data/0000775000175000017500000000000011734430307016727 5ustar vincevincenetsurf-2.9/librosprite-0.0.2/test-data/small0000664000175000017500000000034010724021626017755 0ustar vincevince\3x3_32bpp,P0D2x2_32bpp,<041x1_32bpp,00netsurf-2.9/librosprite-0.0.2/test-data/32bpp-alpha-test0000664000175000017500000007322410724021626021646 0ustar vincevincevvtest42dJ,,0netsurf-2.9/librosprite-0.0.2/test-data/primary-color-16bpp0000664000175000017500000053766010724021626022416 0ustar vincevinceredc,,(bluec,,(||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||greenc,,(netsurf-2.9/librosprite-0.0.2/example.c0000664000175000017500000001151411040407261016633 0ustar vincevince/* * This file is part of librosprite. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 James Shaw */ /** * \file * A test harness using SDL to display all sprites in a sprite file. * * Usage: example \ */ #include #include #include #include "librosprite.h" void sdl_draw_pixel(SDL_Surface* surface, uint32_t x, uint32_t y, uint32_t color); void sdl_blank(SDL_Surface* surface); int load_file_to_memory(const char *filename, uint8_t **result); int create_file_context(char* filename, void** result); int create_mem_context(char* filename, void** result); int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: example spritefile\n"); exit(EXIT_FAILURE); } if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); exit(EXIT_FAILURE); } atexit(SDL_Quit); char* filename = argv[1]; void* ctx; if (create_file_context(filename, &ctx) < 0) { fprintf(stderr, "Unable to create file reader context\n"); exit(EXIT_FAILURE); } printf("Loading %s\n", filename); struct rosprite_area* sprite_area; if (rosprite_load(rosprite_file_reader, ctx, &sprite_area) != ROSPRITE_OK) { fprintf(stderr, "Error loading spritefile\n"); exit(EXIT_FAILURE); }; printf("sprite_count %u\n", sprite_area->sprite_count); printf("extension_size %u\n", sprite_area->extension_size); SDL_Surface *screen; screen = SDL_SetVideoMode(800, 600, 32, SDL_ANYFORMAT); SDL_SetAlpha(screen, SDL_SRCALPHA, 0); for (unsigned int i = 0; i < sprite_area->sprite_count; i++) { struct rosprite* sprite = sprite_area->sprites[i]; printf("\nname %s\n", sprite->name); printf("color_model %s\n", sprite->mode.color_model == ROSPRITE_RGB ? "RGB" : "CMYK"); printf("colorbpp %u\n", sprite->mode.colorbpp); printf("xdpi %u\n", sprite->mode.xdpi); printf("ydpi %u\n", sprite->mode.ydpi); printf("width %u px\n", sprite->width); printf("height %u px\n", sprite->height); printf("hasPalette %s\n", sprite->has_palette ? "YES" : "NO"); if (sprite->has_palette) printf("paletteSize %u\n", sprite->palettesize); printf("hasMask %s\n", sprite->has_mask ? "YES" : "NO"); if (sprite->has_mask) printf("mask_width %u\n", sprite->mode.mask_width); if (sprite->has_mask) printf("maskbpp %u\n", sprite->mode.maskbpp); sdl_blank(screen); for (uint32_t y = 0; y < sprite->height; y++) { for (uint32_t x = 0; x < sprite->width; x++) { sdl_draw_pixel(screen, x, y, sprite->image[y*sprite->width + x]); } } SDL_UpdateRect(screen, 0, 0, 0, 0); fgetc(stdin); } rosprite_destroy_mem_context(ctx); rosprite_destroy_sprite_area(sprite_area); return EXIT_SUCCESS; } int create_file_context(char* filename, void** result) { FILE *f = fopen(filename, "rb"); if (!f) { *result = NULL; return -1; } struct rosprite_file_context* ctx; if (rosprite_create_file_context(f, &ctx) != ROSPRITE_OK) { return -1; } *result = ctx; return 0; } int create_mem_context(char* filename, void** result) { uint8_t* content; int size = load_file_to_memory(filename, &content); if (size < 0) return -1; struct rosprite_mem_context* ctx; if (rosprite_create_mem_context(content, size, &ctx) != ROSPRITE_OK) { return -1; } *result = ctx; return 0; } int load_file_to_memory(const char *filename, uint8_t **result) { int size = 0; FILE *f = fopen(filename, "rb"); if (f == NULL) { *result = NULL; return -1; // -1 means file opening fail } fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); *result = (uint8_t *)malloc(size+1); if ((unsigned int) size != fread(*result, sizeof(char), size, f)) { free(*result); return -2; // -2 means file reading fail } fclose(f); (*result)[size] = 0; return size; } /* color is 0xrrggbbaa */ void sdl_draw_pixel(SDL_Surface* surface, uint32_t x, uint32_t y, uint32_t color) { uint32_t* pixel = ((uint32_t*) (surface->pixels)) + (y * surface->pitch/4) + x; /* pretty sure SDL can do this, but can't figure out how */ uint32_t bg_color = ((int) (x / 4.0) + ((int)(y / 4.0) % 2)) % 2 ? 0x99 : 0x66; uint32_t alpha = color & 0x000000ff; uint32_t r = (color & 0xff000000) >> 24; uint32_t g = (color & 0x00ff0000) >> 16; uint32_t b = (color & 0x0000ff00) >> 8; r = ((alpha / 255.0) * r) + (((255-alpha) / 255.0) * bg_color); g = ((alpha / 255.0) * g) + (((255-alpha) / 255.0) * bg_color); b = ((alpha / 255.0) * b) + (((255-alpha) / 255.0) * bg_color); uint32_t mapped_color = SDL_MapRGB(surface->format, r, g, b); *pixel = mapped_color; } void sdl_blank(SDL_Surface* surface) { for (uint32_t y = 0; y < (uint32_t) surface->h; y++) { for (uint32_t x = 0; x < (uint32_t) surface->w; x++) { sdl_draw_pixel(surface, x, y, (uint32_t) ((int) (x / 4.0) + ((int)(y / 4.0) % 2)) % 2 ? 0x999999ff : 0x666666ff); } } } netsurf-2.9/librosprite-0.0.2/Doxyfile0000664000175000017500000014517510774253516016574 0ustar vincevince# Doxyfile 1.5.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = librosprite # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, # Italian, Japanese, Japanese-en (Japanese with English messages), Korean, # Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, # Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = doc # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a caller dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected # functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that a graph may be further truncated if the graph's # image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH # and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), # the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO netsurf-2.9/librosprite-0.0.2/Makefile0000664000175000017500000000352510777213504016512 0ustar vincevinceAR = ar CC = gcc LD = gcc DOXYGEN = doxygen INSTALL = install SED = sed MKDIR = mkdir PKG_CONFIG = pkg-config ARFLAGS = -cru CFLAGS = -g -Wall -Wextra -Wundef -Wpointer-arith -Wcast-align \ -Wwrite-strings -Wstrict-prototypes \ -Wnested-externs -Werror -pedantic -std=c99 \ -Wno-format-zero-length -Wformat-security -Wstrict-aliasing=2 \ -Wmissing-format-attribute -Wunused -Wunreachable-code \ -Wformat=2 -Werror-implicit-function-declaration \ -Wmissing-declarations -Wmissing-prototypes LDFLAGS = -g -L./ # Installation prefix, if not already defined (e.g. on command line) PREFIX ?= /usr/local DESTDIR ?= .PHONY: all clean docs install uninstall all: librosprite.a example: librosprite.a example.o ${LD} -o $@ example.o ${LDFLAGS} \ $(shell PKG_CONFIG_PATH=.:$(PKG_CONFIG_PATH) $(PKG_CONFIG) --cflags --libs sdl librosprite) palette2c: librosprite.a palette2c.o ${LD} -o $@ palette2c.o ${LDFLAGS} \ $(shell PKG_CONFIG_PATH=.:$(PKG_CONFIG_PATH) $(PKG_CONFIG) --cflags --libs librosprite) librosprite.a: librosprite.o librosprite.pc ${AR} ${ARFLAGS} librosprite.a librosprite.o librosprite.pc: librosprite.pc.in $(SED) -e 's#PREFIX#$(PREFIX)#' librosprite.pc.in > librosprite.pc %.o: %.c ${CC} -c ${CFLAGS} -o $@ $< docs: ${DOXYGEN} clean: rm -f $(wildcard *.o) $(wildcard *.a) example palette2c librosprite.pc rm -rf doc install: librosprite.a librosprite.pc $(MKDIR) -p $(DESTDIR)$(PREFIX)/lib/pkgconfig $(MKDIR) -p $(DESTDIR)$(PREFIX)/lib $(MKDIR) -p $(DESTDIR)$(PREFIX)/include $(INSTALL) --mode=644 -t $(DESTDIR)$(PREFIX)/lib librosprite.a $(INSTALL) --mode=644 -t $(DESTDIR)$(PREFIX)/include librosprite.h $(INSTALL) --mode=644 -t $(DESTDIR)$(PREFIX)/lib/pkgconfig librosprite.pc uninstall: rm $(DESTDIR)$(PREFIX)/lib/librosprite.a rm $(DESTDIR)$(PREFIX)/include/librosprite.h rm $(DESTDIR)$(PREFIX)/lib/pkgconfig/librosprite.pc netsurf-2.9/librosprite-0.0.2/librosprite.h0000664000175000017500000001304410774251070017553 0ustar vincevince/* * This file is part of librosprite. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 James Shaw */ /** * \mainpage * * librosprite is a library for reading RISC OS sprite and palette files. The following subformats are supported: *
    *
  • 1-bit and 8-bit transparency masks
  • *
  • Sprites with custom palettes
  • *
  • Standard RISC OS 1-bit, 2-bit palettes, and 4-bit and 8-bit colour palettes
  • *
  • Old-style sprites with most screen modes from 0-49 supported
  • *
  • 32bpp CMYK
  • *
  • Inline alpha channel, as used by Photodesk and Tinct
  • *
* */ /** * \file librosprite.h * * Sprite file reading is performed by rosprite_load(), and palette file reading by rosprite_load_palette(). * * Retrieving sprite or palette data is performed by a reader. * librosprite implements file and memory readers. * To use a reader, create a context by calling the * rosprite_create_file_context() or rosprite_create_mem_context(). * Pass the reader function, and the context you have created, to the load function, * typically rosprite_load(). */ #ifndef ROSPRITE_H #define ROSPRITE_H #include #include #include typedef enum { ROSPRITE_OK, ROSPRITE_NOMEM, ROSPRITE_EOF, ROSPRITE_BADMODE } rosprite_error; typedef enum { ROSPRITE_RGB, ROSPRITE_CMYK } rosprite_color_model; /** * A reader interface used to load sprite files. */ typedef int (*reader)(uint8_t* buf, size_t count, void* ctx); struct rosprite_file_context; /** * A sprite area comprises zero or more rosprites. Optionally, it may also have an extension_words block. */ struct rosprite_area { uint32_t extension_size; /* size of extension_words in bytes */ uint8_t* extension_words; uint32_t sprite_count; struct rosprite** sprites; /* array of length sprite_count */ }; /** * A sprite mode defines the colour depth, colour model and bitmap resolution of a sprite. */ struct rosprite_mode { /** * The bits per colour channel. Legal values are 1, 2, 4, 8, 16, 24 and 32. */ uint32_t colorbpp; /* maskbpp denotes the amount of alpha bpp used * while mask_width is the bits used to store the mask. * Old modes have the same mask_width as their colorbpp, but the value * is always all-zeroes or all-ones. * New modes can have 1bpp or 8bpp masks */ uint32_t maskbpp; uint32_t mask_width; /* in pixels */ /** * Horizontal dots per inch. Typical values are 22, 45, 90 and 180. */ uint32_t xdpi; /** * Vertical dots per inch. Typical values are 22, 45, 90 and 180. */ uint32_t ydpi; rosprite_color_model color_model; }; struct rosprite_palette { uint32_t size; /* in number of entries (each entry is a word) */ uint32_t* palette; }; /** * A sprite is a bitmap image which has a mode, width and height. */ struct rosprite { /** * The sprite name. This may be up to 12 characters long, and must be zero terminated. */ unsigned char name[13]; struct rosprite_mode mode; bool has_mask; bool has_palette; uint32_t palettesize; /* in number of entries (each entry is a word) */ uint32_t* palette; /** * Width in pixels */ uint32_t width; /** * Height in pixels */ uint32_t height; /** * Image data is a series of words, appearing on screen left-to-right, top-to-bottom. * Each word takes the form 0xRRGGBBAA. A is the alpha channel, where 0 is transparent, and 255 is opaque. */ uint32_t* image; /* image data in 0xRRGGBBAA words */ }; struct rosprite_file_context; /** * Create a file reader context using the specified file handle. * Clients must call rosprite_destroy_file_context() to dispose of the context. * * \param[out] result */ rosprite_error rosprite_create_file_context(FILE* f, struct rosprite_file_context** result); void rosprite_destroy_file_context(struct rosprite_file_context* ctx); int rosprite_file_reader(uint8_t* buf, size_t count, void* ctx); struct rosprite_mem_context; /** * Create a memory reader context using the specified memory pointer. * Clients must call rosprite_destroy_mem_context() to dispose of the context. * * \param[in] p pointer to the start of the memory block * \param[in] total_size the size of the block pointed to by p, in bytes * \param[out] result */ rosprite_error rosprite_create_mem_context(uint8_t* p, unsigned long total_size, struct rosprite_mem_context** result); void rosprite_destroy_mem_context(struct rosprite_mem_context* ctx); int rosprite_mem_reader(uint8_t* buf, size_t count, void* ctx); /** * Load a rosprite_area using the reader provided. * Clients must call rosprite_destroy_sprite_area() to dispose of the rosprite_area. * * \param[out] result The pointer to be populated by this function. */ rosprite_error rosprite_load(reader reader, void* ctx, struct rosprite_area** result); /** * Dispose of a rosprite_area and its children. */ void rosprite_destroy_sprite_area(struct rosprite_area *); /** * Load a RISC OS palette file. A palette file has RISC OS filetype 0xFED, * and is a series of VDU 19 Set Palette commands, each command being 6 bytes long. * * Clients must call rosprite_destroy_palette() to dispose of the rosprite_palette. * * \param[out] result The pointer to be populated by this function. * \see http://www.drobe.co.uk/show_manual.php?manual=/sh-cgi?manual=Vdu%26page=19 */ rosprite_error rosprite_load_palette(reader reader, void* ctx, struct rosprite_palette** result); /** * Dispose of a rosprite_palette and its children. */ void rosprite_destroy_palette(struct rosprite_palette *); #endif netsurf-2.9/librosprite-0.0.2/COPYING0000664000175000017500000000206010774251070016073 0ustar vincevinceCopyright (c) 2008 James Shaw Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.netsurf-2.9/librosprite-0.0.2/librosprite.pc.in0000664000175000017500000000033210773437606020341 0ustar vincevinceprefix=PREFIX exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: librosprite Description: Loads RISC OS sprite files Version: 0.0.1 Libs: -L${libdir} -lrosprite Cflags: -I${includedir} netsurf-2.9/librosprite-0.0.2/librosprite.c0000664000175000017500000007325211646404525017561 0ustar vincevince/* * This file is part of librosprite. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 James Shaw */ /** * \file */ #include #include #include #include #include #include #include "librosprite.h" /** * Reads four bytes, 00, 11, 22 and 33, of a byte array b to give 0x33221100. */ #define BTUINT(b) (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) /** * Reverse the byte order of a word such that 0xAABBCCDD becomes 0xDDCCBBAA. */ #define BSWAP(word) (((word & (0x000000ff)) << 24) | ((word & 0x0000ff00) << 8) | ((word & 0x00ff0000) >> 8) | ((word & 0xff000000) >> 24)) #define ERRCHK(x) do { \ rosprite_error err = x; \ if (err != ROSPRITE_OK) return err; \ } while(0) struct rosprite_header { uint32_t width_words; /* width in words */ /* height defined in sprite struct */ uint32_t first_used_bit; /* old format only (spriteType = 0) */ uint32_t last_used_bit; /** * Image size in bytes */ uint32_t image_size; /** * Mask size in bytes */ uint32_t mask_size; }; struct rosprite_mask_state { uint32_t x; uint32_t y; uint32_t first_used_bit; uint32_t row_max_bit; uint32_t height; uint32_t current_byte_index; uint32_t current_word; uint32_t bpp; }; struct rosprite_file_context { FILE* f; }; struct rosprite_mem_context { uint8_t* base; unsigned long offset; bool known_size; unsigned long size; }; static const struct rosprite_mode oldmodes[] = { /*0*/{ .colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*1*/{ .colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 45, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*2*/{ .colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 22, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*3*/{ .colorbpp = 0, .maskbpp = 0, .mask_width = 0, .xdpi = 0, .ydpi = 0, .color_model = ROSPRITE_RGB }, /*4*/{ .colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 45, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*5*/{ .colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 22, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*6*/{ .colorbpp = 0, .maskbpp = 0, .mask_width = 0, .xdpi = 0, .ydpi = 0, .color_model = ROSPRITE_RGB }, /*7*/{ .colorbpp = 0, .maskbpp = 0, .mask_width = 0, .xdpi = 0, .ydpi = 0, .color_model = ROSPRITE_RGB }, /*8*/{ .colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*9*/{ .colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 45, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*10*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 22, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*11*/{.colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*12*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*13*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 45, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*14*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*15*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*16*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*17*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*18*/{.colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*19*/{.colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*20*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*21*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*22*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi =180, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*23*/{.colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*24*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*25*/{.colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*26*/{.colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*27*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*28*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*29*/{.colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*30*/{.colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*31*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*32*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 90, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*33*/{.colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*34*/{.colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*35*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*36*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*37*/{.colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*38*/{.colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*39*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*40*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*41*/{.colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*42*/{.colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*43*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*44*/{.colorbpp = 1, .maskbpp = 1, .mask_width = 1, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*45*/{.colorbpp = 2, .maskbpp = 1, .mask_width = 2, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*46*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 90, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*47*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 45, .ydpi = 45, .color_model = ROSPRITE_RGB }, /*48*/{.colorbpp = 4, .maskbpp = 1, .mask_width = 4, .xdpi = 45, .ydpi = 90, .color_model = ROSPRITE_RGB }, /*49*/{.colorbpp = 8, .maskbpp = 1, .mask_width = 8, .xdpi = 45, .ydpi = 90, .color_model = ROSPRITE_RGB } }; /* table for converting a 5bit channel into an 8bit channel (used for 16bpp to 32bpp conversion) */ static const uint8_t sprite_16bpp_translate[] = { 0x00, 0x08, 0x10, 0x18, 0x20, 0x29, 0x31, 0x39, 0x41, 0x4a, 0x52, 0x5a, 0x62, 0x6a, 0x73, 0x7b, 0x83, 0x8b, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xde, 0xe6, 0xee, 0xf6, 0xff }; /* palettes generated with palette2c.c * which in turn requires rosprite_load_palette(FILE* f) * defined in this file */ static const uint32_t sprite_1bpp_palette[] = { 0xffffffff, 0xff }; static const uint32_t sprite_2bpp_palette[] = { 0xffffffff, 0xbbbbbbff, 0x777777ff, 0xff }; static const uint32_t sprite_4bpp_palette[] = { 0xffffffff, 0xddddddff, 0xbbbbbbff, 0x999999ff, 0x777777ff, 0x555555ff, 0x333333ff, 0xff, 0x4499ff, 0xeeee00ff, 0xcc00ff, 0xdd0000ff, 0xeeeebbff, 0x558800ff, 0xffbb00ff, 0xbbffff }; static const uint32_t sprite_8bpp_palette[] = { 0xff, 0x111111ff, 0x222222ff, 0x333333ff, 0x440000ff, 0x551111ff, 0x662222ff, 0x773333ff, 0x44ff, 0x111155ff, 0x222266ff, 0x333377ff, 0x440044ff, 0x551155ff, 0x662266ff, 0x773377ff, 0x880000ff, 0x991111ff, 0xaa2222ff, 0xbb3333ff, 0xcc0000ff, 0xdd1111ff, 0xee2222ff, 0xff3333ff, 0x880044ff, 0x991155ff, 0xaa2266ff, 0xbb3377ff, 0xcc0044ff, 0xdd1155ff, 0xee2266ff, 0xff3377ff, 0x4400ff, 0x115511ff, 0x226622ff, 0x337733ff, 0x444400ff, 0x555511ff, 0x666622ff, 0x777733ff, 0x4444ff, 0x115555ff, 0x226666ff, 0x337777ff, 0x444444ff, 0x555555ff, 0x666666ff, 0x777777ff, 0x884400ff, 0x995511ff, 0xaa6622ff, 0xbb7733ff, 0xcc4400ff, 0xdd5511ff, 0xee6622ff, 0xff7733ff, 0x884444ff, 0x995555ff, 0xaa6666ff, 0xbb7777ff, 0xcc4444ff, 0xdd5555ff, 0xee6666ff, 0xff7777ff, 0x8800ff, 0x119911ff, 0x22aa22ff, 0x33bb33ff, 0x448800ff, 0x559911ff, 0x66aa22ff, 0x77bb33ff, 0x8844ff, 0x119955ff, 0x22aa66ff, 0x33bb77ff, 0x448844ff, 0x559955ff, 0x66aa66ff, 0x77bb77ff, 0x888800ff, 0x999911ff, 0xaaaa22ff, 0xbbbb33ff, 0xcc8800ff, 0xdd9911ff, 0xeeaa22ff, 0xffbb33ff, 0x888844ff, 0x999955ff, 0xaaaa66ff, 0xbbbb77ff, 0xcc8844ff, 0xdd9955ff, 0xeeaa66ff, 0xffbb77ff, 0xcc00ff, 0x11dd11ff, 0x22ee22ff, 0x33ff33ff, 0x44cc00ff, 0x55dd11ff, 0x66ee22ff, 0x77ff33ff, 0xcc44ff, 0x11dd55ff, 0x22ee66ff, 0x33ff77ff, 0x44cc44ff, 0x55dd55ff, 0x66ee66ff, 0x77ff77ff, 0x88cc00ff, 0x99dd11ff, 0xaaee22ff, 0xbbff33ff, 0xcccc00ff, 0xdddd11ff, 0xeeee22ff, 0xffff33ff, 0x88cc44ff, 0x99dd55ff, 0xaaee66ff, 0xbbff77ff, 0xcccc44ff, 0xdddd55ff, 0xeeee66ff, 0xffff77ff, 0x88ff, 0x111199ff, 0x2222aaff, 0x3333bbff, 0x440088ff, 0x551199ff, 0x6622aaff, 0x7733bbff, 0xccff, 0x1111ddff, 0x2222eeff, 0x3333ffff, 0x4400ccff, 0x5511ddff, 0x6622eeff, 0x7733ffff, 0x880088ff, 0x991199ff, 0xaa22aaff, 0xbb33bbff, 0xcc0088ff, 0xdd1199ff, 0xee22aaff, 0xff33bbff, 0x8800ccff, 0x9911ddff, 0xaa22eeff, 0xbb33ffff, 0xcc00ccff, 0xdd11ddff, 0xee22eeff, 0xff33ffff, 0x4488ff, 0x115599ff, 0x2266aaff, 0x3377bbff, 0x444488ff, 0x555599ff, 0x6666aaff, 0x7777bbff, 0x44ccff, 0x1155ddff, 0x2266eeff, 0x3377ffff, 0x4444ccff, 0x5555ddff, 0x6666eeff, 0x7777ffff, 0x884488ff, 0x995599ff, 0xaa66aaff, 0xbb77bbff, 0xcc4488ff, 0xdd5599ff, 0xee66aaff, 0xff77bbff, 0x8844ccff, 0x9955ddff, 0xaa66eeff, 0xbb77ffff, 0xcc44ccff, 0xdd55ddff, 0xee66eeff, 0xff77ffff, 0x8888ff, 0x119999ff, 0x22aaaaff, 0x33bbbbff, 0x448888ff, 0x559999ff, 0x66aaaaff, 0x77bbbbff, 0x88ccff, 0x1199ddff, 0x22aaeeff, 0x33bbffff, 0x4488ccff, 0x5599ddff, 0x66aaeeff, 0x77bbffff, 0x888888ff, 0x999999ff, 0xaaaaaaff, 0xbbbbbbff, 0xcc8888ff, 0xdd9999ff, 0xeeaaaaff, 0xffbbbbff, 0x8888ccff, 0x9999ddff, 0xaaaaeeff, 0xbbbbffff, 0xcc88ccff, 0xdd99ddff, 0xeeaaeeff, 0xffbbffff, 0xcc88ff, 0x11dd99ff, 0x22eeaaff, 0x33ffbbff, 0x44cc88ff, 0x55dd99ff, 0x66eeaaff, 0x77ffbbff, 0xccccff, 0x11ddddff, 0x22eeeeff, 0x33ffffff, 0x44ccccff, 0x55ddddff, 0x66eeeeff, 0x77ffffff, 0x88cc88ff, 0x99dd99ff, 0xaaeeaaff, 0xbbffbbff, 0xcccc88ff, 0xdddd99ff, 0xeeeeaaff, 0xffffbbff, 0x88ccccff, 0x99ddddff, 0xaaeeeeff, 0xbbffffff, 0xccccccff, 0xddddddff, 0xeeeeeeff, 0xffffffff }; static inline rosprite_error rosprite_read_word(reader reader, void* ctx, uint32_t* result); static rosprite_error rosprite_get_mode(uint32_t spriteMode, struct rosprite_mode* result); static uint32_t rosprite_palette_lookup(struct rosprite* sprite, uint32_t pixel); static inline uint32_t rosprite_cmyk_to_rgb(uint32_t cmyk); static uint32_t rosprite_next_mask_pixel(uint8_t* mask, struct rosprite_mask_state* mask_state); static rosprite_error rosprite_load_high_color(uint8_t* image_in, uint8_t* mask, struct rosprite* sprite, struct rosprite_header* header); static rosprite_error rosprite_load_low_color(uint8_t* image_in, uint8_t* mask, struct rosprite* sprite, struct rosprite_header* header); rosprite_error rosprite_load_sprite(reader reader, void* ctx, struct rosprite** result); static rosprite_error rosprite_init_mask_state(struct rosprite* sprite, struct rosprite_header* header, uint8_t* mask, struct rosprite_mask_state** result); static uint32_t rosprite_upscale_color(uint32_t pixel, struct rosprite_mode* mode, bool* has_alpha_pixel_data); static inline void rosprite_fix_alpha(uint32_t* image, unsigned long pixels); rosprite_error rosprite_load(reader reader, void* ctx, struct rosprite_area** result) { uint32_t firstSpriteOffset, firstFreeWordOffset; int bytes_read; uint32_t i; struct rosprite_area* sprite_area = malloc(sizeof(struct rosprite_area)); ERRCHK(rosprite_read_word(reader, ctx, &(sprite_area->sprite_count))); ERRCHK(rosprite_read_word(reader, ctx, &firstSpriteOffset)); ERRCHK(rosprite_read_word(reader, ctx, &firstFreeWordOffset)); /* TODO: use this for some sanity checking? */ sprite_area->extension_size = 16 - firstSpriteOffset; sprite_area->extension_words = NULL; if (sprite_area->extension_size > 0) { sprite_area->extension_words = malloc(sprite_area->extension_size); bytes_read = reader(sprite_area->extension_words, (size_t) (sprite_area->extension_size), ctx); if (bytes_read < (signed long) sprite_area->extension_size) { return ROSPRITE_EOF; } } sprite_area->sprites = malloc(sizeof(struct rosprite*) * sprite_area->sprite_count); /* allocate array of pointers */ for (i = 0; i < sprite_area->sprite_count; i++) { struct rosprite* sprite; ERRCHK(rosprite_load_sprite(reader, ctx, &sprite)); sprite_area->sprites[i] = sprite; } *result = sprite_area; return ROSPRITE_OK; } void rosprite_destroy_sprite_area(struct rosprite_area* sprite_area) { uint32_t i; for (i = 0; i < sprite_area->sprite_count; i++) { struct rosprite* sprite = sprite_area->sprites[i]; if (sprite->has_palette) free(sprite->palette); free(sprite->image); free(sprite); } free(sprite_area->sprites); if (sprite_area->extension_size > 0) free(sprite_area->extension_words); free(sprite_area); } rosprite_error rosprite_load_palette(reader reader, void* ctx, struct rosprite_palette** result) { uint32_t c; uint8_t b[6]; unsigned int bytesRead; /* TODO: currently assume palette has linear entries (2nd byte in is 00, 01, 02 etc) */ struct rosprite_palette* palette = malloc(sizeof(struct rosprite_palette)); palette->palette = malloc(sizeof(uint32_t) * 256); /* allocate 256 whether we need them all or not */ c = 0; bytesRead = reader(b, 6, ctx); assert(bytesRead % 6 == 0); while (bytesRead == 6) { assert(b[0] == 19); /* VDU 19 */ /* only process logical colours */ if (b[2] == 16) { /*assert(c == b[1]);*/ uint32_t entry = (b[3] << 24) | (b[4] << 16) | (b[5] << 8) | 0xff; /* last byte is alpha */ palette->palette[c] = entry; c++; assert(c <= 256); } bytesRead = reader(b, 6, ctx); assert(bytesRead % 6 == 0); } palette->size = c; *result = palette; return ROSPRITE_OK; } void rosprite_destroy_palette(struct rosprite_palette* palette) { free(palette->palette); free(palette); } rosprite_error rosprite_create_file_context(FILE* f, struct rosprite_file_context** result) { struct rosprite_file_context* ctx = malloc(sizeof(struct rosprite_file_context)); if (!ctx) return ROSPRITE_NOMEM; ctx->f = f; *result = ctx; return ROSPRITE_OK; } void rosprite_destroy_file_context(struct rosprite_file_context* ctx) { free(ctx); } int rosprite_file_reader(uint8_t* buf, size_t count, void* ctx) { return fread(buf, 1 /*size*/, count, ((struct rosprite_file_context*) ctx)->f); } rosprite_error rosprite_create_mem_context(uint8_t* p, unsigned long total_size, struct rosprite_mem_context** result) { struct rosprite_mem_context* ctx = malloc(sizeof(struct rosprite_mem_context)); if (!ctx) return ROSPRITE_NOMEM; ctx->base = p; ctx->offset = 0; ctx->size = total_size; *result = ctx; return ROSPRITE_OK; } void rosprite_destroy_mem_context(struct rosprite_mem_context* ctx) { free(ctx); } int rosprite_mem_reader(uint8_t* buf, size_t count, void* ctx) { size_t copy_size; struct rosprite_mem_context* memctx = (struct rosprite_mem_context*) ctx; if (memctx->offset + count > memctx->size) { return -1; } // if we're asked for more memory than the block contains, only copy as much as we can if ((memctx->offset + count) > memctx->size) { copy_size = memctx->size - memctx->offset; } else { copy_size = count; } memcpy(buf, memctx->base + memctx->offset, count); memctx->offset += count; return copy_size; } /** * Load a single sprite. * * \param[out] result */ rosprite_error rosprite_load_sprite(reader reader, void* ctx, struct rosprite** result) { uint32_t nextSpriteOffset; uint32_t imageOffset; uint32_t maskOffset, spriteModeWord; uint32_t paletteEntries; uint8_t* image; uint8_t* mask = NULL; struct rosprite* sprite = malloc(sizeof(struct rosprite)); struct rosprite_header* header = malloc(sizeof(struct rosprite_header)); ERRCHK(rosprite_read_word(reader, ctx, &nextSpriteOffset)); reader(sprite->name, 12, ctx); sprite->name[12] = '\0'; ERRCHK(rosprite_read_word(reader, ctx, &header->width_words)); /* file has width - 1 and height - 1 */ header->width_words += 1; ERRCHK(rosprite_read_word(reader, ctx, &(sprite->height))); sprite->height += 1; ERRCHK(rosprite_read_word(reader, ctx, &(header->first_used_bit))); /* old format only (spriteType = 0) */ ERRCHK(rosprite_read_word(reader, ctx, &(header->last_used_bit))); ERRCHK(rosprite_read_word(reader, ctx, &imageOffset)); assert(imageOffset >= 44); /* should never be smaller than the size of the header) */ ERRCHK(rosprite_read_word(reader, ctx, &maskOffset)); ERRCHK(rosprite_read_word(reader, ctx, &spriteModeWord)); ERRCHK(rosprite_get_mode(spriteModeWord, &(sprite->mode))); /* TODO left-hand wastage */ assert((header->last_used_bit + 1) % sprite->mode.colorbpp == 0); /*assert(header->width_words % sprite->mode->colorbpp == 0);*/ sprite->width = (header->width_words * 32 - header->first_used_bit - (31 - header->last_used_bit)) / sprite->mode.colorbpp; sprite->palettesize = imageOffset - 44; sprite->has_palette = (sprite->palettesize > 0); /* sprite has no mask if imageOffset == maskOffset */ if (imageOffset == maskOffset) { sprite->has_mask = false; header->image_size = nextSpriteOffset - 44 - sprite->palettesize; header->mask_size = 0; } else { sprite->has_mask = true; header->image_size = maskOffset - imageOffset; header->mask_size = nextSpriteOffset - 44 - sprite->palettesize - header->image_size; } if (sprite->has_palette) { uint32_t j, word1, word2, entry; assert(sprite->palettesize % 8 == 0); sprite->palette = malloc(sizeof(uint32_t) * sprite->palettesize); paletteEntries = sprite->palettesize / 8; /* Each palette entry is two words big * The second word is a duplicate of the first * I think this is in case you ever wanted flashing colours * PRM1-730 */ for (j = 0; j < paletteEntries; j++) { ERRCHK(rosprite_read_word(reader, ctx, &word1)); ERRCHK(rosprite_read_word(reader, ctx, &word2)); assert(word1 == word2); /* if they aren't equal, flashing colours are desired, which we don't support */ /* swap rr and bb parts -- PRM1-731 */ entry = ((word1 & 0xff000000) >> 16) | (word1 & 0x00ff0000) | ((word1 & 0x0000ff00) << 16) | 0xff; sprite->palette[j] = entry; } } image = malloc(header->image_size); reader(image, header->image_size, ctx); if (sprite->has_mask) { mask = malloc(header->mask_size); reader(mask, header->mask_size, ctx); } /* sanity check image_size */ assert((header->width_words) * 4 * (sprite->height) == header->image_size); /* TODO: sanity check mask_size */ if (sprite->mode.colorbpp > 8) { ERRCHK(rosprite_load_high_color(image, mask, sprite, header)); } else { ERRCHK(rosprite_load_low_color(image, mask, sprite, header)); } free(image); free(mask); free(header); *result = sprite; return ROSPRITE_OK; } /** * Determine the sprite_mode for the specified sprite_mode_word. * * \param[out] result */ static rosprite_error rosprite_get_mode(uint32_t sprite_mode_word, struct rosprite_mode* result) { struct rosprite_mode mode; uint32_t spriteType = (sprite_mode_word & (15 << 27)) >> 27; /* preserve bits 27-30 only */ if (spriteType != 0) { bool hasEightBitAlpha = sprite_mode_word >> 31; /* bit 31 */ /* new modes have 1bpp masks (PRM5a-111) * unless bit 31 is set (http://select.riscos.com/prm/graphics/sprites/alphachannel.html) */ mode.maskbpp = (hasEightBitAlpha ? 8 : 1); mode.mask_width = mode.maskbpp; mode.xdpi = (sprite_mode_word & (8191 << 14)) >> 14; /* preserve bits 14-26 only */ mode.ydpi = (sprite_mode_word & (8191 << 1)) >> 1; /* preserve bits 1-13 only */ mode.color_model = ROSPRITE_RGB; switch (spriteType) { case 1: mode.colorbpp = 1; break; case 2: mode.colorbpp = 2; break; case 3: mode.colorbpp = 4; break; case 4: mode.colorbpp = 8; break; case 5: mode.colorbpp = 16; break; case 6: mode.colorbpp = 32; break; case 7: mode.colorbpp = 32; mode.color_model = ROSPRITE_CMYK; break; case 8: mode.colorbpp = 24; break; default: return ROSPRITE_BADMODE; } } else { assert(sprite_mode_word < 256); /* don't think you can have modes over 255? */ mode = oldmodes[sprite_mode_word]; } /* illegal mode check */ if ((mode.colorbpp == 0) || (mode.xdpi == 0) || (mode.ydpi == 0)) { return ROSPRITE_BADMODE; } memcpy(result, &mode, sizeof(struct rosprite_mode)); return ROSPRITE_OK; } /** * Load a sprite image with 16 or more bpp. * * \param[out] sprite On exit, sprite.image will be populated */ static rosprite_error rosprite_load_high_color(uint8_t* image_in, uint8_t* mask, struct rosprite* sprite, struct rosprite_header* header) { struct rosprite_mask_state* mask_state = NULL; uint32_t currentByteIndex = 0; uint32_t j, x, y, x_pixels, pixel; bool has_alpha_pixel_data = false; uint8_t b; bool old_has_alpha; if (sprite->has_mask) { ERRCHK(rosprite_init_mask_state(sprite, header, mask, &mask_state)); } sprite->image = malloc(sprite->width * sprite->height * 4); /* all image data is 32bpp going out */ /* Spec says that there must be no left-hand wastage */ assert(header->first_used_bit == 0); { const uint32_t bpp = sprite->mode.colorbpp; const uint32_t bytesPerPixel = bpp / 8; const uint32_t row_max_bit = header->width_words * 32 - (31 - header->last_used_bit); /* Last used bit in row */ for (y = 0; y < sprite->height; y++) { x_pixels = 0; for (x = 0; x < row_max_bit; x += bpp) { pixel = 0; for (j = 0; j < bytesPerPixel; j++) { b = image_in[currentByteIndex++]; pixel = pixel | (b << (j * 8)); } old_has_alpha = has_alpha_pixel_data; pixel = rosprite_upscale_color(pixel, &(sprite->mode), &has_alpha_pixel_data); if (old_has_alpha != has_alpha_pixel_data && (y > 0 || x_pixels > 0)) { rosprite_fix_alpha(sprite->image, (y * sprite->width) + x_pixels - 1); } if (sprite->has_mask) { uint8_t mask_pixel = rosprite_next_mask_pixel(mask, mask_state); pixel = (pixel & 0xffffff00) | mask_pixel; } sprite->image[y*sprite->width + x_pixels] = pixel; x_pixels++; } /* Ensure byte index is pointing at start of next row */ if (y + 1 < sprite->height) { currentByteIndex = (currentByteIndex + 3) & ~3; /* Round up to next multiple of 4 */ } } } if (sprite->has_mask) free(mask_state); return ROSPRITE_OK; } /** * Iterate over the specified number of pixels, starting at the image pointer, * and set the alpha channel to 0x00. */ static inline void rosprite_fix_alpha(uint32_t* image, unsigned long pixels) { uint32_t i; for (i = 0; i <= pixels; i++) { image[i] = image[i] & 0xffffff00; } } /** * Load a sprite image with 8 or fewer bpp. * * \param[out] sprite On exit, sprite.image will be populated */ static rosprite_error rosprite_load_low_color(uint8_t* image_in, uint8_t* mask, struct rosprite* sprite, struct rosprite_header* header) { uint32_t current_byte_index, currentword; uint32_t x, y, x_pixels, pixel; uint8_t mask_pixel; struct rosprite_mask_state* mask_state = NULL; if (sprite->has_mask) { ERRCHK(rosprite_init_mask_state(sprite, header, mask, &mask_state)); } sprite->image = malloc(sprite->width * sprite->height * 4); /* all image data is 32bpp going out */ { const uint32_t bpp = sprite->mode.colorbpp; const uint32_t row_max_bit = header->width_words * 32 - (31 - header->last_used_bit); /* Last used bit in row */ const uint32_t bitmask = (1 << bpp) - 1; /* creates a mask of 1s that is bpp bits wide */ current_byte_index = 0; currentword = BTUINT((image_in + current_byte_index)); current_byte_index += 4; for (y = 0; y < sprite->height; y++) { x_pixels = 0; for (x = header->first_used_bit; x < row_max_bit ; x += bpp) { const uint32_t offset_into_word = x % 32; pixel = (currentword & (bitmask << offset_into_word)) >> offset_into_word; pixel = rosprite_palette_lookup(sprite, pixel); /* lookup returns 32bpp */ if (sprite->has_mask) { mask_pixel = rosprite_next_mask_pixel(mask, mask_state); pixel = (pixel & 0xffffff00) | mask_pixel; } sprite->image[y*sprite->width + x_pixels] = pixel; x_pixels++; /* If we're not at the end of the row and we've processed all of this word, fetch the next one */ if (x + bpp < row_max_bit && offset_into_word + bpp == 32) { currentword = BTUINT((image_in + current_byte_index)); current_byte_index += 4; } } /* Advance to first word of next row */ if (y + 1 < sprite->height) { currentword = BTUINT((image_in + current_byte_index)); current_byte_index += 4; } } } if (sprite->has_mask) free(mask_state); return ROSPRITE_OK; } static uint32_t rosprite_palette_lookup(struct rosprite* sprite, uint32_t pixel) { uint32_t translated_pixel; /* because we're dealing with 8bpp or less */ if (sprite->has_palette) { if(pixel < (sprite->palettesize / 8)) { translated_pixel = sprite->palette[pixel]; } else { translated_pixel = sprite_8bpp_palette[pixel]; } } else { switch (sprite->mode.colorbpp) { case 8: assert(pixel < 256); translated_pixel = sprite_8bpp_palette[pixel]; break; case 4: assert(pixel < 16); translated_pixel = sprite_4bpp_palette[pixel]; break; case 2: assert(pixel < 4); translated_pixel = sprite_2bpp_palette[pixel]; break; case 1: assert(pixel < 2); translated_pixel = sprite_1bpp_palette[pixel]; break; default: assert(false); } } return translated_pixel; } static rosprite_error rosprite_init_mask_state(struct rosprite* sprite, struct rosprite_header* header, uint8_t* mask, struct rosprite_mask_state** result) { struct rosprite_mask_state* mask_state = malloc(sizeof(struct rosprite_mask_state)); if (!mask_state) return ROSPRITE_NOMEM; mask_state->x = header->first_used_bit; mask_state->y = 0; mask_state->first_used_bit = header->first_used_bit; mask_state->row_max_bit = sprite->width * sprite->mode.mask_width; mask_state->height = sprite->height; mask_state->bpp = sprite->mode.mask_width; mask_state->current_word = BTUINT(mask); mask_state->current_byte_index = 4; *result = mask_state; return ROSPRITE_OK; } /** * Get the next mask byte. * A mask of 0xff denotes 100% opaque, 0x00 denotes 100% transparent. * * \param[in,out] mask_state */ static uint32_t rosprite_next_mask_pixel(uint8_t* mask, struct rosprite_mask_state* mask_state) { /* a 1bpp mask (for new mode sprites), each row is word aligned (therefore potential righthand wastage */ const uint32_t bitmask = (1 << mask_state->bpp) - 1; const uint32_t offset_into_word = mask_state->x % 32; uint32_t pixel = (mask_state->current_word & (bitmask << offset_into_word)) >> offset_into_word; if (mask_state->x + mask_state->bpp < mask_state->row_max_bit && offset_into_word + mask_state->bpp == 32) { mask_state->current_word = BTUINT((mask + mask_state->current_byte_index)); mask_state->current_byte_index += 4; } mask_state->x += mask_state->bpp; if (mask_state->x >= mask_state->row_max_bit) { mask_state->x = mask_state->first_used_bit; if (mask_state->y + 1 < mask_state->height) { mask_state->current_word = BTUINT((mask + mask_state->current_byte_index)); mask_state->current_byte_index += 4; } mask_state->y++; } /* * if the mask is 1bpp, make sure the whole byte is 0x00 or 0xff */ if (mask_state->bpp < 8) { pixel = (pixel & 1) ? 0xff : 0x00; } return pixel; } /** * Upscale a 16, 24 or 32bpp sprite to the 0xRRGGBBAA representation. * Do not call this function with a sprite with less than 16bpp, * but use a palette lookup instead. */ static uint32_t rosprite_upscale_color(uint32_t pixel, struct rosprite_mode* mode, bool* has_alpha_pixel_data) { uint8_t alpha; switch (mode->colorbpp) { case 32: if (mode->color_model == ROSPRITE_RGB) { /* swap from 0xAABBGGRR to 0xRRGGBBAA */ pixel = BSWAP(pixel); } else { pixel = rosprite_cmyk_to_rgb(pixel); } break; case 24: /* reverse byte order */ pixel = BSWAP(pixel); break; case 16: /* incoming format is b_00000000000000000bbbbbgggggrrrrr */ { uint8_t red = pixel & 31; uint8_t green = (pixel & (31 << 5)) >> 5; uint8_t blue = (pixel & (31 << 10)) >> 10; /* sanity check */ assert(red < 32); assert(green < 32); assert(blue < 32); pixel = (sprite_16bpp_translate[red] << 24) | (sprite_16bpp_translate[green] << 16) | (sprite_16bpp_translate[blue] << 8); } break; case 8: case 4: case 2: case 1: assert(false); /* shouldn't need to call for <= 8bpp, since a palette lookup will return 32bpp */ default: assert(false); /* unknown bpp */ } alpha = pixel & 0xff; if (alpha == 0x00) { if (!(*has_alpha_pixel_data)) { pixel = pixel | 0xff; } } else { *has_alpha_pixel_data = true; } return pixel; } static inline uint32_t rosprite_cmyk_to_rgb(uint32_t cmyk) { uint8_t c = cmyk & 0xff; uint8_t m = (cmyk & 0xff00) >> 8; uint8_t y = (cmyk & 0xff0000) >> 16; uint8_t k = cmyk >> 24; /* Convert to CMY colourspace */ uint8_t C = c + k; uint8_t M = m + k; uint8_t Y = y + k; /* And to RGB */ uint8_t r = 255 - C; uint8_t g = 255 - M; uint8_t b = 255 - Y; return r << 24 | g << 16 | b << 8; } static inline rosprite_error rosprite_read_word(reader reader, void* ctx, uint32_t* result) { unsigned char b[4]; if (reader(b, 4, ctx) < 4) { return ROSPRITE_EOF; } *result = BTUINT(b); return ROSPRITE_OK; } netsurf-2.9/librosprite-0.0.2/palettes/0000775000175000017500000000000011734430307016662 5ustar vincevincenetsurf-2.9/librosprite-0.0.2/palettes/16colour0000664000175000017500000000017010722572407020261 0ustar vincevincewwwUUU333D     Unetsurf-2.9/librosprite-0.0.2/palettes/256colour0000664000175000017500000000300010722572407020342 0ustar vincevince"""333DUf""w33D U ""f 33w DD UUf"fw3w""33""33DU"f3wDU"f3w D!U""f"#3w3$DD%UU&ff"'ww3(DD)UU*"ff+3ww,DDD-UUU.fff/www0D1U2f"3w34D5U6f"7w38DD9UU:ff;ww<DD=UU>ff?ww@AB""C33DDEUFf"Gw3HDIUJ"fK3wLDDMUUNffOwwPQR"S3T̈UݙV"W3XDYUZf[w\̈D]ݙU^f_w`ab""c33dDeUff"gw3hDiUj"fk3wlDDmUUnffowwpqr"s3tuv"w3xDyUzf{w|D}U~fw""33DUf"w3""33DUf"w3"3"3"3"3DU"f3wDDUUffwwDU"f3wDDUUffwwDUfwDUfwDUfwDUfw"3DUfw"3DUfẅݙ̈ݙ̈ݙ"3D̈Uݙfw"3DUfẅݙ̈ݙnetsurf-2.9/librosprite-0.0.2/palettes/16mono0000664000175000017500000000017010722572407017726 0ustar vincevince"""333DDDUUUfffwww     netsurf-2.9/librosprite-0.0.2/palettes/256mono0000664000175000017500000000300010722572407020007 0ustar vincevince            !!!!""""####$$$$%%%%&&&&''''(((())))****++++,,,,----....////0000111122223333444455556666777788889999::::;;;;<<<<====>>>>????@@@@AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ[[[[\\\\]]]]^^^^____````aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz{{{{||||}}}}~~~~netsurf-2.9/librosprite-0.0.2/palettes/4mono0000664000175000017500000000003010722572407017636 0ustar vincevincewwwnetsurf-2.9/librosprite-0.0.2/palettes/2mono0000664000175000017500000000001410722572407017636 0ustar vincevincenetsurf-2.9/libnsgif-0.0.3/0000775000175000017500000000000011734430267014306 5ustar vincevincenetsurf-2.9/libnsgif-0.0.3/include/0000775000175000017500000000000011734430266015730 5ustar vincevincenetsurf-2.9/libnsgif-0.0.3/include/libnsgif.h0000664000175000017500000001117411472245455017705 0ustar vincevince/* * Copyright 2004 Richard Wilson * Copyright 2008 Sean Fox * * This file is part of NetSurf's libnsgif, http://www.netsurf-browser.org/ * Licenced under the MIT License, * http://www.opensource.org/licenses/mit-license.php */ /** \file * Progressive animated GIF file decoding (interface). */ #ifndef _LIBNSGIF_H_ #define _LIBNSGIF_H_ #include #include /* Error return values */ typedef enum { GIF_WORKING = 1, GIF_OK = 0, GIF_INSUFFICIENT_FRAME_DATA = -1, GIF_FRAME_DATA_ERROR = -2, GIF_INSUFFICIENT_DATA = -3, GIF_DATA_ERROR = -4, GIF_INSUFFICIENT_MEMORY = -5, GIF_FRAME_NO_DISPLAY = -6, GIF_END_OF_FRAME = -7 } gif_result; /* The GIF frame data */ typedef struct gif_frame { bool display; /**< whether the frame should be displayed/animated */ unsigned int frame_delay; /**< delay (in cs) before animating the frame */ /** Internal members are listed below */ unsigned int frame_pointer; /**< offset (in bytes) to the GIF frame data */ bool virgin; /**< whether the frame has previously been used */ bool opaque; /**< whether the frame is totally opaque */ bool redraw_required; /**< whether a forcable screen redraw is required */ unsigned char disposal_method; /**< how the previous frame should be disposed; affects plotting */ bool transparency; /**< whether we acknoledge transparency */ unsigned char transparency_index; /**< the index designating a transparent pixel */ unsigned int redraw_x; /**< x co-ordinate of redraw rectangle */ unsigned int redraw_y; /**< y co-ordinate of redraw rectangle */ unsigned int redraw_width; /**< width of redraw rectangle */ unsigned int redraw_height; /**< height of redraw rectangle */ } gif_frame; /* API for Bitmap callbacks */ typedef void* (*gif_bitmap_cb_create)(int width, int height); typedef void (*gif_bitmap_cb_destroy)(void *bitmap); typedef unsigned char* (*gif_bitmap_cb_get_buffer)(void *bitmap); typedef void (*gif_bitmap_cb_set_opaque)(void *bitmap, bool opaque); typedef bool (*gif_bitmap_cb_test_opaque)(void *bitmap); typedef void (*gif_bitmap_cb_modified)(void *bitmap); /* The Bitmap callbacks function table */ typedef struct gif_bitmap_callback_vt { gif_bitmap_cb_create bitmap_create; /**< Create a bitmap. */ gif_bitmap_cb_destroy bitmap_destroy; /**< Free a bitmap. */ gif_bitmap_cb_get_buffer bitmap_get_buffer; /**< Return a pointer to the pixel data in a bitmap. */ /** Members below are optional */ gif_bitmap_cb_set_opaque bitmap_set_opaque; /**< Sets whether a bitmap should be plotted opaque. */ gif_bitmap_cb_test_opaque bitmap_test_opaque; /**< Tests whether a bitmap has an opaque alpha channel. */ gif_bitmap_cb_modified bitmap_modified; /**< The bitmap image has changed, so flush any persistant cache. */ } gif_bitmap_callback_vt; /* The GIF animation data */ typedef struct gif_animation { gif_bitmap_callback_vt bitmap_callbacks; /**< callbacks for bitmap functions */ unsigned char *gif_data; /**< pointer to GIF data */ unsigned int width; /**< width of GIF (may increase during decoding) */ unsigned int height; /**< heigth of GIF (may increase during decoding) */ unsigned int frame_count; /**< number of frames decoded */ unsigned int frame_count_partial; /**< number of frames partially decoded */ gif_frame *frames; /**< decoded frames */ int decoded_frame; /**< current frame decoded to bitmap */ void *frame_image; /**< currently decoded image; stored as bitmap from bitmap_create callback */ int loop_count; /**< number of times to loop animation */ gif_result current_error; /**< current error type, or 0 for none*/ /** Internal members are listed below */ unsigned int buffer_position; /**< current index into GIF data */ unsigned int buffer_size; /**< total number of bytes of GIF data available */ unsigned int frame_holders; /**< current number of frame holders */ unsigned int background_index; /**< index in the colour table for the background colour */ unsigned int aspect_ratio; /**< image aspect ratio (ignored) */ unsigned int colour_table_size; /**< size of colour table (in entries) */ bool global_colours; /**< whether the GIF has a global colour table */ unsigned int *global_colour_table; /**< global colour table */ unsigned int *local_colour_table; /**< local colour table */ } gif_animation; void gif_create(gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks); gif_result gif_initialise(gif_animation *gif, size_t size, unsigned char *data); gif_result gif_decode_frame(gif_animation *gif, unsigned int frame); void gif_finalise(gif_animation *gif); #endif netsurf-2.9/libnsgif-0.0.3/examples/0000775000175000017500000000000011734430267016124 5ustar vincevincenetsurf-2.9/libnsgif-0.0.3/examples/disassemble_gif.pl0000775000175000017500000000417311126561232021601 0ustar vincevince#!/usr/bin/perl # # Disassemble a GIF file and display the sections and chunks within. # # Warning: only part of the specification is implemented. # use strict; use warnings; die "Usage: $0 IMAGE\n" unless @ARGV == 1; my ($image) = @ARGV; open IMAGE, '<', $image or die "$0: open $image: $!\n"; undef $/; my $gif = ; close IMAGE; print "$image: ", length $gif, " bytes\n\n"; my @gif = unpack 'C*', $gif; my $z = 0; output_chunk('Header', 6); output_chunk('Logical Screen Descriptor', 7); my $global_colors = $gif[10] & 0x80; my $color_table_size = 2 << ($gif[10] & 0x07); if ($global_colors) { output_chunk('Global Color Table', $color_table_size * 3); } while (1) { while ($gif[$z] == 0x21) { if ($gif[$z + 1] == 0xf9) { output_chunk('Graphic Control Extension', 5 + 2); } elsif ($gif[$z + 1] == 0xfe) { output_chunk('Comment Extension', 2); } elsif ($gif[$z + 1] == 0x01) { output_chunk('Plain Text Extension', 13 + 2); } elsif ($gif[$z + 1] == 0xff) { output_chunk('Application Extension', 12 + 2); } else { output_chunk((sprintf 'Unknown Extension 0x%.2x', $gif[$z + 1]), $gif[$z + 2] + 3); } while ($gif[$z] != 0) { output_chunk('Data Sub-block', $gif[$z] + 1); } output_chunk('Block Terminator', 1); } if ($gif[$z] == 0x3b) { output_chunk('Trailer', 1); last; } if ($gif[$z] != 0x2c) { last; } output_chunk('Image Descriptor', 10); output_chunk('Table Based Image Data', 1); while ($gif[$z] != 0) { output_chunk('Data Sub-block', $gif[$z] + 1); } output_chunk('Block Terminator', 1); } if ($z != @gif) { output_chunk('*** Junk on End ***', @gif - $z); } # # Output a chunk of data as hex and characters. # sub output_chunk { my ($description, $length) = @_; print "$description"; for (my $i = 0; $i != $length; $i++) { if ($i % 8 == 0) { print "\n"; printf "%8i: ", $z + $i; } if ($z + $i == @gif) { print "EOF\n\n"; print "Unexpected end of file\n"; exit; } my $c = $gif[$z + $i]; printf "%.2x ", $c; if (32 <= $c and $c <= 126) { printf "'%c'", $c; } else { print " "; } print " "; } print "\n\n"; $z += $length; } netsurf-2.9/libnsgif-0.0.3/examples/decode_gif.c0000664000175000017500000001026111060174716020334 0ustar vincevince/* * Copyright 2008 Sean Fox * Copyright 2008 James Bursa * * This file is part of NetSurf's libnsgif, http://www.netsurf-browser.org/ * Licenced under the MIT License, * http://www.opensource.org/licenses/mit-license.php */ #include #include #include #include #include #include #include #include "../libnsgif.h" unsigned char *load_file(const char *path, size_t *data_size); void warning(const char *context, int code); void *bitmap_create(int width, int height); void bitmap_set_opaque(void *bitmap, bool opaque); bool bitmap_test_opaque(void *bitmap); unsigned char *bitmap_get_buffer(void *bitmap); void bitmap_destroy(void *bitmap); void bitmap_modified(void *bitmap); int main(int argc, char *argv[]) { gif_bitmap_callback_vt bitmap_callbacks = { bitmap_create, bitmap_destroy, bitmap_get_buffer, bitmap_set_opaque, bitmap_test_opaque, bitmap_modified }; gif_animation gif; size_t size; gif_result code; unsigned int i; if (argc != 2) { fprintf(stderr, "Usage: %s image.gif\n", argv[0]); return 1; } /* create our gif animation */ gif_create(&gif, &bitmap_callbacks); /* load file into memory */ unsigned char *data = load_file(argv[1], &size); /* begin decoding */ do { code = gif_initialise(&gif, size, data); if (code != GIF_OK && code != GIF_WORKING) { warning("gif_initialise", code); exit(1); } } while (code != GIF_OK); printf("P3\n"); printf("# %s\n", argv[1]); printf("# width %u \n", gif.width); printf("# height %u \n", gif.height); printf("# frame_count %u \n", gif.frame_count); printf("# frame_count_partial %u \n", gif.frame_count_partial); printf("# loop_count %u \n", gif.loop_count); printf("%u %u 256\n", gif.width, gif.height * gif.frame_count); /* decode the frames */ for (i = 0; i != gif.frame_count; i++) { unsigned int row, col; unsigned char *image; code = gif_decode_frame(&gif, i); if (code != GIF_OK) warning("gif_decode_frame", code); printf("# frame %u:\n", i); image = (unsigned char *) gif.frame_image; for (row = 0; row != gif.height; row++) { for (col = 0; col != gif.width; col++) { size_t z = (row * gif.width + col) * 4; printf("%u %u %u ", (unsigned char) image[z], (unsigned char) image[z + 1], (unsigned char) image[z + 2]); } printf("\n"); } } /* clean up */ gif_finalise(&gif); free(data); return 0; } unsigned char *load_file(const char *path, size_t *data_size) { FILE *fd; struct stat sb; unsigned char *buffer; size_t size; size_t n; fd = fopen(path, "rb"); if (!fd) { perror(path); exit(EXIT_FAILURE); } if (stat(path, &sb)) { perror(path); exit(EXIT_FAILURE); } size = sb.st_size; buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %lld bytes\n", (long long) size); exit(EXIT_FAILURE); } n = fread(buffer, 1, size, fd); if (n != size) { perror(path); exit(EXIT_FAILURE); } fclose(fd); *data_size = size; return buffer; } void warning(const char *context, gif_result code) { fprintf(stderr, "%s failed: ", context); switch (code) { case GIF_INSUFFICIENT_FRAME_DATA: fprintf(stderr, "GIF_INSUFFICIENT_FRAME_DATA"); break; case GIF_FRAME_DATA_ERROR: fprintf(stderr, "GIF_FRAME_DATA_ERROR"); break; case GIF_INSUFFICIENT_DATA: fprintf(stderr, "GIF_INSUFFICIENT_DATA"); break; case GIF_DATA_ERROR: fprintf(stderr, "GIF_DATA_ERROR"); break; case GIF_INSUFFICIENT_MEMORY: fprintf(stderr, "GIF_INSUFFICIENT_MEMORY"); break; default: fprintf(stderr, "unknown code %i", code); break; } fprintf(stderr, "\n"); } void *bitmap_create(int width, int height) { return calloc(width * height, 4); } void bitmap_set_opaque(void *bitmap, bool opaque) { (void) opaque; /* unused */ assert(bitmap); } bool bitmap_test_opaque(void *bitmap) { assert(bitmap); return false; } unsigned char *bitmap_get_buffer(void *bitmap) { assert(bitmap); return bitmap; } void bitmap_destroy(void *bitmap) { assert(bitmap); free(bitmap); } void bitmap_modified(void *bitmap) { assert(bitmap); return; } netsurf-2.9/libnsgif-0.0.3/examples/waves.gif0000664000175000017500000055504111027263036017743 0ustar vincevinceGIF89a V  , &C *<*41N$)+7J9` =]%7A/6:564*2Lv"GZ>0GP?DDQPp7HZC%< M2Wh`&GNSR Wi#P&i6O,U$[sef(`y`caJksBWAn2bo-g(k#{*k7h3z-nEd=j(u/t5qAmnqoNk.z=tHr>x:z.)KvEzOu;B#F} ;[3R{U{MM~~I-)+W=84OT@^N+`P[a[GfES 7NEy &IGF44ҧ }4kO< (e,yKJ/P`d3| Λ:٨Y|P@QjӧRZd!Q>VA R/h*}D%Fn)Y:ZK mI(! )y %`bc\ȘͦH PA}HBv"4ȚDP"@ĦX$8Jƒ7ݤN!dO1ԓs %%RNH V!w}!0TvZqW%~i#_kiBI[X%{faƠcB')}Hf VG"D+v ,*C@ ue%DK2DJI"N)r!I1Uч܉'#W~UiFu#Wؾ^I׹zjv®]hc):b**dK`fj=Zj0zЉbf i#d[K&фOEN^$R<]08;G K- ol; RV̱wܖWBYE~RW_ƫa:ؠVXc LfP QB'>wXE%Hp C*ӭD=!9rLEME+STZR4WBfň|UXvb]kݵ&ŗ'`z]ڈcYm.aZ3֩3J̑j D UjBFdTqsj'G]QX2VT+ީ#ЃXPB>@Z4BAeky0rPr/dhR=d*(!0R y ":\GDD=FaI 8f8ٜCE`T#W=6dDWA$$#+xc37|N93*IO ܡKO9V7Vи,5)Q۝SC%-qQ*aJ+ksJ/K^ -`c0 7#G`bFE6!YvCdsZ\OTg9f r7LKoܳ1 u &% :&d'W92&hY5g@ޠ%<H-{T0A \aZ6(Ub V'@t@OD%J^gC8Y+,UFyӌduBΗot$<}U#gD%$ O$Ls~rS)!x֙ \c)zTz6>-@<T$֗ jІڨF5t!^X78 z5\w%aa+IK5R0Ne5qQA %N \*<妕24c屜;sϷD=eSWiH-)P}yD!9LR2`M:)Ė磑-#CAD.M49䨐F6Pe1`t0PP2}hO{ M1gjխPZ@ޖ^Sp223//a(,. R՞uVXl,\KRtt$"I)0n"+#XA- 7EU|̖:d+332_cKBNw|J%X!xG;A+yY$cb凩-\ G= 5t(sohM~2fQCwV3a8PQ@< < k6pnMilϒlxs6Z;&(/|acCC96%6m%#$'aWx#hMjFg7St p@`z i\5XL.Z`'3SdYl@4P@eAh:@'}M ߰Gp0@@5 ` OcAZ-4Z;!q|r.zH''2< !1dh("/u=sBuu0) `p REwnekgg 0 -u57E1U$Z^"_^0,GBB Qj@`% G@ @ZPxN-ikO&mlw\` Uu Ҡ @ (=>׈‡^"c{#0T @qX E X0 pPoLF^1udG-2MeѴ}ЄXq0p  ;p PH5 xPj`fvP|qakr  Q `P!m5D+0b,q)*J p  _Б@` XKtQXl @ FEjeDT<(_2 ЉKMP~K:`@pK hi8 4` ^"8^0  Nvr5n5_[(Pww9 +6DF PLtZb  p p``  AXt%JI @\ @2dT+;IFd2R9V&@;o@ ڠp0q v7XQ@``(AB+A  dU#ToV UZUCc5 y {JA  ()b!>P\ ? ` p ǰ 2D `^TDwC1Hg\Pp2ed7a+&@5Aj S0S8:NFزMˢ%<# )p  y c-b և 8Box5% 1w}1stv볽ګ à + P :pDpv')ϵ FXj@PгŻ S< `p0+*c\)} ppzoF Ġ pK`$J6MBl i tP;i@ 5w-MW& pW PPp ɐ 2X cA + p ,p@ k!Ds(P|1-IR+h `Vi H p sP P0Ol Y  Ь, Q}` 무p;9C$?? mЮ  02B` M0V;@FqM١SXY { A0@ p  ,0- 5D5Cy< VieVрI)hDĵB/ uN\ O ؉μj Ȁ 0 /  #mpggm w`{ JSk@7 3ud l9Sr%3CSk3` K@Jq Np Wx ~ 0-p{.'5/cCI `pp Pi }r- ڶ!wzFO _P ŠM\)ĉ ` 0 $k`tpvKM xl`++q0 PJڿMP n +j0{6 D%  R3:}_ X,0; d -@PQc @ a3@ x"6zX<<7/ya p;Kw` k`Ȇ<.}Q઩Po@@)-] ;~Y, n `tKvpzmƁ 0˰ l j e0{/=TFp 0P[rk 0  R Z<-BOHiQ НxO;va5lq b 3m {a0^X]2$ %^mͫ *P `/re`gxt pF8@ ␌  ?`0 }S` i R: uwwlw0q<3P5A]BP;X< Bm9'e 4 @ p yrn #C 0  >L ڠLHm`QfJ˄ S)O5$QƘg9bBg>CXǟ},dpyc %`J{j>鬒HV`C`本EyG}G[pLǁ$G`AD([^qd@ Vf'cJYG~Vq 71f$6B$gim: C3=tPM%{fJBSX" #\ןz9 XVʢ] `p(&bBg@nE3uabo;$vǝ}6#)k!*"ՠ)ؤPqyQWc}ؚhA}ÑӠ xa(LIgsz Ő7渣Cιh ~1u`LAI"AZfHP;qPh('%@RcJ0qI?α.!ZTch1!{/ъUtlGRҍ B~ʑ+$)y8Q) |H?hA|yfGZp1Y R~fᣄ+a&,yPDB!(O i3T&G T4)ZAHcGya_E5+WF9`ptƠ:AĘ,p9 .(/>?ce1*cx W3;%ZJhą2S@i(Xь(.Up, `)N̎bXGFT$] 3unG9 0>-7 ? \VeЇ8FGh|)`ꦁ-EXg@ݧ4R4V}X1/ڈM TġPF/NM`}DL#1 %7x! L5'ı–y"  ]v(挢89`A m*Vq R-6-Au@jթΔ`hk1a<BKZT[PDuZ\</X @ AwXE찇ie4S*}\ "4:XH+8d}9~8& ;QM,L*X)ӞrvЇf`l;kG2Հ@հ͛i f`mPE IXHS pNG}=! 5̐Y@sˇq^zk7ܷQSP8VJȊ~88 bUШUdQL34@" H"rmh:tkDhWT wQpb/?;/,؇=%؇`S((8tx$@< {XӞ,mW{bvS$f+;q8~k =XNY>ՀЀSs"~_V. GjiXZtI؃?H @4rɷA8~ID82#3cUUDILPQIJ< YgxX Rڄ ;3IEB50~XAxEb ꚴ0XSruH 8]3҇y؃ ň[ARr `<(wSk06AK Y=Sl^'pDh̄f1sz'wLT@ H.S2V`!%Z`xxZA4R3ۨvWUv8"c-@Նrb؇|߼iP(5\H##*rP}hh#L!= %p2TPhPM7٭Bk:+{ :Z H%%y0BpCJ\t@1;Si1R 7x0-I{{`_i8o`Rhv B{P=xZR>-@(IcV=]SDI_U[_ V ax$Z3B0;;fٍ?H5Hf:`20-~H^8Hx̄ iR~332",~x$\ OpukoH(p 8hx` 9i :a4Fxp;^ޑu^ݝJ\I7kkhD} !Fi`d2XhiST~NP䀛omc__(eP=Ze\VE9 тPh}؂9SyYGP\eHYh@#;iC$ `=H H^XUA8bІz9L9HriZX%G?>|Ӿ;>Yc1Nw˨?o'ppt ~8srІ^RRZ%~XfR>=tڡ6U]P-[J,۳usńIPP>[yCJyC(?f`GӪy}x`/AU/ {h=!؁%HD?8xMxB% /"[I i YӇd9qT8 7({y1s`z8h;f2?4pRhHTpiqs[87{50n:|&c5Pb]]`իU^LʮeQ1y ١Sx0k;1s@~X[\S3 X^kX]I@8. t{HHxh`hhW=*E_ؘ;XRGR@9iІL8m TL-UjRwWUD4"˨-y6PPxtJ}RpXIEv,`$"Ȏu/p2 PhkWe(+7HG'w\mC8oH%JP6-Ȁ:v2/sp8jWmրyup؃LE8h(TP臐G YՇ8isyD*P_>tQdGj80GF)[n`<Ą1@,~E8Ks\ k`$mڴ&;vHoM0Sgʒ#xi &M4!DM^Sv6[l}{EiPig 01$"r9bd#Hݻǯ_ItÉkK)Ӑb7FEnY(8p`2ihD(yLZ- ~#!DH Hww)RVhjذff}D5iL1Ө Ӣ"70i"30=Ҕ /#/%HANÈ9t0C=MVD6T*xLH<;O>:N (rB߄"Ud^(H*Bd<,瞢1 -+lI`ħ &+`D<|d*hZ4c68O:vOk!aE)30jeTd >H w2 s"G d"RCL(LO0,PsN !?@TS㋌p|:霐A(d`W,@_OO 1y}s 23<}<;W#;*>3(RhSjR KQa= `0"uO& |؛ @` @oJ:}XO=֌}b g80r : G>,1ĹnDQatcZ0,bN(h@)*1}0D  b^! KHcX)f p#Bl`~vc G= #3? Ђx4zq~#-hF804O 8H,00&L` o&0qIS+i Y8A4 \pAB64q0,$ [ }"e(9`aҒST#;oGp」`H JP!c+ EQL(jF "D >Q G+:DD,2w(p[CBhtkF ٘5/{# Kn3VPR 5LG7@n`1B frT͂p UhY4Xj 7HѰ& H(c"wgD( qP5Y.xi7@"!aZ#x0~#KX|c!C&Xq?%@@CDC[$9C&p@@EC;T4(BH  @C/V҈kA!JN6`T 9GABq |>LA4Lx́l :43B? U=H3 :̂UC!Q=C0̀x@$(*$A&P8d:>ă4B(P8B!!c*C>܃̂:%4@t6jɤLhC*O[(C?PE@P @ A{L)(A$ B 2*(*:kX{pAqՍBp =Lj`"%HAB4?܊8H| E(T)(c;3 [[Ta=DR@ ݂9h 0 $A*|>9B(LSX+ ?d%>B#?v@!`@W8Ѕnp@o6"]4@ +})7K.kP]X́S$+ CA%tetQ%m;Pu),C41 mK)zڶ)lC3Z:(*ALiF3@L? >ă8`CvB1 (@4\ ,/ B4hcEh42>C/h!9@C%0³ՔjՔF@^EdBT煀$h*h @`@bC/?Og @!H$C*IB.LYEݷ0'¹T<A H!{:H ?A|dԲ$ ȇ`T4+z}&XAHX&̒6,, 0֝9H7C{  4@ h\HB HB4-$A [!R@<0_>C'܈#P#X(̂8 C>C0A&D5@9C d9Y8HE|< ̀ҩH59(?K*. M 14c8D> @4 'p9\sq #xAMC,m, DGBԇBԪ0!Tߩͧ9D[69h-͝# IB@5T ?TXC& 8)wc@ 8,iOjfóh)PވR%$T0+L)>g9REʤEԵՀD6Y0d$ā A!xV($CYdE_՝AjZ'HC 8l l,@;X8l:< '0dB Ѐh, t*4=#dR h‘ h@ 0<>6<|&("d*2X8=ԃ=<94C/t¿,O&5"8,); 0B0  >4̄DC$@;/D%d, iC@+?ȃ=+Im1Xf}FhBϤ(S;0E+K*Yb YCx0|q3@O/ڦbkPՀ,̂5*09-tB'B&Zb9<7)d\;#P뉙a*v3} `N-v B%4C;lE˰0cb#N4B(zW' ;D:Bt :w 8BRAO4cE%1@06R'4醡4xRA?C3x#$k%hB'hB$1☢M:O_[#/*A8+3bˑKQ JB0C4$M>,@Դ>#eJ+-3Y-5a !܄[\ V~{*I1c =72PR"N|TGؠeArS4*(nbJwÙ| IRekxI%Oc |2A{Ab#X B2k*d0 bD4L/f 2|fDh-rG@q*Zъ7j  D ) !Pp$l 扔z^m=ɁTCxi^[7AA`S'.U * + =a 8x0ě!1 2 M2S4 ̸HE)hb5LjPD8̶)3\QaA霉 gZ5ַRΣΆF TvpjKܡ@⊟=+K"*6n/B L/,ES9LݨF4r.[E$8 *X9"H4d )Ɯo!W甉5$''ܒg7Tki.+L JDZ M <5?K[*_.P[: X˰},61WEH9 ,ViT2gPC8f-`s ZMAT4'lSCI,[ Nh9(S(5n+Z:Qi1\e!Sg4?0r,4I  VRVfw͘ UR! , V@y |@$HA8E%BhQcC( *(r "<²ʖ,埗5idN5 yTeB-,Y $GH^:L7 >nF \R謤vE!Mh;JWԒ´/1)!wg),`z 1 ]Z^b \,ݥ#}K(,EA9ap'"EKV C:GJ{2P0WI[@Kf˜n'+ҘP:SӤ&\*ҊxrNf.:'{q GD_RT x+LbBh""QE)LHG A#U9XZ aRg:cǃ,2+ MNx; TCt)S x&T V03M՛gV{ZJ"%=1"Q2lT_ѠdFbџb\J@(N8I%1lNΏg< I!B}Ұp9JjДfa 0ɝ.a BNS#r+BG? lFA^ac 2L3[*(U"XBMϼP D "K@gVut2BD@b9=szz&ϱOUnxtZ6yϸ>Y"vl!{X6xeK("`T(1MpDd$ e2B%!mz [RV7t\ Q*W`wN7 )4pKP\3Jf6" s#fF2!i3&nIx,mNXϠYL9CBH6`ad[ZWRJ̩>h=(W[Ă^?eP|[Ta~Mp@No4sr Z2lF",ͫܯBaܕ 2xAЍBN ..A0a0$`?x%GIS|ӕ\$[Ye/Kx%\KQJLj&0<[ITWQPfnޫtWkm@jTϜcGw]v&n ;<Ҁޫa G3}5FB7vbjh)Xi4 پgX$`ق/D*K-ꋂgQ vGDV&EN>@q`xCm<gӖ+:G pGHtO]HURI@%S4QA 0MppU ` `T 02N@ nSogRWC'Tdw(Sv1zR G!Tf@rS;Sc,mtUX:j E T2!(" `  `y4Cc3%` @}..ٓpjMqr10f!wA0EA `р ˔0f)gLY@61O$9&aڠ0 CC&tEWP`` h8\:qRR'<1<'9%@!j@p` 7  pr4 eWKwDeKo v/B_0pxp]` @ !9@<5`"h͖`! _@_ v  N1ȱZ 0w;#){TD47QG%KqC"P QXQ \ @oK0 `  8 @'cJhqp` ڠ p @ jR?TRKG8 ɖ`rQ@Ӵ E Ȇ">kO@  @`  l+&[Y`P e`;N,.tZZ5,1nBo`Џ  sP`JGi 6Np07 4,` p z'b(G_[Kڨ ~Ec?`f!aV98Snq;61Wp P R  " pO|g[472@kpZ54)!HeO=BNwtQBPg%\[ a0XuP1&7@|A=b  @ p Pt{ l+@ 0E y=d 0cL! p`leVLtbrp{6 p p p ps&G,$,!@K'$4p 0<ӑj @S0k@ "&} Y50@  hs Pv +P 0߀ 'rt|Q 05"LP  `pa &lut y0 00G\ P Kl R\ `  9 | p` E w@ ; 0 bR7%H ePz<+&5a5&P @P  P '@ @+ 57T(q"F6FͰ 0VV @ @ = Ob5qH[`DP\ [ ` P  p `?  >ߠ m` ѐk9.:H @mm@t@ p I@ PuV0]` H -@+ ` Z>"{S),8xL@pm0kep P@ wY3P 0. 0 P p p pf :0O kgpO @ÖU-!V0aۑ`G ` fi&W-!E^;D ` `  A Ġ  V`@  tc"r[!Q!KQ`о^kq` ` 9YP^ lP pPp ٮ . t\pvT.  ѐ}HFp S` נ j@ 00 }6CR@ @ p]q ~ 瀑 J`V @oj} Y2-t+0@}c[Y0E \y1i >S0e s9Ig;[ P,ℏ "@pL\ p ?L ^V`OqSMtPrr  h`m@Ѻa`?L@I \CP,?N -&^ {"λ9DN db)R!sĉxnmqpaWcyѧMJ:avوBqfC0]ǝLe²g]L00,oIEng#+`{ju)ȫxd h0!xx'PM*pH:ΰ~p3se B69Ggg5?ȁ4AHTe3 ~JX0A!Dp1> h;x0ՠ01 0,xa 6``ƣ =%p scU'N>(E죉JAm#KonЇ6z b#x!@{B~B> pU^OdEg{3oC(DWQ`z܃At)f`/:;Яel#ц3#1,fY?pя? @`0P  h])9!}Cj6FDBHrd \"F fP #( [P#C Fs>J-N ̪ )8$#>L!8]ܱ#c=́ R”>; ^0;pw7ZQ12=c3=aT}eC䱾@00'0]0eԃ=ґ}#0J'q>;aшF0faW*vw# X>(QCX= 0PG?zA-=!}PBvf\x5R@]р@{T" >aso#h` zYCaFaN.g02V :t6Z`1z VfU% ]Y 8NK"`X[e+AT#x  C\ GkECjŸP?`9̡FV"() 7S'":BW&{S=l<F5Ru2 _s#E E yp_0q-$J+d%q3.q9 1A];QscMm0B |"hWÙdXa l@r| DG)Q[!s b@=az1KCg>ыT xH(RQh{@#P qՏSH`*RU}@5V|GQ_]WưkcH#!L, c^  `^CtPplkGx( {+1h!lQzPF::}CX>0P? iBl706;Ax$G;q'̣$4:qCTU,^E`HB.2܄ !iMRPHu: M.*. |}j4;X bug0g[a+[;aJ}pE>`p؀"(1px|phI:0ͳXy`O I٘~ht }4+:qP#JuW0PxPx&%qx\|§WHwpryb}}~Ȅ=@q_!8^ Vqp'p7@sЇs@bІY} Pkt(Zq܇E :$xx#IWsTqARHAЊLA5w$Z_ ;_( 47 P p78H^ vË (zz?4k؇ҕtX}xd?h *rhaۇY؇W,XIYmhDIdʦ,y%er}؈YH8heTs,~0P8'3KBi~hRIȎ.xXBk@; pځC'$8o@q)+LycȻu|w\zGx$WtM7.䇾$eIS2H˱y`0{M SpY0kq`\4h%h/Sx~x@`%={?Pp'L!oPY؄zDDdJHHsxuȕh@>HExxv^H8(8EekHfHPw|P.%[Hh*H*j I8-AB7 M[AdHS_z9%:5~~(<<4pP1p4 >u #}-Lt{X`xWxi6hqMf`jY~(ɀ HXl# OtŁpwwP!(Oy|*Vt|rP2hi*ۺ%mT``@*(ՀvePm!X's 5EHS7zp C=%X B!H {GV`2GvA3@KAU`ͽydP#Y HpA4:hԄwP夃{\S BxYuoȋ5 f}hrI(h`i MP V8h#gShLvV PQj֦H^М(-ڳEwhm\}=G:+ȇH$؃`\ ^pJSC0H. Ps`V =G/`P8%м4 8S{S^Un(tPSBH7PV ["]I3\P}O}3}{x/(h+xX* ؁s (^@w88KLx |raeJamC( A( :B*`\ (v}Ѐe-^PO`.7ؒ@BۂB`eD0\LXRi8v|]h^U@dUՄEdL0?(AS7ȂXx1?xh^C559hz28O. M?)[ID؇?@B%\L8-~GOH`!V(W+q ~8Yxaav{J7LTȁ{XPPJp4 #;U Y6^3}LHdD^|dQES8AY iPP;uN_P0 r@ȇd1ӱ64~`d}%#0-V`W0ioxtJ2W"k4Zm@+HDj5gaG8 eup!b|)2 WLYp!LT\@%ttI3(@$\0cks՜cbDQnQHdGNdH>x  }8Mx-JuHmyY}pv0ı35(:*4 `!%p#OLq6LCr…g22V}ZP`JM~HQm&HX`:~pbHLAL4 E\sKHp`̏.;,.\3E9n_D=B @0XB5A(HbP#}β20H0```1 m&iځдBāe48rЂz'CfpAGهDDX@pxx"A9~PVhb{~W~Z|-GLhTm"LཹT w؇.~`s<ځ PdUpǘ={iI?wQHa~"xF'_ `H1SV xv+~8?0t A;AIQ[(PMPP+  !pTP)d'2M9^#xGhF%J`uhҚe@B8tbȅ^`|\XOXgJ.PviPy؃xJHJ_'PhDžtT-o Vx:/}s֙7s@雦޳.E>yـp~b؆xa ~0a^+ F8_ fzͣP1):+;rDI?Kt[B.)RaퟥgM$PשS1JEl]=}D‰Bҹ]~đrW:Q`jj5D?bx1D1& H:o %O)xx4VHjUDaE?6PٳϷTRu떔Ѫ\MzlL1$l>|Ѐ䏑6w*%>/l׆P855޺u~ZL:eΔ)?ʫuق$e[sĉBwO^_ܣ 0DE (?0cH8M%H##2BS3 d@AtB%H:ˆ%T5hDVduUV;^8s ԐB 5q?"FPt:]TC4 d *DT=BC?JcҊjX*4?^c(y+&*:t(-n&lxYEc m  n?H،>-XcO%B9^O_O=5TýC9{ -A"2C?7آ5G %pB , hJ(l 4P-Ђo:8˛q&284 '45 P݈AM;Q r,uPA YFqmG= SbX3XXCy`EOCQPo)aw.WN{XctXAibpT"# OD"aG,P"*ю{Dt< ̣Fzb&F Px"2!`}c_ x*@1aR1\ea47 "4'WX؀n4M| /2ɌtFx)Hct+ 5b>p;čvJV+pfC?p;AQ9bw#66 mHAZb0"m 8?ZЁ 2(0CWlTe()0"<a ,xC/ PA R~@㘫lLp3(`@0' fM9! Yp6Hx`(FA ZcC2=Pc?lH&&kc`&"a?`A   m~V\,ܜ4d n8ya?6ퟛ <@r9ȊXC>lՅ# Ї@\puh0 ZF@bD"N1}9 A AG.|`c8(H8"8()I@HB e0asq 32ׅƤD&F R}iY x1 _OјSE* [3' @ =00 Y;p*`5քÆ{؂a +a eB &D>)Ң sAsM$0(9=@NA?,4QAA($5C3P94 E L!P]|C p@!. X>,PA@@8HE? /AD=C/ATGAT 4

\AA*a*°iAô%@ މPÉ#D=)!?)>̀G8/07 _!’  ?X8R6"$"phAK4/<8)C?hf,qHX/3Bp [*C:Xr5:R?.8BFY8Aф68U&/Zx 84C=<`@B'#x3TyJ=&A$p4%H?f # qv!?hNhC2)I9 2= E*?/OC1ASe?i6i9JhSʵ9":ur'P ?E>0 ,_k-K^:|9AaA7HC2)$Ca2 H8(́ x _Xl_ÂN7LC/'TB'B4$i$($A@>PB+ Xø2Hq"Xh<|9U<<6C 0u(0 B+P`T<1|):A5WC%>CD;x:U@^CK;4X` A ^T鈎SI6)T…K<ø,&R@?D@8=>5>bd̂Dx" lD I-րϣ+lB{_+8:|bPrt<` @AhSjq>tftN تB(<& ?|uP91 x1CN?`A)?.zgX?@ :XB B3`Q澋<@? ϼLƚ/0)؃>@+T%?(C A[+C= An@C0@\x sB ,, Cm9h2b#V6b B<'$8   @AYy$<<-C~5>)XI &Tr Bb;X*Gps?C)9?h)EBKt!j(@ @ABň9̀D $B=, _+öPB"PB'|>,AA 0@ñ>TqtW(AUC(8D Ā+O F,3L OBœ|n )75aX$@0 ɡɝA\Op\*4n,A33,9HDo1`8@B$B0L`4\h1-m <BzTF5: `c6QDY'HM0 (Ad(B+o;9„M? @qh 0 oMp"i$S:'4a}S B!hC>X dC>84YԉX&xV\/4+PQ_9aj!* >OY(2HGEEɧPPB?X@;Pbh!܁!\i? BCM[ f: 90VB?319ȱC>0HC>4<-: Mp VʥP6.".3CQ`=Dz܃9$-544H=crG%/Hà8HC3B*œd]c(09:C2PB'LC=+#%/0>G³IC郌%3\zB'4CvéJ;$ā(BC.(sOr*-mhe4ц˃,7>% 8ua ef898% M|x֣7ϓ#>LnTu V'ANHW]9??Vȹ6!N})6CA%:+d+w9\irˑ%/4C3%?x%ti?*=7,^Ndڤ{!\S 2+3\ȣ(= &> #C4e А9<)H < lpb , ê5]yUUzZ4$-n$ e10$ ̰S<R0{rZXI06e\cQ-6lͶM rL;dzw } ;PH${tH3xQC $& *@% U yUF(,:9dJj],G, ڵf_uDP:DK:y&–E̓p<ٽTXk/#(9LҸ.`ČBN!}m:6o5$/w[sOt݇h3#4npN pHHG8@PuIC&ɑP9Y(dG**dW+f\e֘a\NYMqhRt/Hf̰\jήhi%KC[mȣ| :K{dh/{]'Q)*RbP"UP~ALes`Wf ܅v=KKU)&>)`Zete d X늬A Zf KlFl,!]z3œ6: )Siz6^L:q31c=!B.I<9y>8G! DGi9ʤI|@P5\ dr Q1݄Bɾ9G|tP%Y 쐎aԒOO,4IX:c%-='7I LN2 C!ΘrS]ssT;%6IH!dn$H,9aNrk觐&$ *SKqd@bJ<6*Ŋ,DYUe6'jToǘfUvU]J(h;Iey"z&s&Pn)h'59m1UFܸUBquZdԗ_чTrӼVkf} ܀#`\oV%qH` > \)IN)߉hŤtHƕqHUX&yo0#X&!SHT#51Mi9D58BX"HF%|]%DԲ#5|yjU5g?6,sW=@K%! b(//‹&0OTA(f`20+6âǝsơ\R2$P` Q"MdtH60'!PZl"I98YO@SD{.&?W"m.rI0߷>MSC\c?=2P06TƀsKW7& bq kH\NEzF0Ja^b#%aX[D R.,;RJC= CfIK {ea&rnrcD`g}qa>EY"SAH4qyc.s"X>U͞@I,x@ZetHY%p tnZUFPƆlM= C/PTB*cL #)D)RX !'JV9ta-ꞐWu$ЮixR <1\$hV ;y z[xOW!p/| `j#Xb}l_TzR QbȼphcP(Ru(ZmIۢd H؂yդ@9a!9 X蒥&X 7,iWQb%0gM<5]桗~f/AtmZ/CT`B}1J \gʤ3CSS2{N1ZŨUNNG Juø"Zb}xNo"BKJ4=q7Dvl'Ҩ ;bVb"=j''PS2`xKr0aQ|0>J17JLQb s@DoψF"JBhZG MH"ZOҌE*;dD8~Ҩת7Ǻ%E/P}ƈ^66JV&*׀{dNTb~X&NTX,?ŊLmI)da16 HT&Vݒ$4iޤOp'%'N? ,4 e0>a 2̀?aiIzX !Gm1Sn'zTL.NQA'`(䰗VB~al"^D<ȼȨ8p# ! 5` #"8`' ;fT[7$ZUa@ @ P A,2HB1B ov 0 p3Toג-C1C4v<5.2JЅ]|M`Pw&рpP`H f/i//kg!k v0E?M p 0?qP+MH 4+[[ H$O[l` ڀ 'mNuZIj @ JGIS5R'VMI/fi;^&k.w 0J`^wĠʀ{ Pa%((@ v` RT7,ku_ 3)0kc0 Ҡ L " sĐ*T{ V #O@ / /@  `TzrBdTi^ ` 1ByO*h…T<|-;% VuQ` (Ts O`F` K@ c'@ tNƆvSw^%a# @"#*" "&T"11K^$/+"@ 00 [ Ͱfs"%,zVp bP4QC[@DtaE45 p_L'(R2sX*sp`"B1o,T"F9I^Un *z P z 2@ @ [8Z@ g -qO7*3UNc|j` V`@ JVw0 0 &k2]I o J J+@@ZQqoSp;B^v>w00e0 *t8 .⡝$A @W J; 0_@"`" fG[2 ;!\K01Vj@pPaPXCllY _ÔQ j' _ Ұ`P FXq8Zp  lx[ c0R'0 @s nS,϶Bnr"p  P pP p p R0 lX%T2K:  si-`U{91j.M%@f Vv{ ?A  Ds oA @ڐ pewXap PÖZ j10e!2B!!0{ȋl2 1;ZgI0n) P P upp Ѐ p  [g T*0f. f bw `@ ;454U jk  ̠ ypW)ȫ p [| @>@(+p @ 0ey?R&1  ?  ۪>U&O0т/"PWP;t\u0P 0 P/0oH il & Mh!` Ҡ $h Y {L-ְSPS NB1"6Y _6 ߐTp 0 Yv1e7AQ8Y ` \V@} [%0P"PгƟ 㰽 P 0 p:pp _  q@ p50 h m@g`݄  , ? -#Ũ eA\DcՕt%j}` `WAh"plv;< , (4(S! YQriD ^ {HiVPx[k@` o}# j#Z Pŀ ]@@ P` ܢ 檠 °-@avk0t@pxn[m S Ê oWwQT'J0DXTj}x İ -ϐ0`(F` 8!u)F[ C  npF p-^ ِ u` 0 @ Ȑ ~g`'ok@ {L ` `V`  p `l` ` ` oM\O Ѡ ʳJq j]mJ AM @7w=צݸ -q08R* Su)| %k' ` VPF>V `PUP> _ Ő pm,` 0@^~ P `t`v&aխPb_rq`0kpJ !2S4nUsݑ#_D5wԨ@,F:Jۗ G,r(;e8¢eJdm~QrDQRGMRBڴ)BxjS'JZD韥Nd)ujPIr*jx7oZ|'1 y6AؚwWV֬9sΚ{\2-lSE)~LI45ୋR˜4'=}kO 9"6H9z! 1~2iXgG~rZb [.hCF*g~܉‰~pē4䟴,"$1%湫}|~ه0>Ŋ2{f0D~9"馜bArT@c矻GD}9ye!f+s%kqg.9v/`%BrWe5V-&`b1Bh#5*A$"&"OZI'9ZbxAĆxP1 WHi adltQpmi1~JMD$IMB ~>D'M^Ї|^Y~Y{qgSx {,Hm -'b,A5z}Qg"D .BYx$r ְÎ4gX켘d9ym uX5HX9(!&0B0 I掍 $(Kw$kx!uPwkX!.qcR@bawYa-A꟦H!v@r~h9^d䬰"BTRƮw'GeTREG-Qjt(`74U343q|05 ?za=Fw4 e! O)x;^`E: C"F"1QЪ|``CsC ~ 8 p+(.'X' 6Ԡ)/w,X +B?q<$)#V q`#b=,[D$1$?H&, q VG/HUbPFrh H68h'FEc /am#/?ԡph99G>ᏺ ߑu#9Ue [gP,!rXcʈaרAA`Q,`(H 8U+!H q|c7t\ 77Q0:uk.l2%7pYBӐksxh؆4V1uKBnq,B W[18|(i0;5IX4&8~`ba>}h9`ChA fk`x UysF FX4i^Ї;hSm!|ȁ./(s+Vf`I8X$HT8\F^0UEw {{8qbXNeP$@ \BCG9RhRP_R\-Ѕ<|2EO@~KDq;Cm&,KoBc<p7I/C1~Hh;p7ಂ.Y}(-O~Sh602XBh~Pxhb_XG`yu )H.DHx/( ('@oi7HF{XvNk8!(f{hҜG;^krP[x-qXzS !+ #+ІS_J01gnzmzK@ ۦZ8۰<:~XLĠ8I>pB3kph:(%6JH^0ą@bQz0P{h6H9muEϋ{WH(al8 HɄ`x؇hhLǴ@hD%pNЇu|I(xPPo^ok@FDk~M0%.y7EeT x8I}֫TcaJC,=]2R: ۸;uyCp~5(9;kI z:8@;hk`mhwRM\YAJ*%6 }db0IT#z}rrr0$.~'} 5UX6-`}0C`HX@uH.YShtMx ^ L DbGI8ЉkW`H$8H2p ZTKc:,]4 xODUdZLOϞlCh[(V2Mx3{$5480q&VǵhPMpM.}Ї&}pe'X(ISws@% Y%fmwE`ЀetMR*z%`[Hp 5Lh0(H(( .m)^շ.Z~kaFfC0 0C>8YAJ:QF;fö{ p5&?w=yh_ мvNCsDs kQ^W4@XSEx-DAP00R9Gy׀CM spx-{0  Zp8r@tC=IL5~ `_f_x`fav `kcU<@ZB{g~wN\;X=E,bH lB Eբ?h$E)$ 4I+ &,2Y?Ï0@DJSlc-@~r<4G'vO?kUWdUVaA:Em<%t(7MS[PGAr"!Pҋ9gYƏSLa+cO:-ϔi4q&nգ5Te Kӡ65#,J "!8rO!فKS ̳#sB&X)oB?8Q*zp%qҏ_4S2\>?BlAS_*'?ctQEeT-bR!0X| PDȓ <6l*Rjx)L3۬S>lBŏjXAs;)`XDJt1;sS';ߤ-< -D?S){h`š$0-ZN,M #?f |2M&4f=@%x=r%?cPO?D`IC?M`}SQ D I@yVr>L0ԽBx}"[H pǤq BA}g桌5 ep KBP(c;ģ)b"R0hG0JxЀŇ`4CՇQiG2t!)A $̀_8zcos̀ HNt XcR+`A (`pϰ>Td?C,Bf0QAAڀ6G&q ` b'b8䎃|~@ rPCģxc) 3Hb>K0(,HtapAX ;́(HUҸ a0A @C1~q F)̱280.EeA 94F>ML,A %P*ÿy3 ZA48 7#,(*q *LЈbM (zR> |p@|CC R"#v r^=:!aH9@2`aUA; "5?@!Đ! ; A ESdM6ǥ20~8@ яU> G4]x;[@@̱PHA< 2g}mX^!< C70)`r'uQ z= ־ñifW wpDf DYF"=(*G4!0-udX)` ~h+H\ )_8C?H Ӛ6* ԦvuT=CA;zSbܣC@=?Cpp!,iЊV^Gpq#fXq 3z5/9D KTWf?1lRXbx5#!@"rËrm C]^>SvcSD 0\Z 0C^=d|`E+cT5-m_H)ېJ-{A 0H0Lp\ S#(`(4&R,H?X ^L :X`%`X$0C !, deL"P%$".XC>؂i(D@e G&$>Ԥ[C;;@?()`"&F) )0;8?|C*A**ϋ?$E2LJ #({ H3b 62,CLC=!#I2DC4*@$B49jC?XL'>?4 ;ߔt``S ?C 8+&De]M@ [*xԃ48B'4D"\ D!OzYJp ,C+dÜvx_(dS<8 { ){EQBbȎCt$BD1WWza׈ AyU`,x<'X, H?DC!X"C4BnQeДL5C?%YZA#9ݜ-AU!D&;B`#" m" 69?0/Yx@0C/ ќ;,@$|'xdC>CZCD_E@?tgw ClT(U_/$9@1098)DC.O-OW% l{_J J{U<?.PB B!?ȃC3B*v|j(?&j0=Nh0W6TK+HȁĎCHi$,@{?4A(ؙȂ>PNQO9EW-MQB:CD>4:+<)M/)9.-R/B ? xF $;|=h-"TF"t9C@e8B?C, fud2<;jOF@8A@ohHC?­B$@ ? p/BAZ!~4M?pl  @tkey7( YVB'hXف9CXpX!1,|;>܃-Ёb?H?,8P!)9h@/pA$D@Jd*wZJ\ UF 9Ԁ?BP[B !x'|@!;Af@ GGpq j2|"-7OUX 8ރ,)V۱1;lZvXjY T.C"2B!, &>~r4U\C ,AmC X>nd@n3Í"цPe<;B/C=@|:<S>6)x>Û@$\>|"+("^DC&A EX6*+2DX6:kZ+|C<;x3҂!@D'$C;,b=Cu K@hiB,L;C' qHC4V%B0(%7T_3&P(F0H8М);>9v'p)p" D3dI\=--,|bVsnWyC>@S4sgO\Aras@+^TF)As"l@c;yF˗sGd@$ J 2t@ 2(PK.e#A\uŪSWNo?os,KRһדG8Ǝȁ!9q"#$)șwiՌWC)3D@ J)2k)A*‹ifG iuJګF L2J:J,0O:$\V)lBsz$P $L,1O0ѓQd#E2c\J.=MMwĮO%D\8y'|2.Eۯ@XQPHZw DdCJ)PBJWU/G4!F^Kgs9,EJDS13R14%4Xa\SSLrxW$=LW"2᥉&3n÷7Aݑo9Y飏BF-@F2ZTHa\? /V"AVs%*13w5aj6 23Ra x̔!͈%KcCD138.)8% }sJ~vPPFRmMBYIuzU+o(UV7AH)W d V]'Xr)CBeE`Q*1hf5cb,K@PUf)Vj Ko3p?ƵVM+E2Q&kOf/^ Lgc&0(d@+OI Ee:CQ8J#R\i>Wyꉡs\YJ@HrE3Ën'52Y(a<~xI+c@˽Vr,mRא6Gl0KR]=\8n;#=1x[{&67rRl{1aZTШH N;tJtWb!J+ (k=ʋ ߬rgH4`FQRj&8L%fNa39bmTb) n.\]s\TuxM*&k"H2TD&RtЁmP fbT{㛥 \U,qHr* BPt} d#ȂWhAJ8u]a-,L^TNMH֕ӛ+M2RhD̋iendQωj}ܥ1DMQcq[IjRCuCHNdg\RРX)+n*iO۳BR D$39Bqw i6W 01NYgeFsgpa^}_LJr# ! , VAyD("D H"JGdcD^|P C <$HpB[B6[xΛlU3 ѣr$T9Oܙ#:(P jVCaBkQ!Fpuϑ%(9қ߿;)NBIqQ?&oPFY֜gVFʿ O.9KcGr⿋i67OdyIPfNt4*jn)SI#_>w~BaU+Ű_׮}6lYPd k#$H%YbۃD蠄}uBI'x`td ffYdXdx)8+lA[dBBDEFi8Pk&FO܍AAB2MOHGSOlQ %bVQwr”{gXBXHY{gm(h\q%! ^ %h2&fa_Rabe]")aFx*2Ք\L tm+$2"$o֫&qH ܏ q.dN?yYNAqY&N[hGvaSl$R1TAEsd%'|2~#H"8WafI1!:*b>&bꃤB LF ͆mDFD=w26$eP&cdnN.\;״W:^h!Q=DEvxwI.PIT^iWWHg(\˶g;0_ Exc*<*vhex,%q;-b~.eo.9 2HiS4JҖ. vY@NtMP)T"٩]Z.Nj˞ѧ@K%. *bJ|$7N1K*N-qRB62V!zR4Jd2#rRp## &Iϔ#P 'JSCO6)CVpv {"'?KlkX-;,[[61B/#W-1/h^(!BRQePhFC* .0EV%9Mq(lf;@5n#T`C+TɌVj(dw#ײMnhI˾}~N4 HFT#*ϰ,&;Ȭ)FYOBɜ!he-ymRJډoÓ؆UUь2\hULP6)]xduݕ?`K#ƛWnDt<CQTcB- +9>IN`H|xފx( Xd 5@!kAk, LnwƈV|K!m0?: tJPb-0+W1]N'@eJ͹Qj $CB:s )#Mud#Y 'v/T[Ƽ:E%? $:  ЀFYP~KaW&EN cթ510.T ۘa4,S!UY bu Q6-lJFBЦb<쬉mi E Rӎє, u rG; 4ыScK!2p_!N ‡Arj)͚*>aaamXLgEHLSG !&F"l!ZIBfrs %UP7ivDSGL!b6x,AhAD sX=AX*L{45{e_6|A PK$ y!_y>% C S>,5*L1Akftvf`=TDU2z$+2*v`@ sHg:qA"4BC5&&\".^%` [gs BG ~Wk6{DC6uQpDDL7NFy @ RW4Y*Ҥ883zNDZ3G ap  01sbFq",41ኆ-6!;9́O|;(n'OXL  `]` |Gسc@6^}=Bv r(!LQ(~ 0 @ 3S[eesz*PlfvV`aP =2M F'% JG#;gD4543Uٱ 0\Q@`P0  [H s` @T@ ӳ'tQ 7Ѡ  puq x~!)HKXD ! '  *w"" R17`1aXsY  / {0=ёTr3t @T@>S;@aё%6OֲHx q@0}}VSqv qGG@ ~߀IѰB` @ Pc| J)@fq6{DKy}i"R Y(g"y8 Z{{6rS PP@/ 0 ۴MFb30 v@p%R]?A3Hj`   h` o0'Pv& K0g5 r  ] A5 gCP 4dPt}5RFR(җ3 ` l3e0 3 E?8R P@ pp " 쀑  1F1Wt23Tm{%ĥA":HF#4Qp0}e` S  .1I}@ gpvS ѰԸ@ 6&8 Ws 7>x(qLY/XY14[l.N truP ؠ uP`D @ "KNSZFSgvPO2R-;| &W5ar-d  0ӇV &s0X 'c XX p8 pJ(RQo4  K (t>v3!B8s c& z 1_#C<  P P P X" R / PӐ 7;:߰ @Bp ڠ  2Ah{;`` e"BqHj i ePsp 0r0pp   dhH)PDbcA(H; *#e RK R2yL !, 1ZR5rAnP P@ p` \ `/Š s1пop`0p P%  0`b&ѠTp q*6Zai0 6P~@pcL 7 ;v B B+C0#!vDy )qWy ~{ v0ؖz* JOJ P`P W "PG ` p f20 `_ V 0 p%^p`   `I0Q;?#b&pPx p &ƃ.,tVk&Y!` İi'g<ۥoZ A+T𠎠L$rwqƤA R+p VP Em0 8gY P M u\ $- )- MR`΀5@mm@m @P{a `k@` [H 6` ,&л X<K-+$]^s'\C16"^ oܬqp6 | +, K`bLX"ysA_ohk }SeP 䰅C-Ë1!Wo|u@] ȾP p P v~ @:@4nt ~Jߠt}Ā; {J P`~զsP4: VRQV5<}J'w@ _oE[k(f tۈ1Ŋ 5G$E ( 3 v[0`Ci @PiPaV` `LYα^_Pِ +"P ! 絰@f0 }Jvg`0ޯ ` y% 0 i  m`Jp#o``q eO.O. e_iv Z,/;|?o S ` q دx/qWp` x"a!Kypig  oPm X`` `pS~hNaWPP00P P oN q^ 窀 p/rupP` Spt` k-`FI5tM .ʔ S+{W\h5KHΝ@rs9$)Y(Н9}'N2>elX1c'oHo?F9Šҩ^Ҵ1cUtjF?Kj-uj-)O4QSNIՏ߾~Ǐg?+[W~mKEh/^qQNb08اbu{6bm̗ZSEoala 4V;vYҖ巰Gދ^T.:`$矶}6Hc "MyYG^ސPIIP:I)%4'!٬uPQZ1XbPVF~$+Jh} Iw@axz'J4P+N鄒F&'rtyǞx%ȱb [^fݡ<6v*mrZ `Io,~qGq1~0D4BE{-F+;5CP9g2G5Y5p9B{!$ +ĝ{`)xSq!gM9dr'brǞ`!F@!ZahKXpaϠE˗>ܲKOBNz .#7^q,sHTNYfYi{% jCrTcSzQGcA~IE5 a\RaD; %ְ5g\(ɛNDcC 6g@ˈհiAqG)"oΩ^qSC:f'baFy#9 d_٣XA^ P@)-b7 ~Tˑ)euI9Pfkl+J"R'tGX`S??e PG+VAU { `6GY PTժa c@c1fq3 Ai ?#bq{iϠ L=ucc# Xh@ p0(D WC4+ ,|ܣ +@J B4qHx܃3=VVh ( vij%L䉷bhY@HP1> b;Yiri^[ ~ ޡ$xAtcVG4ChN;4D?Fb7zcs$͙ 0B R"P N6zb`#ƊFWWW \jB}K\Ԓ2.$/?R\~W*{ 0C`.AP*\Bd?0 (>7ۀ* CPV4D4 T(X"P[<|3 q(ws\ΑsẒð6`D\/bN)<<+CI,F@AFlD><3혹@69}ؕʑ/yҀ?wMh>H}X2bf \%o{HXF= wHymTkFk@$(`px}0\r,0M(@KsXxM8Mi袦1~Ȅ[j9rp{.; #!DxW0` ~І pTpSp(ԅ:p(!Ѹʑ-LpWhD-5PLJ>p/AHX.ZiPX`JB[uxg/02؇J0}kX5`zwp4   t6^ +Ryp[H0yƔ)8- f915k'p% DHDD' b7 T7؁T2@`4^01 1! h 0%xLV qHaR0G8_X3'0U@|UcPU@Ш`D<99P(Ҩ60e y8Mȣm5KC wXiPFkȈ_Xd8({$7rPGt0%5q*RӤR,M#pvȪ* E7$8-mІ@.`@'HTT3H}ZTwԔ V7Uo[ _ x_@a:ZZ0U[ې>P<#DsHj~(~AIR,EG5SІ_8&(4чv8( ;k36]@_  wP8 q 1c+-(yp=7eE~@1M+z| wxeȄBFh;2؃.'@Nw[ zJ`^Fx)UaaEc`U8J3FDU6h#4J; T`ЇAPOh7f{3y(h 8/85x{wx(肧.;yMxw@'hQ/n>:0y>1M*XH{(}?GC8k `^9́}[8vk'/0jmt8@Sށ0 S8XIXZeeHGh Y5Kx[Nf[<4fP#~X2r\BĔRtyhWwE{x:0=.|?^!C i`` @q.8AkۃLIW mGwhۂje@{*Zw؇z}kS.i&ӊS2dڇtHe\hs Q[P0+Ru088hxH\`MXVA R؅Ga.켥flYUIF"77!6hud$Sk 6S.Aw!02p/z; *hekoهk BHh84k2ߦ4^zm4p=`㓆oІpX,|A/*XyCtbqh){8`T8RORfx\蒼~@'&i.1u^E+H Ryd]xb FMm8V # UP~kfGffeevQ>r4 P(j ofiLxy~HWIiwxEH#^( #2yxgJI0TBPWfH$!xq8FbO( K IyWH9H)+D`9kW.?z:8ꇭ89~W8qE  R(N $K"Ejժ`jՊJ5jب'⑪:U5[8keΜDM„i>hdB  H `3;CH9R<5[W?^H[FΦ}ʬ;L0k .5y \yIܵWP2 'XhC (dȐ>HA9 b{5)Th9bܹ#GWZ/,~':p4py4fKa?s '-^B%#WCJ`<@ذIdKJ( KBlL#PBJ4 JQGab$:1SQI08 V %^xA;vM24G*svO:kX`earE:H |p &#)0[ Lh=LK.0!tB D>PB0# / 3 #ѭӅAAu0pRyx9d$ QpN' 8TD- '8")?)D.CESpؔ(Na2QK&|lA= ;8H \@O@b?X*(ӆkL1sa8EJ߶s75?0B ((A/2!3ϥ#,l:C # PAs_0XΥ8 *-#xN3h`'P6 %bgO-pJ qHÏH ){ K*‰0` E#(ʼ.S Ԋ 3M2Ï7<q(rFS1E\@m  GhmcІтi%(AmfD:LHG Zx[2BXu@* Jhc) 'Cي;0-Hc X'@?J # G X@~m2pA'#\h*4vDp CPļE78/BT {C^`!~}c!i&G0w,X(C=5'I V&,! #2{CASFP`G{#!TA eN @Bz8W1>2NV*A~("O4}Ї4Lo? qCG?3e\cÉzQq"] JRb;8! 0 C(rJ#&@HE"Oz U%Yr [?16X%6P`4SCkCL2X ?%< `P,9Yp(` b4Ca7qĆm8JCfbG Bb8gЂdH+@ ؏4Ⰷ?ܑ ؠ { F"%h]P1ȣ"K{Ą=A  ܀ Ep@7Iڪ'$ m =wAȨ` tXC4 YA!XBDa;TvD6rQ Kh?fт@k`7h g!PЎsX!N@ .7 VCt@n;x0c߸>RˏhoA qP98)DԀN8?Axd]*ioJae p105!ҡ Sġ mІTXAL+BPuǁ7,Shc8BV•qS ZЩJAwfJ!TޤpB"F<1VxA}R l@- %2hC(?#.^H͘xA[@(^YA %dB;E2!9.ʀːt |ͦ@x# @"78BvmXN d#P)(Hc)Hyy@"\ ,Tܣ?@͉9?P4??ԃd<*Yܟ;P \=C/h<[` `h@U9? ,1̇p;|Ixء -Ll?ȁdU;xŠ @0AQ?p;rU#U^#>|/Yɘ$! =(_?La477 A,ڏB:8CŁvB' ,W p$D!0CG!1`\XB?B0DLs\uTB"51P4,b0;D>GRA:S/BT)8 )(B3D4 6B* &a ́*?$$<# 2 0 hA@@@.C!EX?C;C0p*N ><+34D?̂@BR- ?#B%B@X3S&\*M 1ph ., )J~8(9 e<'/ Dp)Y!%'4D? R)A +Ȣ>C<9[(C'(c6DH>Xh--3<9\$$A y>B ¡z;dL?X(P 0*hFB,P <],exB9B?AA&(l > 5<âBR:  l23M 4B|@c?8: TT "i#/.^LH9?ځ$Z3`Li:,vgB.1<`X?,fGnB/d@.¡C*́Ɲ>A < @N-* } Ee*B@=\_˹Jh2pV$;EF@ C*Px@&̂9ثAH@hB T P\bk A&Iѹ<(% :wHå1?h?x%PB**0j ŀB4@-98A<A4b;i@4P9}e@ p @@.CH:lKM6N%c610=$@ T4 @?. Y8 ʴX)=w)L;(?\Yrl؀d)@$P @t;8!$ p߶R$(^>C>hCt$*r@vB%\_"xC0A Tp0/e4C~E$A x@0vG[{?)$$ti mii)C/4D*l,& $< | j@Ac$11L^*Cp5*lB&O $C㥒67#4YRXA$؂5>C3Tj'x;AtpGB 8~S!P8 ?o;@C(. u UǓȝ@*(5%%AT+'(-ZCCr&he9 rxh@ ,84ʐbe5B -;No-KK-igq'N>j˂3Û8@ ,@8 Tgg'=(h2ĂdiIAv*ugw23d1AQw(@   @!(6+5A@ ,,)5>܃(B G?؃4J"2t#PB% 'B=9@v@9T< q"ڔ8XQ Q:b>>X+@8pY*9-T*y'x2),$Ct4B%!70L\H?/B{ЙoN]C&8ԃ!zg.hC4X‘XJj %"-=i <(C$x_l?:p,)?CG_bYC3Y'PB"Xzt:%Xot8C8C;C;ā)\)z[&==PD*$<ƚ񄨋-i;&qclBJrR\C/8ϳԼ`% B?<t/h;̩KXmC8kY /PA켑]2:&+Ln#܁ H &B .2B .$Oߺ%B.4/ӵ=ԃ(6S<| 1%Jsz'$@Np ՉS>{×Ov~RxSy`oV ,VUUlȹs ;ȊF?r7#\w,Cw4:g5o2ݪ*ݬK>u[u*UO8c5jC -Fq*TРAg- PhF mh6$4lG Q*T(Cfĵw?'-kG j*8*TNyɒ%OfF?E _FE{^uIQXi8V|Ze`)jVAJ -|Z diMˊHcR)Ô1A:9ACZcTCIC((;; 2 -bcO<-LF"ḿUl+ ( ;dN('Z'NZ:.TB9%P*JO\F!eRRi$XN=u( ©+ P(a*1f )Yq- *Zj+pDkmKHVQAX2ДҲ a$څ7/8A#4SPCӑJ줄J;K EOB!52ɼxSO S!@N]H1wZJkG 1Ŧej:٘CVejMgmY-iQ9j 3/[24R 7Gu0]F 9F(6K\pD;n;LT!L7KH!šSFԕqVMP 6LVVk6V7j+,%&RyGTr)Y,AcL-,MAD !SOG _~;pc[1e)]R CrRTPB *UJD8uL0!ZMhi lW9eEE+U|$kG Dʆ$}e {R!TlbE L`mnC `Eb U)Sml) *C27Ǖjt@?NVb06‘R唭F/@SpՔ+nʅԂX0[زժb02lьP%f01gDs,4 [.${楾axطaگ;|ߘNGmǚi(s Oh-IXA`B%q)T@RAAi u䖦\P2ˆF4QVQ*hzZT|@xaK\C|\ >m?m{EDK}7ٶF2]Fĝ&M&0 =΃ GlaǁQ@] ftd82섏,j|b:BG歖^h7\HVZT3G8.$8JG) a{XDZDR,jC$H[WhQ͙9q{MDM9iŘ~ N"_LyPU#NuUT] bJmiUZ3i򃮓zh!GGr69XNtWq%} "HߋlI{ҙT8;gK&2,?G4Op3 0hš0IhQ?[2WlIVSA[5-%**zHXXO_pI\=RH9JIWg:Xr4{clHDxݲKqM6Lf= Oyζ`rQ٩DCWĶe9pCŦ:PijWX:LЏcuV>$qWGV?xIC`XCml+e5p{aQLԮ6O]9㩧bM r`"RK$ZNё?ʃ*s"+[q~OXSjqV)TcgTBw-Gz67< f{Ol@+Ki q&Q]YLmJB]?O9*5,:-Ob`o4AqM$L"R6$4LFA8TJUr.A8! , V@"I'HHC(DŋE421GK!I#!"\ I-O`eMlm†͖jz e(Qr$'S9w/TV ںР@y5D@d۷uD]wQʷ/%Kz)Q4xPZ_(R" yTe˖O"u*g(4ieiB:bD"kF`suEKF$ț'.[jl9H:mڌ ?o/hO5رIFkh}];H%[ ?cs]ŗ%u^ &`u'Yb8vd!))() )E-n@@(F QuC4hđ@#1[o Pp!$N11r?8OZ uSD)H^TMŕV!w!V %WYo!%ׁxM(آ 6jIbya(&fɣZR'dqvb U*$s P5 .Pk9Do#V+jbqTM[MDMj%NaǗPNafvlnaew9'XfjV!%Hڵnݛ]?&_Ahj2'9fي*gF='JOCP!B%jM -9TcE&%s5\-t<݄StG eTNQ}Pr  &!z] RH0mYr`%v9"`HuI8?' 'xBi(T1&'cggZʹѬJ4䭲r+6WP&\A/ T&^IukWawTVetbVZz_YvՅ7];rp]$`f{c.d&BBDUxӳ86z+V nx5,&"Mbfy%JX S<3ٰ)}VސL%@l1D BPf۾좉-D\(] b19RVf$.$`FUFh "y`Z-sAch& 4k;ֱQ$(%\.*_y{4 {^W8bo_Ys(}z.M`"64Rr PsXE*VUF"ҫ $Uյ8I"Vl$zNHk;Ydy!eSڅ.9*Z7b-KA-aoQ_4 B-ĥ#LqQǩQbR8r/q9;1$aHhp MJV⚄%aٜiYzxCzxS(k*,SBG|PH)ԋpLHI ClyL3&ЊFAlƍf*Ӥ,C\RB y@`:4YHYITNN4qKNSZ,/9޷"𠧮LĆf;4)OY [  2' 7D4bQqЇD#NdAIN]_Fs`E#$AG$$oSȤ9IhQ)XbQַTQ$uJ%,FD` H%$<>L!ۂ,#k8'iTGeM ݒ'Ĕ$MaD2ayİDf7No@rTԴ=;%^ e+ 2)3q=L52QD/"f4S@x3bHlVXI9GeF*ozw %/B΋_zIIYwҥ)jv" V2qPG*vD(`A =Z@>b()|48|iCmJTϔ|(ʰ}RS(f1  r`>BRvQma>ms("7q UTLzl1s 0 YAL,"+{t{\hD2sQQ4HTtO4[H2V\ЂROve"G ca.P2p2/ ৎ YPfO'2u$ \bPBfE͠5isA  7 x0Y4w?8  fmM˒^ʌP0P W_   p  ` +@ J"kxI ` p Os^ "AIUvCcG ` Ю0 c5 <`ѧ &  A pz}b>8 w LUz,Ehs)fbSc6 @& ˷`""1ȅ @P / z P f`0 \ @`H נvҰ ` O}A<SI-]C .;kA yP> p p7` PL=wK^s#FG;pҭFE F,id,Y)'MBӨPْ߼hzb2`}K Sp'(9TXd?uԕd1zǡgA_jnoc#ꈠjG; :هRÛ{{pDPÐX}#g^Yg~9g\-5Z-J $A Jc}G(XHa:S`' DPǐ*SYgzǞuPVqdmNr˭:2$}pMX‹(~ŊtI*^XVRN9F/8l+@ŁbAjY#*ИaVg=,gQ$~'rǎ3bœ/(A$pDvYu e %qYuD 9֙9بr;Pqf!9᲏x~haRh|X 'lax3-aSH f kkSfQ< UMiu81%T< / I52GiZVg{q8 r#o`,j+b7#|xA| 8حg@Ïq  ?JxTF/;@؜WEax( X?hQo Q(9щ*ja[^v;Ѕ~4t!>xRT jpXi(Axh:NCkD _8xKaml{h7 t>7ueOP>pl ](Fi#V~l@*G<n@H3ح ?qE,ń(\! L_O~`>p=ksS&,#1s}#9?q04&L%bӎZƆa-n ڷ$ $]Hя!,fX8 %G b@ x X/aNG giVNv&ɡ)̖8nx &TYp=o9^! [?md?BGBxf @^(j3­ؑ," E`7n C[jF`S3-!gNjrv(i1aфEh+@ `4_*qq@B`qXM  [(< *xa iG2q|C.zk %6܆.H1Js W1fhc bqBˏ}x?(PtIxnxw-o)Bqjv+ж.zbo}1!u`Cx`<2CT s D)v?aoE͈F*YBg? H[9><7Xl8ҭ* Ab`6a x5Q>t`G ሒG3XZk\D3arrKl`sPH X1htSE/!#L|ӢpQpdxy*hJo$=nY| !Mwj!a9P˺RdLZ6ؗ3h6X~64@О; 08ЗzX`MX^Eyyh}^GRH!( ,@!XAePSA@wHX((4Dyi҇Vh@h{0{*{ЄZe6xs^ˍʀy`*X>$R~b~M`pWe邮b{舰ty]@д=LӴrň$uj@@<Lpnc@@Q {N[/ 5؇`Qᵞ`~(0Xw@x`#fOq{Xw 5Y.xD@oiPݨ((! ESY %Fxb G91K{8fVXPȡJ[-o}C}8Q M~PD|{is0T~$8Ȅh Hz0Sp8a9T-`} H>Xla#c@~|/W5L8 |P7x 6HGSBXZ=8A#~P/ʤ c``RU6{xIp$ y@B#*m*=xT 9rx)@HHPp7H'h}8I! GF&iM$BGF!s{`ިr؇H[I%( C{ M`!  (؃`0m.V958H{xY}hwoRp؉KcuPza,]up{:= { SP+c@;}^ac}0J`bPx~@VI 0~wxE"1z%PL}tx?Pbhi%8HH$$ L ~}ȄxTPtM xu`^P~'Wr~؃8MǢTe^E x'3 8Uk^\P4 PNjpqiZU/Q_Qj *7x^@<4\ xh(~8^: m(%Oyd*0}){9 mb+T hekh;r p ii{(=0wRN؁4k/!Ѐ%bP$0!$*(khbGTpvl{ ؓzL5J`MH(+X:eb VT`_@`KJN19c3ZQaF<:_tU>@ПX`Hih{8y(}y{p (%Fȗ5(y`@Px}!@2@E(@.Pmڇ|(K`8ZY[EXPN` `FHwX{7'`ȄXN(20 8-hXt0B~`0'pyzļHw `I Z pé.V/XluYE$WZ8-q[PU௫-5,q9<`0D)3 ¤2; }0[\F`wbhwzZo \HG(P 3M`ր^>PzHxPvL*Ԁ(4>T]yDЂ8_x/!htHpZxw.r؁%989[#X{19&9T 7r4y d]Q[bԕ3/LPc>s]76{؞T1S k8⥃WЇR*M }5~ ~cF!/zЊ!b (&2&y [7C\{ȇypwKH<iЀfnր{J kpLIȁX>HkL`HPZ rK$育8dE%}H %+ps"h-Rh2b-v[phQi4Ȃ X~8 dFx}8}ItGx0Ohx.P&H&5\ha" wLJ.0buPx$` [~ی`B8'H2`H墍p8 }HIKEY=kH(!ЌiaH,!P[fX V鲉x8F\g>cU[pFcXIxMn"*y-*4 gd5؃;8@px%B`+ЇmXFP …v郹yo,,p+heZ WPkY( Puw%gITx@yU@v HZf tlUt [ه$d_&?[&rwf@zQ8b؆`x~yWUPx#:kaٹNIʹ| @Gy76/2hE4x,(4F Љ:H80VWhJТx6xwxh Ҫ8E'2SH( 9r@!H@`RRʫ7-Rl!FR 2dR(Xӷϟ?}@C 2H 2I(ͬY*@>TZLK$>b4?CtTpUhCK?P?*ӈ(BJ?J>;DA8G?K fx L< ـ r-la2jfjvh @>^x4!?N=-csvLa#k^=,qD:l?4= 9HBHH )@?2;,(-M(;:Pb!SO&(C&ŏ>L % "H *B7BL0HC ,XL:4; U4A&p?ק >IJ'͘  %Ap_,kt4c ,34B LChFQD1 LF5c[0d x' EKaT#=G8jh[$ {,S(wE^hR`s0`Ґ qXP0 4  ;\u"G?aCpB( *21Lp#p{+D>q`G тPAZΊ$L+тht`TC kZ.`!'6)ML HliLDl`jFIAn{C3 (F<Gr0 j5lnZCk(MךF2X !Cq=qd`L by1 l2{e G{1LvbJUr fq$P%%(UD DʨGKYJCHE҄&b1r?* `&0&C5…5 a {Nbͥ;0GQ7t1骡,[Z{8H`B#Q4nhpT"y0Y!=]HUSr `DH yÕ]WLR`"*$VmhdW >P*qИ'(_QqP@->  M1ygddȣ: !V%`[1a `t{E &T 7 i<щv+W/a8U30*(9k\0 ;nbYAH)ܑ$w|p1>r1@AՂ1 {=A<\# TRŊxHi V TN&Gc39v - 4 Kd@8Xp (ްѝvb`1~$Y*ap+V&n F̀E,B+`=]q .-0><& g0?ѝgt C?@<>1a4}AaFA+=[]p4cwQ}7(n5+Q^D0!E …) OX D*1~(F/h @nUy`$^;XB'ȱ{#(d< RD#zHæ]G?f~iTWEl,p66'&1(znx~>Yl7f 8?vF_5sXADAJE5CA!'?|]:C; (;715ܕ|?D(8L @6XϽ!>e'%5t@8C=ԃ=Lԃ49tUp>>H9;D 4C=ĀQ((MaI?l7HAY ٍFك0, m\lL#F_l̆'@4C[xiA(\MY$A{zJI}YEAC:dHI=d < @?Z=?X"@LPhC/t:WEH$?$cWq $>9\X4lJX&dB@ h,(<)LHB/lC=06D1,\C+ gIuG!"F3A(r A mܤ4e q5eSmp?B%P/JAC0@ AX 7D5|9C;$?@4,ZBa(^(|d*4|т?$MgDf+BF7$ª# :C0(QB/<ܡ8^'+C*)$ AU C;ᴛ9G^7G$>CդMfI\z Gbqph=t2/#?@:5@8dQ&-CUf*8Iv~G'< <4CyM ΁Fa݄?Bl M#0Pp?\?TA?5XAX0n.ف#>C&H$$1B_@ K? A?C4B@d/*/p@&-PR (9$AA=@@@Wf 4CP@=Iv"*2,(1¤ )*/,ƛϽ"= @F#_10+٨&ċB?t?!34VY{é?C(wQ'4t *0H5d+t T!1@0%`#*/ A2C;X,$Udď P<64/(L;|q 8C:8=7Sgq+gsT2TQ`祜AxC< 8d9tiP. PE Ԁ',>;K&@e"8 0a46Ë"7<>B>xH2?,>v@ $ /^ t5hC0Y;h/͞9 ?̀tAl/)aIu֠uZ- ?p@Xb,@dʥȃ8hT>+kdtX1Z{Wd`+"!P7LkC;|R  P%K , 1;(B ""/tBw*`t<(@$B&4w A k>T Ab;m &#Bj:lBXIaé1(8Ԁ, @&l < AS.<ic +8"?CT /?ǀi @!)%t1Dw<7tdXC>D@hC>X<8dMT@D7)C$,XE<8C! ,@'B(Ѥ,4_dTd /?07<,?,H  C=0׵xK&h xL!>0iLH;L샴ÛZK4Y#(^C@:;?@C) O/5A [@ 8Q3mBA9*g"¸N"#%X)4:8̂h"؂X@JZiI3?~'ScE VGV;E ֝9lQ;,WYOJnHjN^3J6lT>R˩oH1Kn>;Ϟ9CT(>whМΙd̝[nݺsRc_㻃2r>~ĥ$Hy*ĈѠJp#*U'JUrȐ#Kn=ѿDQɜ>Qԋ)O:u)ԨN>yo֨QX"u*=m=IkVV ꎧب%dBA#RGiBaPrPzj%>d*d;hcRt jԒCYc d@q. 2JFđ@JscOFZzFugmF4=q^HıNN< e6FiziwHtS㔔MѦ{LRe X/@Z^]*"(}JW-$=D@A ǧNr0´pѪ g× }6[0r&); i#R%rݻ1d*##-z{AHs6Fp#` yosOCG$K 8B!f!0q%DGcB ŹMI d>m%6JEh[IOVUۚ\Z1[&ǖ*%f ZYfK?v[iz H"GhJKIC2.5z2A--JC6F.RJ8\HMtc,vNCSO8ebf9K%ӘO EpgL $Y_eyq%%?̱1!j_G{*[Tjl#4.2ɮ@Ok#Vwх!w|x $ 0]yY⠄% B1S%F6#4i%bf&X_3RČ2Ocd&􎆜ҝzӟ5HctD]pVT6Ezh F(z^FԢAmp^>%\x\"$ѥ]{dr+^L#͆(;c'7#l'41%!l׻P$4{R B@)XCT =U\"IDĞaȖ Qjr 0weGҋw-|4ׅ@:):`M<[?&0tb7 %4͓ nPw1k qO,d'v 2yHCA*X@ڐ6Y{+RևN4Ijnb(rxbٶ;4.S ?!k}h5$Gp "/miJLm.Ǜtc`%*s6F=e; Й 2G>)5$Nյ?5.:Bs->%QTK)ɚ޵XS<淂"\ɡܦrS^/LSu;"I!mN J`*AQU|.:6I9x q6PevvO)* eh V‚m,2ЊuFdnKЊ=m-ɳpģ J$y~o97I]n\0 {L "/C4.`1!JuJTpJOcДVٮvhtCփ5;*6 BrGtV3켞(AC4JcHYղedK*fɺQ~u1\?VkK]2I 2/ hoQSTF1jmީyj\~.fڤ>c߅5˙z6uP =rp)Xv`WoG+,KbmpZ= V*,e0EFqӥH&R.-9`MT 6$lt[6N?" HF5 <]WMP֞B)xVk*R7NiQd髶AT%^5?du ME-ޜ!c[/ќra73:NkP`珿^v0dlZIS.{;ʽ*S{P_s=}e&Sc'3;ާH>\4{;|Owp_xqFX:5b "Y^sĘuH5!k\6ڭw  g׃ʡr_WqDV>[$, Hn54Hb 켽%bI\⚄Gn*/P q"p 'F&76x/4^b#tbƮb\#cH:(THioVh"XctZ?ZD$£8+[,B/4ýȦ0jo|j})oj vJ^NLJ._d/`$6GtO0b븼 eL:Z2e4 goC=H?#@P IyJ:. ! , V  Bo! N|h1cG$uތ^s5wWwF꠯^=?@ Dl!UHA(#e#PR׀e_ vҗ%x≄B]2vb :J*46?'N),rYgBq^PHJ1Đp >hDH'5$A 4SMNϱM\FP}G&wykIHSZi5|w7?O ѧZ|RH\tU\Xע4W]Fj(hh'zbBgdfY(|FJ*MBJRIiB҆Qi͆l=$ 1yE@9ӕ0L$^<[^@SM[tB!k&uTT|s e z#mUB%5!`w j(T@dN `UJ/ ^&"Hr"˘2 G -iBHS-+L5yNP5hay:599tҞٲ79!f7m,{޶8 D=h R b11Vdw*XF#V0CHKFGMYY}2VBNUtiPi0Z<0q'iQPüP'-Ȭ2?Ŋ,5X=C,! e #ÿ2;89R L+ܵFR=zBG^uNl M*=m'rxri/AatwUGzN(,įl*KUŀgx+Тa05(.Zd^S(Nq#5b;'8Z1AYe$΅E]y:!I1!"֩n8VAF<197iAZtVMlq.!wQIVrG|iQˀ$I|o]Ębi':թPd1ژ',)Ա19JΰL}aAx5#ԖV-^hO% EF\K~2[KqJ R)ux.\?Au``ه?Cz (e@DGY%A+#(YM4F%X<Ը1dr+b^ZGJb;AARP [6U "ɒYYv4)yF6$(=hD\\kPf<נPg)?a4X9FqK4Fꫨ@#릾ma߀M 5 L#&.ע"VYa)w-%C֕Ld%.ۙJtT cӖ0%vi(J3]5Nwy xC^xb*4;B F<~竏W^*>OfgR'O1f>} fD8Xazj劝I0Zn[A"$kwG}FU"q Va r0~MoJ?Mښ&\cшCfxb6Q\xG?oL{χdEnĀS AYA`Ps:e* p :fR@nt | @M3GP\bBVUW<${قHQ4j5-u]FJZǷ@Pt^6m.r V`0 aQs @~ P/q^8"Ye7 q!) 580f[8 H9uFaT,[0ahā42TP ߰ @ tOU< A{M4UB.@TزT00F]8|@MJϣ` QXV` qj `pP a  Y7B8}A)x `4*Sr!{Z!`#f8!3-f?@,N6#0'  @ VU&t4Pnp2B 9|,.q-.r)s.@ Xi  P`TK@V y/#( 0` (UEp7z7(xYvQ?fS8! %@BG8Z{G>*³ @_ KC PSV*&BP`#MxP%óUHs<s@ 0p@  0`1@UKR 0  6GpB@dLڐ0E]TFt{ !"r !U!C @"jffsqֈ3\[0 /` `p,;sE0 v \_h4sj. _PDK 0i p`  p '(y@ P) VdYA\tY1e6 hts ?"G& EwSr@ pЧy$ߠ%Y ` C  D]Zo<1&t {w* @`R  `@s h}0 : aEcXqt salx8e l+{(!Bl8s!Xt @ ""J"MN 0P/ `G / P; *}J `+d^PPx| a@ -I<6.lUӛṭ nwv o&wP{ʰъ tqPco7QP 0 0 @@ Y?~FGsFQ  + + 9kts540 д p*`` p & ްЙ%3Qbq Pc ik{%QQg4"C aoISiN-u]hz U `5 `Q0 @ѰR tq ;G 5F`@F pSat 1eB`b6N` 3 ~  ~s+  D~z2 PȪp 2@@  ^l怑up(&Z K p"42mPXP =EwRj_ ngp  p # ,+<+] 02d s(GrD` @ @ `9p`̀ ZZ?w /@0"p| "  π `ȅ 3Mf)P` ʠ ` *࿽`a` p} |7.v7$Ql V8 ;V=t"Sd!bSL q{2p )  ~x{p T  0w |!sA2yeg?0``J`` ~aJ! p `xɀG%61P0Ч ȵp :0 »\1tlhXّ5)ȉd Œ> <+Yb=ɇWwL EG~ m+UcuY9 ?~q-xA1QrLհ3A"cծq >b0 =`!Mn g5C?#|c:ay,eG-6tiB@<} 29(&h$hCto fСd3x {h(A!Q Dp dRHF8y; faE*@RbI`ˇa#X :`wC-?^ w@_9!;C0G1`ظ(`FQ2D QBȸ$01=j4q`)gl8͙;D0ΰ~gJ o"\w |#O= !aQ1aC-G H8!plKQFTC]Q A0& Iw<(,3QZPOHV(h~ÊCֆ7d AB3-& _]X87ȫbx <G`{Whp:e p{p6!ь#fR!\+T)'{`F/H!A;$,#1؄+qx8%~X% x} {xmF(`(-?'%ױoh|X%_cTyR`M0Dp \F[\Ї7p:ZaFT瘓} % ?t}D!=b cgp{( ҥ]kBh8G9a:YC:,x_X9T~88`(A$@\'PCuS27 Xy8wT@erhwӇ^uhhke[s; Ws1}t35}p+:b<L؁ r+'e`%X4  iV,܇MC'o}8}،@ _ZPQQ85mRW<a]iІ^9: ݰHx9fij(+;MhfH*w $(L&k_kh}:^bo(shp HF@*xTs -hgrxfP}HcusU9s=h`pWL[p-txt@" hhV1iXOV@9a@ -Z 4́|Ә==,\8PmA`$"x9kPfhm@zX$2xz`S@PRGs([%@@9P1 ȄwP{t؁@]qb/T`?c K (Q) ~0w} HЀ 8f0\w3m^D`^x==7#DwȉM#x$w`L-8 f(/{(Y_HH,z͸ݦS5_)>ph H˗Ųy;á?v;4s 0Ї%Qߢ(G0&w'D^H8]Y ~(?gK`qu(rbBN]هY'p*˪ЄiX6~`X8`c^z8pZԝPH4^@{XقrH~KH _fYUH8:ߘu70PRHAh 0oЍ509mpS2wX!{^%{ #r#R' Lp:l؁b[A8C5Ms!b>hЀx (H?ᡅt u#~ΞbxNVxPSuHHk'8~fwqgc~aVR}|(q`\yxZXSиm.cYWSLV8R.~KiHNسy0z.bsP TI582{tPx}H]~؄"-A*Ll!RbxCUTvg*2dZQ u=ȝhplTru}ptP(s_ b ucP@h`pӋ2vxx5\JU`^LqHb|WpdU`ZHSo,国Ytu<@FزASH xx(OP8B J\#_`mHo.&Sf2X&( 9iSHI'8TkH'H#x#8PS}T`pvhy!=2 ؎OT@"YE{cfXE8HV2,` U넋~86EP[؅FPuYUo_/_L40p᠎%ytIܐLxhtFȢAXj(P Hntw cp(==7  )ᡄUHi8,2=yp@؁Mk@XWTrp$#\Hymh};F@c(ջXt\S8Z`I/NU~0uoomL|! 9'C[h3鴑$?B Is~ڙOY5eXoIPsN4;0E4hĆ8 +Z#E=rk1Cb$#Jų=wh1q~5ۗT&[`wډ$qʑrCetϟX*ԨQGW=[!{# ҫH1jSZZŲ?oƏ_>yQUKTj/z>ɒ!G`lx0tD!taJb5!(EkbAGgNCHq5c?1>QdTh*QUN0bH $?PeY5 PB /cOx h3482 . xqe{jB]ցe!̰,1 )6)"HO?DJ9НJ*Q .d=@/pw<0A|(+b"PD\_n  , OvHNL!4lN+KMrW=LC 1B4ҘS #p1!r4CdrO(%BI!$ˆ8M:X Q`֧!"?-$1"ivJ?-?Zr4 8 ,R,ԥŠu,'$"p" '/޳xn+{@| _*1%A?r .Ӵ3=9$+v1NGa]VxI?H %wFsP .LR!PB5¥ ,-rp@,BY!HIX Ѓk Dhk ?'-װ/֑ K^#3l eH5`@BX@? ZPb|} B O"2!J0TG#LH*N }wp # }x%G Ȑ T dx.o0" >aRjD!yC"48='ڐF Wy@.PaoX(gQGp:Y\L&Ј15QYl"=l?a}8яS4Ѱ;pMS*  aW881wbz Gh6q"0DpXa`/ <ă.?xc39HMm#@2 ZF g3Kb:ȑ iyp0c{~DK؁ Sв?z48 q@9I0h)X8VHi# ~` I#&t ZЪ)Ma nCa <Tb$h j;OrPE!+d J6#иGB  B0,!1P#h>bX2 F&Yhp2"q8ǡ bN~ !# s̯W@+B>9܉P+z8}#oTH XαN)xL8h&  aHNX7`A\ i#g:b 1Vcxp$6 g "G<9ܡ DGicC ^qs(x F xBs?X`(3)X?q1̀Poј?^ ,1(2C= ?x"?Bxms/=C/00*).?ȋ^==8C&""(" .DAl H#4l B;XZTZC3pL&8h@hM(CA)( ,9C<3p (:P#5:샣C2O`(0(CV%a9 E$XN<&a6܃2|9[ َ84.5@ ?$C_p|: XƠ ?K0yI?dtA@6C%̂>|Y<%@@ieiŀ hq<]܅4*hk)d(`(32C?sBGYQ*C/G(LCC!.=Bg`'yD8D=C 43 Z ]CFB0\`: qCp#;؀̵C=t#8G1C>CX?M%ΑC;H8h4L6?1؃hCAEJ^]0)?HQu  PcA^U5 4 @ ` a  @h#?H0B>XAUd؋$DUq[*C:L4?xR+|CL|9L8>(?DL=l 2|Z$a (7e4>Q4C3< I=4lxP#$#pP'4Z0@@h>C DV i?CPn_7L )?ҢɆ4 @:$)(&t`bvc`'8,@]ee"D<L'@ $V>XiA`A(9h7 :R2p sb$',?C4Ht6 1qIB=C38 P0C 6g @ l̯AYyB;u|C?TC0@de"p5HC/B*|CPYB%`Ghe00@ &܎Ռ6l?`26B&)C?t (ԃnsD(H~XUB;Ckȼ*" "[lx\B.$];xCQ?`-><6\U%!)oC;U2J PA&Z=ӃW-2•d-؀?(V0*xB"l @̅V>eh%7\@m\eiVTpx9=A<8hCt*+$A +p?>XC=DjXBdeV ,C;lC%@9 6 S;8$.lc+: @hpKBdއe%,l T߉ ip>8U#A(FL!/Pvۇa4CUo$d DB&l$D ,Ad(%Gm]Jul`*NFBw|  llc@Ȃ>XBq#dIB,xOc&5^q(ܐKAÌ,X-@ް=4?XP6h//DA& ]eTFBCYPz'xjΎ$@\w*C4̀OC:,?I)-OPp~ʯ+ ,n6@J?ʐ{[:& :wY|v<ă9;<߈7|A(8 8$o_x-LCM G^2!+28\:C3):#( 7L,B3dʒ"xSDt&DZ:1 wl*Dç=C ؂ïz*2к%_=֏B3q>"}oB׫+@L00Y<&td0,xB\8B%xշ?SB%к\Zqx1HP'?@tI`*bOp2 2 nLMӚG, e\z\Hi͒ou+R,qHS55[sN0s.9Gw#RVɥh%Vr>Ί,Ԉ)? C* O-K3,D\}cAfD[}4F{FAzCN4^7(9u$KtGQ5;Dtd/̀N} PDfO$qy)`ae]jCH7ɿ*o*􉧕3&U)꧝~*ļje y;uYYڐ^h+И HfzÑjӰ7,vĒK4NHQ"^Nl3n G%RX)dsP<3JZ UP>b`B^M/-Za8+J0 #ff<mE⌱R}4D%7"ć)7f;7/|כ􆾋Ћ[r8&`hY*V! N uS!QFv̥je#ȡR0]> L(W&JhĤH3%8T**X(&Fx/lk2b}YgZE׊/CjܥD!Snʘd j٨GVԕb]-rvixV/:#N0z<5ՠ5_'D0JXMo(&pI7n3*4+i4a^f )S(XbrYfU+F,]͡DN(*GyhdtqZ_$7K 'AsâBx$h*qЇRHD}[*Sm JٖO ^W4rSK<83cŠ='-yf%MZ2RH$%SQ~F\( /R09U1F9auW ɼPF̢g$Af4#( xҲ##MFWE#Y[V$R΍]E?,PSɿɤ=c-VuP-$Tѵc*HU B83DʨvabC&2}d6# FBSJLmiYCk5Hߚ.5!H":Y;GMTB"mNE4Yv5@)J {F*Wkd:BԡLt^@RXrڝF/_M2//c4-C f4 lΔٛzAԶ %$> DF1t8EABNur;NE]W5h5X9vvw,Zx1kf )*dl,h%6>k n~C$\N\'e$^( Jw>WWR!b=L&.KIh'! , V<"P PDb O:bÊiQ"ƈ96|BC"XP0aze67sQFF6; 9r"]w3@iոՐWC zkXC1Z_!e먮]K(YR{Ra )ǡFIE)R3k̙Կ-P@r B!ذ!FyumStI$ de`̗^4| D fP՛祥;l'玜>U ȩzZ QUP Fc Mȫ^g ve%T"W\ƅ`y2%ɅuFɅ=F)qf)B0%DEҌQF ZmC' ģnmLyQrDN)RQBuZqPQ^xUEuU h$~??u)`%#9]{!&!%TH?zd\OBv٤&b)s((!!C?j )$kn[BbO4q8=aLZ(yӒ Ev> b&esٞzbVXqU].! ڥ #zu u^`8^>dL:cJe駬tACRvR nD'_ܭhZj^P"ls,8tX&Ew2yQAtTOe^NC}GTuthɩ}W %# ݯ%-JL?db*xJ /A<+-tl1yF 6Bi$=Dh*h,s)MP]RJmSM5TswW]X`-^XZbiUR Vb%hEɾJ^畾_y+,(%z rfr* *DE΀\Tي"|B&dcAALvNڕv*:;֗ĔiL+ϹR.\I#6i,i c=?c';/PK n9% ~'w p IQmAKAd$ U:\m(  2&[j-aY=yutB/:KNx#= AMY K 1Vvm?g~WjlJ5_ TB)r7t {اwTf ˀ +$AWAD!v|RrAHfdg( O'Ó@aJR3NiQU&5lMrb ZhMn꣐_GeCD1㉅"Rh:3S(AFĎBo؛vd:s#pSr)dȄɒl'%Kh=7'JD%X%!%W!RpLPͰ7fY?'€hzFUEr Ҩr@ O m"fq pt 8,‚K%[͒\ȅ  Ũ `H1 0  R @ ˹B0 렔  a w dmx(|"%ǎR)0w!{CY2)e[t[pKl^Н  -9܃ ڠ *"Qt0 lP.x{8#%;h|Ϣ|l0Н p)Pp` HѠͰ @ _qWE60/ss'U^RC >aRRe_]]x"7e" 'g&F2 D_  S (  @ @ 3Ny  @ P}`u&Ah9OXGw@` ؒ o P&4 jqZ' ]=q p`^7ՖG>HVr%!!e 0RL߰dXFdDf?gdFQHH0_DPPӐ e' P:0 :; ra^@ | Vk`tpOh[t\8A6C-A    T3pHPʠRRI haq@ _A jj ^ аG CzQrRR>( MH  P Y 0 f""?rnӐ"@ `@p ` p p Rp `7S(P*0 ` }`uPU@&i;RS w@ 0 ͐ p ^@ p @ ? @<8+8@8,@Wp tE!ybg䐓lP& @v,aj`PD    | `ɵ ` 1P `ppr. :Z  i!4BTB4E@iPX@ *dHplO"O p < JE9ks 4eRcV1=TB 9 Uh @ @ 1 `i {oF‹نH} XV `⠈@ G(w` zcYP MWb  8m+ @j hj  H=գbR mQ p : @ pq&M}.T! }J+6 ,0-8i @8 :EmwQ ~;B` cz>?qX7"@Y |@ w0aPŅ _vfP a,wpWP 6 p< :`HM"#`Mo$m[’jVa@aP` <Ѫ(j@ VMSP4&6ׁ jN <)@90H q BN<`re!RLR7} @ e0~ ^s8wm% 4P ŀ_ 苾k ÀӔ"` &Eepv`g Z&EAi` t@owDa0~M}4P<c=3` qU-RÇ8VdϿy6%m=~+g?s\Z_'KjI'O( 5j=rYb0PV!+V̙R&3RRZj*6[ϟfs@ŋ8vԡSW[gȌ5L`h| _?Lnm;og.Y}J|5'/f[5G;qw:`@2e?iGh} #'Н;nnu 4h9s3uq -Fϣ9qMC9e}J$Qxqb((0Nr%i$)p'Bhb(^'+(V+bxGOԈf)l{j20z @h3xAx"G5h6X3X6ڂ /qNJZ+ -{ygty'o^!摤(bؐ9=0`8gJÐAxIk!V(WxHbyҺ'ǐ+ќC*i@ S4rPr3 B'vꄔ 8f~Y}P~^Š~HGRi-m֑}gg䒫u̍q斚[ČnS?A&.a3cfaCP\@ m|k? A{ S9l ƶBCp@+w#hW$TE&8(n,` v(Ӑ#;#*1icD p.CU]pc%z2 x]:" QqCD$(L.)"ED7n<~!=q}K&!PhY)<~GX/?Z! ) R\FqLi[?PqJ*ǺeZԁ ụgUK?A L Jk7\BhhC.,Tk(Fp,*C[DҠ,T;Uß 5Úԙup} BTCA# )A?1~#Iڰ+nR GH?Ęэ B2Ѓ#X"vrMUP  @q8%HpOah‚-ajhf3 "TuɶJ] $s~ՏeĐF<桏4a'_!O؂{4k!-pJDPYHCqa Gv{@-  '`Pܣ <~cĀŀqQϱX+Ȣ#:^ZШ4jjHv#-bND^9.c$p)|J#+l$Ć@,4!-}bZZqPT.$Jn1(!CK8u !Aj C2T PC=ζYsI0j0u~TPЅ`58zNK8>LALRI,RT1qvBs?0Jy'FҤ\?91Bq")fK:X|)ĜVq , qMZ abd`@I*/,#->dk 1-8P\N'&XJ2,[F`}šW;#6FO76:1 ("8E',[>G9U8B ( dBh L{LcD'h=Z2i qI+OupY0G= `X9 -s8Q& wcg%*$a c :#ԲL ] ^q ~l:u1X(,`;mPiI\(,,-01R>znctkAx{0,k [%XP4X H}xXs ISze(Ȅ}q`f F81҄}`%@r9w0mh4:䂅z(!TRoZP>sM~BI @ۨr2fR`txVQwHzyx~8`Ux-@0 @u8@Wh]P{pE1pO뵻K;6(0(N9OBxCق%P~Г5P~pKoІTȶJ #'HWHvt"N`Bx.Á J ك(MuXAЄPpC\e JpjLJp(Y(_a~ȄZNZ }艠f`o]H~xH6$}% ~?Ї\U|]Vxa 9Nʾ̾k bxl V͝.bYtf*H@;@X ;KS <لW`؄Mw f82肐xxiJ.+p('@k@(阃A8oJ`\N~YȄ.0xJ;YЇJxqȄpSY؇Nh0NxΜp^moe^bpKwSXT8SSȅo( sjNH/V@* {xlzfkc0ƕg K9m\$m"7զi fC05^#:%Bk+6Ԉ }P0@+X%P20p?2/8'8mPPM(xKKXtCh@󳅝ЀրG8<8Y8T~ Lv꟝kH; vbk@ R^hbaZPF#iH׃?kNk .%Ri5Zp lăFgW{V&w zX;g>i *5x7rSK%SHK3AH2y?oC?%I'8.MOTii71m$HH##}O4KМs T`!@@ux؃ hXHTX '~@zSm|a= }L^`Nqhr҆xz f@JfbqRx=j^X`VXp!kTאm`]8{'}llQ* rgK4@~Xry̠)h(R)Fv\ Ls5Xo(0#hb)?pXnj=]ph$IBQ Jy12$#YJ&.=~ṃ!60 ? 3;+s~'PRp<35;֬B! )ttBJ[Bt0;ҏ8B4Ə>h*T:C.x ?W#()Wq)J`$EPl8vZgmz0߰1kБ=pSXa!UJ?x?h/ 9$LXCK #@E?2H'8?!"!${ 9Aoc #س=9Ӱ2dL!!I"-Tāx9DB)(J0v ?5 ;Dӏ;eO??rUWSbiORsN#b#_Nz ,Rcd1YU?Y}@ /@Yd-^xьfvAkVmm!?+G-G s1N +h<ʇ#? kH3DdXs=HZ1?^(̐AIK| %H"hS 9 vt X!(S0)}O|c;H-FSO71ɓ0 @&UKi(!ILh &Pq! EAA.u5G{C6 6jSpʠne X6q&s0 F3BAxc@~0CY(D(cDPAG3C?ZI4αo>j0y(剤A:#IG֕NIeyC쐇X*q+d M@xD IB Q@ .]$.q PI?Qr, ,a-x,!wagiXJ* _گeC'!v xv3`BP p1z `0q /H@yC `3,tPKgth&HBXa%odB K8 ~})HA`-Tc)!N OmS˪8U[>B iN%H.oāI=1h_:z%<`AEЇ.b$nͬ4 "@  p@ Ё x[F (H/sB ' :#Cv]D߁HGk6%(.[{'XA<6dNA$-H"8G+,1 C () A"(L><f.+Y#P{B@=ja v(6+RS!pB*^.`!`?q Ȥ^! S\G7aXwl+`aJ ^ z{< @8cćap"L:Qp<>2 /UC,CRapyTG8$ ՆS0vJA0B+EZ%Ȉ;SgHGCG=ޱrX#A8LV?@Aǽ|E2lÎ !C=x| R!l)qp7Rbta]+X]vHĮ@8P`@ 9n93 coEOZ e C3 ¢fGC Q;LC?XC3(0=I97$(2%xB?PB(|C;C ?)N{$K IQ$> #h?ċqC>C=W=¹(XA` PA$ TCp(4|7+\-+<)|SP.B]AV؏W$fi! $ AO @9bp0boVd=,!B4mC/P $.2A&!&XA\ AaAB?h=Dա  %>D 4V+:PA ,f <4=h*@|?|8B/*C@C& B+$ AD@E YCd6pM"K ?HHO=HDEL-:CE]P(\ 1?CAB;*A 0qZ!D0b88>Tpf38="@@?̂#T#PB&:)<?= C 8U`K$*(;n$38# q!&6C/R'd)BDVx$I*.UK"/qA_"69FQH(l H hP>ʠʃ 8B=TѩA/55?`AH%E<$)t*L=HA>8B_ʚ2B#\3\@؆Yg ̂>3'Pp 9<#R*d%d??$AÅA&CJ 27 p@ OEX3h'n`"yHV ɕeL^9 d*c1ن<  ,X0HZ=FktJM&,e*Ryqgʾ-(e6(OQB0C/G pBP?C,&|CF=*OUh4tei*dfg(@SM   Gjž)HP2&!P-@ >47: ͆× @ P3|/a+h3 5=1CH%9C%*A&@MC" @ S=qKe,[%9;' UCi/1I\88C& 3āGMC(`=63HU>7/3?p.Tp>zXHe6/1+hB()LCJ1,p;6)3*&<:r4'!*)Q~}NHOɁo2-0HC#1X2v'! l0 |hI.Hc u=X,/"8?1WB|llZ>%^ 99q>)YxvB&*9;4~O*G_GD9B70T>?W@84lԨFdكN;r.""G9rQMRȽW{bx"M oΠ> dΠAC C)\ҦIk֋Nvdh@FYZN2*d.GCT[FT?J(!`K)M}᪤iT'K†4jT(͡hEKo޿V(Rq"E*lX̭t/"=9 ( +C($;dA.Ca⢋00C*9/ޢDFB1K4O2餓P|ij5ijQ!R|-`)SIe^fiU\X\%!9HO>ȣM 3zObH栩jZhO6D)䍝0F胫AiO1$P-Ԣ6ݔS)WuVG*adNH9EF|/ "!=ēN4$ Hi|`lqOaP$si-ViVZ3ԅL$e7{6>N$c9 rtM~N8( Dh꫕2L= -Ury a$u͙Z]A`C[Ѥ0)d/d;Gj= 6j)lR\B 5rOIeݞW^X\U"I xσΦdfOX Jj)8i>#?£0lBPu-Ar5B܉vG8PdWg)ZGrک<ȸ ]Θ|ViU_XhRh n$^HDP!4b(A :vİ+:t,蕯d@!Oze NR%C&t#\U+ܽwZ%LWejj$Ya̹S]UdRb)^o3?ž׀Q_zpK/@ac<  }Bן?!'JPg) BU Qh"0HeZQb1bj! E,^1F92^ H2VXl<yIOx51f*]qt//pIGaj\EГjb sr4Q#h݇'Q~NŽ(It鲡LH ^³Se#aw$F ĈôWi `T RxbYc"4s 9lAW..o}oiD\9 Tc#l\Ǒ4$?qNQG(`AU $Dx'.ǫh*F2h>YPGN#Q]}ȗ0<ь,ѫHEJuԉQSH #mVG>ِ"}3[)^Wjk椪R\M'~Ӟ<榅G'rT:jL?-Os͢s[R48ULu2JYEwFcZuWCX†6Fj<D,[a,d=6al,uk\f+VЂ8b,+TOOչ .~ Cju@\ (Hu] &%e`'P2W \\W_ =ѓQqT[ծPHak"dխ`6mKźRҞblR4s`oYpmAb$?9o 3F\($;sVoɥ '_OB;M^TH!KP~x;<+a2GIkӪi]XCe.miG? I (.mlMe3%+ ߵHD(iT W{֢I<D:q?+!#r8ӦD,]]aRZZ _øOulYZWVe 9oؼLjT4fSΒ]-N'8 ЁHvN$nH3k$wN­[0C1*3,uϺ".8އ2Ei- aJU6mahӄ-򬍴zM\cCWL+8ɑsGy5! Ik5ΨS`(WUܦbS3p'*9~nt A'qkVxifUF1E: +yJ~}9xQk}&{޹e7c)h{-9x! , VB H"!#!*Oń1&4DE?.gaI[Rn_J/^lF @SYw@uzgWi d YF̦U{֑#ouKxGNCDo< SILԩ˕/k>E)RWAFBk֪!%N 5KpF[eJƷT\gʛ4o*ϹS Ϟ>{>4RrߙϠ@:^VC\ 1*hۯ?g1B\te ^u_2dxRX' bBJg|)b\IeEQC7h[n#%mhdM.YSN)ZPwO%O^^QDQEHS9^ S!HUeO~9bH% %v\Xb`az-%&TJVcQ6)Tf*V[pt!BA!v#46RFPBFI,+LN&4yF}OwlwfT9%VWUPo̡!wh5|bu|eɇ[T"v Ȩ% u(||ׂ~]xrd)qکdʊ,B*\VINPW泟}-ߠ,A i3bP0ƌ2_($j)IB:'f AVf:[Ad "HR#ѣE L[NtxXO JgJzAI{xYg?BP5(G Q''ƻx~R` ũQπtM`38,H1Ε&I! ,X$0d5:@$h5,l$t-Ek9U@$:)a2'hR78,bJ?"?2KQ.rD%c%Awq&2BR#Ja $9͋3%gFT)i%UB9 rv9kf6(tlUhfuHel dd-Ǫρ LMJ7QC֙eLV*".>*yJǖ&LY:nL-H~DbVe Cd 8? 3LJę]FkgJ2,d o Y5䄯9d 9*iVԖHG:4T)J[.7r+UʥXmk{WĈJi_A*d}8MR96)J Vю~?籩o{"˵-1=_!GW141mn)"ˆ8Zq(<G8^äq9Z%1D[̈U##|mlZ>wY>EKwޙ1f/3Y[x[cM1Xhnw"F%4DȬ2ArUS8А9 I!ÄDK T CmáZLC.a~8 ~s3 |ХJyO HlS0y(aFhk1\Rgqa?6T@ 9,\yG3~I=q $%khP^IH):^:%/$Ї>h®@a=J(A qL#^ۥ!(>,`TEzs7A\SFW@1!!!T1vs4N#9A/cirP EUA(:h32 pp+5Pz&07œpUS5T7LwAm EFfD B)ST TEaA919-]ceW 0 Đ p5h#3N:R2+GG UP!bE:W]35V"JqGY`QQ`PG @TpQ p $e@ 0 pЄ '_ fs 060 EW!BzF?~A@! 6ns{S1Bi49  H.tiVV8o`ӥP,-,nt]8^ @ `&Fa s `+< @poG  NY @@ I pKuTzLXY;A ;b l!!1U2["Tȁ q0#-O q 0p{ vp@/& T C!&pP'C? o r G@:` J@`  0lsx_ d@LCLSu`?g!g  E!!QGM܄[h$%PH2  p lpR )2F9 km` ` F qJA-@FWH&< `@ 6q0VP=\aA @ p I/A>~2Sf txL"F:ɴ8ݖzS  @N%RnF a6] 6 ,K 0P M 9*2+A  kSkpgV`%IZd 6aC_2 Jpi/N@ ` 00 gKwz   ZL(m(?|L?0 `x ЄVp[Ae9b@a@$b) 'iPp P f 0`2*  hR,2 Ҡ kP VgҐTP>dr}ZplJV& h5lpprP@ P7 g<8C`TT@ :E?Ebt?E{  p~qP P 2*#ê/@ 0[ p ` p pp/ rp$3VR4UvP` S-`1R;W@K $q7?qr0uE8   Mf m` $21A  0 8 5 f0PnP~Ѱ `s4` @{V ] ҐОL Ѱm P#.=}Kb<F`,-,`Zp' j k`v,;@8+PK 0RT0C%1x ⚌i 𠔶VШ# 9 0jp`>P p 7 sQzzv@%c^A m`m 鰍 Nn`rt  ɰ&JTyVJlN-3л+`6J f `0z@ @ -+?EPCqPsPڦk  ?N`s`h ŀ_  8 Ȁ؀   4J,5oOV i~wNL&p` znJp qn cCH1.qeܣ6aΜ@ԢFLlHEyk?~3H3{,!?w49rDR(bQg/t0 | WE! B ;s4 # 5ea|yC"+dĐJ v[GBwØ^P4J'-DO %[L'(1!}Jge(s46Ԣ-(+ɫrrºcyʢ~WD)ӕcqeCF-֩gW834}䨍-ĒDހ36 mέظ9nF^Y8i柁0Vharpfak\.7PyD*ܑJbrZGhiFKv )yi' K[=)ĨMDu#P'Sĩ)~iFu,Ǭt&ǁnٸFD0J|Kzԃ|S`ه-2 -OZ@5ЅI4Ԑ{@b+G0౫~ģ [:G',D {@!pBDX@(GLq-nU]F7duY](H1 RXcRBLk M(oأ>}" )$'9bȼ%$Y7Lf ac>n"p1D*~qPˈ*^4:HB{.٠.p AWhC,8l i9L@I=fЂ= pGGoCOae=!z##ƁB':Ӆ"#.䮙P4&]?FUE =х~HʘEpܣT<@As( vl쨃0̒?Hf ht|:0vxB.؂#p_hC#G=<` Vmc1- Pb.:T,^x$ҐNaV=9 d nÎ!Ѐ;o18QsL V|H7 }('NzvdDzW'ddD ON RbD0G>r<]C?a{c0G<82{hԠS#B14j|!Y`ɧ6z?T1&a ;ѠX.m3-eB?DsMjx B ZûgxT-h#wĭԠnuG;zA n  D%H8[[t)>+DtD{r ]B;1z`)H1P87='G=ṛn?ΡHbq,嗾4*ɪcC`G@}xH9겅z j < AR$=E\%,( :921nVhI(E/q>cEDek̃.$4Qa qL .x0h+F_ԣ- 8w"A9VN\.Rc ?1 b¹p.,au# Gx?JӌTh7 V{;点46}#G$QNlIr-H`G@#$^CpmbP~c v;C`9za{#VP |Ѐ R(H. FGۍw8>OX\ K8 POz-ІM"]i0mhP`*إo:X耇iHc%n6FXy@'P*҇xІ_脴fyVcL(=Kher@TH[]a ~@!GЇu0p[JSҩw{Asۇ ݣHS8wȄ?xw`93 @hȄ=qdx0©UP$V+4ؤK@c8KK_~zB⯧pD~h0(20y+~$2AXx@3`w`S @Hh#l I` {x\`u#w04'{@%!xE2PB'}  + ~,fs3 J8~ІHp}}Yh3SM؇Tk;pПsfA~@ x${hb 93J$I^Z+FK0cQ쒟d_8_cz`k|L@B۰ H󂶂@:mXPF[ h`%`x~`Aad2kr0h5(5І{P0pWx,!xmt.؄!4uU}x0;("y',(@xu xk ~0 \؇8#hpTЈo ^^WwXhaEЈuŚHdy08pGiʲ#8s"f/r`VXS#pQRcxE{aUPQnq yu$R]>`ͩ[ 9;xY2Z"0X+(?~؆ +2hh2HHMЇ].}?;F %!B0~#hdi.*`Іex+m0}`)t8 0~7;UHvПvDRT^۩FpGK]T &6UńIQ[PQZ<@Jc3>c/:礓Ұ߈c C`m؃3(08x5+TrhH65p .pڇ]IB0@@bww@N(2Pa}D[Ujxp2! N`.pd.}}҆ܐBP$=yЇ{`AIrʉ$X3KR4dAR@粀XPG|_Zgʽca\~nׄ,VQz >pUˀ ( /M 583xLx(R}8Ac+|kCBF%?`P$@1$H(HX!({X[s [NwkDLxlqINfNm-0ed>z9^ [rq^by@ˍ})9>V`\`oJ) }JR҇P[Pmw&h~Q3+I2 xu{ '8 NYʓKߝm`u0pLx{C҇v`qp,6iYH]P?8X@p.VP(*X8b Ѐ(ZpT^( 0䜁%pPvk D:/ }`x߱ iQ؃u8SDlֲ(VR̨twվGb^Z8mbЅQ^2bV]5]3]$F <ѓ:P\ ,` )bQ,~h/@L`ei].0H!Ρ[9@ҳՂX p@v~H( `E.`^vx2UhIXb`OS={@oEpG$a.UPL5 [gVg23-/F"`YpZ\+ - 0,mgk\X=.h+%4W5ł#PLF,=h!Y01bҸB(m~X`Ȅ@!kE@$2Ny`fY#s:3{:^hspg$ s8OM u8p?j1Z@w5Ђd%*Jh[hxrxoh(}<Чm=4@x8;6脤Gx @Q 0H0B8sc&h^7 w~Oli,Tȏ#Z;y2vȡ;qA8^sxmB@xdFt9+O߬BoR|ŁCB# {Bb&N;.f)R%I!B"ԪUN<T`O -jzasދFTjC(bֺoI0-Z 7ۖ>|ĸLj/Ǭ%JNwFQk摻6H6)Sf֚x?[fO!6Aw 5hc- 8 m1@ԁ',~*CPO7<Ï6Rİrʻ<4sOFBK/4K*FUj# V\ZlbdFE0 $ ^A/lĩRusJC`XaD]FV #HaDG# w1G sܱف(͸t'O/‹?,s 7u88#v">i:C;sM<p;s "1LT8Rq94(y;4PO; 3⬣0OK=lBI wP8X%$$Ob"U\$` xCqR?^a# }P)e 3tm Q BPS0EFp^lw ^h'd#p8 "ԓD S%bC< F "q#qAd 54aTbPD!NhcJ8? Q[A<@dp6i(DP$XN @?ȡ eN X0i0 szDqЇ! ;m:uXbGF0,uteJBG=ȑIZ<)< bU `L4f0:呞 .bC?~VsBgc#9tG?ā8 °H6A6ֱf7 #  |co)b]t=a{pwCp}@ 3aabHY!!oC >yӛ+` hQz{+hMA#@dI 0C& ,8C;Z5^ԃ6 DQ JB"Ađ>1A9"@4XOPRRT4,|$@ VE^t(0m !ˌ?TœQBy`9B!́)):Y?H;>m:M?D< >,: A@%C?B x]0tH6!BC0$CP@CRڃ6#BZ"tHd@,bP4氅 h#M5CdW&xȄ*(=,cH1))^;CODLL@7,+\?l.@E3'|("@Axg2)ˌ0;iC?X$(gGP!DT:B0XC=,;؂` 4u8B2@@>6MIF')BĀ5 8u@h5C?_;ø>$D.p* `(?R)0qBPLxZUi |4܀d1qAA 7(s59xP$!A0(>Y2 `bA(%-l%*J,D*ob. #LJ+@2T Z=P>DC8C0R .BlMxG%P"+%XB$B*BИzcL4t@ DA&B4 =|驭F(AM(&1 8$l‚ACqiq+ EB87@u@.1EEr p$ V1ȃ8QAjmjY&C|,?1t9A$|öكPB3|$;%%M' 9A $,@5+Cyd?(* 9C/;l.tQ(`%m4f dB*?W=ޣdҰDKC@=2%1)`:h.<|-|#s ?0SEqPl$ N>H Bz?(lhS@ ,S7>'X@@ ?)$AP3XA;Ayxi4AD]3Bȁ="P ,AB8@ 4-X+< B @ LnAx@ h~EZihz$#A $AB0>Bb k 47:tM۴ DT8+. 3&QP4h:)? o$AXA9 A=B žHsBdZC0BĀx@h {@Iqp@\B9? P8SxB !=We@=6K 6B ?""/ 0;Cr6-*$>2S&d2zx'|<@<(A (ȃ=P2<"\!܃5gi ouUT%[buyBAsB*K+*؂2C/ v B/9:&C>C0(;`;̀ [D@A&B&\tykId40AD>C<5C"H빃8HLøPC!@ t+>ԃL&}C/\=?x줭zB;dy7/ lb (2WSx}+)t<Bx_uu{ML=tA4X:M(@,B4ÞC', G601(KPJPB B/hA$K59M^,@ ̀/F*ނ->І)PA&3S,Xj|%%yC;p<0 p@,.wӷG<0(5ï=kgٮMY%#;() 8A&%?B"Cb+lܸbrx+=I>aC0Ä_565͂j=/h<60ˇmi:D(B')< 8>}>]۪ %+/L,e 0>h o]Z($9>lRPOCUJ+C/¼xBjSh(Hi+*R8PdClgkr 蔇>CF(Q"|R&$&6(?=(,ƪ9T.xB$tS0R(dBX\Yb5_:Q7o&rw`%1#z> EZ:vi9^F[Nz# %r|8ňx8(9 D<`tSB@ jdRz*ג&J< EDO(Q1ĻXf=eds6UTr\lU:[m\-5F::9԰!ڈl˷;] ʚdN9;-'Ҩ~irOFQ R$f/(9嘑#TNA@UAveG:yeKBK;Vcu{RzWR~TYXuZT`!E3L[LfBFd{(EcP:2 )BZ )+MEI"1ȊfBa4nFa~t;YӖ<$eń=]KE5[n[_T{WڒpI;蓞܄1"k"wFQ11yPQFTTAՅ,EUf U͈Frv8 1W[XQM[ւ*h ZPĈ7smAɮ9}kyt%,CFND4=A).@;2Vye+ *ie|%S!ĥ,, ڌ 9T[0BYiU4C)J4!D &j( w5.<ΦPEY(oC'0= ! Nmi# F""m8Z@P[Y RKƕJ p@+U>͹JUq]f"MX7v %O(WACCyxԪaX)jNgzO`wnҤ9utEɆ &yrF$y8GylAXN!*Srq9hIJ&Uxݻ%g}+7"Z$QkI؂R+9xbF6e>PJv)<0}^ 7f(V2v Q#Fӿ Qj1xYإZ):?dpUfs0vtY tl E".d6iHv )n5fs Ѱ3!mHn9Q4TCE?5@`.K*4ɂwz, Q`]EFACr`ȬRZ{סY<ɶӲ61niF.WߵA_َIl ;X-[^n̙^r̉ l U"QBQR9PܑJ9V4(A[54ȐYCeoZGpuv]JQt޽:]RN4!DIqN SOQx ʆ"eg42?޴+|l _isִ :0y?5}&jQ5WN}J;)֬ Cˆ Zm%rZ{-x^P?x2 _2eEbChv)+@IJ @OA@fԗo!7АQm@BdDLmQSA8RZud]v[eR"%&xG 5ySETlExW?uYy!uѵ?vEIxa%8R%?XduBJer:X?ƥiR@mo1B)BԚKP,ҬEK/E O`yAEPDTYUlQ\5|]IWҟZyo1^y9_"{=v(d|EBbY-b*+ 4m(vq {piDBbRodqc DQRӶ^lWSYP=?VA߼^#rgx®| cʈtH\ӥÎh-LI(Ƙ#≉f|:Jf)>f!@l\k@Rp!D =DC EyECTPJev>uPE1MgwSu;nl.\A{_'#_[g}M0/hN%0 XVb衇#RuTHFH h%u+!a9j`2$F%']ĭ;,%xY 39k?Zaհ.G?ei[b}E@Z!-uk,"~TV! !0 MENDd89RˁIVm>kY+u@q3$2u9;yaX090S2)ݺ7P*EU'N]X>MADV%)Lo_4 Q\8e}3G9Zʝrb:LsPHGk@iIsP'v@ )=F1QBؐ)SC+K^ƕm_*,/\0g*.\Ksaxd$C̘L*hTќ%RHaĂ;8Hz*AwGhi&$ZMPL3QMWc!NћO5ZhEK%hFE201L}bgNї(HfV5,A41k"+՝.!bbӒ*,na*%)5h:>[JWAtlf 6>PE&L>rd% hR ceHd_Sy.S31XI=dWgs@,t:cYCl% Gzlղ,LKJ4-iA(]p7pqK`@ލ굕\rɆY/þ-P*!ԔP4SJO} ,V19  +#=HO8@T8)°ЂH4J/x2`K"Jx ņ E21{x^{vU>^iYxOs[1Ö.O BD~XfDZSYFNA۱ ĪJW:aHW.SNufɬ[.gQ>R){̣H}(\," %.emS6!9,?궰 1p23r=yvp*Br#KۑJwVhg\ &='wsj਎ +rH q@>!ωMC.S3xi"`dH9Byyu}4`'m2N1"Vt%P,sCA3Av2;,'C21 @ u`\ql9^[?]A1/RJr@ KXM7 0w qT 0 'SLze|R/65%0a7/`%2"!BZFZ)?#@0"2Z%k@2Ch"baV#11 01%B3-66s.ե` QX o X@pG`@5 @0Ҡ 'Y  S 7b0a&!Ma"B&Tr86 1u**"}zG}QZ@@ Ā 0fP l` qS{YRs  1d`0 @ &a,^ ha 0 `  х< ϰȰ P @ 6⑐Y207i  ߰  @`; 6~o|kSw` 0n Z ֐* 'ٕPo 0 q `: Ұ BM1 wFq"ڀ Q}d x1Pg`9?zo%C /pЅl  Ѿp p*r 밯* ّeEq&y oP `F{M & : ɠkQo0'CD} $K@@IK@  B(P נz-4I  P x0}Y / m` 0sQ px P @ P @_ m ] `p I=n@V @ E^vV9Qm`V@ <9cf ii p&ljCc/Q'<<<{ ]`  頱pE ,% c" P0J @V m pV@ +Je`0,N۾@p `+`+ @ PLS?*Pn\bIh5赺قG?h7O݂ YĢ'!: a Ʀ'?*؄U,e) Kzy|xq^X?pI`hP;e;1~(:9{mFST2=xĒ&LzDAp#1aU̧1юqc[Qx4M"1Ĥ1LS.JX\b?bI 2AƆr?` WzQ1%3Xazg#B PXI)q5CV@\oSL౎~ԣ8<!D6q;  % ^F!$U=) kh|c`Fh㎞e~BW u,^LtWNTIC g ǢN}ܗ0O6ILx6l|N i4D{2*tcPHC84GY q*!Ytj#= pj%" G00`<ދi0#!\?f `$1 d8hF(JyD߸9A RĘhciDNJqqYyb)}i }X`+O|"`|/ulv: ͸TM%F;Ae:/@d2?^'!m^S`Ȅz{P@ @H``2 L@b~p 9o wh fȻyNP0rtySe!IP~%8kxf Zh7.4q=>cvax]hZz@>1~EpR8)0/?PX % H0{WXA03Q\0{ڀt8,S*xw?F"ePPMI@*zH8,@!(HeP$R$X.C0iptWi f,JRhyJ#$.*x`r;}zH8`*`{x!؃4PzVH=X`RHRH'R.68Y(c08 SɴggUP[|u>S $6ʀCdC;臏3` ǨiH} HHO /{BX 8 P4SP^Å}XZ hL|@Q[vfhY{.(PspL o @8}XzrHySɄRڄ=y8o`$f7RHx1ycTUT_aPI8K5>hPI_ZPQc|I>p8MBIF * $/pw: Xh0ʊ5X@Q 90h}{Pyo؄4%h(pE[8T4rlF,h̔Lr+mPyW.p8s0H8^8L!@P!H!@wXhx (H}'wW`!.*#d8ӓ/D_0K+K(Kh+O PW`P[l8|E4(2)5p_@ F3?PpIa]0`+ hohF!Hx?H58# .!E@F`F2L+--{h O}zH}І`( 8em`w%$@?PXF`t8HP$YЇ0ϧ1E XBb*Pb XG8(])H\X%Pb5VUPdXE0J8M`DMHb N CpDŐpeq~h͜ ?2ZJ W ?%rpʳW$ yHtPS0 [Npui( jՌ̛u0ds`xGoXSՀ7}S8(4}ME.Pxub܃MP?(q O/O}cU'ՅG(R\ OńIIW\4@ (\PPNQGW[Y Š6@=utKS9؇#EX Uѣ0ZP Ȳy0PhpipPohsm@xދ ~H%`bsPH Հ}Sw`u kM}'Ї`}@5yfoAcwYEIkRE ` f6[ORx 8:aZIPac,oɐ>G!}hH}x?XYSp5PXѱ|Q&2pUP&H:$]$F25C@Ah3 szx{؇Y Lh4qi^OX@}@Kp%i"Oo:z W i mHoDhUV V-~knf[fc <Ȃ=2--82 k{~Po.Zu[%v +6)rQ~8u0 PmhMT402`~CAOЄpnZaO($hMYhYȌ\k bAyЀ(8jHNFjIsaqq腓`"r ؇k0>jXrf{`.SHlRI:/a^xG0RkcRa8ָ >qĮ3 鑾:U)В@ :S ,hk pkXu'OЇ?x(xxT%OJaZ ;wJ1dv_X8pd͌~; [0YoR(H tb fs0rSRaoy^7 Oykx;\V ɒ 6@h6 h|qUpnfHgH$SvfbP;^(x!Z0I(?Q?w?r(Wfx0!ȄІ@ê@s~]bf!`_KBWYwІh8H9HPoo?}Ho8{XܓOmP`?{*P.0obԆf#xSp<V`Td빞W@kU0g]xWI 4ʺL( f8-V=陞AJB6e(er:8ֈXы>I+&& :'0L' @ l^'sCUhCG;Z| KDfM`oTem*jHExL5s8f@q q0`>ESH)&Z *6lxaE RUKՄDlyѭ.UϢz&AӃA>"ȹT/[T9ӕN3gʹO8g„%XٓIQ.Q9p!Ah\3aEJ"?\"/ՠ@3Ĉ(Z̾_=k"A?Gya og~zae_Y% ^=?AmBtwu(E*~* DRJjI?3MR#-K`"D @TG1GY Tԉ44 #jlਡ#CYa F$m&s?qFeO:G4G?X#N=?8(c)H $uoeCāC 1<(8H j0RH!K3O>D(ܓ#A ԣO40 LZ ?FsWl9liNCV&2Ɯ,X !P? fq X ||8@QCā<[@-=B!1p3hg 9αw#% ,Ե%;@E1`>Y"{?B1 u?( ,4 }]&!92G (%0z؇ГL@ Lp={*&Д H1d\ J ڠshB*l,(R`%eKϔu^@>p;f4h;a{c7$X`ox?CA4#(=x1NCU,plQNU^P"oh"? DN82'x'BjB:4jxE PAhG Ԋ@z !ك"(@A  ` 0 E , ~C0^8@C? >9]`@Q+, ^0^`@ͨG=sq Q":?H܃ap 5[\JG`F(?~4fijo[G=0Qp ŅHa!I)_8A r8$#q]+<@ F3zQbF̀q@K$S"z^PVx#-pC0}8INpԠ{$>$3cbA `=ADsEއ;UYщos09B-&DQQ^P\&CMŐxV8^ْ$880ȁh̃$]AP3,DC?B́eQ3l>HClB!Ot)?9d o>C+8?PJ" B*̂5l>XCF@-DL?H#Ā eZCF@ @ x@2]y)t6:@$Xm؆>C :LĻ@D?##hClѼ<|0-AQ\RpRSP!?l! Ch쎏?́'C?Bu!ʁ#B3~̓)A`X9c!4C(fY:2A )18 ?(T+L?HC (B?>t Dw ܤ0%U @@@%PB?dC86CB$ ?`]>4" 67ha)5̃B3L98mH=T܁QC>pJ>ȃ<d2d'aR'AS4dCjCB=9%hS@A+%#',b\);D)LC/C=:8#?DB10 tBdԔ@$<ԃ-8A d9 9 @F q4P(I=?.)tF@ 9C:?D,(C46Hy<+BB/=λ!n#4mz08 @1&i&'?ЋA,!(CW?\4C,P-,l;!X*,(s6C48A='$%:փ#((&0Q,>@C04&B=} %@@C"P>f0l"A85r?#̌5@@r>89Cm A C3%xe+8N1l77+ Ж̅A4k&6CcO؂;܅>$C]D@xA&C4(8 /? B(-*9+,q/C=f/Ef)=ivFS;$;plo $&6/$6z3,;C;B2B,)0 0{*&)- N2D)@H8Ѐ ,PԀ;>_. *ij1ª"p,C4̀ Ā$t"hA @d5[3%F"?$A&AO(0A]Z9 JC**>@f/ CbL`-GtԒB2'` AlX7/aV%x%̋a>H(5C>>4gs7ψD2cU@ 9X&6hS A=Vr^6(C0(4 ~K'uaC05$=HC!B4uv;,d0@-^i׊K%%_#+*?> Ā럍@00F48܃$\Tl2^,\'zv-X#~#P*@$X%41؃];LCfsb -M\I'g'0ƻA hQ-4@q>\R¶]>; <ԃqC @7>W텰4.0( m(ė A0`SyD/s*l-vjRZB.46Ú'X@ @xC?xBJ۲E/RC/&@ ,;X4$/\8_ ^*r郯_|o*@n-B*lj_B't*pz;2Cu+XM+]Ã8BoFh1`|0g/%1.Tr_5C/Bjl^1'@5Cl>T?PZ^B/H: ;L**D<.Lgz YIF.LC;^ԃ;>4CFk3ebD*Ђx;=žug:$7$Kdû7-%(jZ#X êklΈ2PGLfbf5@ȹΠB׏_?ӷ/(Ȑug.ARWSp %F(Qrs'9 =d1iC9 4C=,r$C=GD> "Duɿ*1p0'KN4jM@,O*BV IJʒKŶXTlLq` ,0X-K4[{-J9òƌt&Z/k3/+$K 650 c8N@N_8A(@vDDEaa(a8+$H<TR+>*.g:EVCٵ]iTpbqVt[pAM ֢ĬgEX["'\ΌZHZ7f3B_4Yθ "h<| )Ou.X?&G /?SP=ST2O4NF‹VyeъyYUĜ؟[_W 8L 3]iR&ӽߋNW&Cn9l fv;Tϛno>8`F*oT'Mv)9YB!:AB)bNe*$bYeg "\n-\ -L` -Jv17s$3ܛC>I#t|!TE)3;9Pg9:+4qFaDǨ$"O4qnT!!XrIdZF"},p;[]u~ VU06KRCP7 RF$=bؐ mJNVX;"z<$)<rOOU~BG,5(洔&҉2y D0 P6 B"-tX` kv$(f 4<5MzL#HG91:G8Jjׄ6M8diCv "]WoFfI& Cҁ=btN<ДSjQO7Q ATJROǿ&:P. j*]VϬ^eWZТ+EW&ъmt\gA5t7S4f8Q̗瀩3<$737֌zpR'U= JdUr 0Bϫij*ke-b15 `Mo79%؎Æ8!xBR D)/$Uxʸ=y38bϷ#NDsSgUT ss\B!Uҳ.2S41aB#.x7&q3o{ | $=̙# n>`tTR큘#Mنs T̉qT岲UX,3ӠHH-Uրª?! , V@" (H4E-F$9^l( &'[ҋM/5qdÓM5l6nړ ўr$MzGN;lܙCU꠫wj5dhWu-ĨYGw֑۴nGQ]v)ݫ_'OBeRCi⍣HE|ԩS*"E*g-arE<#GxJamx9E^#s\5GoBdg{^eWX'Y׃nQRI|Eډ%MZ(raU*shETdPQ zЏ~FhD,K=aDKv=tEuPwnP2ցcqUx^uWzRW/Zsnhb&Ia vB'12eJ?2erfSB훌BniB:P:@2BўIKTEKuXeQ]M95TY_%HާUXbu?o|ݧ~H%vVbM–PCQ&ʐbNpc?[{È?ARJŊ`#iYXӿ<0_D&d2 f9TW,PӛuҠ!BY֭EK!Uwq! M:ѩuIZsWd}>|1[%ғ7ow%F2۴0{94 ;G1S@9as 2 BJ2DG$g;baHOBCG5-v̰fE4goɑu7vȕ'5=AWl0ڰX}Q P0  Q o' `Kob 0  g.EXX}QSd? R!q!!3) !f@N6z{][VKqhVO+CA,  BZPԢ%`-p 8h ḛOpB``p` N@A /#k\rV'gxw6v E Am_pxN""#2!CPBr{RaU `?Vn;iA[ppg`W ́5AiP˥ @ K15B MV0?5 ͸ P]qC 'r'X6 Eu0a RX88#1wg! ߠ1S}x vts9Q4Zp-[  p wheC\k`v@gm `CQKSJ(1pb-.QA` ]jQ T1@KЌ`PpO }]k WfE0B?m(p ͠  vh@:9am`>gρ$\+ D  1#LGA @*H.CT2ܡ%Vtr 0TT$ RB ]p'|B О`lkjEo'QayuF? ` ``` `!``uW8! up_   n,Qa1r$C3l g@zVՁ4bJ8 }0 ciCӒ+?a 5?5!2 `@ @ TmBuF X:z1KH  ` p 20p " @r@4V:p0:|Kc:%I1Q߰a0i g"=Oa5RZ# P /2@ 0{װ^RH>0RxxLbiSgFq8F8 f!Rz c!2 "v" P^pIE[0P P ]l Ϡ 0pR O Av*G-A r4$;1cQw0 È `e kCb"&uUL.s D@ `pZ}@ 0]`!/uR4Ґа_{@džf  ! `0X +HFV 0Z ;˼ p p  [[p 7sQ%ʡ{$ \@q @ @ 9` AQpU )  0 ӍkP@5@p -IP` e(ʆf p Ҹİ  u X PF4P ՠX̼ P  w0kt:ɠ K((%Z  @i`%j0`e0PawB5W k08Nq zkp0 P q0밦 "C ѧ0]`:Q0 ZI+< J&ӡ,0P ؏-3;  p$0 31 @ۙG  @ ,Ϣ4U`pۅ ֐ \wP(PQ@ wEDaj"}@/Rb|,@;I+nh C `ߠn1-`_fad_MY8 B X  V Pm e(OP3.42޼ ܀ L p0 pD kO`pIvЫQpے *i0` mЙ;`)  ` P0Qw ~nPC-R]EdT^G K+0+90,06T @ 9LJx:s_ Y!0!F(` ' İ1pI)3ڎ31^ : 'z Ȁ f` N5{f`S@ V0lp ] j:v= u.~6j 0>TT q+6@y4]Sf F`q!0X@0@+[XRF~ZoD6^&ߝ~0СWۿn㺕CRdgԩ_?|ܐqwO[ -欜Yce͚3qjL0alfŊsBe" H'莿5eX6;ro;w4^oҢk(PAӧoV,Z|nb<:A#+R#FfӮd)bҤ-=x:դ&K)=x'<ex3Rw7\?~ Eѷ)9[4O0X^}k H 6%Qt\nyhȢ~ƚ wu0as`lY=%;Z5D-* 6b0yI ;اTX'9" +L_c#+0$Fe>D8ZV-XpbW9qW^AERq-Egs~8D: %(:K4{܇~\zWq p9WLL1e(V J" {8 bqФ裒 4 eIL-!E)xFrd 5rB@'|E`z ,&Ƣ (HWgb#dԘK9k}~LK颅MN~^!%q* ѥUESgU:M<M)1'էrⰅ(f)l1EB$#2ccQ'JTqv9r>Dg+\p fBG^;GaodB: +a|F6V)I,ip0xse^J ~Xa(R@B'p^g9G#:ZF֌ea hXG;귎W$xX7QƑ*!; "o%9Fmhsh>xa@64(G䒀D(zMQbs&N]X1  iZ/q(=iN(PL0DcR͐FrG0@4ᔖ"~:zAAF1@Z p U  ECCi-Dڰ!w wA,pb\ "dw1  $жPaoCs# B*x2 %bC%p~PFXu]0Yo@>FTG^!EQ &=)}T8)H ^H3p R"ƣ -?!TF* a[@uAŅ =܀0'dDop3B={cZ=+aHU?H Tu:jiP"sdw#P:&sH"@% E$xA8au QZx&`-AD!@mDr/ ֮}mL3G3~{w@a~X1N+ i|]Ų, ~TF5>qOhV22Q uNQ[pqH!2hTyHH$al`2L+! RnGMd!$-Pw,r t6k }F ^ ~?bb샐D>@wB Z4c7hXhG/tbY*~rԷO MhcF0!yd?#PqWUBT|\%-G5,jp6Z2 _Ѓ&" yVf] ? -ȁG=~.zeb(5`t)L9:` `Xaf0%X%P u`^8F115$~XyxyX(0tІkp$`}`z1wxHGsxT@MzD*}L`EІ̐ 22i7x%2p.xL !oPt$0hЇ1wZPHT0S=i("0a0g+(DĸG8cPhqH+5 ~@EJh,1R0}y8zEk{aq>?z3= +Pw#X&8#p%}f0O .P(HD@!@ӈo@kxuH@PǶk;؃p;ix\^Ce(yo@H8u@Xm4} 2 }hV+;1' %`8zz=؄4 ^X"+2?Cb# g@8Rkg0_[UJ z>@_p>pߒ|ghױ`{zs#i5` D3l568hWhH&HmP`Qxo; PCp{,t\MwL8xhDYY fAJhM`$h Mxxox((.  [ `uX}Hy؁M `x4 %8`kSV %!h81CPJ]HĖ>IZJWq룆E>Ȃ(X~Ng#Z@d X|vCЇ48A5E: }`U(H0{Ȍw@Z. 21wHS8I: Xh6<%2PPu\MTG{ Q6ڰH qPx}wP @qY#($ mq؇` 7hT2^8qR!WfӤ. 81įU{wb#R4Jp 0K0dx]KJPtVDlPn8{LQ4@2gN(9\;{@5rr0!6@2X(s؃q`ZBhU%#$T /  k}`3=P N\ a9VwXΛx8sHb@rE`fKmӇW{Hs܁#~< "1X`S(~H>801Ӆ DfQgJhEX7VvPј0xK;}x@8k62z03JD}؄&V4ee (7(?*+#@A\F5=S@E/ڰ [PhXAAA]NFx㘇`h1YL̈́y8Kj{tA'Pc1R/=,8R48GXD]] cgUQPLQSv~`YE;itp)a㈂}:2 ӥbbQHh@&4`X  )txD0Fwx:~TP!`Hp#@Aw,Yvx0PF~p A PJ`:wPkh=~HLw0?[$Q.s%!qRC$^h'$[ 6Vd)/P cR(]R|῝IXaf-kK@3ޚ؄өyBHmP2X:R(!b .48ϰ*XxS0A0mA6u 5sLp؂%4;D}SbxHpI/.jA%\li8/Œ{x{V[ip =$$;~`*^uE[UbsH ʫ4llgg3`:5^15X}؇e+5 5W~)#ts`P MpFj&P,$ϔt2+9(؃]{ *`/ F% C% 4b]P`~ژ$ I'jHd߇N؇WHo XpewV}؄! Lvi y~[аS 2kc#RO)pVQ)h[PpFEEg{7`VU~^p58H`hY btt ဇS%h!R X=؃K k*0&#:gC@ i%SMI2PD@́A՟$yBEӋY'H~h{'n#'8H/w3jL,S&iGNR [ O߼}hɝ*)~iVnbEkYSƋ?%A:E* aElo_U (2L@0pԒK/?|"x`xQE.sQGYEQFa(vsQ!̳U\uuVD3?e1e0K(̜3>Ș5˼$A"Y*bi&]q$ͤ?2#h# 9 I2IP70O!??@p!h6)C N?#*䴐:i3tWCѼ5J@E?4A(%4}udL҈prDLhh[=븼>A($4#!3,!H }/#2 9Ĵdr?xD@>&,Q?O1B@$ybrH&`Ã~hQ`Pqd1(1XbI/! F LH+L0;JױaSs5GA7w1K#/ ab9efi 4Gp2 m8b8<d5 AВ P81G4ArDІ6 i E  Rm^c;~-A?AIr )䓐'>\m fЁ &IiDGF=0@|pЀ, c@00YP7*0$!Wc4G<ͣWʠ0Aa +L45!6! Y` 41%1?3ApB<0H(^%(@3 ?X (jF>ҡ [<Րc$8C ~C?K}hȁ4<s\11_6 k!Yl}>C`"0 Qr we'n jP1 T*^Vlx0))VeZ 0_Ycsh0i0BPD W!Hf A X,ʚ`A <`7Ȉi8A2)zAYbHD$p|"ʨ?BAPjN G:0h\X(:]b0T8EC!D,,f~2 & 0`&Έߛb0&nP=f\.쑏\B5X ĸh|E$~c"Q6A3A$,aj$j(V]<, (@A FЂ7TDYTQ5Y1Bmw.xG=oXG42mXC: s8;я!-`n(\莢K:A{@4h iC=!,҇>iEEYSx(G1l`ᢉL L@#",(> {Ԛ xяud(rͬ)h>bb Kshyr (xry>̡`5AA0b=Dl2DXv?# ,38V D49N $`%?\qϔF8r &=ݽU30)A+ZVw#EX$5:@Su M̰ R ʅ8z!  ?Q"5Pgh^* Q#6,fB+A CiB8(gKa :1|4 %(яt%p?C8*a :S&a EtAsh̃z@ ~@wh|#@Cu3hC8t-)5`t ?YAB*,`~xPB=C \?d"A`HBR!\.ȁ?4ˉ])˜Z7W0,A]@8 M.O,%4Ch08A#J@ 34:='tf4F@E*uC;PBGwBy>OP! %$?cyȄDTHX4h{ɁK#5-%X#=JR'I!B=x9) Bbq'0=: pL W4a 䊩eB1x@q@;H,F 1 B!9Hv@ ;C3X z@. :A@* B5j4?@ ]@ B:7d2lC+tWa ,BV@!8s$7@gUQ/ M?G´0,CX9HC&$+J:aAtB!b4P4xP_.= &/x)*F dBלZ4{B>@uP=4C0p<@iPB"0BI;CyB~5C= @ym'i|Up=$v4:F -@@+X=XJ"?;<l@ @<;4h, 8C8!)B,)BAb6m9\*t-A P. ]8@0Ă;C' ;@ 0BZq>,!28mBa)EO.Q3ԃ39$ā؀$9x=)I-CA@Bq(4?DׂZ2L,n*"hVA'h|%$%|>9-~Z2X5 ֟Y;*<.yH/46@ /C39C%*1/?~T¼BW[!n7]iǧ)g1B%1gxVDmr^QթA;HC+_a-͏ .?C)}溕DQ3pd Bmt1|:[ F6b<-Z6DB j GA1( -8C=Ug;B'0.K'D[1X; vQ/ABB`/u?/}4ahͫt*&yJ{o28@Ƀ7~yC PԦRX. Y )ÚSBT'%:4%P{fB*HC;D`19B/г@j^=PQ"J +8%O?~@£Ej9RF"%qTRK\<{QRL)VHZE7x8[ ֩UT[jN׮䄕FMXre6cݺ-[6s޹3'-T۲rԐ u읰jԜech.^eɐX :' w- tz F`&9qژѲz> d8%VzZU GK]OT!CK>dH|y4Q EK۹uIH<|e(OR饙i$Q<IiTXQ(Vdin\V*+;-5J2,,6ڊ@q#EQkFcQPLQ{+58 d$Lh@KͳA~>$N5+ aGpT7Frd簻;Y(;FsȻs<@)"Jk?M:dBRKI%| $J)\J)gT3L. C >:+{+0ۂ,lD. -T4%o|-A @꣫,K>4D ΄cAN\AL89$ΐBҤ3OhPG ,1ϼJ ԓdJtRK#/A&<u%"e$ZOOᐪa-YDL3cKj+F@3Sc58C+i4hbVBiwx)ykN5xC{Ӕ98m<TO<)JL%qǨ˪ÒY4K7y痗hѴD5J{-|w㤗{;߷OSN/ `"H=ܒJ)Mg>TRtd(D>]E)=y.x.-IVDeKeR,]&Hz k%n"=\];$' zYWosqJt!B@lj0w'wC\G<Xz(щg"+T' @CI`"|?R@ -S#ʧBWu+y-ȓa -Eg^ iXB y&Hf[Z-zN;װWk+Zڨ1h >Gbb*1')"s%4ԱD#6hUjiJT1(Lg IF4\őXE+>cZAF2VbId=Hx&5iPc%bA]'>ސ\d2z_r 4 䗰) IEB'/aܤ,hң O)'a|JdJYqAd 43U%Ǥhkq[J$05މI>b@!2[x\\NssS^6E_('TB 14A@o!}ʦ#yUMS0? (eLD:HcCh5fnQZ` ti6CQhZVhjj /Ù9ALPh+8@ϚeireN]xc?m nzW(:#`uImʜoa2}J)FȆ3h*Zl4 dݫit3lAwGaVWUkʙĞumDLG89Ms؄fMpj[fCEQ:v2C&( P'3~s2L0=zCNr"*wϥc%K*IO5Tq*\Ey@lDʬϚ2(K-l/Sk ST ŎԚ7XINo/R3Cb%>2|✫:NuߠS5Pu{8DƭusE9$R"2 Q/ -ϖ*, ؄k3XR,Xy%Pҭפ7ƮF83uWg;{1y㳾a숧H#n0u4anVucOnOU}A4[IzHDP@;netsurf-2.9/libnsgif-0.0.3/libnsgif.pc.in0000664000175000017500000000033711173435713017035 0ustar vincevinceprefix=PREFIX exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: libnsgif Description: Provides gif loading and conversion Version: VERSION Libs: -L${libdir} -lnsgif Cflags: -I${includedir} netsurf-2.9/libnsgif-0.0.3/src/0000775000175000017500000000000011734430267015075 5ustar vincevincenetsurf-2.9/libnsgif-0.0.3/src/libnsgif.c0000664000175000017500000011435711237646216017052 0ustar vincevince/* * Copyright 2004 Richard Wilson * Copyright 2008 Sean Fox * * This file is part of NetSurf's libnsgif, http://www.netsurf-browser.org/ * Licenced under the MIT License, * http://www.opensource.org/licenses/mit-license.php */ #include #include #include #include #include #include "libnsgif.h" #include "utils/log.h" /* READING GIF FILES ================= The functions provided by this file allow for efficient progressive GIF decoding. Whilst the initialisation does not ensure that there is sufficient image data to complete the entire frame, it does ensure that the information provided is valid. Any subsequent attempts to decode an initialised GIF are guaranteed to succeed, and any bytes of the image not present are assumed to be totally transparent. To begin decoding a GIF, the 'gif' structure must be initialised with the 'gif_data' and 'buffer_size' set to their initial values. The 'buffer_position' should initially be 0, and will be internally updated as the decoding commences. The caller should then repeatedly call gif_initialise() with the structure until the function returns 1, or no more data is avaliable. Once the initialisation has begun, the decoder completes the variables 'frame_count' and 'frame_count_partial'. The former being the total number of frames that have been successfully initialised, and the latter being the number of frames that a partial amount of data is available for. This assists the caller in managing the animation whilst decoding is continuing. To decode a frame, the caller must use gif_decode_frame() which updates the current 'frame_image' to reflect the desired frame. The required 'disposal_method' is also updated to reflect how the frame should be plotted. The caller must not assume that the current 'frame_image' will be valid between calls if initialisation is still occuring, and should either always request that the frame is decoded (no processing will occur if the 'decoded_frame' has not been invalidated by initialisation) or perform the check itself. It should be noted that gif_finalise() should always be called, even if no frames were initialised. Additionally, it is the responsibility of the caller to free 'gif_data'. [rjw] - Fri 2nd April 2004 */ /* TO-DO LIST ================= + Plain text and comment extensions could be implemented if there is any interest in doing so. */ /* Maximum colour table size */ #define GIF_MAX_COLOURS 256 /* Internal flag that the colour table needs to be processed */ #define GIF_PROCESS_COLOURS 0xaa000000 /* Internal flag that a frame is invalid/unprocessed */ #define GIF_INVALID_FRAME -1 /* Maximum LZW bits available */ #define GIF_MAX_LZW 12 /* Transparent colour */ #define GIF_TRANSPARENT_COLOUR 0x00 /* GIF Flags */ #define GIF_FRAME_COMBINE 1 #define GIF_FRAME_CLEAR 2 #define GIF_FRAME_RESTORE 3 #define GIF_FRAME_QUIRKS_RESTORE 4 #define GIF_IMAGE_SEPARATOR 0x2c #define GIF_INTERLACE_MASK 0x40 #define GIF_COLOUR_TABLE_MASK 0x80 #define GIF_COLOUR_TABLE_SIZE_MASK 0x07 #define GIF_EXTENSION_INTRODUCER 0x21 #define GIF_EXTENSION_GRAPHIC_CONTROL 0xf9 #define GIF_DISPOSAL_MASK 0x1c #define GIF_TRANSPARENCY_MASK 0x01 #define GIF_EXTENSION_COMMENT 0xfe #define GIF_EXTENSION_PLAIN_TEXT 0x01 #define GIF_EXTENSION_APPLICATION 0xff #define GIF_BLOCK_TERMINATOR 0x00 #define GIF_TRAILER 0x3b /* Internal GIF routines */ static gif_result gif_initialise_sprite(gif_animation *gif, unsigned int width, unsigned int height); static gif_result gif_initialise_frame(gif_animation *gif); static gif_result gif_initialise_frame_extensions(gif_animation *gif, const int frame); static gif_result gif_skip_frame_extensions(gif_animation *gif); static unsigned int gif_interlaced_line(int height, int y); /* Internal LZW routines */ static void gif_init_LZW(gif_animation *gif); static bool gif_next_LZW(gif_animation *gif); static int gif_next_code(gif_animation *gif, int code_size); /* General LZW values. They are shared for all GIFs being decoded, and thus we can't handle progressive decoding efficiently without having the data for each image which would use an extra 10Kb or so per GIF. */ static unsigned char buf[4]; static unsigned char *direct; static int maskTbl[16] = {0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff}; static int table[2][(1 << GIF_MAX_LZW)]; static unsigned char stack[(1 << GIF_MAX_LZW) * 2]; static unsigned char *stack_pointer; static int code_size, set_code_size; static int max_code, max_code_size; static int clear_code, end_code; static int curbit, lastbit, last_byte; static int firstcode, oldcode; static bool zero_data_block = false; static bool get_done; /* Whether to clear the decoded image rather than plot */ static bool clear_image = false; /** Initialises necessary gif_animation members. */ void gif_create(gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks) { memset(gif, 0, sizeof(gif_animation)); gif->bitmap_callbacks = *bitmap_callbacks; gif->decoded_frame = GIF_INVALID_FRAME; } /** Initialises any workspace held by the animation and attempts to decode any information that hasn't already been decoded. If an error occurs, all previously decoded frames are retained. @return GIF_FRAME_DATA_ERROR for GIF frame data error GIF_INSUFFICIENT_FRAME_DATA for insufficient data to process any more frames GIF_INSUFFICIENT_MEMORY for memory error GIF_DATA_ERROR for GIF error GIF_INSUFFICIENT_DATA for insufficient data to do anything GIF_OK for successful decoding GIF_WORKING for successful decoding if more frames are expected */ gif_result gif_initialise(gif_animation *gif, size_t size, unsigned char *data) { unsigned char *gif_data; unsigned int index; gif_result return_value; /* The GIF format is thoroughly documented; a full description * can be found at http://www.w3.org/Graphics/GIF/spec-gif89a.txt */ /* Initialize values */ gif->buffer_size = size; gif->gif_data = data; /* Check for sufficient data to be a GIF (6-byte header + 7-byte logical screen descriptor) */ if (gif->buffer_size < 13) return GIF_INSUFFICIENT_DATA; /* Get our current processing position */ gif_data = gif->gif_data + gif->buffer_position; /* See if we should initialise the GIF */ if (gif->buffer_position == 0) { /* We want everything to be NULL before we start so we've no chance of freeing bad pointers (paranoia) */ gif->frame_image = NULL; gif->frames = NULL; gif->local_colour_table = NULL; gif->global_colour_table = NULL; /* The caller may have been lazy and not reset any values */ gif->frame_count = 0; gif->frame_count_partial = 0; gif->decoded_frame = GIF_INVALID_FRAME; /* 6-byte GIF file header is: * * +0 3CHARS Signature ('GIF') * +3 3CHARS Version ('87a' or '89a') */ if (strncmp((const char *) gif_data, "GIF", 3) != 0) return GIF_DATA_ERROR; gif_data += 3; /* Ensure GIF reports version 87a or 89a */ /* if ((strncmp(gif_data, "87a", 3) != 0) && (strncmp(gif_data, "89a", 3) != 0)) LOG(("Unknown GIF format - proceeding anyway")); */ gif_data += 3; /* 7-byte Logical Screen Descriptor is: * * +0 SHORT Logical Screen Width * +2 SHORT Logical Screen Height * +4 CHAR __Packed Fields__ * 1BIT Global Colour Table Flag * 3BITS Colour Resolution * 1BIT Sort Flag * 3BITS Size of Global Colour Table * +5 CHAR Background Colour Index * +6 CHAR Pixel Aspect Ratio */ gif->width = gif_data[0] | (gif_data[1] << 8); gif->height = gif_data[2] | (gif_data[3] << 8); gif->global_colours = (gif_data[4] & GIF_COLOUR_TABLE_MASK); gif->colour_table_size = (2 << (gif_data[4] & GIF_COLOUR_TABLE_SIZE_MASK)); gif->background_index = gif_data[5]; gif->aspect_ratio = gif_data[6]; gif->loop_count = 1; gif_data += 7; /* Some broken GIFs report the size as the screen size they were created in. As such, we detect for the common cases and set the sizes as 0 if they are found which results in the GIF being the maximum size of the frames. */ if (((gif->width == 640) && (gif->height == 480)) || ((gif->width == 640) && (gif->height == 512)) || ((gif->width == 800) && (gif->height == 600)) || ((gif->width == 1024) && (gif->height == 768)) || ((gif->width == 1280) && (gif->height == 1024)) || ((gif->width == 1600) && (gif->height == 1200)) || ((gif->width == 0) || (gif->height == 0)) || ((gif->width > 2048) || (gif->height > 2048))) { gif->width = 1; gif->height = 1; } /* Allocate some data irrespective of whether we've got any colour tables. We always get the maximum size in case a GIF is lying to us. It's far better to give the wrong colours than to trample over some memory somewhere. */ gif->global_colour_table = (unsigned int *)calloc(GIF_MAX_COLOURS, sizeof(int)); gif->local_colour_table = (unsigned int *)calloc(GIF_MAX_COLOURS, sizeof(int)); if ((gif->global_colour_table == NULL) || (gif->local_colour_table == NULL)) { gif_finalise(gif); return GIF_INSUFFICIENT_MEMORY; } /* Set the first colour to a value that will never occur in reality so we know if we've processed it */ gif->global_colour_table[0] = GIF_PROCESS_COLOURS; /* Check if the GIF has no frame data (13-byte header + 1-byte termination block) * Although generally useless, the GIF specification does not expressly prohibit this */ if (gif->buffer_size == 14) { if (gif_data[0] == GIF_TRAILER) return GIF_OK; else return GIF_INSUFFICIENT_DATA; } /* Initialise enough workspace for 4 frames initially */ if ((gif->frames = (gif_frame *)malloc(sizeof(gif_frame))) == NULL) { gif_finalise(gif); return GIF_INSUFFICIENT_MEMORY; } gif->frame_holders = 1; /* Initialise the sprite header */ assert(gif->bitmap_callbacks.bitmap_create); if ((gif->frame_image = gif->bitmap_callbacks.bitmap_create(gif->width, gif->height)) == NULL) { gif_finalise(gif); return GIF_INSUFFICIENT_MEMORY; } /* Remember we've done this now */ gif->buffer_position = gif_data - gif->gif_data; } /* Do the colour map if we haven't already. As the top byte is always 0xff or 0x00 depending on the transparency we know if it's been filled in. */ if (gif->global_colour_table[0] == GIF_PROCESS_COLOURS) { /* Check for a global colour map signified by bit 7 */ if (gif->global_colours) { if (gif->buffer_size < (gif->colour_table_size * 3 + 12)) { return GIF_INSUFFICIENT_DATA; } for (index = 0; index < gif->colour_table_size; index++) { /* Gif colour map contents are r,g,b. * * We want to pack them bytewise into the * colour table, such that the red component * is in byte 0 and the alpha component is in * byte 3. */ unsigned char *entry = (unsigned char *) &gif-> global_colour_table[index]; entry[0] = gif_data[0]; /* r */ entry[1] = gif_data[1]; /* g */ entry[2] = gif_data[2]; /* b */ entry[3] = 0xff; /* a */ gif_data += 3; } gif->buffer_position = (gif_data - gif->gif_data); } else { /* Create a default colour table with the first two colours as black and white */ unsigned int *entry = gif->global_colour_table; entry[0] = 0x00000000; /* Force Alpha channel to opaque */ ((unsigned char *) entry)[3] = 0xff; entry[1] = 0xffffffff; } } /* Repeatedly try to initialise frames */ while ((return_value = gif_initialise_frame(gif)) == GIF_WORKING); /* If there was a memory error tell the caller */ if ((return_value == GIF_INSUFFICIENT_MEMORY) || (return_value == GIF_DATA_ERROR)) return return_value; /* If we didn't have some frames then a GIF_INSUFFICIENT_DATA becomes a GIF_INSUFFICIENT_FRAME_DATA */ if ((return_value == GIF_INSUFFICIENT_DATA) && (gif->frame_count_partial > 0)) return GIF_INSUFFICIENT_FRAME_DATA; /* Return how many we got */ return return_value; } /** Updates the sprite memory size @return GIF_INSUFFICIENT_MEMORY for a memory error GIF_OK for success */ static gif_result gif_initialise_sprite(gif_animation *gif, unsigned int width, unsigned int height) { unsigned int max_width; unsigned int max_height; struct bitmap *buffer; /* Check if we've changed */ if ((width <= gif->width) && (height <= gif->height)) return GIF_OK; /* Get our maximum values */ max_width = (width > gif->width) ? width : gif->width; max_height = (height > gif->height) ? height : gif->height; /* Allocate some more memory */ assert(gif->bitmap_callbacks.bitmap_create); if ((buffer = gif->bitmap_callbacks.bitmap_create(max_width, max_height)) == NULL) return GIF_INSUFFICIENT_MEMORY; assert(gif->bitmap_callbacks.bitmap_destroy); gif->bitmap_callbacks.bitmap_destroy(gif->frame_image); gif->frame_image = buffer; gif->width = max_width; gif->height = max_height; /* Invalidate our currently decoded image */ gif->decoded_frame = GIF_INVALID_FRAME; return GIF_OK; } /** Attempts to initialise the next frame @return GIF_INSUFFICIENT_DATA for insufficient data to do anything GIF_FRAME_DATA_ERROR for GIF frame data error GIF_INSUFFICIENT_MEMORY for insufficient memory to process GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame GIF_DATA_ERROR for GIF error (invalid frame header) GIF_OK for successful decoding GIF_WORKING for successful decoding if more frames are expected */ static gif_result gif_initialise_frame(gif_animation *gif) { int frame; gif_frame *temp_buf; unsigned char *gif_data, *gif_end; int gif_bytes; unsigned int flags = 0; unsigned int width, height, offset_x, offset_y; unsigned int block_size, colour_table_size; bool first_image = true; gif_result return_value; /* Get the frame to decode and our data position */ frame = gif->frame_count; /* Get our buffer position etc. */ gif_data = (unsigned char *)(gif->gif_data + gif->buffer_position); gif_end = (unsigned char *)(gif->gif_data + gif->buffer_size); gif_bytes = (gif_end - gif_data); /* Check if we've finished */ if ((gif_bytes > 0) && (gif_data[0] == GIF_TRAILER)) return GIF_OK; /* Check if we have enough data * The shortest block of data is a 4-byte comment extension + 1-byte block terminator + 1-byte gif trailer */ if (gif_bytes < 6) return GIF_INSUFFICIENT_DATA; /* We could theoretically get some junk data that gives us millions of frames, so we ensure that we don't have a silly number */ if (frame > 4096) return GIF_FRAME_DATA_ERROR; /* Get some memory to store our pointers in etc. */ if ((int)gif->frame_holders <= frame) { /* Allocate more memory */ if ((temp_buf = (gif_frame *)realloc(gif->frames, (frame + 1) * sizeof(gif_frame))) == NULL) return GIF_INSUFFICIENT_MEMORY; gif->frames = temp_buf; gif->frame_holders = frame + 1; } /* Store our frame pointer. We would do it when allocating except we start off with one frame allocated so we can always use realloc. */ gif->frames[frame].frame_pointer = gif->buffer_position; gif->frames[frame].display = false; gif->frames[frame].virgin = true; gif->frames[frame].disposal_method = 0; gif->frames[frame].transparency = false; gif->frames[frame].frame_delay = 100; gif->frames[frame].redraw_required = false; /* Invalidate any previous decoding we have of this frame */ if (gif->decoded_frame == frame) gif->decoded_frame = GIF_INVALID_FRAME; /* We pretend to initialise the frames, but really we just skip over all the data contained within. This is all basically a cut down version of gif_decode_frame that doesn't have any of the LZW bits in it. */ /* Initialise any extensions */ gif->buffer_position = gif_data - gif->gif_data; if ((return_value = gif_initialise_frame_extensions(gif, frame)) != GIF_OK) return return_value; gif_data = (gif->gif_data + gif->buffer_position); gif_bytes = (gif_end - gif_data); /* Check if we've finished */ if ((gif_bytes = (gif_end - gif_data)) < 1) return GIF_INSUFFICIENT_FRAME_DATA; else if (gif_data[0] == GIF_TRAILER) { gif->buffer_position = (gif_data - gif->gif_data); gif->frame_count = frame + 1; return GIF_OK; } /* If we're not done, there should be an image descriptor */ if (gif_data[0] != GIF_IMAGE_SEPARATOR) return GIF_FRAME_DATA_ERROR; /* Do some simple boundary checking */ offset_x = gif_data[1] | (gif_data[2] << 8); offset_y = gif_data[3] | (gif_data[4] << 8); width = gif_data[5] | (gif_data[6] << 8); height = gif_data[7] | (gif_data[8] << 8); /* Set up the redraw characteristics. We have to check for extending the area due to multi-image frames. */ if (!first_image) { if (gif->frames[frame].redraw_x > offset_x) { gif->frames[frame].redraw_width += (gif->frames[frame].redraw_x - offset_x); gif->frames[frame].redraw_x = offset_x; } if (gif->frames[frame].redraw_y > offset_y) { gif->frames[frame].redraw_height += (gif->frames[frame].redraw_y - offset_y); gif->frames[frame].redraw_y = offset_y; } if ((offset_x + width) > (gif->frames[frame].redraw_x + gif->frames[frame].redraw_width)) gif->frames[frame].redraw_width = (offset_x + width) - gif->frames[frame].redraw_x; if ((offset_y + height) > (gif->frames[frame].redraw_y + gif->frames[frame].redraw_height)) gif->frames[frame].redraw_height = (offset_y + height) - gif->frames[frame].redraw_y; } else { first_image = false; gif->frames[frame].redraw_x = offset_x; gif->frames[frame].redraw_y = offset_y; gif->frames[frame].redraw_width = width; gif->frames[frame].redraw_height = height; } /* if we are clearing the background then we need to redraw enough to cover the previous frame too */ gif->frames[frame].redraw_required = ((gif->frames[frame].disposal_method == GIF_FRAME_CLEAR) || (gif->frames[frame].disposal_method == GIF_FRAME_RESTORE)); /* Boundary checking - shouldn't ever happen except with junk data */ if (gif_initialise_sprite(gif, (offset_x + width), (offset_y + height))) return GIF_INSUFFICIENT_MEMORY; /* Decode the flags */ flags = gif_data[9]; colour_table_size = 2 << (flags & GIF_COLOUR_TABLE_SIZE_MASK); /* Move our data onwards and remember we've got a bit of this frame */ gif_data += 10; gif_bytes = (gif_end - gif_data); gif->frame_count_partial = frame + 1; /* Skip the local colour table */ if (flags & GIF_COLOUR_TABLE_MASK) { gif_data += 3 * colour_table_size; if ((gif_bytes = (gif_end - gif_data)) < 0) return GIF_INSUFFICIENT_FRAME_DATA; } /* Ensure we have a correct code size */ if (gif_data[0] > GIF_MAX_LZW) return GIF_DATA_ERROR; /* Move our pointer to the actual image data */ gif_data++; if (--gif_bytes < 0) return GIF_INSUFFICIENT_FRAME_DATA; /* Repeatedly skip blocks until we get a zero block or run out of data * These blocks of image data are processed later by gif_decode_frame() */ block_size = 0; while (block_size != 1) { block_size = gif_data[0] + 1; /* Check if the frame data runs off the end of the file */ if ((int)(gif_bytes - block_size) < 0) { /* Try to recover by signaling the end of the gif. * Once we get garbage data, there is no logical * way to determine where the next frame is. * It's probably better to partially load the gif * than not at all. */ if (gif_bytes >= 2) { gif_data[0] = 0; gif_data[1] = GIF_TRAILER; gif_bytes = 1; ++gif_data; break; } else return GIF_INSUFFICIENT_FRAME_DATA; } else { gif_bytes -= block_size; gif_data += block_size; } } /* Add the frame and set the display flag */ gif->buffer_position = gif_data - gif->gif_data; gif->frame_count = frame + 1; gif->frames[frame].display = true; /* Check if we've finished */ if (gif_bytes < 1) return GIF_INSUFFICIENT_FRAME_DATA; else if (gif_data[0] == GIF_TRAILER) return GIF_OK; return GIF_WORKING; } /** Attempts to initialise the frame's extensions @return GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame GIF_OK for successful initialisation */ static gif_result gif_initialise_frame_extensions(gif_animation *gif, const int frame) { unsigned char *gif_data, *gif_end; int gif_bytes; unsigned int block_size; /* Get our buffer position etc. */ gif_data = (unsigned char *)(gif->gif_data + gif->buffer_position); gif_end = (unsigned char *)(gif->gif_data + gif->buffer_size); /* Initialise the extensions */ while (gif_data[0] == GIF_EXTENSION_INTRODUCER) { ++gif_data; gif_bytes = (gif_end - gif_data); /* Switch on extension label */ switch(gif_data[0]) { /* 6-byte Graphic Control Extension is: * * +0 CHAR Graphic Control Label * +1 CHAR Block Size * +2 CHAR __Packed Fields__ * 3BITS Reserved * 3BITS Disposal Method * 1BIT User Input Flag * 1BIT Transparent Color Flag * +3 SHORT Delay Time * +5 CHAR Transparent Color Index */ case GIF_EXTENSION_GRAPHIC_CONTROL: if (gif_bytes < 6) return GIF_INSUFFICIENT_FRAME_DATA; gif->frames[frame].frame_delay = gif_data[3] | (gif_data[4] << 8); if (gif_data[2] & GIF_TRANSPARENCY_MASK) { gif->frames[frame].transparency = true; gif->frames[frame].transparency_index = gif_data[5]; } gif->frames[frame].disposal_method = ((gif_data[2] & GIF_DISPOSAL_MASK) >> 2); /* I have encountered documentation and GIFs in the wild that use * 0x04 to restore the previous frame, rather than the officially * documented 0x03. I believe some (older?) software may even actually * export this way. We handle this as a type of "quirks" mode. */ if (gif->frames[frame].disposal_method == GIF_FRAME_QUIRKS_RESTORE) gif->frames[frame].disposal_method = GIF_FRAME_RESTORE; gif_data += (2 + gif_data[1]); break; /* 14-byte+ Application Extension is: * * +0 CHAR Application Extension Label * +1 CHAR Block Size * +2 8CHARS Application Identifier * +10 3CHARS Appl. Authentication Code * +13 1-256 Application Data (Data sub-blocks) */ case GIF_EXTENSION_APPLICATION: if (gif_bytes < 17) return GIF_INSUFFICIENT_FRAME_DATA; if ((gif_data[1] == 0x0b) && (strncmp((const char *) gif_data + 2, "NETSCAPE2.0", 11) == 0) && (gif_data[13] == 0x03) && (gif_data[14] == 0x01)) { gif->loop_count = gif_data[15] | (gif_data[16] << 8); } gif_data += (2 + gif_data[1]); break; /* Move the pointer to the first data sub-block * Skip 1 byte for the extension label */ case GIF_EXTENSION_COMMENT: ++gif_data; break; /* Move the pointer to the first data sub-block * Skip 2 bytes for the extension label and size fields * Skip the extension size itself */ default: gif_data += (2 + gif_data[1]); } /* Repeatedly skip blocks until we get a zero block or run out of data * This data is ignored by this gif decoder */ gif_bytes = (gif_end - gif_data); block_size = 0; while (gif_data[0] != GIF_BLOCK_TERMINATOR) { block_size = gif_data[0] + 1; if ((gif_bytes -= block_size) < 0) return GIF_INSUFFICIENT_FRAME_DATA; gif_data += block_size; } ++gif_data; } /* Set buffer position and return */ gif->buffer_position = (gif_data - gif->gif_data); return GIF_OK; } /** Decodes a GIF frame. @return GIF_FRAME_DATA_ERROR for GIF frame data error GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame GIF_DATA_ERROR for GIF error (invalid frame header) GIF_INSUFFICIENT_DATA for insufficient data to do anything GIF_INSUFFICIENT_MEMORY for insufficient memory to process GIF_OK for successful decoding If a frame does not contain any image data, GIF_OK is returned and gif->current_error is set to GIF_FRAME_NO_DISPLAY */ gif_result gif_decode_frame(gif_animation *gif, unsigned int frame) { unsigned int index = 0; unsigned char *gif_data, *gif_end; int gif_bytes; unsigned int width, height, offset_x, offset_y; unsigned int flags, colour_table_size, interlace; unsigned int *colour_table; unsigned int *frame_data = 0; // Set to 0 for no warnings unsigned int *frame_scanline; unsigned int save_buffer_position; unsigned int return_value = 0; unsigned int x, y, decode_y, burst_bytes; int last_undisposed_frame = (frame - 1); register unsigned char colour; /* Ensure this frame is supposed to be decoded */ if (gif->frames[frame].display == false) { gif->current_error = GIF_FRAME_NO_DISPLAY; return GIF_OK; } /* Ensure we have a frame to decode */ if (frame > gif->frame_count_partial) return GIF_INSUFFICIENT_DATA; if ((!clear_image) && ((int)frame == gif->decoded_frame)) return GIF_OK; /* Get the start of our frame data and the end of the GIF data */ gif_data = gif->gif_data + gif->frames[frame].frame_pointer; gif_end = gif->gif_data + gif->buffer_size; gif_bytes = (gif_end - gif_data); /* Check if we have enough data * The shortest block of data is a 10-byte image descriptor + 1-byte gif trailer */ if (gif_bytes < 12) return GIF_INSUFFICIENT_FRAME_DATA; /* Save the buffer position */ save_buffer_position = gif->buffer_position; gif->buffer_position = gif_data - gif->gif_data; /* Skip any extensions because we all ready processed them */ if ((return_value = gif_skip_frame_extensions(gif)) != GIF_OK) goto gif_decode_frame_exit; gif_data = (gif->gif_data + gif->buffer_position); gif_bytes = (gif_end - gif_data); /* Ensure we have enough data for the 10-byte image descriptor + 1-byte gif trailer */ if (gif_bytes < 12) { return_value = GIF_INSUFFICIENT_FRAME_DATA; goto gif_decode_frame_exit; } /* 10-byte Image Descriptor is: * * +0 CHAR Image Separator (0x2c) * +1 SHORT Image Left Position * +3 SHORT Image Top Position * +5 SHORT Width * +7 SHORT Height * +9 CHAR __Packed Fields__ * 1BIT Local Colour Table Flag * 1BIT Interlace Flag * 1BIT Sort Flag * 2BITS Reserved * 3BITS Size of Local Colour Table */ if (gif_data[0] != GIF_IMAGE_SEPARATOR) { return_value = GIF_DATA_ERROR; goto gif_decode_frame_exit; } offset_x = gif_data[1] | (gif_data[2] << 8); offset_y = gif_data[3] | (gif_data[4] << 8); width = gif_data[5] | (gif_data[6] << 8); height = gif_data[7] | (gif_data[8] << 8); /* Boundary checking - shouldn't ever happen except unless the data has been modified since initialisation. */ if ((offset_x + width > gif->width) || (offset_y + height > gif->height)) { return_value = GIF_DATA_ERROR; goto gif_decode_frame_exit; } /* Decode the flags */ flags = gif_data[9]; colour_table_size = 2 << (flags & GIF_COLOUR_TABLE_SIZE_MASK); interlace = flags & GIF_INTERLACE_MASK; /* Move our pointer to the colour table or image data (if no colour table is given) */ gif_data += 10; gif_bytes = (gif_end - gif_data); /* Set up the colour table */ if (flags & GIF_COLOUR_TABLE_MASK) { if (gif_bytes < (int)(3 * colour_table_size)) { return_value = GIF_INSUFFICIENT_FRAME_DATA; goto gif_decode_frame_exit; } colour_table = gif->local_colour_table; if (!clear_image) { for (index = 0; index < colour_table_size; index++) { /* Gif colour map contents are r,g,b. * * We want to pack them bytewise into the * colour table, such that the red component * is in byte 0 and the alpha component is in * byte 3. */ unsigned char *entry = (unsigned char *) &colour_table[index]; entry[0] = gif_data[0]; /* r */ entry[1] = gif_data[1]; /* g */ entry[2] = gif_data[2]; /* b */ entry[3] = 0xff; /* a */ gif_data += 3; } } else { gif_data += 3 * colour_table_size; } gif_bytes = (gif_end - gif_data); } else { colour_table = gif->global_colour_table; } /* Check if we've finished */ if (gif_bytes < 1) { return_value = GIF_INSUFFICIENT_FRAME_DATA; goto gif_decode_frame_exit; } else if (gif_data[0] == GIF_TRAILER) { return_value = GIF_OK; goto gif_decode_frame_exit; } /* Get the frame data */ assert(gif->bitmap_callbacks.bitmap_get_buffer); frame_data = (void *)gif->bitmap_callbacks.bitmap_get_buffer(gif->frame_image); if (!frame_data) return GIF_INSUFFICIENT_MEMORY; /* If we are clearing the image we just clear, if not decode */ if (!clear_image) { /* Ensure we have enough data for a 1-byte LZW code size + 1-byte gif trailer */ if (gif_bytes < 2) { return_value = GIF_INSUFFICIENT_FRAME_DATA; goto gif_decode_frame_exit; /* If we only have a 1-byte LZW code size + 1-byte gif trailer, we're finished */ } else if ((gif_bytes == 2) && (gif_data[1] == GIF_TRAILER)) { return_value = GIF_OK; goto gif_decode_frame_exit; } /* If the previous frame's disposal method requires we restore the background * colour or this is the first frame, clear the frame data */ if ((frame == 0) || (gif->decoded_frame == GIF_INVALID_FRAME)) { memset((char*)frame_data, GIF_TRANSPARENT_COLOUR, gif->width * gif->height * sizeof(int)); gif->decoded_frame = frame; /* The line below would fill the image with its background color, but because GIFs support * transparency we likely wouldn't want to do that. */ /* memset((char*)frame_data, colour_table[gif->background_index], gif->width * gif->height * sizeof(int)); */ } else if ((frame != 0) && (gif->frames[frame - 1].disposal_method == GIF_FRAME_CLEAR)) { clear_image = true; if ((return_value = gif_decode_frame(gif, (frame - 1))) != GIF_OK) goto gif_decode_frame_exit; clear_image = false; /* If the previous frame's disposal method requires we restore the previous * image, find the last image set to "do not dispose" and get that frame data */ } else if ((frame != 0) && (gif->frames[frame - 1].disposal_method == GIF_FRAME_RESTORE)) { while ((last_undisposed_frame != -1) && (gif->frames[--last_undisposed_frame].disposal_method == GIF_FRAME_RESTORE)); /* If we don't find one, clear the frame data */ if (last_undisposed_frame == -1) { /* see notes above on transparency vs. background color */ memset((char*)frame_data, GIF_TRANSPARENT_COLOUR, gif->width * gif->height * sizeof(int)); } else { if ((return_value = gif_decode_frame(gif, last_undisposed_frame)) != GIF_OK) goto gif_decode_frame_exit; /* Get this frame's data */ assert(gif->bitmap_callbacks.bitmap_get_buffer); frame_data = (void *)gif->bitmap_callbacks.bitmap_get_buffer(gif->frame_image); if (!frame_data) return GIF_INSUFFICIENT_MEMORY; } } gif->decoded_frame = frame; /* Initialise the LZW decoding */ set_code_size = gif_data[0]; gif->buffer_position = (gif_data - gif->gif_data) + 1; /* Set our code variables */ code_size = set_code_size + 1; clear_code = (1 << set_code_size); end_code = clear_code + 1; max_code_size = clear_code << 1; max_code = clear_code + 2; curbit = lastbit = 0; last_byte = 2; get_done = false; direct = buf; gif_init_LZW(gif); /* Decompress the data */ for (y = 0; y < height; y++) { if (interlace) decode_y = gif_interlaced_line(height, y) + offset_y; else decode_y = y + offset_y; frame_scanline = frame_data + offset_x + (decode_y * gif->width); /* Rather than decoding pixel by pixel, we try to burst out streams of data to remove the need for end-of data checks every pixel. */ x = width; while (x > 0) { burst_bytes = (stack_pointer - stack); if (burst_bytes > 0) { if (burst_bytes > x) burst_bytes = x; x -= burst_bytes; while (burst_bytes-- > 0) { colour = *--stack_pointer; if (((gif->frames[frame].transparency) && (colour != gif->frames[frame].transparency_index)) || (!gif->frames[frame].transparency)) *frame_scanline = colour_table[colour]; frame_scanline++; } } else { if (!gif_next_LZW(gif)) { /* Unexpected end of frame, try to recover */ if (gif->current_error == GIF_END_OF_FRAME) return_value = GIF_OK; else return_value = gif->current_error; goto gif_decode_frame_exit; } } } } } else { /* Clear our frame */ if (gif->frames[frame].disposal_method == GIF_FRAME_CLEAR) { for (y = 0; y < height; y++) { frame_scanline = frame_data + offset_x + ((offset_y + y) * gif->width); if (gif->frames[frame].transparency) memset(frame_scanline, GIF_TRANSPARENT_COLOUR, width * 4); else memset(frame_scanline, colour_table[gif->background_index], width * 4); } } } gif_decode_frame_exit: /* Check if we should test for optimisation */ if (gif->frames[frame].virgin) { if (gif->bitmap_callbacks.bitmap_test_opaque) gif->frames[frame].opaque = gif->bitmap_callbacks.bitmap_test_opaque(gif->frame_image); else gif->frames[frame].opaque = false; gif->frames[frame].virgin = false; } if (gif->bitmap_callbacks.bitmap_set_opaque) gif->bitmap_callbacks.bitmap_set_opaque(gif->frame_image, gif->frames[frame].opaque); if (gif->bitmap_callbacks.bitmap_modified) gif->bitmap_callbacks.bitmap_modified(gif->frame_image); /* Restore the buffer position */ gif->buffer_position = save_buffer_position; /* Success! */ return return_value; } /** Skips the frame's extensions (which have been previously initialised) @return GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame GIF_OK for successful decoding */ static gif_result gif_skip_frame_extensions(gif_animation *gif) { unsigned char *gif_data, *gif_end; int gif_bytes; unsigned int block_size; /* Get our buffer position etc. */ gif_data = (unsigned char *)(gif->gif_data + gif->buffer_position); gif_end = (unsigned char *)(gif->gif_data + gif->buffer_size); gif_bytes = (gif_end - gif_data); /* Skip the extensions */ while (gif_data[0] == GIF_EXTENSION_INTRODUCER) { ++gif_data; /* Switch on extension label */ switch(gif_data[0]) { /* Move the pointer to the first data sub-block * 1 byte for the extension label */ case GIF_EXTENSION_COMMENT: ++gif_data; break; /* Move the pointer to the first data sub-block * 2 bytes for the extension label and size fields * Skip the extension size itself */ default: gif_data += (2 + gif_data[1]); } /* Repeatedly skip blocks until we get a zero block or run out of data * This data is ignored by this gif decoder */ gif_bytes = (gif_end - gif_data); block_size = 0; while (gif_data[0] != GIF_BLOCK_TERMINATOR) { block_size = gif_data[0] + 1; if ((gif_bytes -= block_size) < 0) return GIF_INSUFFICIENT_FRAME_DATA; gif_data += block_size; } ++gif_data; } /* Set buffer position and return */ gif->buffer_position = (gif_data - gif->gif_data); return GIF_OK; } static unsigned int gif_interlaced_line(int height, int y) { if ((y << 3) < height) return (y << 3); y -= ((height + 7) >> 3); if ((y << 3) < (height - 4)) return (y << 3) + 4; y -= ((height + 3) >> 3); if ((y << 2) < (height - 2)) return (y << 2) + 2; y -= ((height + 1) >> 2); return (y << 1) + 1; } /* Releases any workspace held by the animation */ void gif_finalise(gif_animation *gif) { /* Release all our memory blocks */ if (gif->frame_image) { assert(gif->bitmap_callbacks.bitmap_destroy); gif->bitmap_callbacks.bitmap_destroy(gif->frame_image); } gif->frame_image = NULL; free(gif->frames); gif->frames = NULL; free(gif->local_colour_table); gif->local_colour_table = NULL; free(gif->global_colour_table); gif->global_colour_table = NULL; } /** * Initialise LZW decoding */ void gif_init_LZW(gif_animation *gif) { int i; gif->current_error = 0; if (clear_code >= (1 << GIF_MAX_LZW)) { stack_pointer = stack; gif->current_error = GIF_FRAME_DATA_ERROR; return; } /* initialise our table */ memset(table, 0x00, (1 << GIF_MAX_LZW) * 8); for (i = 0; i < clear_code; ++i) table[1][i] = i; /* update our LZW parameters */ code_size = set_code_size + 1; max_code_size = clear_code << 1; max_code = clear_code + 2; stack_pointer = stack; do { firstcode = oldcode = gif_next_code(gif, code_size); } while (firstcode == clear_code); *stack_pointer++ =firstcode; } static bool gif_next_LZW(gif_animation *gif) { int code, incode; int block_size; int new_code; code = gif_next_code(gif, code_size); if (code < 0) { gif->current_error = code; return false; } else if (code == clear_code) { gif_init_LZW(gif); return true; } else if (code == end_code) { /* skip to the end of our data so multi-image GIFs work */ if (zero_data_block) { gif->current_error = GIF_FRAME_DATA_ERROR; return false; } block_size = 0; while (block_size != 1) { block_size = gif->gif_data[gif->buffer_position] + 1; gif->buffer_position += block_size; } gif->current_error = GIF_FRAME_DATA_ERROR; return false; } incode = code; if (code >= max_code) { *stack_pointer++ = firstcode; code = oldcode; } /* The following loop is the most important in the GIF decoding cycle as every * single pixel passes through it. * * Note: our stack is always big enough to hold a complete decompressed chunk. */ while (code >= clear_code) { *stack_pointer++ = table[1][code]; new_code = table[0][code]; if (new_code < clear_code) { code = new_code; break; } *stack_pointer++ = table[1][new_code]; code = table[0][new_code]; if (code == new_code) { gif->current_error = GIF_FRAME_DATA_ERROR; return false; } } *stack_pointer++ = firstcode = table[1][code]; if ((code = max_code) < (1 << GIF_MAX_LZW)) { table[0][code] = oldcode; table[1][code] = firstcode; ++max_code; if ((max_code >= max_code_size) && (max_code_size < (1 << GIF_MAX_LZW))) { max_code_size = max_code_size << 1; ++code_size; } } oldcode = incode; return true; } static int gif_next_code(gif_animation *gif, int code_size) { int i, j, end, count, ret; unsigned char *b; end = curbit + code_size; if (end >= lastbit) { if (get_done) return GIF_END_OF_FRAME; buf[0] = direct[last_byte - 2]; buf[1] = direct[last_byte - 1]; /* get the next block */ direct = gif->gif_data + gif->buffer_position; zero_data_block = ((count = direct[0]) == 0); if ((gif->buffer_position + count) >= gif->buffer_size) return GIF_INSUFFICIENT_FRAME_DATA; if (count == 0) get_done = true; else { direct -= 1; buf[2] = direct[2]; buf[3] = direct[3]; } gif->buffer_position += count + 1; /* update our variables */ last_byte = 2 + count; curbit = (curbit - lastbit) + 16; lastbit = (2 + count) << 3; end = curbit + code_size; } i = curbit >> 3; if (i < 2) b = buf; else b = direct; ret = b[i]; j = (end >> 3) - 1; if (i <= j) { ret |= (b[i + 1] << 8); if (i < j) ret |= (b[i + 2] << 16); } ret = (ret >> (curbit % 8)) & maskTbl[code_size]; curbit += code_size; return ret; } netsurf-2.9/libnsgif-0.0.3/src/Makefile0000664000175000017500000000011511163550400016516 0ustar vincevince# Sources DIR_SOURCES := libnsgif.c include build/makefiles/Makefile.subdir netsurf-2.9/libnsgif-0.0.3/src/utils/0000775000175000017500000000000011734430266016234 5ustar vincevincenetsurf-2.9/libnsgif-0.0.3/src/utils/log.h0000664000175000017500000000103211060174716017157 0ustar vincevince/* * Copyright 2003 James Bursa * Copyright 2004 John Tytgat * * This file is part of NetSurf, http://www.netsurf-browser.org/ * Licenced under the MIT License, * http://www.opensource.org/licenses/mit-license.php */ #include #ifndef _LIBNSGIF_LOG_H_ #define _LIBNSGIF_LOG_H_ #ifdef NDEBUG # define LOG(x) ((void) 0) #else # define LOG(x) do { fprintf(stderr, x), fputc('\n', stderr); } while (0) #endif /* NDEBUG */ #endif /* _LIBNSGIF_LOG_H_ */ netsurf-2.9/libnsgif-0.0.3/bin/0000775000175000017500000000000011734430267015056 5ustar vincevincenetsurf-2.9/libnsgif-0.0.3/gif_display0000775000175000017500000000005011027263070016510 0ustar vincevinceset -e make bin/decode_gif $1 | display netsurf-2.9/libnsgif-0.0.3/Makefile0000664000175000017500000000171611547272514015754 0ustar vincevince# Component settings COMPONENT := nsgif COMPONENT_VERSION := 0.0.3 # Default to a static library COMPONENT_TYPE ?= lib-static # Setup the tooling include build/makefiles/Makefile.tools # Toolchain flags WARNFLAGS := -Wall -W -Wundef -Wpointer-arith -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ -Wmissing-declarations -Wnested-externs -pedantic # BeOS/Haiku standard library headers create warnings ifneq ($(TARGET),beos) WARNFLAGS := $(WARNFLAGS) -Werror endif CFLAGS := -D_BSD_SOURCE -I$(CURDIR)/include/ \ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS) ifneq ($(GCCVER),2) CFLAGS := $(CFLAGS) -std=c99 else # __inline__ is a GCCism CFLAGS := $(CFLAGS) -Dinline="__inline__" endif include build/makefiles/Makefile.top # Extra installation rules I := /include INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/libnsgif.h INSTALL_ITEMS := $(INSTALL_ITEMS) /lib/pkgconfig:lib$(COMPONENT).pc.in INSTALL_ITEMS := $(INSTALL_ITEMS) /lib:$(OUTPUT) netsurf-2.9/libnsgif-0.0.3/COPYING0000664000175000017500000000210711060174716015335 0ustar vincevinceCopyright (C) 2004 Richard Wilson Copyright (C) 2008 Sean Fox Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. netsurf-2.9/libnsgif-0.0.3/build/0000775000175000017500000000000011734430271015400 5ustar vincevincenetsurf-2.9/libnsgif-0.0.3/build/makefiles/0000775000175000017500000000000011734430272017341 5ustar vincevincenetsurf-2.9/libnsgif-0.0.3/build/makefiles/Makefile.top0000664000175000017500000004232311537116272021610 0ustar vincevince# Top-level Makefile fragment # # Expected inputs: # # BUILD Type of build to perform: # release - Release build # debug - Debug build # COMPONENT Name of the component (sans leading "lib" iff a library) # COMPONENT_VERSION Component version number (x.y.z) # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # TARGET Target platform identifier # # Optional inputs: # # BUILDDIR Directory to build into (defaults to # build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE)) # CC_CAN_BUILD_AND_DEP Flag whether $(CC) is capable of calculating dependency # information at the same time as compiling sources. # Set to "yes" if it can. # DESTDIR Sandboxed FS root (e.g. for packaging) # HOST Host platform identifier # REQUIRED_PKGS List of required pkg-config packages # # The client may also override all toolchain settings, including: # # ARFLAGS Archiver flags for the current compilation # CFLAGS C compiler flags for the current compilation # CXXFLAGS C++ compiler flags for the current compilation # LDFLAGS Linker flags for the current compilation # # TESTCFLAGS Any test-specific CFLAGS # TESTCXXFLAGS Any test-specific CXXFLAGS # TESTLDFLAGS Any test-specific LDFLAGS # # TESTRUNNER Test runner invocation command # The test runner takes a command line in the form # # # Targets provided: # # all Default target. Builds component using current settings # test Build and run test suite, using current settings. # coverage Determine test suite coverage (requires lcov) # profile Build with profiling support enabled (requires gprof) # docs Produce documentation (requires doxygen) # clean Clean the build # distclean Remove distribution files, too # install Install component into prefix. # uninstall Remove component from prefix. # # Variables provided: # # major-version Extracts the major version (x) from COMPONENT_VERSION # minor-version Extracts the minor version (y) from COMPONENT_VERSION # patch-version Extracts the patch version (z) from COMPONENT_VERSION # OUTPUT Path + filename of build target ############################################################################### # Sanity checks ############################################################################### # Name of component must be defined by client ifeq ($(COMPONENT),) $(error COMPONENT not defined) endif # As must the version ifeq ($(COMPONENT_VERSION),) $(error COMPONENT_VERSION not defined) endif # As must the component type ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not defined) endif # Target platform must be defined by the client ifeq ($(TARGET),) $(error TARGET not defined) endif # Build type, too ifeq ($(BUILD),) $(error BUILD not defined) endif ############################################################################## # Makefile variables ############################################################################## Q ?= @ VQ ?= @ ############################################################################## # Exported variables (also OUTPUT, further down) ############################################################################## major-version := $(word 1,$(subst ., ,$(COMPONENT_VERSION))) minor-version := $(word 2,$(subst ., ,$(COMPONENT_VERSION))) patch-version := $(word 3,$(subst ., ,$(COMPONENT_VERSION))) ############################################################################## # Build environment ############################################################################## # Build directory BUILDDIR ?= build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE) # Build tree subdirs COVERAGEDIR := $(BUILDDIR)/coverage DOCDIR := $(BUILDDIR)/docs # Determine if we want to build testcases ifeq ($(MAKECMDGOALS),test) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),profile) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),coverage) WANT_TEST := yes else WANT_TEST := no endif # List of items to delete on clean CLEAN_ITEMS := # List of items to delete on distclean DISTCLEAN_ITEMS := # List of items to build for testing TEST_ITEMS := # List of targets to run for testing TEST_TARGETS := # List of targets which are prerequisites for running tests TEST_PREREQS := # List of items to (un)install INSTALL_ITEMS := # List of targets to run before building $(OBJECT) PRE_TARGETS := # List of targets to run after building $(OBJECT) POST_TARGETS := # Source files SOURCES := # Include configuration Makefile fragment -include Makefile.config # Set the default target (before including any children) __default: all # Include Makefile fragments in subdirectories define do_include DIR := $$(dir $(1)) include $(1) endef MAKE_INCLUDES := $(wildcard */Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Calculate objects to build OBJECTS := $(addprefix $(BUILDDIR)/,$(filter %.o, \ $(subst /,_,$(subst .c,.o,$(SOURCES))) \ $(subst /,_,$(subst .cpp,.o,$(SOURCES))) \ $(subst /,_,$(subst .cmhg,.o,$(SOURCES))) \ $(subst /,_,$(subst .s,.o,$(SOURCES))))) bin_for_test = $(addprefix $(BUILDDIR)/,$(firstword $(subst :, ,$(ITEM)))) TEST_BINARIES := $(foreach ITEM,$(TEST_ITEMS),$(bin_for_test)) # Determine if we're building any C++ sources ifneq ($(filter %.cpp,$(SOURCES)),) CXX_IN_BUILD := yes else CXX_IN_BUILD := no endif # Determine the output filename ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) ifeq ($(findstring lib-shared,$(COMPONENT_TYPE)),lib-shared) SHAREDLIBNAME := lib$(COMPONENT)$(LIBEXT) SONAME := $(SHAREDLIBNAME).$(major-version) OUTPUT := $(BUILDDIR)/$(SHAREDLIBNAME).$(COMPONENT_VERSION) else OUTPUT := $(BUILDDIR)/lib$(COMPONENT)$(LIBEXT) endif else OUTPUT := $(BUILDDIR)/$(COMPONENT)$(EXEEXT) endif ############################################################################### # Build targets ############################################################################### .PHONY: all test coverage profile docs clean distclean install uninstall \ __default __precov __partial_clean __postshared ifeq ($(COMPONENT_TYPE),lib-shared) POST_TARGETS := __postshared $(POST_TARGETS) __postshared: $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SONAME) $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SHAREDLIBNAME) endif # Default target all: $(PRE_TARGETS) $(OUTPUT) $(POST_TARGETS) # Build and execute testsuite test: all $(TEST_PREREQS) $(TEST_BINARIES) $(TEST_TARGETS) $(VQ)$(ECHO) $(ECHOFLAGS) " TEST: Testing complete" # Compute coverage __precov: __partial_clean $(Q)$(LCOV) --directory . --zerocounters coverage: __precov test $(Q)$(LCOV) --directory $(BUILDDIR) --base-directory $(CURDIR) \ --capture --output-file $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(LCOV) --extract $(COVERAGEDIR)/$(COMPONENT)_tmp.info \ "$(CURDIR)/src*" -o $(COVERAGEDIR)/$(COMPONENT).info $(Q)$(RM) $(RMFLAGS) $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(GENHTML) -o $(COVERAGEDIR) --num-spaces 2 \ $(COVERAGEDIR)/$(COMPONENT).info # Build for profiling profile: __partial_clean test # Compile documentation docs: $(BUILDDIR)/stamp $(Q)$(DOXYGEN) build/Doxyfile # Clean build tree __partial_clean: -$(Q)$(RM) $(RMFLAGS) $(CLEAN_ITEMS) -$(Q)$(RM) $(RMFLAGS) gmon.out -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.d) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcda) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcno) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.o) clean: __partial_clean -$(Q)$(RM) $(RMFLAGS) -r build/docs -$(Q)$(RM) $(RMFLAGS) -r $(BUILDDIR) # Remove auto-generated non-build-tree items distclean: clean -$(Q)$(RM) $(RMFLAGS) $(DISTCLEAN_ITEMS) # The installation target, and associated canned command sequences. # For reference, the syntax of INSTALL_ITEMS is: # # :[';']* # # We also permit a trailing ';' in the file list. __comma := , __empty := __space := $(empty) $(empty) __required = $(if $(REQUIRED_PKGS),Requires: $(subst $(__space),$(__comma) ,$(strip $(REQUIRED_PKGS))),) # Install a pkg-config control file ($1) to the specified location ($2) define install_pkgconfig $(Q)$(ECHO) $(ECHOFLAGS) "sed -e... $1 >$(BUILDDIR)/$(1:.in=)" $(Q)$(SED) \ -e 's#PREFIX#$(PREFIX)#' \ -e 's#MAJOR#$(major-version)#' \ -e 's#MINOR#$(minor-version)#' \ -e 's#PATCH#$(patch-version)#' \ -e 's#VERSION#$(COMPONENT_VERSION)#' \ -e 's#REQUIRED#$(__required)#' \ $1 >$(BUILDDIR)/$(1:.in=) $(INSTALL) $(INSTALLFLAGS) -m 644 $(BUILDDIR)/$(1:.in=) \ $2/$(1:.in=) endef # TODO: Is this scheme portable? define install_shared_lib $(INSTALL) $(INSTALLFLAGS) -m 755 $1 $2/$(notdir $1) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SONAME) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SHAREDLIBNAME) endef # Install a file ($1) to the specified location ($2) define install_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(call install_pkgconfig,$1,$2), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call install_shared_lib,$1,$2), \ $(INSTALL) $(INSTALLFLAGS) -m 644 $1 $2))) endef # Install a list of files ($2) to the specified location ($1) # We create the installation location if it doesn't already exist define install_to_dest $(Q)$(MKDIR) $(MKDIRFLAGS) $(DESTDIR)$(PREFIX)$1 $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call install_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef install: all $(foreach ITEM,$(INSTALL_ITEMS), \ $(call install_to_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) # Uninstallation # TODO: Work out how to safely remove symlinks define uninstall_shared_lib $(RM) $(RMFLAGS) $2/$(notdir $1).$(COMPONENT_VERSION) endef # Uninstall a file ($1) from the specified location ($2) define uninstall_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(RM) $(RMFLAGS) $2/$(1:.pc.in=.pc), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call uninstall_shared_lib,$1,$2), \ $(RM) $(RMFLAGS) $2/$(notdir $1)))) endef # Uninstall a list of files ($2) from the specified location ($1) # TODO: Come up with a safe way of removing directories, too define uninstall_from_dest $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call uninstall_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef uninstall: $(foreach ITEM,$(INSTALL_ITEMS), \ $(call uninstall_from_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) ############################################################################### # Actual rules ############################################################################### $(BUILDDIR)/stamp: $(Q)$(MKDIR) $(MKDIRFLAGS) $(BUILDDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(COVERAGEDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(DOCDIR) $(Q)$(TOUCH) $(TOUCHFLAGS) $(BUILDDIR)/stamp $(OUTPUT): $(BUILDDIR)/stamp $(OBJECTS) ifeq ($(COMPONENT_TYPE),lib-static) $(VQ)$(ECHO) $(ECHOFLAGS) " AR: $@" $(Q)$(RM) $(RMFLAGS) $@ $(Q)$(AR) $(ARFLAGS) $@ $(OBJECTS) else $(VQ)$(ECHO) $(ECHOFLAGS) " LINK: $@" ifeq ($(CXX_IN_BUILD),yes) $(Q)$(CXX) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) else $(Q)$(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) endif endif ############################################################################### # Autogenerated, implied rules ############################################################################### DEPFILES := BUILDFILES := ifeq ($(CC_CAN_BUILD_AND_DEP),yes) # C compiler can compile and dep simultaneously define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else ifeq ($(CC_CANNOT_DEP),yes) # C compiler cannot calculate dependencies define dep_c endef define dep_cxx endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else # C compiler must calculate dependencies first, then compile (default) define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CC) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CXX) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef endif endif define build_cmhg ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " CMHG: $1" $$(Q)$$(CMHG) $$(CMHGFLAGS) $1 -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_s ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) "ASSEMBLE: $1" $$(Q)$$(CC) $$($3) $1 -c -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef BUILDCFLAGS = $(CFLAGS) $(SHAREDCFLAGS) BUILDCXXFLAGS = $(CXXFLAGS) $(SHAREDCXXFLAGS) BUILDASFLAGS = $(ASFLAGS) $(SHAREDCFLAGS) # Generate dependency rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),BUILDCXXFLAGS))) # Generate compilation rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),BUILDCXXFLAGS))) $(eval $(foreach SOURCE,$(filter %.cmhg,$(SOURCES)), \ $(call build_cmhg,$(SOURCE),$(subst /,_,$(SOURCE:.cmhg=.o))))) $(eval $(foreach SOURCE,$(filter %.s,$(SOURCES)), \ $(call build_s,$(SOURCE),$(subst /,_,$(SOURCE:.s=.o)),BUILDASFLAGS))) # Similarly for test sources ifeq ($(WANT_TEST),yes) ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) TESTLIB := $(OUTPUT) TESTLDFLAGS += -L$(BUILDDIR)/ -l$(COMPONENT) endif TESTCFLAGS := $(CFLAGS) $(TESTCFLAGS) TESTCXXFLAGS += $(CXXFLAGS) TESTLDFLAGS += $(LDFLAGS) define link_test $2: $($3) $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " LINK: $2" ifeq ($$(CXX_IN_BUILD),yes) $$(Q)$$(CXX) -o $$@ $1 $$($4) else $$(Q)$$(CC) -o $$@ $1 $$($4) endif endef srcs_for_test = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) objs_for_test = $(addprefix $(BUILDDIR)/, \ $(subst /,_,$(addsuffix .o,$(basename $(srcs_for_test))))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(call link_test,$(objs_for_test),$(bin_for_test),TESTLIB,TESTLDFLAGS))) endif # Include dependency makefiles ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) -include $(sort $(DEPFILES)) endif netsurf-2.9/libnsgif-0.0.3/build/makefiles/Makefile.clang0000664000175000017500000000232611545435603022072 0ustar vincevince# Clang-specific toolchain setup # We assume that we're using a standard GCC/binutils environment, as well # as clang being mostly GCC-compatible on the command line CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### CC_CAN_BUILD_AND_DEP ?= yes netsurf-2.9/libnsgif-0.0.3/build/makefiles/Makefile.norcroft0000664000175000017500000000220311545435603022634 0ustar vincevince# Norcroft specific toolchain setup CCDEF := -D CCOPT := -Otime CCNOOPT := CCDBG := -g CCINC := -I CCLIB := -L # TODO: Norcroft CC cannot do assembler as C CCAS := CCSHR := CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g LDSHR := ARFLG := -c # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) $(error Coverage is not supported with Norcroft) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) $(error Profile is not supported with Norcroft) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -zM CXXFLAGS := $(CXXFLAGS) -zM LDFLAGS := $(LDFLAGS) -zM endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. CC_CANNOT_DEP := yes netsurf-2.9/libnsgif-0.0.3/build/makefiles/Makefile.gcc0000664000175000017500000000457011545435603021545 0ustar vincevince# GCC specific toolchain setup # We assume that we're using a standard GCC/binutils environment CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions for various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="__attribute__((aligned))" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) COVCFLAGS ?= -fprofile-arcs -ftest-coverage COVCXXFLAGS ?= -fprofile-arcs -ftest-coverage COVLDFLAGS ?= -lgcov CFLAGS := $(CFLAGS) $(COVCFLAGS) CXXFLAGS := $(CXXFLAGS) $(COVCXXFLAGS) LDFLAGS := $(LDFLAGS) $(COVLDFLAGS) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) PROFCFLAGS ?= -pg PROFCXXFLAGS ?= -pg PROFLDFLAGS ?= -pg CFLAGS := $(CFLAGS) $(PROFCFLAGS) CXXFLAGS := $(CXXFLAGS) $(PROFCXXFLAGS) LDFLAGS := $(LDFLAGS) $(PROFLDFLAGS) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -mmodule CXXFLAGS := $(CXXFLAGS) -mmodule LDFLAGS := $(LDFLAGS) -mmodule endif ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CC_CAN_BUILD_AND_DEP := no CC_CANNOT_DEP := yes CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. ccvsn := $(shell $(CC) -dumpversion) # ccvsn = x.y.z GCCVER := $(word 1,$(subst ., ,$(ccvsn))) # GCCVER = x # If the major version (x, above) is not 2, then assume build & dep. # This will break if using a version of GCC < 2, but that's unlikely. ifneq ($(GCCVER),2) CC_CAN_BUILD_AND_DEP ?= yes endif netsurf-2.9/libnsgif-0.0.3/build/makefiles/Makefile.pkgconfig0000664000175000017500000000426511476474557022777 0ustar vincevince# General purpose pkg-config macros # Determine if a package is available # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_available ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package availability) endif ifeq ($$(shell $$(PKGCONFIG) --exists $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Retrieve the version of a package # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif $(1) := $$(shell $$(PKGCONFIG) --version $(2)) endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number define pkg_config_package_min_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number # 4: Highest accepted version number define pkg_config_package_compare_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) ifeq ($$(shell $$(PKGCONFIG) --max-version=$(4) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif else $(1) := no endif endef # Add package to compiler/linker flags # 1: Name of package to add details of # 2: CFLAGS variable to extend, or none # 3: LDFLAGS variable to extend, or none define pkg_config_package_add_flags ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifneq ($(2),) $(2) := $$($(2)) $$(shell $$(PKGCONFIG) --cflags $(1)) endif ifneq ($(3),) $(3) := $$($(3)) $$(shell $$(PKGCONFIG) --libs $(1)) endif endef netsurf-2.9/libnsgif-0.0.3/build/makefiles/Makefile.subdir0000664000175000017500000000741711165262413022277 0ustar vincevince# Child makefile fragment # # Inputs (reset on exit) # # DIR_SOURCES List of source files in this directory # DIR_TEST_ITEMS List of test items in this directory # DIR_INSTALL_ITEMS Items to install in form :; # # Toolchain is provided by top-level makefile # # Variables provided by top-level makefile # # BUILDDIR The location of the build tree root # COMPONENT The name of the component # CURDIR The location of the source tree root # EXPORTDIR The location of the export directory # WANT_TEST Whether to build testcases # # do_include Canned command sequence to include a child makefile # # Variables provided by parent makefile: # # DIR The name of the directory we're in, relative to CURDIR # # Variables we can manipulate: # # CLEAN_ITEMS The list of items to remove for "make clean" # DISTCLEAN_ITEMS The list of items to remove for "make distclean" # TEST_ITEMS The list of items to build for "make test" # TEST_TARGETS The list of target names to run for "make test" # INSTALL_ITEMS The list of items to (un)install # # SOURCES The list of sources to build for $(COMPONENT) # # Plus anything from the toolchain # Push parent directory onto the directory stack sp := $(sp).x dirstack_$(sp) := $(d) d := $(DIR) # Sources SRCS_$(d) := $(DIR_SOURCES) TEST_ITEMS_$(d) := INSTALL_ITEMS_$(d) := # Append to sources for component SOURCES := $(SOURCES) $(addprefix $(d), $(SRCS_$(d))) # Test sources ifeq ($(WANT_TEST),yes) ifneq ($(DIR_TEST_ITEMS),) # Extract the binary name from the ITEM binary = $(subst /,_,$(addprefix $(d),$(firstword $(subst :, ,$(ITEM))))) # Extract the list of sources from the ITEM sources = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) # We can't simply use the output of foreach here, # as it space separates its output, which kinda defeats the point. define append_test_src TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d))$1; endef define append_test TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d)) $1: $$(eval $$(foreach TSRC,$2, \ $$(call append_test_src,$$(addprefix $$(d),$$(TSRC))))) endef # Append test items, prepending $(d) to each source file $(eval $(foreach ITEM,$(DIR_TEST_ITEMS), \ $(call append_test,$(binary),$(sources)))) TEST_ITEMS := $(TEST_ITEMS) $(TEST_ITEMS_$(d)) TEST_TARGETS := $(TEST_TARGETS) test_$(d) # Extract the binary name from the TEST binary_name = $(firstword $(subst :, ,$(TEST))) # Target for tests in this directory test_$(d): $(d) $(addprefix $(BUILDDIR)/, \ $(foreach TEST,$(TEST_ITEMS_$(d)),$(binary_name))) $(Q)$(SHAREDLDPATH) $(TESTRUNNER) $(BUILDDIR) \ $(CURDIR)/$< $(subst /,_,$<) $(EXEEXT) endif endif # Install items ifneq ($(DIR_INSTALL_ITEMS),) # Extract the destination directory from the variable dest_dir = $(firstword $(subst :, ,$(ITEM))) # Extract the list of files to install files = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) define append_install_file INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d))$1; endef define append_install_item INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d)) $1: $$(eval $$(foreach FILE,$2, \ $$(call append_install_file,$$(addprefix $$(d),$$(FILE))))) endef # Append items to install (along with install location), prepending $(d) # to each item in the file list $(eval $(foreach ITEM,$(DIR_INSTALL_ITEMS), \ $(call append_install_item,$(dest_dir),$(files)))) INSTALL_ITEMS := $(INSTALL_ITEMS) $(INSTALL_ITEMS_$(d)) endif # Reset the inputs DIR_SOURCES := DIR_TEST_ITEMS := DIR_INSTALL_ITEMS := # Now include any children we may have MAKE_INCLUDES := $(wildcard $(d)*/Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Pop off the directory stack d := $(dirstack_$(sp)) sp := $(basename $(sp)) netsurf-2.9/libnsgif-0.0.3/build/makefiles/Makefile.tools0000664000175000017500000003224511537136047022152 0ustar vincevince# Tools Makefile fragment # # Expected inputs: # # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # # Optional inputs: # # BUILD Type of build to perform: # release - Release build (default) # debug - Debug build # OPTCFLAGS Optional C compiler flags for $(BUILD) # OPTCXXFLAGS Optional C++ compiler flags for $(BUILD) # OPTLDFLAGS Optional linker flags for $(BUILD) # TARGET Target platform (defaults to host) # PREFIX Absolute installation path prefix # (defaults to /usr/local) # ############################################################################### # Sanity checks ############################################################################### ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not set) endif # Default build to release ifeq ($(BUILD),) BUILD := release endif ############################################################################### # Host/target platform detection ############################################################################### # Autodetect host if necessary ifeq ($(HOST),) HOST := $(shell uname -s) endif # Simple host sanitisation ifeq ($(HOST),) # Don't ask HOST := riscos else ifeq ($(HOST),RISC OS) HOST := riscos endif ifeq ($(HOST),BeOS) HOST := beos endif ifeq ($(HOST),Haiku) HOST := haiku endif ifeq ($(HOST),AmigaOS) HOST := amiga endif ifeq ($(findstring MINGW,$(HOST)),MINGW) HOST := windows endif endif ifeq ($(TARGET),) # Default target to host. Please add exceptions as required. TARGET := $(HOST) ifeq ($(HOST),haiku) # This isn't necessarily correct -- they have differences. However, in the # general case, this will work. If there are differences that are actually # important wrt the target platform (as opposed to the build host) then # we'll just have to introduce a haiku target, too. TARGET := beos endif endif # Sanitise HOST and TARGET # TODO: Ideally, we want the equivalent of s/[^A-Za-z0-9]/_/g here HOST := $(subst .,_,$(subst -,_,$(subst /,_,$(HOST)))) TARGET := $(subst .,_,$(subst -,_,$(subst /,_,$(TARGET)))) # Now setup our tooling ifeq ($(TARGET),riscos) ifeq ($(HOST),riscos) # Building on native RISC OS GCCSDK_INSTALL_ENV ?= CC__ := gcc CXX__ := g++ CMHG ?= cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= # On certain versions of RISC OS (<>4 || kernel < 8.75), # the kernel will clean up the current redirection on # OS_Exit, including closing the associated file handles. # This is problematic for UnixLib, as it's invariably using # those filehandles in a pipe between parent and child processes. # This affects us as, anywhere where we shell out and want to # capture the output of the child process may fail. # Fortunately, if we know the child process is built against # UnixLib, then we also know that it won't call OS_Exit when it # exits, instead returning directly to our exit handler (and thus # preserving the redirection). This only works, however, if the # child application is specified using its absolute path, or # found in Run$Path. In the case of Perl, it does not appear in # Run$Path, so we must invoke it using its absolute path so that # the SharedUnixLibrary successfully detects it as a child process. PERL ?= .bin.perl # This is nasty, but needed because $(CURDIR) will # contain colons, and thus confuse make mightily $(shell SetMacro Alias$$$(COMPONENT)pwd Set %0 :|$$CSD>|mUnset Alias$$$(COMPONENT)pwd) $(shell $(COMPONENT)pwd $(COMPONENT)$$Dir) CURDIR := <$(COMPONENT)$$Dir> else # Cross compiling for RISC OS ifeq ($(origin GCCSDK_INSTALL_ENV),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/env),) GCCSDK_INSTALL_ENV := /opt/netsurf/arm-unknown-riscos/env else GCCSDK_INSTALL_ENV := /home/riscos/env endif endif ifeq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/cross/bin),) GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-unknown-riscos/cross/bin else GCCSDK_INSTALL_CROSSBIN := /home/riscos/cross/bin endif endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) CMHG ?= PATH="$(GCCSDK_INSTALL_CROSSBIN):$(PATH)" $(GCCSDK_INSTALL_CROSSBIN)/cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/share/pkgconfig" pkg-config ifneq ($(COMPONENT_TYPE),riscos-module) ifeq ($(origin CC),default) ifneq ($(findstring arm-unknown-riscos-gcc,$(CC__)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif else ifneq ($(findstring arm-unknown-riscos-gcc,$(CC)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif endif else EXEEXT := ,ffa endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib CMHGFLAGS := -p -tgcc -32bit -apcs 3/32/nonreent/fpe2/noswst/nofpr/nofp # Default prefix PREFIX ?= $(GCCSDK_INSTALL_ENV) endif # BeOS-like targets ifeq ($(TARGET),beos) ifeq ($(HOST),beos) # Building on BeOS CC__ := gcc # No pkg-config PKGCONFIG ?= # Default prefix BEOS_INSTALL_ENV ?= /boot/home/config else ifeq ($(HOST),haiku) # Building on Haiku # Default prefix BEOS_INSTALL_ENV ?= /boot/common else # TODO: more sensible default BEOS_INSTALL_ENV ?= /home/jmb/haiku/env BEOS_INSTALL_CROSSBIN ?= /home/jmb/haiku/haiku/generated/cross-tools/bin CC__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*g++) AR__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*ar) PKGCONFIG := PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/share/pkgconfig" pkg-config endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -I$(BEOS_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -I$(BEOS_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(BEOS_INSTALL_ENV)/lib PREFIX ?= $(BEOS_INSTALL_ENV) endif # Windows ifeq ($(TARGET),windows) ifeq ($(HOST),windows) # Building on Windows CC__ := gcc CXX__ := g++ AR__ := ar PKGCONFIG ?= else # Cross compiling for Windows -- assumes mingw toolchain MINGW_INSTALL_ENV ?= /usr/local/mingw CC__ := i586-mingw32msvc-gcc CXX__ := i586-mingw32msvc-g++ AR__ := i586-mingw32msvc-ar PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(MINGW_INSTALL_ENV)/lib # Default prefix PREFIX ?= $(MINGW_INSTALL_ENV) endif # AmigaOS (3/4; m68k/ppc: we can treat them identically) ifeq ($(findstring amiga,$(TARGET)),amiga) ifeq ($(findstring amiga,$(HOST)),amiga) # Building on AmigaOS # Nothing to do, as we assume the default tooling works else # Cross compiling for AmigaOS ifeq ($(TARGET),amigaos3) GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-unknown-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-unknown-amigaos/cross/bin else GCCSDK_INSTALL_ENV ?= /opt/netsurf/ppc-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/ppc-amigaos/cross/bin endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib PREFIX ?= $(GCCSDK_INSTALL_ENV) endif endif # Default prefix PREFIX ?= /usr/local ############################################################################### # Tool defaults ############################################################################### CP ?= cp DOXYGEN ?= doxygen ECHO ?= echo GENHTML ?= genhtml ifeq ($(HOST),$(TARGET)) HOST_CC ?= $(CC) HOST_CXX ?= $(CXX) else HOST_CC ?= cc HOST_CXX ?= c++ endif INSTALL ?= install LCOV ?= lcov LN ?= ln MAKE ?= make MKDIR ?= mkdir MKDIRFLAGS ?= -p MV ?= mv PERL ?= perl PKGCONFIG ?= PKG_CONFIG_PATH="$(PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)" pkg-config GREP ?= grep SED ?= sed TOUCH ?= touch XSLTPROC ?= xsltproc ############################################################################### # Override defaulted tools ############################################################################### # CC ifeq ($(findstring ccc-analyzer,$(CC)),ccc-analyzer) # We're being invoked by scan-build, so export # the compiler we would have used such that # scan-build works with cross-compilation. # There's no need to do this if we would have # used the default compiler. ifdef CC__ export CCC_CC := $(CC__) endif else # Only set CC if it's not already set in the # environment and we have a value for it. # Otherwise, leave it to be defaulted. ifeq ($(origin CC),default) ifdef CC__ CC := $(CC__) endif endif endif # CXX ifeq ($(origin CXX),default) ifdef CXX__ CXX := $(CXX__) endif endif # AR ifeq ($(origin AR),default) ifdef AR__ AR := $(AR__) endif endif ############################################################################### # Auto-detect the toolchain ############################################################################### # Check for GCC first, as that's most likely # TODO: Using shell redirection like this probably hurts portability ccspecs := $(shell $(CC) -dumpspecs 2>&1) ifeq ($(findstring libgcc,$(ccspecs)),libgcc) # Looks like GCC toolchain := gcc else # Not GCC, so enquire further ccvsn := $(shell $(CC) --version 2>&1) ifeq ($(ccvsn),) # Version string is blank ifeq ($(HOST),riscos) # For some reason we never see the output of SCL apps, so might be # Norcroft. However it might also be a GCC linked against a buggy # UnixLib. # TODO: Something more useful than blindly assuming GCC. ccvsn := GCC # ccvsn := Norcroft endif endif # "Norcroft ..." ifeq ($(word 1,$(ccvsn)),Norcroft) toolchain := norcroft endif # "GCC ..." ifeq ($(word 1,$(ccvsn)),GCC) toolchain := gcc endif # "clang ..." ifeq ($(word 1,$(ccvsn)),clang) toolchain := clang endif ifeq ($(word 1,$(ccvsn)),Apple) ifeq ($(word 2,$(ccvsn)),clang) # Apple clang toolchain := clang endif endif endif ifeq ($(toolchain),) $(error Unable to detect toolchain) endif # TODO: It would be nice to avoid this hard-coded path include build/makefiles/Makefile.$(toolchain) ############################################################################### # Default assembler/compiler/linker/archiver flags ############################################################################### ifeq ($(BUILD),release) OPTCFLAGS ?= $(CCDEF)NDEBUG $(CCOPT) OPTCXXFLAGS ?= $(CXXDEF)NDEBUG $(CXXOPT) else OPTCFLAGS ?= $(CCDBG) $(CCNOOPT) $(CCDEF)DEBUG OPTCXXFLAGS ?= $(CXXDBG) $(CXXNOOPT) $(CXXDEF)DEBUG OPTLDFLAGS ?= $(LDDBG) endif ifeq ($(origin ARFLAGS),default) ARFLAGS := $(ARFLG) endif # TODO: This assumes that the C compiler can cope with assembler ASFLAGS ?= $(CCAS) CFLAGS := $(CFLAGS) $(OPTCFLAGS) $(CCDEF)BUILD_TARGET_$(TARGET) $(CCDEF)BUILD_HOST_$(HOST) CXXFLAGS := $(CXXFLAGS) $(OPTCXXFLAGS) \ $(CXXDEF)BUILD_TARGET_$(TARGET) $(CXXDEF)BUILD_HOST_$(HOST) ASFLAGS := $(ASFLAGS) $(CFLAGS) LDFLAGS := $(LDFLAGS) $(OPTLDFLAGS) ############################################################################### # lib-shared defaults ############################################################################### # Default library extension ifeq ($(COMPONENT_TYPE),lib-static) LIBEXT ?= .a else LIBEXT ?= .so endif # If we're building a shared library, modify the flags appropriately ifeq ($(COMPONENT_TYPE),lib-shared) # Default CFLAGS/LDFLAGS for shared libraries SHAREDCFLAGS ?= $(CCSHR) $(CCDEF)PIC SHAREDCXXFLAGS ?= $(CXXSHR) $(CCDEF)PIC SHAREDLDFLAGS ?= $(LDSHR) SHAREDLDPATH ?= LD_LIBRARY_PATH="$(BUILDDIR):$(LD_LIBRARY_PATH)" endif ################################################################################ # Package config macros ################################################################################ include build/makefiles/Makefile.pkgconfig netsurf-2.9/libnsbmp-0.0.3/0000775000175000017500000000000011734430262014312 5ustar vincevincenetsurf-2.9/libnsbmp-0.0.3/include/0000775000175000017500000000000011734430262015735 5ustar vincevincenetsurf-2.9/libnsbmp-0.0.3/include/libnsbmp.h0000664000175000017500000001035611471576216017731 0ustar vincevince/* * Copyright 2006 Richard Wilson * Copyright 2008 Sean Fox * * This file is part of NetSurf's libnsbmp, http://www.netsurf-browser.org/ * Licenced under the MIT License, * http://www.opensource.org/licenses/mit-license.php */ /** \file * BMP file decoding (interface). */ #ifndef libnsbmp_h_ #define libnsbmp_h_ #include #include #include /* bmp flags */ #define BMP_NEW 0 #define BMP_OPAQUE (1 << 0) /** image is opaque (as opposed to having an alpha mask) */ #define BMP_CLEAR_MEMORY (1 << 1) /** memory should be wiped */ /* error return values */ typedef enum { BMP_OK = 0, BMP_INSUFFICIENT_MEMORY = 1, BMP_INSUFFICIENT_DATA = 2, BMP_DATA_ERROR = 3 } bmp_result; /* encoding types */ typedef enum { BMP_ENCODING_RGB = 0, BMP_ENCODING_RLE8 = 1, BMP_ENCODING_RLE4 = 2, BMP_ENCODING_BITFIELDS = 3 } bmp_encoding; /* API for Bitmap callbacks */ typedef void* (*bmp_bitmap_cb_create)(int width, int height, unsigned int state); typedef void (*bmp_bitmap_cb_destroy)(void *bitmap); typedef void (*bmp_bitmap_cb_set_suspendable)(void *bitmap, void *private_word, void (*invalidate)(void *bitmap, void *private_word)); typedef unsigned char* (*bmp_bitmap_cb_get_buffer)(void *bitmap); typedef size_t (*bmp_bitmap_cb_get_bpp)(void *bitmap); /* The Bitmap callbacks function table */ typedef struct bmp_bitmap_callback_vt_s { bmp_bitmap_cb_create bitmap_create; /**< Create a bitmap. */ bmp_bitmap_cb_destroy bitmap_destroy; /**< Free a bitmap. */ bmp_bitmap_cb_set_suspendable bitmap_set_suspendable; /**< The bitmap image can be suspended. */ bmp_bitmap_cb_get_buffer bitmap_get_buffer; /**< Return a pointer to the pixel data in a bitmap. */ bmp_bitmap_cb_get_bpp bitmap_get_bpp; /**< Find the width of a pixel row in bytes. */ } bmp_bitmap_callback_vt; typedef struct bmp_image { bmp_bitmap_callback_vt bitmap_callbacks; /**< callbacks for bitmap functions */ uint8_t *bmp_data; /** pointer to BMP data */ uint32_t width; /** width of BMP (valid after _analyse) */ uint32_t height; /** heigth of BMP (valid after _analyse) */ bool decoded; /** whether the image has been decoded */ void *bitmap; /** decoded image */ /** Internal members are listed below */ uint32_t buffer_size; /** total number of bytes of BMP data available */ bmp_encoding encoding; /** pixel encoding type */ uint32_t bitmap_offset; /** offset of bitmap data */ uint16_t bpp; /** bits per pixel */ uint32_t colours; /** number of colours */ uint32_t *colour_table; /** colour table */ bool limited_trans; /** whether to use bmp's limited transparency */ uint32_t trans_colour; /** colour to display for "transparent" pixels when * using limited transparency */ bool reversed; /** scanlines are top to bottom */ bool ico; /** image is part of an ICO, mask follows */ bool opaque; /** true if the bitmap does not contain an alpha channel */ uint32_t mask[4]; /** four bitwise mask */ int32_t shift[4]; /** four bitwise shifts */ uint32_t transparent_index; /** colour representing "transparency" in the bitmap */ } bmp_image; typedef struct ico_image { bmp_image bmp; struct ico_image *next; } ico_image; typedef struct ico_collection { bmp_bitmap_callback_vt bitmap_callbacks; /**< callbacks for bitmap functions */ uint16_t width; /** width of largest BMP */ uint16_t height; /** heigth of largest BMP */ /** Internal members are listed below */ uint8_t *ico_data; /** pointer to ICO data */ uint32_t buffer_size; /** total number of bytes of ICO data available */ ico_image *first; } ico_collection; void bmp_create(bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_callbacks); void ico_collection_create(ico_collection *ico, bmp_bitmap_callback_vt *bitmap_callbacks); bmp_result bmp_analyse(bmp_image *bmp, size_t size, uint8_t *data); bmp_result bmp_decode(bmp_image *bmp); bmp_result bmp_decode_trans(bmp_image *bmp, uint32_t transparent_colour); void bmp_finalise(bmp_image *bmp); bmp_result ico_analyse(ico_collection *ico, size_t size, uint8_t *data); bmp_image *ico_find(ico_collection *ico, uint16_t width, uint16_t height); void ico_finalise(ico_collection *ico); #endif netsurf-2.9/libnsbmp-0.0.3/examples/0000775000175000017500000000000011734430263016131 5ustar vincevincenetsurf-2.9/libnsbmp-0.0.3/examples/linux.bmp0000664000175000017500000114725611031063543020001 0ustar vincevinceBM6(,^x  մ滼Z^`?HL0&: 0?5Qcj#BT,B-D.F.F0H/H.E.G2L3M2M2M4N3L/H,D9M7Vhgqv8J,C/D0F1L3N3M2N5P5P6R5T7U6U6V8W6U6S4S4Q3L.F*B /El;R1H.D,C0J4P6T8W9X:Y:Z;[;Z:Y9X8V6S4Q0L0I/I3KF^|mu{ #1-A0K1J4N5P5Q6U7V8V9W>Y=]>_?`?b@b@c?b>a=_<];\:Y6T4R6Q%F^nv(Ph6R5S5Q4P6S;Z@cDiFkHnIoHnGlEiCgAd?a=^:Z7T4P0K+C,B 5L+Qg3A ):/D3L4N4O5R7S9X<]?aAeDhGlJpKsNuOwOxNwLuJsHpGnFkDgAc=^:X8T:V2WnTqF^9W:Y:\<^>a@dDiIoLtNwOzP{P{OyNwLtJsIqGoFlCh@b<\7U2N.H,D,B8M^zJY_ (7+@/F0J4O5P8T9X=^BfGmLtOxQ|SVXZ[[ZXWUUS~Q{MvHoCg?`=\<\ @`V{Lk~@[;[=_@bBeDjGoJsNwR|UVVVVUTSQ~O|NyMwKuIrGnDj@d:[5S0K-D,@/FNm|?JQ -<+A/G1G0M3U7W>_BfGnLvQ}VZ]_acdeedcba`^]ZVQ{KsFjBd?`A`Rqq-Wo8T7T=^BhGnJrMwP|TVXZ[\]\\\[YWUTRP|NyKuIrFnCh>`9V4M-E+@.D;^pglp %2+A.G2I5M7V;_@fGnLuQ|UZ_dfhijklllkkkjigea]YS~LtGmDhDg Gjl=d|Da9X<\AbFjLtP|TWY[^__``abbbba`^\ZWUSP}MyKuHpEjBc;Y3O.H)C/C!J`'8-@/D/I3P:Y?cElJuP}UY]bfjmnnopqqqqqqqpomkgb^XR}LwGoCh IlOwYz&Qi cFoMzTZ_beilnprstuvwxxxyyyyxwutqnjga]XSOxJo(Zx|Z}Sp Dc Hl KsMvP{S~V[^beghikmnoopqrrrrrqpnmlkihfca_\YURNzJuGoCi>`8W0M.D.C?Ta/@-G1O7V=aFnMyT[`ehjmoqrtuwxyz{||}}}}|{{ywtrokgb]WR{ NtUuטT{/cQtIpKsNuOvR|UX\_begiklnpqrtuwx y y yxxxvusrqomljhfc`]ZVSO{KuGpCi>a6W0K.D'9 """\\\Keu/A1L6Q:ZCiLvSZ`eilnorsuvxy{|~~|zxurojeaZW T|[}vQ{Vy NtPyQ{TWVVWY\_behjklopstvxz|~}{ yxvtrpomjheb^[XTO|KvGpBi=`4S.H*C'8Uf0E2P7V>aIqQ~X_dilnprtvxy{|~}{xuqmhd`\ WZꥼʀ5qZS~R|UWXZZ[\^_bdghkmopqtvx{|}}zwvtromjgc`\XTO}KvGoCh:\2O/F,>  KKKUYZ 0@/H5P:ZBhMxU\bhlopsuwy{}~{wtplie _ ZU{ܙp>oeb`_aa`___adfhjlnqqrstwy|~~|zwtqolhda]YTO}JvFn@e8W2K.B'%%%MMMzzzGGG %80F7P<]FmP}X_fkoqsuwz|~}zxtplg a \^捺qF1}t plihgffghgghiknprstuuvwy{~|yvtpliea]YTO|JtEk=_4R-H(@ 999bbbvvvwww}}}尰bbb+=1I7U=`HrS[binqtvy{}}zwsnjd ^a膺Eyrrqo mmlkkkllmnopprs tuvxxxyz{}{yuqmieb]YTO{IqBg9Z2O/H'&&&***777???@@@HHHIII<<<888:::@@@???>>>DDDAAABBBLLLIIIGGG@@@@@@BBBFFFHHHSSSTTTTTTTTTTTTNNN@@@777;;;GGG[[[[[[WWWggggggggggggggggggggg&&&*?1L7W?dKwU^fmqtwy|~}zuqle agR/{v tpnnonnoppqrsttuvwwyyz{{|}~}zvrnjfb^XSLvFm>a6U1M&8$:1L8XAgM{Waiotvy|}wsmh ekc/}zyw rpqrrsttuvwxyzzz{{|}~|wrnjgc]WP|JrCg9Z3Q.G$;4O;[EkP~Zdlrwy}{upl jmXꅷD'#}"|ws pqqrrsuwxyy{}}~~|wrokga[TNwFl=]6R0J)'<6R<]GpS]gouy}zupm lJ_7%y sq p ponpqsvxy{}}wrnje_XQ}Jq@c8V3N$7):4T=aJsVaksy} zuq o2pC6 zs ssqqqqqssux{}|vqmhb[TMwDi=\6P"6);7W@fLwXdnv{ zu q"z^4xr r rrstuvwxy|}zuple^WP{Gm?_7O&7)>8YCkO{[grz ~y vwP= ~w trsv x z } ~   ~xtoiaZSIp?`6P&=)@;]FoQ]jt|  ~ z x3E, } |||~     |vqkc\TJr@b7T(@*C>`JsT`lv~    }~cJ)  ysme]SJrAa;T)>)C@dLvWbny   %5   |vpg^THo@_;R%8)AAfNyYeq{    a\.     yri_TFl<[4N'*ABhO{[gs}   FϛU    }uk`R}Di9W1I '?BgO{\iu~  ,FգI  xm_Q{Ad6S%6"4AeOz]jv  #VۻI   zo`Ox>_2N))?bNx\kx  *cW    {o^Ks8X(> '>`Mv\kx   )q_   zmZEl3Q,:[Kr[jx  'i    whTAe-F ,,,dddyyylllXXX<<< 8XIoZiw  &c'     tbOx@`'777``` wwwaaa>>>!!!3QGkXhw "N8    q\Kq3K&&&]]]Ȋ[[[$$$+FEhW~gv  #hH     lVAc GKLˊMMM#:BdT{eu 'cg    yf Qw+AߜDDD,@aRycs 5  vgB^CLPɄ###?^Pxbr~ -U    }7ߕ111>]Pwaq~ +f.   8睝EEE_Yky ;m Kxxx:YXjx o  2ֱ3MUhv p  &oEEE%8R{et n   Daaa.Pwbr~  i   ,ׂ%Oraq}   i  VLmbq|    j  Cٵ Ghbq{   L_   .؄Cccr{  "DX   #VBacr{  $YZ  D׬ԚBacr{   דǿ9T dpx  $t9   *m~ "/g ov~  -,     Hشq|'HZl nu}  %Q#  0|_$rn u}  &d    $]t-xp v~  (tk    Gةy2zq w  ${k  2ք¼z5}t y  +'Z   S½|6w {   ,W  ;֋½}8{    )~]  &g½;   *R   Gײº=  .|X    .y? &bn   "T‚A   7    =׋¼ÄD!   %8   *d…F" ~~}}|{{{|  (e3    L؛¿E! }|{zzyyyxxwwwy{}  )L;   :ĿŻD~}{ywutssrrstsstuvxz}  ?V1    (^¿ÈB}{yusqpomlkklmmmnprrtwz{~  &SD   B֓ā>|ywtqnlkjjieca__agiklnqtuw{ BnB6.'$   -s}; zvspmjhhe`OtA`5O(:#5.-&7-B;VJk`jonpty 'PX7'$"   Kּ}9 |wsqmjh`Ov%8#6OU{jmrx  ;~=!    6ԉ|7 ysomiaOt #3Ziqy  AiB#   *c~;  ~vpkfX.E 6P`r !R|>#   Qں<  }ulcR{/$4fz !dW#   Cۙǁ< }rgR{,%f!1!  0t˂< |oZ%8i!@"  $Z⇾> |k4O s   "X   HA zS{ i  "f   /s@ u2Ii   #U   Q< kq  %7  47 d~ %(   ![2 _~+6 &k  9/ YqLZ %:  #|, Ui l )#  V, _s)1  >P  7, j_t 1+  $׏8 | '0 &Bt  8K!  $ L^ ~ >>866RRRMMMEEE[[[111QQQIIIXXXMMM RRRHHH444[[[RRRUUU^WW966RRRBBBB??KJJ RRRnnnlll===! TSSRRRVVV777ZYYSSS```LLL666QQQ:::\\\###111$$$MLLTSSjjjA>>_\\ zzz %$$^^^&&&xxxXXX***>>>ZZZYYY///  SSS??? :::IFFFFF fff,,,uuu B??PPP>>> :::]]]??? <<>>"""VVV###\\\ BBBQQQSSSWWW XXXAAA NNN XXX!!!hhh^]]///FGGRRRvvv]``9:: RRR*)) ;;;PPPQQQ555|||4--?::6;;477+**ONN1,,$ qqqMMM866EDDABBBCC=>>('' 677GFF966LLL&&&777DDDGGGJJJDDD<<<*(( XWW444___XXXaaa??? 2--FCCKJJMJJIJJ=@@455*((MLL;;;a__888MMM&!!DAAIHHJHHIIICCC100 GGG---...+++ZWWB??999CCCEEEFFFB??+))000AAA nnnOOO:::jjj 1//@==@@@==='''JJJ$$$ :::??? 8--211"""555:==555LLLVVVFFFhhh!NHH~~~CAAKGG!!!OMM&$$ ######}||SSSwww LLL9;;SSSsss yvv<<<?;;<;; B@@hhh DDDiii000NNN666777qqq<<<-,,SPP666{{{'''IGG=<<"!!\[[3,,###444[[[<<< ~~|||###^[[<;; jjjYXX XXX?>> 100XXX999 qqq---kii"""!B;;444 CAAkkk +++BAA+((wwwxww 511?>>!""(((ppp[[[rrr %%%777777###+++DDDB??322yxxjii# PLLYWWKJJ+%% kjj¿!!!ICCFCC844FFFzzzRQQjjj 0//zyyccc|||gggVVV///:99{zz~~~III)))poo///dcc BBBKGGGGGggg/))|yy777ooomjj777NLLJJJuuuXVV[[[@@@vvvHHHFEE555""" jjj>==zyy*** ---QQQ666hhh\ZZQQQVVV-,,...222jii&&&655 <;;mmmkjjiii888vvv -,,NNNÿ YYY766ľKKKgggȾYYY ýWWWYYY ,++ƿ ussrrrþ 666ƾ HHHTTT+++ס OOOyuvqpvOOObbb333 {X{jdbb acfikmnooooonmkhgg h j nqty?{˾\\\w;z ld b a c f j p u x z{{||}}| y vrolkm o r tvz'[Ƹ###"""x?|"ngdbd i n u |  }yvut t u w xyz!}E}ooo+**!!!}D$pie cdh q z  }|{ { { |||~#4rÿ333 222ZYYZZZROO;88 ###yxxJ)skg edgo {    #.Tsst@@@dddpppommgaaYTT433\\\onnF+rkgedgkv  #*9s¿999\\\pppyyyxwwnll_\\GFFnnnhffL&pjgcceip{ %,Trtu---[ZZpnnyww||||||srrbaaPOO,++hhhaaaQQRQ*riea`adipy *;^234QPPojjxx{{|{{yyyrqq___OOO-,,(((<<2)!   ]| Lnlux} '4@IID;2)! &" 7I  Szksy "-9EIIC:0(! $.$ z  0V}nv~ %17/'!  %%1: !gy~  #/5;?@A>6.%  BP %a   '*,/8BG>4( l...6DKa %**)0>> ,,, 鬬FDD<<<򋋋;::RQQZXXZTT$##533XXX AAA``` ... 綶uttomm www||| D::SQQNIID@@ eee}}}GGG444))) ;;;FFF ~~~%$$OMM HHH_^^ xxx鄄bbbUUUcccmll<<<^^^OMMXXXNMMNMM+++TTT```{{󮮮 XXXvvveee""";;;D@@!!!OOO~~~a`` ###PPP vuu^^^<99񚚚aaatttIII VVVwwwNNNmmmkkk @@@𫫫)''푑000oooۜIIIQQQZWWեsss```FFF 666౱xxxQQQSNN̓mmmlll޷cccQQQCBBuuuTSS侾|||000 QQQ)))zww鰬'$$)((Ϸ[[[ QQQjffٱXVV ZXXӽuuu888%%%QQQIGGxssȹ}}+++lll}}}\\\ 666QQQ"""khh}}RQQIIItttvvv+++CCCQQQDBBvsu¹nll YWWvuuǼ[[[PPPQQQWZ_qw}||oll766$$$>>>zxxǽyyy111yyyQQQ]XZ~yyywwhdd,++XXXPMMyxxccc QQQ QMMkhh~||{ww`^^"!!XWW===222mmmpppQQQ 744YUUrnn~|||yysnnZXX???z{{ PPPxxx:::???444QQQ,,,6559881//2225//GGGwwwsssDDD PNNRRRQQQ NMM:77 777\[[qnn|xx}}{{yvvtttuuulllXWW$$$ BAAcaa###222QQQ###vuu111 .++C??422+++%%% OOO|||EEE```QQQdbbedd """YXXlllQQQ---CCCSSSUUUVRR0))588jkkbaaQQQ NLLyyysssAAA QQQ -""JFFYPPA>>QQQQQQQQQQQQDDD:::FFFlll@@@aaaYYYiiiwwx'''>>>BBB""" ^^^&&&:99=;;988111$$$??? ///DBBNIILIIHGG???666))) DDD555HHHYVVZUUUSSONNIHHA@@888---  666HHH\\\dcccbb___XWWQPPGGG???666((( iiiLLL666III```pppooopppjii```UUUKJJAAA:::333---###555HHH___qqqsssuuutssmmmdccYXXMLLBBB;;;666%%% ''' 544GEE[[[llluttwwwywwyvvpnndccWVVHHH<<<444 ???-))IDDZXXkkkvvv|||~~{{xuujhhXXXIII=<<0//LLL%!!F@@XTTiiiwww}}}}}vsthffXWWIHH>;;/.. %$$?<88%$$}}}bbb!!!:::MMM^^^ijjnprnrunqthfgYWWGFF877 ,,,566IJJWWWabbcefbegaceUUUGGG;;;&&& '''###/00DFFOOOSTTTUURRRLKLABB688%%%# @::EDD@CCBBBA???::633 2++8//.,,###      ***GGG<<<\\\===$$$)))BBBrrrHHH~~~!!!555EEE TTT{{{$$$ ***{{{iii!!!000ڪUUU333 XXX}}}ŽlllLLL555###)))666'''$$$"""666:::777111444===AAATTTnetsurf-2.9/libnsbmp-0.0.3/examples/decode_ico.c0000664000175000017500000001117711172610263020355 0ustar vincevince/* * Copyright 2008 Sean Fox * Copyright 2008 James Bursa * * This file is part of NetSurf's libnsbmp, http://www.netsurf-browser.org/ * Licenced under the MIT License, * http://www.opensource.org/licenses/mit-license.php */ #include #include #include #include #include #include #include #include #include "../include/libnsbmp.h" /* Currently the library returns the data in RGBA format, * so there are 4 bytes per pixel */ #define BYTES_PER_PIXEL 4 /* White with alpha masking. */ #define TRANSPARENT_COLOR 0xffffffff unsigned char *load_file(const char *path, size_t *data_size); void warning(const char *context, bmp_result code); void *bitmap_create(int width, int height, unsigned int state); void bitmap_set_suspendable(void *bitmap, void *private_word, void (*invalidate)(void *bitmap, void *private_word)); void invalidate(void *bitmap, void *private_word); unsigned char *bitmap_get_buffer(void *bitmap); size_t bitmap_get_bpp(void *bitmap); void bitmap_destroy(void *bitmap); int main(int argc, char *argv[]) { bmp_bitmap_callback_vt bitmap_callbacks = { bitmap_create, bitmap_destroy, bitmap_set_suspendable, bitmap_get_buffer, bitmap_get_bpp }; uint16_t width, height; ico_collection ico; bmp_result code; struct bmp_image *bmp; size_t size; unsigned short res = 0; if ((argc < 2) || (argc > 4)) { fprintf(stderr, "Usage: %s collection.ico [width=255] [height=255]\n", argv[0]); return 1; } width = (argc >= 3) ? atoi(argv[2]) : 255; height = (argc == 4) ? atoi(argv[3]) : 255; /* create our bmp image */ ico_collection_create(&ico, &bitmap_callbacks); /* load file into memory */ unsigned char *data = load_file(argv[1], &size); /* analyse the BMP */ code = ico_analyse(&ico, size, data); if (code != BMP_OK) { warning("ico_analyse", code); res = 1; goto cleanup; } /* decode the image */ bmp = ico_find(&ico, width, height); assert(bmp); code = bmp_decode(bmp); /* code = bmp_decode_trans(bmp, TRANSPARENT_COLOR); */ if (code != BMP_OK) { warning("bmp_decode", code); /* allow partially decoded images */ if (code != BMP_INSUFFICIENT_DATA) { res = 1; goto cleanup; } } printf("P3\n"); printf("# %s\n", argv[1]); printf("# width %u \n", bmp->width); printf("# height %u \n", bmp->height); printf("%u %u 256\n", bmp->width, bmp->height); { uint16_t row, col; uint8_t *image; image = (uint8_t *) bmp->bitmap; for (row = 0; row != bmp->height; row++) { for (col = 0; col != bmp->width; col++) { size_t z = (row * bmp->width + col) * BYTES_PER_PIXEL; printf("%u %u %u ", image[z], image[z + 1], image[z + 2]); } printf("\n"); } } cleanup: /* clean up */ ico_finalise(&ico); free(data); return res; } unsigned char *load_file(const char *path, size_t *data_size) { FILE *fd; struct stat sb; unsigned char *buffer; size_t size; size_t n; fd = fopen(path, "rb"); if (!fd) { perror(path); exit(EXIT_FAILURE); } if (stat(path, &sb)) { perror(path); exit(EXIT_FAILURE); } size = sb.st_size; buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %lld bytes\n", (long long) size); exit(EXIT_FAILURE); } n = fread(buffer, 1, size, fd); if (n != size) { perror(path); exit(EXIT_FAILURE); } fclose(fd); *data_size = size; return buffer; } void warning(const char *context, bmp_result code) { fprintf(stderr, "%s failed: ", context); switch (code) { case BMP_INSUFFICIENT_MEMORY: fprintf(stderr, "BMP_INSUFFICIENT_MEMORY"); break; case BMP_INSUFFICIENT_DATA: fprintf(stderr, "BMP_INSUFFICIENT_DATA"); break; case BMP_DATA_ERROR: fprintf(stderr, "BMP_DATA_ERROR"); break; default: fprintf(stderr, "unknown code %i", code); break; } fprintf(stderr, "\n"); } void *bitmap_create(int width, int height, unsigned int state) { (void) state; /* unused */ return calloc(width * height, BYTES_PER_PIXEL); } void bitmap_set_suspendable(void *bitmap, void *private_word, void (*invalidate)(void *bitmap, void *private_word)) { (void) bitmap; /* unused */ (void) private_word; /* unused */ (void) invalidate; /* unused */ } void invalidate(void *bitmap, void *private_word) { (void) bitmap; /* unused */ (void) private_word; /* unused */ } unsigned char *bitmap_get_buffer(void *bitmap) { assert(bitmap); return bitmap; } size_t bitmap_get_bpp(void *bitmap) { (void) bitmap; /* unused */ return BYTES_PER_PIXEL; } void bitmap_destroy(void *bitmap) { assert(bitmap); free(bitmap); } netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/0000775000175000017500000000000011734430262017760 5ustar vincevincenetsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/readme.txt0000664000175000017500000000077711032370343021763 0ustar vincevinceBMP Suite - sample BMP image files By Jason Summers Version: 2001.04.27 For more information: http://pobox.com/~jason1/bmpsuite/ Contents -------- g01bw.bmp g01wb.bmp g01bg.bmp g01p1.bmp g04.bmp g04p4.bmp g08.bmp g08offs.bmp g08os2.bmp g08w126.bmp g08w125.bmp g08w124.bmp g08p256.bmp g08pi256.bmp g08pi64.bmp g08res22.bmp g08res21.bmp g08res11.bmp g08p64.bmp g08s0.bmp g16def555.bmp g16bf555.bmp g16bf565.bmp g024.bmp g32def.bmp g32bf.bmp -- end -- netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g16bf555.bmp0000664000175000017500000004010211032370343021613 0ustar vincevinceBMB@B(@@|!Bc)Jk1Rs9Z{  $ ( , 0 48<@DHLPTX\`dhlptx| @` ! %@)`-159=B F@J`NRVZ^c g@k`osw{1111111111111111111111111111111!Bc)Jk1Rs9Z{  $ ( , 0 48<@DHLPTX\`dhlptx| @` ! %@)`-159=B F@J`NRVZ^c g@k`osw{1111111111111111111111111111111!Bc)Jk1Rs9Z{ !"# $%&'( )$*(+,,0-4.8/<0@1D2H3L4P5T6X7\8`9d:h;lx?|!Aa !!%A)a-159=B!FAJaNRVZ^c!gAkaosw{1111111111111111111111111111111!Bc)Jk1Rs9Z{ !"# $%&'( )$*(+,,0-4.8/<0@1D2H3L4P5T6X7\8`9d:h;lx?|!Aa !!%A)a-159=B!FAJaNRVZ^c!gAkaosw{1111111111111111111111111111111!Bc ) J k  1 R s  9 Z { @ABC DEFGH I$J(K,L0M4N8Oy?} )Ii  !)%I)i-159= B)FIJiNRVZ^ c)gIkiosw{9999999999999999999999999999999$!$B$c$$$$$%)%J%k%%%%%&1&R&s&&&&&'9'Z'{''''' !" # $%&'(!)%*)+-,1-5.9/=0A1E2I3M4Q5U6Y7]8a9e:i;my?} )Ii  !)%I)i-159= B)FIJiNRVZ^ c)gIkiosw{9999999999999999999999999999999(!(B(c((((()))J)k)))))*1*R*s*****+9+Z+{+++++@AB C DEFGH!I%J)K-L1M5N9O=PAQERISMTQUUVYW]XaYeZi[m\q]u^y_} *Jj  !*%J)j-159= B*FJJjNRVZ^ c*gJkjosw{9999999999999999999999999999999(!(B(c((((()))J)k)))))*1*R*s*****+9+Z+{+++++@AB C DEFGH!I%J)K-L1M5N9O=PAQERISMTQUUVYW]XaYeZi[m\q]u^y_} *Jj  !*%J)j-159= B*FJJjNRVZ^ c*gJkjosw{9999999999999999999999999999999,!,B,c,,,,,-)-J-k-----.1.R.s...../9/Z/{/////`ab c defgh!i%j)k-l1m5n9o=pAqErIsMtQuUvYw]xayezi{m|q}u~y} +Kk  !+%K)k-159= B+FKJkNRVZ^ c+gKkkosw{9999999999999999999999999999999,!,B,c,,,,,-)-J-k-----.1.R.s...../9/Z/{/////`ab c defgh!i%j)k-l1m5n9o=pAqErIsMtQuUvYw]xayezi{m|q}u~y} +Kk  !+%K)k-159= B+FKJkNRVZ^ c+gKkkosw{99999999999999999999999999999990!0B0c000001)1J1k11111212R2s22222393Z3{33333 !%)-159=AEIMQUY]aeimquy} ,Ll  !,%L)l-159= B,FLJlNRVZ^ c,gLklosw{===============================0!0B0c000001)1J1k11111212R2s22222393Z3{33333 !%)-159=AEIMQUY]aeimquy} ,Ll  !,%L)l-159= B,FLJlNRVZ^ c,gLklosw{===============================4!4B4c444445)5J5k55555616R6s66666797Z7{77777 !%)-159=AEIMQUY]aeimquy} -Mm  !-%M)m-159= B-FMJmNRVZ^ c-gMkmosw{===============================4!4B4c444445)5J5k55555616R6s66666797Z7{77777 !%)-159=AEIMQUY]aeimquy} -Mm  !-%M)m-159= B-FMJmNRVZ^ c-gMkmosw{===============================8!8B8c888889)9J9k99999:1:R:s:::::;9;Z;{;;;;; !%)-159=AEIMQUY]aeimquy}.Nn !.%N)n-159=B.FNJnNRVZ^c.gNknosw{===============================8!8B8c888889)9J9k99999:1:R:s:::::;9;Z;{;;;;; !%)-159=AEIMQUY]aeimquy}.Nn !.%N)n-159=B.FNJnNRVZ^c.gNknosw{===============================1>R>s>>>>>?9?Z?{????? !%)-159=AEIMQUY]aeimquy}/Oo !/%O)o-159=B/FOJoNRVZ^c/gOkoosw{===============================1>R>s>>>>>?9?Z?{????? !%)-159=AEIMQUY]aeimquy}/Oo !/%O)o-159=B/FOJoNRVZ^c/gOkoosw{===============================@!@B@c@@@@@A)AJAkAAAAAB1BRBsBBBBBC9CZC{CCCCC " & * . 2 6:>BFJNRVZ^bfjnrvz~0Pp !0%P)p-159=B0FPJpNRVZ^c0gPkposw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB@!@B@c@@@@@A)AJAkAAAAAB1BRBsBBBBBC9CZC{CCCCC " & * . 2 6:>BFJNRVZ^bfjnrvz~0Pp !0%P)p-159=B0FPJpNRVZ^c0gPkposw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBD!DBDcDDDDDE)EJEkEEEEEF1FRFsFFFFFG9GZG{GGGGG !" #$%&'(")&**+.,2-6.:/>0B1F2J3N4R5V6Z7^8b9f:j;nz?~1Qq !1%Q)q-159=B1FQJqNRVZ^c1gQkqosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBD!DBDcDDDDDE)EJEkEEEEEF1FRFsFFFFFG9GZG{GGGGG !" #$%&'(")&**+.,2-6.:/>0B1F2J3N4R5V6Z7^8b9f:j;nz?~1Qq !1%Q)q-159=B1FQJqNRVZ^c1gQkqosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBH!HBHcHHHHHI)IJIkIIIIIJ1JRJsJJJJJK9KZK{KKKKK@AB CDEFGH"I&J*K.L2M6N:O>PBQFRJSNTRUVVZW^XbYfZj[n\r]v^z_~2Rr !2%R)r-159=B2FRJrNRVZ^c2gRkrosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBH!HBHcHHHHHI)IJIkIIIIIJ1JRJsJJJJJK9KZK{KKKKK@AB CDEFGH"I&J*K.L2M6N:O>PBQFRJSNTRUVVZW^XbYfZj[n\r]v^z_~2Rr !2%R)r-159=B2FRJrNRVZ^c2gRkrosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBL!LBLcLLLLLM)MJMkMMMMMN1NRNsNNNNNO9OZO{OOOOO`ab cdefgh"i&j*k.l2m6n:o>pBqFrJsNtRuVvZw^xbyfzj{n|r}v~z~3Ss !3%S)s-159=B3FSJsNRVZ^c3gSksosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBL!LBLcLLLLLM)MJMkMMMMMN1NRNsNNNNNO9OZO{OOOOO`ab cdefgh"i&j*k.l2m6n:o>pBqFrJsNtRuVvZw^xbyfzj{n|r}v~z~3Ss !3%S)s-159=B3FSJsNRVZ^c3gSksosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBP!PBPcPPPPPQ)QJQkQQQQQR1RRRsRRRRRS9SZS{SSSSS "&*.26:>BFJNRVZ^bfjnrvz~4Tt !4%T)t-159=B4FTJtNRVZ^c4gTktosw{1F1F1F1F1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4FP!PBPcPPPPPQ)QJQkQQQQQR1RRRsRRRRRS9SZS{SSSSS "&*.26:>BFJNRVZ^bfjnrvz~4Tt !4%T)t-159=B4FTJtNRVZ^c4gTktosw{1F1F1F1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4FT!TBTcTTTTTU)UJUkUUUUUV1VRVsVVVVVW9WZW{WWWWW "&*.26:>BFJNRVZ^bfjnrvz~5Uu !5%U)u-159=B5FUJuNRVZ^c5gUkuosw{1F1F1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5FT!TBTcTTTTTU)UJUkUUUUUV1VRVsVVVVVW9WZW{WWWWW "&*.26:>BFJNRVZ^bfjnrvz~5Uu !5%U)u-159=B5FUJuNRVZ^c5gUkuosw{1F1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5FX!XBXcXXXXXY)YJYkYYYYYZ1ZRZsZZZZZ[9[Z[{[[[[[ "&*.26:>BFJNRVZ^bfjnrvz~6Vv !6%V)v-159=B6FVJvNRVZ^c6gVkvosw{1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5F5FX!XBXcXXXXXY)YJYkYYYYYZ1ZRZsZZZZZ[9[Z[{[[[[[ "&*.26:>BFJNRVZ^bfjnrvz~6Vv !6%V)v-159=B6FVJvNRVZ^c6gVkvosw{1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5F5F5F\!\B\c\\\\\])]J]k]]]]]^1^R^s^^^^^_9_Z_{_____ "&*.26:>BFJNRVZ^bfjnrvz~7Ww !7%W)w-159=B7FWJwNRVZ^c7gWkwosw{1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5F5F5F5F\!\B\c\\\\\])]J]k]]]]]^1^R^s^^^^^_9_Z_{_____ "&*.26:>BFJNRVZ^bfjnrvz~7Ww !7%W)w-159=B7FWJwNRVZ^c7gWkwosw{1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5F5F5F5F5F`!`B`c`````a)aJakaaaaab1bRbsbbbbbc9cZc{ccccc # ' + / 3 7;?CGKOSW[_cgkosw{8Xx !8%X)x-159=B8FXJxNRVZ^c8gXkxosw{RJRJRJRJRJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJ`!`B`c`````a)aJakaaaaab1bRbsbbbbbc9cZc{ccccc # ' + / 3 7;?CGKOSW[_cgkosw{8Xx !8%X)x-159=B8FXJxNRVZ^c8gXkxosw{RJRJRJRJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJd!dBdcddddde)eJekeeeeef1fRfsfffffg9gZg{ggggg !" #$%&'(#)'*++/,3-7.;/?0C1G2K3O4S5W6[7_8c9g:k;o{?9Yy !9%Y)y-159=B9FYJyNRVZ^c9gYkyosw{RJRJRJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJd!dBdcddddde)eJekeeeeef1fRfsfffffg9gZg{ggggg !" #$%&'(#)'*++/,3-7.;/?0C1G2K3O4S5W6[7_8c9g:k;o{?9Yy !9%Y)y-159=B9FYJyNRVZ^c9gYkyosw{RJRJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJh!hBhchhhhhi)iJikiiiiij1jRjsjjjjjk9kZk{kkkkk@AB CDEFGH#I'J+K/L3M7N;O?PCQGRKSOTSUWV[W_XcYgZk[o\s]w^{_:Zz !:%Z)z-159=B:FZJzNRVZ^c:gZkzosw{RJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJVJh!hBhchhhhhi)iJikiiiiij1jRjsjjjjjk9kZk{kkkkk@AB CDEFGH#I'J+K/L3M7N;O?PCQGRKSOTSUWV[W_XcYgZk[o\s]w^{_:Zz !:%Z)z-159=B:FZJzNRVZ^c:gZkzosw{RJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJVJVJl!lBlclllllm)mJmkmmmmmn1nRnsnnnnno9oZo{ooooo`ab cdefgh#i'j+k/l3m7n;o?pCqGrKsOtSuWv[w_xcygzk{o|s}w~{;[{ !;%[){-159=B;F[J{NRVZ^c;g[k{osw{RJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJVJVJVJl!lBlclllllm)mJmkmmmmmn1nRnsnnnnno9oZo{ooooo`ab cdefgh#i'j+k/l3m7n;o?pCqGrKsOtSuWv[w_xcygzk{o|s}w~{;[{ !;%[){-159=B;F[J{NRVZ^c;g[k{osw{RJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJVJVJVJVJp!pBpcpppppq)qJqkqqqqqr1rRrsrrrrrs9sZs{sssss #'+/37;?CGKOSW[_cgkosw{<\| !<%\)|-159=B^~ !>%^)~-159=B>F^J~NRVZ^c>g^k~osw{sNsNsNsNtNtNtNtNtNtNtNtNuNuNuNuNuNuNuNuNvNvNvNvNvNvNvNvNwNwNwN1zRzszzzzz{9{Z{{{{{{{ #'+/37;?CGKOSW[_cgkosw{>^~ !>%^)~-159=B>F^J~NRVZ^c>g^k~osw{sNsNsNtNtNtNtNtNtNtNtNuNuNuNuNuNuNuNuNvNvNvNvNvNvNvNvNwNwNwNwN1~R~s~~~~~9Z{ #'+/37;?CGKOSW[_cgkosw{?_ !?%_)-159=B?F_JNRVZ^c?g_kosw{sNsNtNtNtNtNtNtNtNtNuNuNuNuNuNuNuNuNvNvNvNvNvNvNvNvNwNwNwNwNwN1~R~s~~~~~9Z{ #'+/37;?CGKOSW[_cgkosw{?_ !?%_)-159=B?F_JNRVZ^c?g_kosw{sNtNtNtNtNtNtNtNtNuNuNuNuNuNuNuNuNvNvNvNvNvNvNvNvNwNwNwNwNwNwNnetsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08res22.bmp0000664000175000017500000002206611032370343021734 0ustar vincevinceBM6$6(@   $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g04.bmp0000664000175000017500000001016611032370343021050 0ustar vincevinceBMvv(@UUU@@@DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330DDDDDDDDDDDDDDDD3333333333333330UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" UUUUUUUUUUUUUUUU""""""""""""""" ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww0330wwwwwww00wwwwwww0030wwwwwww00wwwwwww3333wwwwwwwwwwwwwwnetsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g32def.bmp0000664000175000017500000007746611032370343021550 0ustar vincevinceBM66(@  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxx```a``b``c``d``e``f``g``h``i``j``k``l``m``n``o``p``q``r``s``t``u``v``w``x``y``z``{``|``}``~`` ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxaaabaacaadaaeaafaagaahaaiaajaakaalaamaanaaoaapaaqaaraasaataauaavaawaaxaayaazaa{aa|aa}aa~aaaa ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxbbbcbbdbbebbfbbgbbhbbibbjbbkbblbbmbbnbbobbpbbqbbrbbsbbtbbubbvbbwbbxbbybbzbb{bb|bb}bb~bbbbbb    (( 00 88 @@ HH PP XX `` hh pp xx     ( (0 08 8@ @H HP PX X` `h hp px x    (( 00 88 @@ HH PP XX `` hh pp xx cccdcceccfccgcchcciccjcckcclccmccnccoccpccqccrccscctccuccvccwccxccycczcc{cc|cc}cc~cccccccc ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxdddeddfddgddhddiddjddkddlddmddnddoddpddqddrddsddtdduddvddwddxddyddzdd{dd|dd}dd~dddddddddd ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxeeefeegeeheeieejeekeeleemeeneeoeepeeqeereeseeteeueeveeweexeeyeezee{ee|ee}ee~eeeeeeeeeeee ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxfffgffhffiffjffkfflffmffnffoffpffqffrffsfftffuffvffwffxffyffzff{ff|ff}ff~ffffffffffffff ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxggghggiggjggkgglggmggnggoggpggqggrggsggtgguggvggwggxggyggzgg{gg|gg}gg~gggggggggggggggg    (( 00 88 @@ HH PP XX `` hh pp xx     ( (0 08 8@ @H HP PX X` `h hp px x    (( 00 88 @@ HH PP XX `` hh pp xx hhhihhjhhkhhlhhmhhnhhohhphhqhhrhhshhthhuhhvhhwhhxhhyhhzhh{hh|hh}hh~hhhhhhhhhhhhhhhhhh$$$$ $(($00$88$@@$HH$PP$XX$``$hh$pp$xx$$$$$$$$$$$$$$$$$$$$$ $ ($(0$08$8@$@H$HP$PX$X`$`h$hp$px$x$$$$$$$$$$$$$$$$$$$$$ $(($00$88$@@$HH$PP$XX$``$hh$pp$xx$$$$$$$$$$$$$$$$iiijiikiiliimiiniioiipiiqiiriisiitiiuiiviiwiixiiyiizii{ii|ii}ii~iiiiiiiiiiiiiiiiiiii(((( ((((00(88(@@(HH(PP(XX(``(hh(pp(xx((((((((((((((((((((( ( (((0(08(8@(@H(HP(PX(X`(`h(hp(px(x((((((((((((((((((((( ((((00(88(@@(HH(PP(XX(``(hh(pp(xx((((((((((((((((jjjkjjljjmjjnjjojjpjjqjjrjjsjjtjjujjvjjwjjxjjyjjzjj{jj|jj}jj~jjjjjjjjjjjjjjjjjjjjjj,,,, ,((,00,88,@@,HH,PP,XX,``,hh,pp,xx,,,,,,,,,,,,,,,,,,,,, , (,(0,08,8@,@H,HP,PX,X`,`h,hp,px,x,,,,,,,,,,,,,,,,,,,,, ,((,00,88,@@,HH,PP,XX,``,hh,pp,xx,,,,,,,,,,,,,,,,kkklkkmkknkkokkpkkqkkrkkskktkkukkvkkwkkxkkykkzkk{kk|kk}kk~kkkkkkkkkkkkkkkkkkkkkkkk0000 0((0000880@@0HH0PP0XX0``0hh0pp0xx000000000000000000000 0 (0(000808@0@H0HP0PX0X`0`h0hp0px0x000000000000000000000 0((0000880@@0HH0PP0XX0``0hh0pp0xx0000000000000000lllmllnllollpllqllrllslltllullvllwllxllyllzll{ll|ll}ll~llllllllllllllllllllllllll4444 4((4004884@@4HH4PP4XX4``4hh4pp4xx444444444444444444444 4 (4(040848@4@H4HP4PX4X`4`h4hp4px4x444444444444444444444 4((4004884@@4HH4PP4XX4``4hh4pp4xx4444444444444444mmmnmmommpmmqmmrmmsmmtmmummvmmwmmxmmymmzmm{mm|mm}mm~mmmmmmmmmmmmmmmmmmmmmmmmmmmm8888 8((8008888@@8HH8PP8XX8``8hh8pp8xx888888888888888888888 8 (8(080888@8@H8HP8PX8X`8`h8hp8px8x888888888888888888888 8((8008888@@8HH8PP8XX8``8hh8pp8xx8888888888888888nnnonnpnnqnnrnnsnntnnunnvnnwnnxnnynnznn{nn|nn}nn~nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn<<<< <((<00<88<@@<HH<PP<XX<``<hh<pp<xx<<<<<<<<<<<<<<<<<<<<< < (<(0<08<8@<@H  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@?????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG88888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH77777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII66666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ55555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK44444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL33333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM22222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN11111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO00000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP/////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ.............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-----------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*****************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\#############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwww????????xxxxxxxxxxxxxxx????yyyyyyyyyyyyyyy???????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{????????????|||||||||||||||}}}}}}}}}}}}}}}netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g01wb.bmp0000664000175000017500000000207611032370343021377 0ustar vincevinceBM>>(@?????>~???????????????>~?????????????؍?ٍ>۽~?netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08pi64.bmp0000664000175000017500000002206611032370343021561 0ustar vincevinceBM6$6(@ @  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g24.bmp0000664000175000017500000006006611032370343021056 0ustar vincevinceBM6`6(@` ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxx```a``b``c``d``e``f``g``h``i``j``k``l``m``n``o``p``q``r``s``t``u``v``w``x``y``z``{``|``}``~`` ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxaaabaacaadaaeaafaagaahaaiaajaakaalaamaanaaoaapaaqaaraasaataauaavaawaaxaayaazaa{aa|aa}aa~aaaa ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxbbbcbbdbbebbfbbgbbhbbibbjbbkbblbbmbbnbbobbpbbqbbrbbsbbtbbubbvbbwbbxbbybbzbb{bb|bb}bb~bbbbbb    (( 00 88 @@ HH PP XX `` hh pp xx     ( (0 08 8@ @H HP PX X` `h hp px x    (( 00 88 @@ HH PP XX `` hh pp xx cccdcceccfccgcchcciccjcckcclccmccnccoccpccqccrccscctccuccvccwccxccycczcc{cc|cc}cc~cccccccc ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxdddeddfddgddhddiddjddkddlddmddnddoddpddqddrddsddtdduddvddwddxddyddzdd{dd|dd}dd~dddddddddd ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxeeefeegeeheeieejeekeeleemeeneeoeepeeqeereeseeteeueeveeweexeeyeezee{ee|ee}ee~eeeeeeeeeeee ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxfffgffhffiffjffkfflffmffnffoffpffqffrffsfftffuffvffwffxffyffzff{ff|ff}ff~ffffffffffffff ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxggghggiggjggkgglggmggnggoggpggqggrggsggtgguggvggwggxggyggzgg{gg|gg}gg~gggggggggggggggg    (( 00 88 @@ HH PP XX `` hh pp xx     ( (0 08 8@ @H HP PX X` `h hp px x    (( 00 88 @@ HH PP XX `` hh pp xx hhhihhjhhkhhlhhmhhnhhohhphhqhhrhhshhthhuhhvhhwhhxhhyhhzhh{hh|hh}hh~hhhhhhhhhhhhhhhhhh$$$$ $(($00$88$@@$HH$PP$XX$``$hh$pp$xx$$$$$$$$$$$$$$$$$$$$$ $ ($(0$08$8@$@H$HP$PX$X`$`h$hp$px$x$$$$$$$$$$$$$$$$$$$$$ $(($00$88$@@$HH$PP$XX$``$hh$pp$xx$$$$$$$$$$$$$$$$iiijiikiiliimiiniioiipiiqiiriisiitiiuiiviiwiixiiyiizii{ii|ii}ii~iiiiiiiiiiiiiiiiiiii(((( ((((00(88(@@(HH(PP(XX(``(hh(pp(xx((((((((((((((((((((( ( (((0(08(8@(@H(HP(PX(X`(`h(hp(px(x((((((((((((((((((((( ((((00(88(@@(HH(PP(XX(``(hh(pp(xx((((((((((((((((jjjkjjljjmjjnjjojjpjjqjjrjjsjjtjjujjvjjwjjxjjyjjzjj{jj|jj}jj~jjjjjjjjjjjjjjjjjjjjjj,,,, ,((,00,88,@@,HH,PP,XX,``,hh,pp,xx,,,,,,,,,,,,,,,,,,,,, , (,(0,08,8@,@H,HP,PX,X`,`h,hp,px,x,,,,,,,,,,,,,,,,,,,,, ,((,00,88,@@,HH,PP,XX,``,hh,pp,xx,,,,,,,,,,,,,,,,kkklkkmkknkkokkpkkqkkrkkskktkkukkvkkwkkxkkykkzkk{kk|kk}kk~kkkkkkkkkkkkkkkkkkkkkkkk0000 0((0000880@@0HH0PP0XX0``0hh0pp0xx000000000000000000000 0 (0(000808@0@H0HP0PX0X`0`h0hp0px0x000000000000000000000 0((0000880@@0HH0PP0XX0``0hh0pp0xx0000000000000000lllmllnllollpllqllrllslltllullvllwllxllyllzll{ll|ll}ll~llllllllllllllllllllllllll4444 4((4004884@@4HH4PP4XX4``4hh4pp4xx444444444444444444444 4 (4(040848@4@H4HP4PX4X`4`h4hp4px4x444444444444444444444 4((4004884@@4HH4PP4XX4``4hh4pp4xx4444444444444444mmmnmmommpmmqmmrmmsmmtmmummvmmwmmxmmymmzmm{mm|mm}mm~mmmmmmmmmmmmmmmmmmmmmmmmmmmm8888 8((8008888@@8HH8PP8XX8``8hh8pp8xx888888888888888888888 8 (8(080888@8@H8HP8PX8X`8`h8hp8px8x888888888888888888888 8((8008888@@8HH8PP8XX8``8hh8pp8xx8888888888888888nnnonnpnnqnnrnnsnntnnunnvnnwnnxnnynnznn{nn|nn}nn~nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn<<<< <((<00<88<@@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08w124.bmp0000664000175000017500000002070211032370343021467 0ustar vincevinceBM!6(|=  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<>(@@@@@?????????????>~???????????????>~?????x?'rp$`?&r@$B?ww?netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08rle.bmp0000664000175000017500000000343411032370343021557 0ustar vincevinceBM6(@  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy} @ ? A > B = C < D ; E : F 9 G 8 H 7 I 6 J 5 K 4 L 3 M 2 N 1 O 0 P / Q . R - S , T + U * V ) W ( X ' Y & Z % [ $ \ # ] " ^ ! _  `  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x y ????????z ????{ ???????|  ????} ????????????~  netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08p64.bmp0000664000175000017500000002046611032370343021412 0ustar vincevinceBM6!6(@ @  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}???????????????????????????????????????????????????????????????>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>===============================================================<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::999999999999999999999999999999999999999999999999999999999999999888888888888888888888888888888888888888888888888888888888888888777777777777777777777777777777777777777777777777777777777777777 66666666666666666666666666666666 6666666666666666666666666666666 55555555555555555555555555555555 5555555555555555555555555555555 44444444444444444444444444444444 4444444444444444444444444444444 33333333333333333333333333333333 3333333333333333333333333333333 22222222222222222222222222222222 2222222222222222222222222222222111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000000///////////////////////////////////////////////////////////////...............................................................---------------------------------------------------------------,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++***************************************************************)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((('''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$###############################################################"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""################################################################$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))****************************************************************++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----------------------------------------------------------------................................................................////////////////////////////////////////////////////////////////0000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111122222222222222222222222222222222 22222222222222222222222222222222 33333333333333333333333333333333 33333333333333333333333333333333 44444444444444444444444444444444 44444444444444444444444444444444 55555555555555555555555555555555 55555555555555555555555555555555 66666666666666666666666666666666 66666666666666666666666666666666 7777777777777777777777777777777777777777777777777777777777777777888888888888888888888888888888888888888888888888888888888888888899999999999999999999999999999999999999999999999????????:::::::::::::::::::::::::::::::::::::::::::::::????;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;???????<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<????===============================================????????????>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>???????????????????????????????????????????????netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g04rle.bmp0000664000175000017500000000163211032370343021551 0ustar vincevinceBMv(@$UUU@@@ D 30 D 30 D 30 D 30 D 30 D 30 D 30 D 30 D 30 D 30 D 30 D 30 D 30 D 30 D 30 D 30 U " U " U " U " U " U " U " U " U " U " U " U " U " U " U " U " f  f  f  f  f  f  f  f  f  f  f  f  f  f  f  f  w w w w w w w w w w 0330w 00w 0030w 00w 3333w w netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g04p4.bmp0000664000175000017500000001010611032370343021306 0ustar vincevinceBMFF(@UUU33333333333333333333333333333330333333333333333333333333333333303333333333333333333333333333333033333333333333333333333333333330333333333333333333333333333333303333333333333333333333333333333033333333333333333333333333333330333333333333333333333333333333303333333333333333333333333333333033333333333333333333333333333330333333333333333333333333333333303333333333333333333333333333333033333333333333333333333333333330333333333333333333333333333333303333333333333333333333333333333033333333333333333333333333333330""""""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""" """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333330330333333333333333333333330033333333333333333333333003033333333333333333333333003333333333333333333333333333333333333333333333333333333333333333333333333netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/test.html0000664000175000017500000001024111032370343021615 0ustar vincevince BMP Suite Images

BMP Suite Images

FilebppCommentsImage
g01bw.bmp1black and white palette (#000000,#FFFFFF)
g01wb.bmp1white and black palette (#FFFFFF,#000000). Should look the same as g01bw, not inverted.
g01bg.bmp1blue and green palette (#4040FF,#40FF40)
g01p1.bmp11-color (blue) palette (#4040FF)
g04.bmp4basic 4bpp (16 color) image
g04rle.bmp4RLE compressed.
g04p4.bmp44-color grayscale palette
g08.bmp8basic 8bpp (256 color) image
g08p256.bmp8biClrUsed=256, biClrImportant=0 [=256]
g08pi256.bmp8biClrUsed=256, biClrImportant=256
g08pi64.bmp8biClrUsed=256, biClrImportant=64. It's barely possible that some sophisticated viewers may display this image in grayscale, if there are a limited number of colors available.
g08rle.bmp8RLE compressed.
g08os2.bmp8OS/2-style bitmap. This is an obsolete variety of BMP that is still encountered sometimes. It has 3-byte palette entries (instead of 4), and 16-bit width/height fields (instead of 32).
g08res22.bmp8resolution 7874x7874 pixels/meter (200x200 dpi)
g08res11.bmp8resolution 3937x3937 pixels/meter (100x100 dpi)
g08res21.bmp8resolution 7874x3937 pixels/meter (200x100 dpi). Some programs (e.g. Imaging for Windows) may display this image stretched vertically, which is the optimal thing to do if the program is primarily a viewer, rather than an editor.
g08s0.bmp8bits size not given (set to 0). This is legal for uncompressed bitmaps.
g08offs.bmp8bfOffBits in header not set to the usual value. There are 100 extra unused bytes between palette and bits.
g08w126.bmp8size 126x63 (right and bottom slightly clipped)
g08w125.bmp8size 125x62
g08w124.bmp8size 124x61
g08p64.bmp864-color grayscale palette
g16def555.bmp1615-bit color (1 bit wasted), biCompression=BI_RGB (no bitfields, defaults to 5-5-5)
g16bf555.bmp1615-bit color, biCompression=BI_BITFIELDS (bitfields indicate 5-5-5)
g16bf565.bmp1616-bit color, biCompression=BI_BITFIELDS (bitfields indicate 5-6-5)
g24.bmp2424-bit color (BGR)
g32def.bmp3224-bit color (8 bits wasted), biCompression=BI_RGB (no bitfields, defaults to BGRx)
g32bf.bmp3224-bit color (8 bits wasted), biCompression=BI_BITFIELDS (bitfields indicate BGRx)

By Jason Summers, 4/2001

netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g16def555.bmp0000664000175000017500000004006611032370343021773 0ustar vincevinceBM6@6(@@!Bc)Jk1Rs9Z{  $ ( , 0 48<@DHLPTX\`dhlptx| @` ! %@)`-159=B F@J`NRVZ^c g@k`osw{1111111111111111111111111111111!Bc)Jk1Rs9Z{  $ ( , 0 48<@DHLPTX\`dhlptx| @` ! %@)`-159=B F@J`NRVZ^c g@k`osw{1111111111111111111111111111111!Bc)Jk1Rs9Z{ !"# $%&'( )$*(+,,0-4.8/<0@1D2H3L4P5T6X7\8`9d:h;lx?|!Aa !!%A)a-159=B!FAJaNRVZ^c!gAkaosw{1111111111111111111111111111111!Bc)Jk1Rs9Z{ !"# $%&'( )$*(+,,0-4.8/<0@1D2H3L4P5T6X7\8`9d:h;lx?|!Aa !!%A)a-159=B!FAJaNRVZ^c!gAkaosw{1111111111111111111111111111111!Bc ) J k  1 R s  9 Z { @ABC DEFGH I$J(K,L0M4N8Oy?} )Ii  !)%I)i-159= B)FIJiNRVZ^ c)gIkiosw{9999999999999999999999999999999$!$B$c$$$$$%)%J%k%%%%%&1&R&s&&&&&'9'Z'{''''' !" # $%&'(!)%*)+-,1-5.9/=0A1E2I3M4Q5U6Y7]8a9e:i;my?} )Ii  !)%I)i-159= B)FIJiNRVZ^ c)gIkiosw{9999999999999999999999999999999(!(B(c((((()))J)k)))))*1*R*s*****+9+Z+{+++++@AB C DEFGH!I%J)K-L1M5N9O=PAQERISMTQUUVYW]XaYeZi[m\q]u^y_} *Jj  !*%J)j-159= B*FJJjNRVZ^ c*gJkjosw{9999999999999999999999999999999(!(B(c((((()))J)k)))))*1*R*s*****+9+Z+{+++++@AB C DEFGH!I%J)K-L1M5N9O=PAQERISMTQUUVYW]XaYeZi[m\q]u^y_} *Jj  !*%J)j-159= B*FJJjNRVZ^ c*gJkjosw{9999999999999999999999999999999,!,B,c,,,,,-)-J-k-----.1.R.s...../9/Z/{/////`ab c defgh!i%j)k-l1m5n9o=pAqErIsMtQuUvYw]xayezi{m|q}u~y} +Kk  !+%K)k-159= B+FKJkNRVZ^ c+gKkkosw{9999999999999999999999999999999,!,B,c,,,,,-)-J-k-----.1.R.s...../9/Z/{/////`ab c defgh!i%j)k-l1m5n9o=pAqErIsMtQuUvYw]xayezi{m|q}u~y} +Kk  !+%K)k-159= B+FKJkNRVZ^ c+gKkkosw{99999999999999999999999999999990!0B0c000001)1J1k11111212R2s22222393Z3{33333 !%)-159=AEIMQUY]aeimquy} ,Ll  !,%L)l-159= B,FLJlNRVZ^ c,gLklosw{===============================0!0B0c000001)1J1k11111212R2s22222393Z3{33333 !%)-159=AEIMQUY]aeimquy} ,Ll  !,%L)l-159= B,FLJlNRVZ^ c,gLklosw{===============================4!4B4c444445)5J5k55555616R6s66666797Z7{77777 !%)-159=AEIMQUY]aeimquy} -Mm  !-%M)m-159= B-FMJmNRVZ^ c-gMkmosw{===============================4!4B4c444445)5J5k55555616R6s66666797Z7{77777 !%)-159=AEIMQUY]aeimquy} -Mm  !-%M)m-159= B-FMJmNRVZ^ c-gMkmosw{===============================8!8B8c888889)9J9k99999:1:R:s:::::;9;Z;{;;;;; !%)-159=AEIMQUY]aeimquy}.Nn !.%N)n-159=B.FNJnNRVZ^c.gNknosw{===============================8!8B8c888889)9J9k99999:1:R:s:::::;9;Z;{;;;;; !%)-159=AEIMQUY]aeimquy}.Nn !.%N)n-159=B.FNJnNRVZ^c.gNknosw{===============================1>R>s>>>>>?9?Z?{????? !%)-159=AEIMQUY]aeimquy}/Oo !/%O)o-159=B/FOJoNRVZ^c/gOkoosw{===============================1>R>s>>>>>?9?Z?{????? !%)-159=AEIMQUY]aeimquy}/Oo !/%O)o-159=B/FOJoNRVZ^c/gOkoosw{===============================@!@B@c@@@@@A)AJAkAAAAAB1BRBsBBBBBC9CZC{CCCCC " & * . 2 6:>BFJNRVZ^bfjnrvz~0Pp !0%P)p-159=B0FPJpNRVZ^c0gPkposw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB@!@B@c@@@@@A)AJAkAAAAAB1BRBsBBBBBC9CZC{CCCCC " & * . 2 6:>BFJNRVZ^bfjnrvz~0Pp !0%P)p-159=B0FPJpNRVZ^c0gPkposw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBD!DBDcDDDDDE)EJEkEEEEEF1FRFsFFFFFG9GZG{GGGGG !" #$%&'(")&**+.,2-6.:/>0B1F2J3N4R5V6Z7^8b9f:j;nz?~1Qq !1%Q)q-159=B1FQJqNRVZ^c1gQkqosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBD!DBDcDDDDDE)EJEkEEEEEF1FRFsFFFFFG9GZG{GGGGG !" #$%&'(")&**+.,2-6.:/>0B1F2J3N4R5V6Z7^8b9f:j;nz?~1Qq !1%Q)q-159=B1FQJqNRVZ^c1gQkqosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBH!HBHcHHHHHI)IJIkIIIIIJ1JRJsJJJJJK9KZK{KKKKK@AB CDEFGH"I&J*K.L2M6N:O>PBQFRJSNTRUVVZW^XbYfZj[n\r]v^z_~2Rr !2%R)r-159=B2FRJrNRVZ^c2gRkrosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBH!HBHcHHHHHI)IJIkIIIIIJ1JRJsJJJJJK9KZK{KKKKK@AB CDEFGH"I&J*K.L2M6N:O>PBQFRJSNTRUVVZW^XbYfZj[n\r]v^z_~2Rr !2%R)r-159=B2FRJrNRVZ^c2gRkrosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBL!LBLcLLLLLM)MJMkMMMMMN1NRNsNNNNNO9OZO{OOOOO`ab cdefgh"i&j*k.l2m6n:o>pBqFrJsNtRuVvZw^xbyfzj{n|r}v~z~3Ss !3%S)s-159=B3FSJsNRVZ^c3gSksosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBL!LBLcLLLLLM)MJMkMMMMMN1NRNsNNNNNO9OZO{OOOOO`ab cdefgh"i&j*k.l2m6n:o>pBqFrJsNtRuVvZw^xbyfzj{n|r}v~z~3Ss !3%S)s-159=B3FSJsNRVZ^c3gSksosw{BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBP!PBPcPPPPPQ)QJQkQQQQQR1RRRsRRRRRS9SZS{SSSSS "&*.26:>BFJNRVZ^bfjnrvz~4Tt !4%T)t-159=B4FTJtNRVZ^c4gTktosw{1F1F1F1F1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4FP!PBPcPPPPPQ)QJQkQQQQQR1RRRsRRRRRS9SZS{SSSSS "&*.26:>BFJNRVZ^bfjnrvz~4Tt !4%T)t-159=B4FTJtNRVZ^c4gTktosw{1F1F1F1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4FT!TBTcTTTTTU)UJUkUUUUUV1VRVsVVVVVW9WZW{WWWWW "&*.26:>BFJNRVZ^bfjnrvz~5Uu !5%U)u-159=B5FUJuNRVZ^c5gUkuosw{1F1F1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5FT!TBTcTTTTTU)UJUkUUUUUV1VRVsVVVVVW9WZW{WWWWW "&*.26:>BFJNRVZ^bfjnrvz~5Uu !5%U)u-159=B5FUJuNRVZ^c5gUkuosw{1F1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5FX!XBXcXXXXXY)YJYkYYYYYZ1ZRZsZZZZZ[9[Z[{[[[[[ "&*.26:>BFJNRVZ^bfjnrvz~6Vv !6%V)v-159=B6FVJvNRVZ^c6gVkvosw{1F1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5F5FX!XBXcXXXXXY)YJYkYYYYYZ1ZRZsZZZZZ[9[Z[{[[[[[ "&*.26:>BFJNRVZ^bfjnrvz~6Vv !6%V)v-159=B6FVJvNRVZ^c6gVkvosw{1F1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5F5F5F\!\B\c\\\\\])]J]k]]]]]^1^R^s^^^^^_9_Z_{_____ "&*.26:>BFJNRVZ^bfjnrvz~7Ww !7%W)w-159=B7FWJwNRVZ^c7gWkwosw{1F1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5F5F5F5F\!\B\c\\\\\])]J]k]]]]]^1^R^s^^^^^_9_Z_{_____ "&*.26:>BFJNRVZ^bfjnrvz~7Ww !7%W)w-159=B7FWJwNRVZ^c7gWkwosw{1F2F2F2F2F2F2F2F2F3F3F3F3F3F3F3F3F4F4F4F4F4F4F4F4F5F5F5F5F5F5F`!`B`c`````a)aJakaaaaab1bRbsbbbbbc9cZc{ccccc # ' + / 3 7;?CGKOSW[_cgkosw{8Xx !8%X)x-159=B8FXJxNRVZ^c8gXkxosw{RJRJRJRJRJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJ`!`B`c`````a)aJakaaaaab1bRbsbbbbbc9cZc{ccccc # ' + / 3 7;?CGKOSW[_cgkosw{8Xx !8%X)x-159=B8FXJxNRVZ^c8gXkxosw{RJRJRJRJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJd!dBdcddddde)eJekeeeeef1fRfsfffffg9gZg{ggggg !" #$%&'(#)'*++/,3-7.;/?0C1G2K3O4S5W6[7_8c9g:k;o{?9Yy !9%Y)y-159=B9FYJyNRVZ^c9gYkyosw{RJRJRJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJd!dBdcddddde)eJekeeeeef1fRfsfffffg9gZg{ggggg !" #$%&'(#)'*++/,3-7.;/?0C1G2K3O4S5W6[7_8c9g:k;o{?9Yy !9%Y)y-159=B9FYJyNRVZ^c9gYkyosw{RJRJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJh!hBhchhhhhi)iJikiiiiij1jRjsjjjjjk9kZk{kkkkk@AB CDEFGH#I'J+K/L3M7N;O?PCQGRKSOTSUWV[W_XcYgZk[o\s]w^{_:Zz !:%Z)z-159=B:FZJzNRVZ^c:gZkzosw{RJRJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJVJh!hBhchhhhhi)iJikiiiiij1jRjsjjjjjk9kZk{kkkkk@AB CDEFGH#I'J+K/L3M7N;O?PCQGRKSOTSUWV[W_XcYgZk[o\s]w^{_:Zz !:%Z)z-159=B:FZJzNRVZ^c:gZkzosw{RJRJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJVJVJl!lBlclllllm)mJmkmmmmmn1nRnsnnnnno9oZo{ooooo`ab cdefgh#i'j+k/l3m7n;o?pCqGrKsOtSuWv[w_xcygzk{o|s}w~{;[{ !;%[){-159=B;F[J{NRVZ^c;g[k{osw{RJRJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJVJVJVJl!lBlclllllm)mJmkmmmmmn1nRnsnnnnno9oZo{ooooo`ab cdefgh#i'j+k/l3m7n;o?pCqGrKsOtSuWv[w_xcygzk{o|s}w~{;[{ !;%[){-159=B;F[J{NRVZ^c;g[k{osw{RJSJSJSJSJSJSJSJSJTJTJTJTJTJTJTJTJUJUJUJUJUJUJUJUJVJVJVJVJVJVJp!pBpcpppppq)qJqkqqqqqr1rRrsrrrrrs9sZs{sssss #'+/37;?CGKOSW[_cgkosw{<\| !<%\)|-159=B^~ !>%^)~-159=B>F^J~NRVZ^c>g^k~osw{sNsNsNsNtNtNtNtNtNtNtNtNuNuNuNuNuNuNuNuNvNvNvNvNvNvNvNvNwNwNwN1zRzszzzzz{9{Z{{{{{{{ #'+/37;?CGKOSW[_cgkosw{>^~ !>%^)~-159=B>F^J~NRVZ^c>g^k~osw{sNsNsNtNtNtNtNtNtNtNtNuNuNuNuNuNuNuNuNvNvNvNvNvNvNvNvNwNwNwNwN1~R~s~~~~~9Z{ #'+/37;?CGKOSW[_cgkosw{?_ !?%_)-159=B?F_JNRVZ^c?g_kosw{sNsNtNtNtNtNtNtNtNtNuNuNuNuNuNuNuNuNvNvNvNvNvNvNvNvNwNwNwNwNwN1~R~s~~~~~9Z{ #'+/37;?CGKOSW[_cgkosw{?_ !?%_)-159=B?F_JNRVZ^c?g_kosw{sNtNtNtNtNtNtNtNtNuNuNuNuNuNuNuNuNvNvNvNvNvNvNvNvNwNwNwNwNwNwNnetsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08res21.bmp0000664000175000017500000002206611032370343021733 0ustar vincevinceBM6$6(@ a  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g01p1.bmp0000664000175000017500000000207211032370343021303 0ustar vincevinceBM::(@@@netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g32bf.bmp0000664000175000017500000007750211032370343021370 0ustar vincevinceBMBB(@  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxx```a``b``c``d``e``f``g``h``i``j``k``l``m``n``o``p``q``r``s``t``u``v``w``x``y``z``{``|``}``~`` ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxaaabaacaadaaeaafaagaahaaiaajaakaalaamaanaaoaapaaqaaraasaataauaavaawaaxaayaazaa{aa|aa}aa~aaaa ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxbbbcbbdbbebbfbbgbbhbbibbjbbkbblbbmbbnbbobbpbbqbbrbbsbbtbbubbvbbwbbxbbybbzbb{bb|bb}bb~bbbbbb    (( 00 88 @@ HH PP XX `` hh pp xx     ( (0 08 8@ @H HP PX X` `h hp px x    (( 00 88 @@ HH PP XX `` hh pp xx cccdcceccfccgcchcciccjcckcclccmccnccoccpccqccrccscctccuccvccwccxccycczcc{cc|cc}cc~cccccccc ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxdddeddfddgddhddiddjddkddlddmddnddoddpddqddrddsddtdduddvddwddxddyddzdd{dd|dd}dd~dddddddddd ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxeeefeegeeheeieejeekeeleemeeneeoeepeeqeereeseeteeueeveeweexeeyeezee{ee|ee}ee~eeeeeeeeeeee ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxfffgffhffiffjffkfflffmffnffoffpffqffrffsfftffuffvffwffxffyffzff{ff|ff}ff~ffffffffffffff ((0088@@HHPPXX``hhppxx  ((0088@@HHPPXX``hhppxx ((0088@@HHPPXX``hhppxxggghggiggjggkgglggmggnggoggpggqggrggsggtgguggvggwggxggyggzgg{gg|gg}gg~gggggggggggggggg    (( 00 88 @@ HH PP XX `` hh pp xx     ( (0 08 8@ @H HP PX X` `h hp px x    (( 00 88 @@ HH PP XX `` hh pp xx hhhihhjhhkhhlhhmhhnhhohhphhqhhrhhshhthhuhhvhhwhhxhhyhhzhh{hh|hh}hh~hhhhhhhhhhhhhhhhhh$$$$ $(($00$88$@@$HH$PP$XX$``$hh$pp$xx$$$$$$$$$$$$$$$$$$$$$ $ ($(0$08$8@$@H$HP$PX$X`$`h$hp$px$x$$$$$$$$$$$$$$$$$$$$$ $(($00$88$@@$HH$PP$XX$``$hh$pp$xx$$$$$$$$$$$$$$$$iiijiikiiliimiiniioiipiiqiiriisiitiiuiiviiwiixiiyiizii{ii|ii}ii~iiiiiiiiiiiiiiiiiiii(((( ((((00(88(@@(HH(PP(XX(``(hh(pp(xx((((((((((((((((((((( ( (((0(08(8@(@H(HP(PX(X`(`h(hp(px(x((((((((((((((((((((( ((((00(88(@@(HH(PP(XX(``(hh(pp(xx((((((((((((((((jjjkjjljjmjjnjjojjpjjqjjrjjsjjtjjujjvjjwjjxjjyjjzjj{jj|jj}jj~jjjjjjjjjjjjjjjjjjjjjj,,,, ,((,00,88,@@,HH,PP,XX,``,hh,pp,xx,,,,,,,,,,,,,,,,,,,,, , (,(0,08,8@,@H,HP,PX,X`,`h,hp,px,x,,,,,,,,,,,,,,,,,,,,, ,((,00,88,@@,HH,PP,XX,``,hh,pp,xx,,,,,,,,,,,,,,,,kkklkkmkknkkokkpkkqkkrkkskktkkukkvkkwkkxkkykkzkk{kk|kk}kk~kkkkkkkkkkkkkkkkkkkkkkkk0000 0((0000880@@0HH0PP0XX0``0hh0pp0xx000000000000000000000 0 (0(000808@0@H0HP0PX0X`0`h0hp0px0x000000000000000000000 0((0000880@@0HH0PP0XX0``0hh0pp0xx0000000000000000lllmllnllollpllqllrllslltllullvllwllxllyllzll{ll|ll}ll~llllllllllllllllllllllllll4444 4((4004884@@4HH4PP4XX4``4hh4pp4xx444444444444444444444 4 (4(040848@4@H4HP4PX4X`4`h4hp4px4x444444444444444444444 4((4004884@@4HH4PP4XX4``4hh4pp4xx4444444444444444mmmnmmommpmmqmmrmmsmmtmmummvmmwmmxmmymmzmm{mm|mm}mm~mmmmmmmmmmmmmmmmmmmmmmmmmmmm8888 8((8008888@@8HH8PP8XX8``8hh8pp8xx888888888888888888888 8 (8(080888@8@H8HP8PX8X`8`h8hp8px8x888888888888888888888 8((8008888@@8HH8PP8XX8``8hh8pp8xx8888888888888888nnnonnpnnqnnrnnsnntnnunnvnnwnnxnnynnznn{nn|nn}nn~nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn<<<< <((<00<88<@@<HH<PP<XX<``<hh<pp<xx<<<<<<<<<<<<<<<<<<<<< < (<(0<08<8@<@HU#Zkk^=(0Zޚs5}7O~fC#Wl~5ꏚ7KGM8<>P O'ɀd@}2>P O'ɀd@}2>P O'ɀd_|;Rwqw&d@}2>P O'ɀd@}2>P O'ɀd@}2>P O'ɀd@}2>P H])lpKtEXtSoftwarePNGDIB test app%IENDB`netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/png/04.png0000664000175000017500000000043011032370343021464 0ustar vincevincePNG  IHDR@X0PLTEUUU@@@E< IDATxA 0 &=pKj X,` XX2.{Ɏ_L䯋 z!TT4 t0_U  e=nh*  0C'tAV +FtEXtSoftwarePNGDIB test app%IENDB`netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/png/08p64.png0000664000175000017500000000126611032370343022032 0ustar vincevincePNG  IHDR@OXYPLTE  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}b>IDATxهjQ@ћ{UX^0Ab}uJ}}>WPۥW/{ꞫViP_|Ґh wQ !yo;_/X+w1&=ob\{^ńIyS"$EQ̈`σ{1'=wb^{nł܈EK"s%ER`υXs&=gb]{NņM9["s$EP`ρ}'=ɏo=$'e=ɿ/֓j=/֓j=֓e=֓m=֓||e=Ǘ֓||m= ֓b=K֓f=֓j=֓n=IXO|zk֓<_$ϗx<4_)Su!tEXtSoftwarePNGDIB test app%IENDB`netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/png/08w124.png0000664000175000017500000000263211032370343022114 0ustar vincevincePNG  IHDR|=XEtIME $- pHYs  ~PLTE  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}!t-IDATxڅSf3۶4I7mmFMs۶m۶Yl&H/79<휝;X?cH@ aQ/B^ ixB߃䟛7 9yK ݱ{Ad ^Ȇ!b70<Q g .`8x  F' N`$x bFG `46 8~cO`jƃ{ v` j &; 6` j &[ V` j  `jk f`0Y/Pc0 Rj怫 `.j `> `!2 `182 `)8 `98V `%8rV `58rր `-8ցCzp3TlA~CeFp0TlJ`(hBJ`(lv"`(jv.}#YIENDB`netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/png/08w125.png0000664000175000017500000000265211032370343022117 0ustar vincevincePNG  IHDR}>1tIME ,¥ pHYs  ~PLTE  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}!t=IDATxڅeЗe3tҍ"AiFBwtJw4 t7R%3<0s{~9;+wP DpP(^A} "l(W3x "9^ <_7݃ :{MnA#y5hx9 `b8{ ` b9 w@lG߂6 q-Q;0c Q0\ 5V`<$rLW߃+ Dp$qLG"H.d߄Ppߡ+:;~Cg&~_qߡ 51 LK&tEXtSoftwarePNGDIB test app%IENDB`netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/png/08w126.png0000664000175000017500000000266511032370343022124 0ustar vincevincePNG  IHDR~?stIME )Q pHYs  ~PLTE  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}!tHIDATxڅedCtH#]/4RRR"0CwKtJRG 3gY]@K A3X^ z p֫[ <᭷_7݃7 6<_݂ A$K] D (:!>j h]RG01,u#m`$ĴXڂm+0q,c ;7kxZoRs0 \,5%RS0\I,} &`8Yj s#K Hn! RXjf?@JK,pTg@jKup9i-sIRm0[ wRM2Zc `8 2[_AKUpdT,A6KOnS 9,URE,U+>Ry X*V OT vʀ`(`4XvJ`(d$–J`(b8` XcpgQIENDB`netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/png/01bw.png0000664000175000017500000000043111032370343022013 0ustar vincevincePNG  IHDR@ _:(PLTEٟIDATx1@Eы$I! 1%@Ia;T2p_q2>it Mit M BMP Suite Reference Images

BMP Suite Reference Images

FilebppCommentsReference
g01bw.bmp1black and white palette (#000000,#FFFFFF)
g01wb.bmp1white and black palette (#FFFFFF,#000000). Should look the same as g01bw, not inverted.
g01bg.bmp1blue and green palette (#4040FF,#40FF40)
g01p1.bmp11-color (blue) palette (#4040FF)
g04.bmp4basic 4bpp (16 color) image
g04rle.bmp4RLE compressed.
g04p4.bmp44-color grayscale palette
g08.bmp8basic 8bpp (256 color) image
g08p256.bmp8biClrUsed=256, biClrImportant=0 [=256]
g08pi256.bmp8biClrUsed=256, biClrImportant=256
g08pi64.bmp8biClrUsed=256, biClrImportant=64. It's barely possible that some sophisticated viewers may display this image in grayscale, if there are a limited number of colors available.
g08rle.bmp8RLE compressed.
g08os2.bmp8OS/2-style bitmap. This is an obsolete variety of BMP that is still encountered sometimes. It has 3-byte palette entries (instead of 4), and 16-bit width/height fields (instead of 32).
g08res22.bmp8resolution 7874x7874 pixels/meter (200x200 dpi)
g08res11.bmp8resolution 3937x3937 pixels/meter (100x100 dpi)
g08res21.bmp8resolution 7874x3937 pixels/meter (200x100 dpi). Some programs (e.g. Imaging for Windows) may display this image stretched vertically, which is the optimal thing to do if the program is primarily a viewer, rather than an editor.
g08s0.bmp8bits size not given (set to 0). This is legal for uncompressed bitmaps.
g08offs.bmp8bfOffBits in header not set to the usual value. There are 100 extra unused bytes between palette and bits.
g08w126.bmp8size 126x63 (right and bottom slightly clipped)
g08w125.bmp8size 125x62
g08w124.bmp8size 124x61
g08p64.bmp864-color grayscale palette
g16def555.bmp1615-bit color (1 bit wasted), biCompression=BI_RGB (no bitfields, defaults to 5-5-5)
g16bf555.bmp1615-bit color, biCompression=BI_BITFIELDS (bitfields indicate 5-5-5)
g16bf565.bmp1616-bit color, biCompression=BI_BITFIELDS (bitfields indicate 5-6-5)
g24.bmp2424-bit color (BGR)
g32def.bmp3224-bit color (8 bits wasted), biCompression=BI_RGB (no bitfields, defaults to BGRx)
g32bf.bmp3224-bit color (8 bits wasted), biCompression=BI_BITFIELDS (bitfields indicate BGRx)

By Jason Summers, 4/2001

netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/png/08.png0000664000175000017500000000264711032370343021504 0ustar vincevincePNG  IHDR@OXYPLTE  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}!t>IDATxc^Am۶۶m;ضm۶m۶6٤ny_3}7/so㸪[<x/l=~;xnw@ߧ|5ο ?vuugD`0j A0:Y0 !4kw fҬ- ހКkF`4xj /A8ZY 0<4kƃg fDҬ)Ț5cE`2xjLA4Y0 14{ f pҬ. ؚmG`6jV 7A}?xm< ]-w@}+h³?t7]af_{ܴsvKH z]oi>6;}5NP,z_!}%~f!z_ W.z_ +}%~}-LWB WB_ W.z_ +}%~ޗCB+WB jFz_ ":AJ}`Wf_Ҍ 6ߚtEXtSoftwarePNGDIB test app%IENDB`netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08res11.bmp0000664000175000017500000002206611032370343021732 0ustar vincevinceBM6$6(@ aa  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08s0.bmp0000664000175000017500000002206611032370343021321 0ustar vincevinceBM6$6(@  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08offs.bmp0000664000175000017500000002223211032370343021727 0ustar vincevinceBM$(@   $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08w126.bmp0000664000175000017500000002166611032370343021503 0ustar vincevinceBM#6(~?  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@??????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB==============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP//////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ..............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\##############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxx????????yyyyyyyyyyyyyyy????zzzzzzzzzzzzzzz???????{{{{{{{{{{{{{{{????|||||||||||||||????????????}}}}}}}}}}}}}}}~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08p256.bmp0000664000175000017500000002206611032370343021473 0ustar vincevinceBM6$6(@   $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g16bf565.bmp0000664000175000017500000004010211032370343021614 0ustar vincevinceBMB@B(@@AEI MQUY] (08@ H P X ` hpx@!@)19B@JRZc@ks{@@@΀@ c c c c c c c c c c c c c c c ccccccccccccccccAEI MQUY] !"#$ %(&0'8(@)H*P+X,`-h.p/x0123456789:;<=>?@!@)19B@JRZc@ks{@@@΀@ c c c c c c c c c c c c c c cccccccccccccccccA E  I M  Q  U Y]@ABCD E(F0G8H@IHJPKXL`MhNpOxPQRSTUVWXYZ[\]^_A!A)19BAJRZcAks{AAA΁A c c c c c c c c c c c c c ccccccccccccccccccA E  I M  Q  U Y]`abcd e(f0g8h@iHjPkXl`mhnpoxpqrstuvwxyz{|}~A!A)19BAJRZcAks{AAA΁A c c c c c c c c c c c c cccccccccccccccccccAEI MQUY] (08@HPX`hpxȚЛ؜B!B)19BBJRZcBks{BœB½B΂B,c,c,c,c-c-c-c-c-c-c-c-c.c.c.c.c.c.c.c.c/c/c/c/c/c/c/c/c0c0c0cAEI MQUY] (08@HPX`hpxȺлؼB!B)19BBJRZcBks{BœB½B΂B,c,c,c-c-c-c-c-c-c-c-c.c.c.c.c.c.c.c.c/c/c/c/c/c/c/c/c0c0c0c0cAEI MQUY] (08@HPX`hpxЀшҐӘԠըְ׸C!C)19BCJRZcCks{CÜCýC΃C,c,c-c-c-c-c-c-c-c-c.c.c.c.c.c.c.c.c/c/c/c/c/c/c/c/c0c0c0c0c0cAEI MQUY] (08@HPX`hpxC!C)19BCJRZcCks{CÜCýC΃C,c-c-c-c-c-c-c-c-c.c.c.c.c.c.c.c.c/c/c/c/c/c/c/c/c0c0c0c0c0c0c A !E!!!"I""" #M###$Q$$$%U%%%&Y&&&']''' !)19A I Q Y a iqyD!D)19BDJRZcDks{DĜDĽD΄DMkMkMkMkMkMkMkMkNkNkNkNkNkNkNkNkOkOkOkOkOkOkOkOkPkPkPkPkPkPkPk A !E!!!"I""" #M###$Q$$$%U%%%&Y&&&']''' ! "#$!%)&1'9(A)I*Q+Y,a-i.q/y0123456789:;<=>?D!D)19BDJRZcDks{DĜDĽD΄DMkMkMkMkMkMkMkNkNkNkNkNkNkNkNkOkOkOkOkOkOkOkOkPkPkPkPkPkPkPkPk(A((()E)))*I*** +M+++,Q,,,-U---.Y.../]///@A BCD!E)F1G9HAIIJQKYLaMiNqOyPQRSTUVWXYZ[\]^_E!E)19BEJRZcEks{EŜEŽE΅EMkMkMkMkMkMkNkNkNkNkNkNkNkNkOkOkOkOkOkOkOkOkPkPkPkPkPkPkPkPkQk(A((()E)))*I*** +M+++,Q,,,-U---.Y.../]///`a bcd!e)f1g9hAiIjQkYlaminqoypqrstuvwxyz{|}~E!E)19BEJRZcEks{EŜEŽE΅EMkMkMkMkMkNkNkNkNkNkNkNkNkOkOkOkOkOkOkOkOkPkPkPkPkPkPkPkPkQkQk0A0001E1112I222 3M3334Q4445U5556Y6667]777 !)19AIQYaiqyɚћٜF!F)19BFJRZcFks{FƜFƽFΆFmkmkmkmknknknknknknknknkokokokokokokokokpkpkpkpkpkpkpkpkqkqkqk0A0001E1112I222 3M3334Q4445U5556Y6667]777 !)19AIQYaiqyɺѻټF!F)19BFJRZcFks{FƜFƽFΆFmkmkmknknknknknknknknkokokokokokokokokpkpkpkpkpkpkpkpkqkqkqkqk8A8889E999:I::: ;M;;;Y>>>?]??? !)19AIQYaiqyЁщґәԡթֱ׹G!G)19BGJRZcGks{GǜGǽG·Gmkmknknknknknknknknkokokokokokokokokpkpkpkpkpkpkpkpkqkqkqkqkqk8A8889E999:I::: ;M;;;Y>>>?]??? !)19AIQYaiqyG!G)19BGJRZcGks{GǜGǽG·Gmknknknknknknknknkokokokokokokokokpkpkpkpkpkpkpkpkqkqkqkqkqkqk@A@@@AEAAABIBBB CMCCCDQDDDEUEEEFYFFFG]GGG "*2:B J R Z b jrzH!H)19BHJRZcHks{HȜHȽHΈHsssssssssssssssssssssssssssssss@A@@@AEAAABIBBB CMCCCDQDDDEUEEEFYFFFG]GGG ! "#$"%*&2':(B)J*R+Z,b-j.r/z0123456789:;<=>?H!H)19BHJRZcHks{HȜHȽHΈHsssssssssssssssssssssssssssssssHAHHHIEIIIJIJJJ KMKKKLQLLLMUMMMNYNNNO]OOO@A BCD"E*F2G:HBIJJRKZLbMjNrOzPQRSTUVWXYZ[\]^_ I !I)19 BIJRZ cIks{ Iɜ Iɽ IΉ IsssssssssssssssssssssssssssssssHAHHHIEIIIJIJJJ KMKKKLQLLLMUMMMNYNNNO]OOO`a bcd"e*f2g:hBiJjRkZlbmjnrozpqrstuvwxyz{|}~ I !I)19 BIJRZ cIks{ Iɜ Iɽ IΉ IsssssssssssssssssssssssssssssssPAPPPQEQQQRIRRR SMSSSTQTTTUUUUUVYVVVW]WWW "*2:BJRZbjrz™ʚқڜ J !J)19 BJJRZ cJks{ Jʜ Jʽ JΊ JsssssssssssssssssssssssssssssssPAPPPQEQQQRIRRR SMSSSTQTTTUUUUUVYVVVW]WWW "*2:BJRZbjrz¹ʺһڼ J !J)19 BJJRZ cJks{ Jʜ Jʽ JΊ JsssssssssssssssssssssssssssssssXAXXXYEYYYZIZZZ [M[[[\Q\\\]U]]]^Y^^^_]___ "*2:BJRZbjrzЂъҒӚԢժֲ׺ K !K)19 BKJRZ cKks{ K˜ K˽ K΋ KsssssssssssssssssssssssssssssssXAXXXYEYYYZIZZZ [M[[[\Q\\\]U]]]^Y^^^_]___ "*2:BJRZbjrz K !K)19 BKJRZ cKks{ K˜ K˽ K΋ Ksssssssssssssssssssssssssssssss`A```aEaaabIbbb cMcccdQdddeUeeefYfffg]ggg #+3;C K S [ c ks{ L !L)19 BLJRZ cLks{ L̜ L̽ LΌ L{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{`A```aEaaabIbbb cMcccdQdddeUeeefYfffg]ggg ! "#$#%+&3';(C)K*S+[,c-k.s/{0123456789:;<=>? L !L)19 BLJRZ cLks{ L̜ L̽ LΌ L{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{hAhhhiEiiijIjjj kMkkklQlllmUmmmnYnnno]ooo@A BCD#E+F3G;HCIKJSK[LcMkNsO{PQRSTUVWXYZ[\]^_ M !M)19 BMJRZ cMks{ M͜ Mͽ M΍ M{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{hAhhhiEiiijIjjj kMkkklQlllmUmmmnYnnno]ooo`a bcd#e+f3g;hCiKjSk[lcmknso{pqrstuvwxyz{|}~ M !M)19 BMJRZ cMks{ M͜ Mͽ M΍ M{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{pApppqEqqqrIrrr sMssstQtttuUuuuvYvvvw]www #+3;CKS[cks{Ù˚ӛۜN!N)19BNJRZcNks{NΜNνNΎN{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{pApppqEqqqrIrrr sMssstQtttuUuuuvYvvvw]www #+3;CKS[cks{ù˺ӻۼN!N)19BNJRZcNks{NΜNνNΎN{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{xAxxxyEyyyzIzzz {M{{{|Q|||}U}}}~Y~~~] #+3;CKS[cks{Ѓығӛԣիֳ׻O!O)19BOJRZcOks{OϜOϽOΏO{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{xAxxxyEyyyzIzzz {M{{{|Q|||}U}}}~Y~~~] #+3;CKS[cks{O!O)19BOJRZcOks{OϜOϽOΏO{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{AÀEǁI˂ MσQӄUׅYۆ]߇ $,4<D L T \ d lt|P!P)19BPJRZcPks{PМPнPΐPAÀEǁI˂ MσQӄUׅYۆ]߇ ! "#$$%,&4'<(D)L*T+\,d-l.t/|0123456789:;<=>?P!P)19BPJRZcPks{PМPнPΐPAÈEljIˊ MϋQӌU׍Yێ]ߏ@A BCD$E,F4G?T!T)19BTJRZcTks{TԜTԽTΔTQQQQQQQRRRRRRRRSSSSSSSSTTTTTTTTAèEǩI˪ MϫQӬU׭Yۮ]߯@A BCD%E-F5G=HEIMJUK]LeMmNuO}PQRSTUVWXYZ[\]^_U!U)19BUJRZcUks{U՜UսUΕUQQQQQQRRRRRRRRSSSSSSSSTTTTTTTTUAèEǩI˪ MϫQӬU׭Yۮ]߯`a bcd%e-f5g=hEiMjUk]lemmnuo}pqrstuvwxyz{|}~U!U)19BUJRZcUks{U՜UսUΕUQQQQQRRRRRRRRSSSSSSSSTTTTTTTTUUAðEDZI˲ MϳQӴU׵Y۶]߷ %-5=EMU]emu}ř͚՛ݜV!V)19BVJRZcVks{V֜VֽVΖVqqqqrrrrrrrrssssssssttttttttuuuAðEDZI˲ MϳQӴU׵Y۶]߷ %-5=EMU]emu}ŹͺջݼV!V)19BVJRZcVks{V֜VֽVΖVqqqrrrrrrrrssssssssttttttttuuuuAøEǹI˺ MϻQӼU׽Y۾]߿ %-5=EMU]emu}Ѕэҕӝԥխֵ׽W!W)19BWJRZcWks{WלW׽WΗWqqrrrrrrrrssssssssttttttttuuuuuAøEǹI˺ MϻQӼU׽Y۾]߿ %-5=EMU]emu}W!W)19BWJRZcWks{WלW׽WΗWqrrrrrrrrssssssssttttttttuuuuuuAEIŠ MÎQĒUŖYƚ]Ǟ&.6>F N V ^ f nv~X!X)19BXJRZcXks{X؜XؽXΘXAEIŠ MÎQĒUŖYƚ]Ǟ !"#$&%.&6'>(F)N*V+^,f-n.v/~0123456789:;<=>?X!X)19BXJRZcXks{X؜XؽXΘXAȂEɆIʊ MˎQ̒U͖YΚ]Ϟ@ABCD&E.F6G>HFINJVK^LfMnNvO~PQRSTUVWXYZ[\]^_Y!Y)19BYJRZcYks{YٜYٽYΙYAȂEɆIʊ MˎQ̒U͖YΚ]Ϟ`abcd&e.f6g>hFiNjVk^lfmnnvo~pqrstuvwxyz{|}~Y!Y)19BYJRZcYks{YٜYٽYΙYAЂEцIҊ MӎQԒUՖY֚]מ׀&.6>FNV^fnv~ƙΚ֛ޜZ!Z)19BZJRZcZks{ZڜZڽZΚZAЂEцIҊ MӎQԒUՖY֚]מנ&.6>FNV^fnv~ƹκֻ޼Z!Z)19BZJRZcZks{ZڜZڽZΚZA؂EنIڊ MێQܒUݖYޚ]ߞ&.6>FNV^fnv~ІюҖӞԦծֶ׾[![)19B[JRZc[ks{[ۜ[۽[Λ؂EنIڊ MێQܒUݖYޚ]ߞ&.6>FNV^fnv~[![)19B[JRZc[ks{[ۜ[۽[ΛEI MQUY]'/7?G O W _ g ow\!\)19B\JRZc\ks{\ܜ\ܽ\Μ\ӜӜӜӜӜӜӜӜԜԜԜԜԜԜԜԜ՜՜՜՜՜՜՜՜֜֜֜֜֜֜֜QUY] !"#$'%/&7'?(G)O*W+_,g-o.w/0123456789:;<=>?\!\)19B\JRZc\ks{\ܜ\ܽ\Μ\ӜӜӜӜӜӜӜԜԜԜԜԜԜԜԜ՜՜՜՜՜՜՜՜֜֜֜֜֜֜֜֜QUY]@ABCD'E/F7G?HGIOJWK_LgMoNwOPQRSTUVWXYZ[\]^_]!])19B]JRZc]ks{]ݜ]ݽ]Ν]ӜӜӜӜӜӜԜԜԜԜԜԜԜԜ՜՜՜՜՜՜՜՜֜֜֜֜֜֜֜֜לQUY]`abcd'e/f7g?hGiOjWk_lgmonwopqrstuvwxyz{|}~]!])19B]JRZc]ks{]ݜ]ݽ]Ν]ӜӜӜӜӜԜԜԜԜԜԜԜԜ՜՜՜՜՜՜՜՜֜֜֜֜֜֜֜֜ללQUY]'/7?GOW_gowǙϚכߜ^!^)19B^JRZc^ks{^ޜ^޽^Ξ^QUY]'/7?GOW_gowǹϺ׻߼^!^)19B^JRZc^ks{^ޜ^޽^Ξ^QUY]'/7?GOW_gowЇяҗӟԧկַ׿_!_)19B_JRZc_ks{_ߜ_߽_Ο_QUY]'/7?GOW_gow_!_)19B_JRZc_ks{_ߜ_߽_Ο_netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08.bmp0000664000175000017500000002206611032370343021056 0ustar vincevinceBM6$6(@   $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g01bw.bmp0000664000175000017500000000207611032370343021377 0ustar vincevinceBM>>(@?????????????>~???????????????>~?????x?'rp$`?&r@$B?ww?netsurf-2.9/libnsbmp-0.0.3/examples/bmpsuite/g08os2.bmp0000664000175000017500000002143211032370343021476 0ustar vincevinceBM# @  $$$(((,,,000444888<<<@@@DDDHHHLLLPPPUUUYYY]]]aaaeeeiiimmmqqquuuyyy}}}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}  $(,048<@DHLPUY]aeimquy}@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@???????????????????????????????AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB===============================CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE:::::::::::::::::::::::::::::::FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9999999999999999999999999999999GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG8888888888888888888888888888888HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH7777777777777777777777777777777IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII6666666666666666666666666666666JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ5555555555555555555555555555555KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK4444444444444444444444444444444LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL3333333333333333333333333333333MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM2222222222222222222222222222222NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1111111111111111111111111111111OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO0000000000000000000000000000000PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP///////////////////////////////QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ...............................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR-------------------------------SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT+++++++++++++++++++++++++++++++UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU*******************************VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)))))))))))))))))))))))))))))))WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW(((((((((((((((((((((((((((((((XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'''''''''''''''''''''''''''''''YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\###############################]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"""""""""""""""""""""""""""""""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!________________________________ ````````````````````````````````aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffgggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkllllllllllllllllllllllllllllllllmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnooooooooooooooooooooooooooooooooppppppppppppppppppppppppppppppppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr ssssssssssssssssssssssssssssssss tttttttttttttttttttttttttttttttt uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyy????????zzzzzzzzzzzzzzz????{{{{{{{{{{{{{{{???????|||||||||||||||????}}}}}}}}}}}}}}}????????????~~~~~~~~~~~~~~~netsurf-2.9/libnsbmp-0.0.3/examples/decode_bmp.c0000664000175000017500000001037411172610263020357 0ustar vincevince/* * Copyright 2008 Sean Fox * Copyright 2008 James Bursa * * This file is part of NetSurf's libnsbmp, http://www.netsurf-browser.org/ * Licenced under the MIT License, * http://www.opensource.org/licenses/mit-license.php */ #include #include #include #include #include #include #include #include #include "../include/libnsbmp.h" #define BYTES_PER_PIXEL 4 #define TRANSPARENT_COLOR 0xffffffff unsigned char *load_file(const char *path, size_t *data_size); void warning(const char *context, bmp_result code); void *bitmap_create(int width, int height, unsigned int state); void bitmap_set_suspendable(void *bitmap, void *private_word, void (*invalidate)(void *bitmap, void *private_word)); void invalidate(void *bitmap, void *private_word); unsigned char *bitmap_get_buffer(void *bitmap); size_t bitmap_get_bpp(void *bitmap); void bitmap_destroy(void *bitmap); int main(int argc, char *argv[]) { bmp_bitmap_callback_vt bitmap_callbacks = { bitmap_create, bitmap_destroy, bitmap_set_suspendable, bitmap_get_buffer, bitmap_get_bpp }; bmp_result code; bmp_image bmp; size_t size; unsigned short res = 0; if (argc != 2) { fprintf(stderr, "Usage: %s image.bmp\n", argv[0]); return 1; } /* create our bmp image */ bmp_create(&bmp, &bitmap_callbacks); /* load file into memory */ unsigned char *data = load_file(argv[1], &size); /* analyse the BMP */ code = bmp_analyse(&bmp, size, data); if (code != BMP_OK) { warning("bmp_analyse", code); res = 1; goto cleanup; } /* decode the image */ code = bmp_decode(&bmp); /* code = bmp_decode_trans(&bmp, TRANSPARENT_COLOR); */ if (code != BMP_OK) { warning("bmp_decode", code); /* allow partially decoded images */ if (code != BMP_INSUFFICIENT_DATA) { res = 1; goto cleanup; } } printf("P3\n"); printf("# %s\n", argv[1]); printf("# width %u \n", bmp.width); printf("# height %u \n", bmp.height); printf("%u %u 256\n", bmp.width, bmp.height); { uint16_t row, col; uint8_t *image; image = (uint8_t *) bmp.bitmap; for (row = 0; row != bmp.height; row++) { for (col = 0; col != bmp.width; col++) { size_t z = (row * bmp.width + col) * BYTES_PER_PIXEL; printf("%u %u %u ", image[z], image[z + 1], image[z + 2]); } printf("\n"); } } cleanup: /* clean up */ bmp_finalise(&bmp); free(data); return res; } unsigned char *load_file(const char *path, size_t *data_size) { FILE *fd; struct stat sb; unsigned char *buffer; size_t size; size_t n; fd = fopen(path, "rb"); if (!fd) { perror(path); exit(EXIT_FAILURE); } if (stat(path, &sb)) { perror(path); exit(EXIT_FAILURE); } size = sb.st_size; buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %lld bytes\n", (long long) size); exit(EXIT_FAILURE); } n = fread(buffer, 1, size, fd); if (n != size) { perror(path); exit(EXIT_FAILURE); } fclose(fd); *data_size = size; return buffer; } void warning(const char *context, bmp_result code) { fprintf(stderr, "%s failed: ", context); switch (code) { case BMP_INSUFFICIENT_MEMORY: fprintf(stderr, "BMP_INSUFFICIENT_MEMORY"); break; case BMP_INSUFFICIENT_DATA: fprintf(stderr, "BMP_INSUFFICIENT_DATA"); break; case BMP_DATA_ERROR: fprintf(stderr, "BMP_DATA_ERROR"); break; default: fprintf(stderr, "unknown code %i", code); break; } fprintf(stderr, "\n"); } void *bitmap_create(int width, int height, unsigned int state) { (void) state; /* unused */ return calloc(width * height, BYTES_PER_PIXEL); } void bitmap_set_suspendable(void *bitmap, void *private_word, void (*invalidate)(void *bitmap, void *private_word)) { (void) bitmap; /* unused */ (void) private_word; /* unused */ (void) invalidate; /* unused */ } void invalidate(void *bitmap, void *private_word) { (void) bitmap; /* unused */ (void) private_word; /* unused */ } unsigned char *bitmap_get_buffer(void *bitmap) { assert(bitmap); return bitmap; } size_t bitmap_get_bpp(void *bitmap) { (void) bitmap; /* unused */ return BYTES_PER_PIXEL; } void bitmap_destroy(void *bitmap) { assert(bitmap); free(bitmap); } netsurf-2.9/libnsbmp-0.0.3/examples/monitor.ico0000664000175000017500000031054611032370343020316 0ustar vincevince ( 00hh(> h3 900A(L^Ph  00(>( xrø҇ΤؗYRRYI*OHݪ/xxxf{hc3/˨7{/( @rjc{q˲ʙ҈˿ޜ#"""zC/wwzBC34J333G7wD3C!$G8ݪGw"#4w0-* yyyyyOmkZY^R5(! yyyy$gvtromjeV%yyyyy+4CFbWk3yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy( @db]shtvwz{}xy֫rޯdWūɯkͲ|hݷɷ|ֻ}rz¹|ļxпDŽypƾĜŗʁǕĤ{ŝ|̃ǟºǣĴ̏}͐ļ˝Їȵƾ̣҉ɹҏՉҖ֊Ҡ͹Փٌ֔۔ٝܕڞ٨۟ޘݦڹߨ߱ >Kzt> -76?S^t~z& ?%'Sgw?''>Sn~ ?>:)%2 %:^nUPeS12*-:?le611)13{Z*6 'a--xxP -8krO-Fkr|||. AC\qxx}}xxx$?Lkfkkx|x}xxxxkK[|kqqk|xxxx|xx|xukk\a]|\kkkqyxyx|rkhhoTb`|ookkqkkkqkoh\E -gfqkohkqqdd``H=3Yv`\o``````JN0 DW`q```\`VQI0Ucoqv``VQVE" s_|o`QQH!s]qo`!mi`,%sMGBIEf|(tttttmRR9<0@=E`q,ttpjg^^X;;4/+#5SD?>:@(0`kd\rkcunf}peuj{otvwy}ɩ{جs_ūXsk\fງwj}˹ŻҽپznÌć|łû•xŽžȅŒǾqƔwzĠèɌ|̃ǟºǫûþ}Ї͜Ηƾӆ҉ӐՉ֊ՓκӦٌ֔ӯٓ۔ܕڞޘݦ۷ݯߨ߲   %>Oi1,QQ>"#Dcssb 1#/DQfss1.9HQbhnu#4# 9OObfssDƭf/#9:DXbhuuxb#,DiHD5,.> #9:D=SXcD y^0%1>>5 %*/99OO "-}C* *5##9Hb #2g0 .5:4:D"Ew9$   Ɔ ,,T_*  ,Ƹ**l}2   1.myE! 1/~m :9tl#=9tzzK ,9Ert{299Brttt):DKkjttt{ttO9Pkjrzvtzj _XVpjtzzz{ttzq _XVvvttz{tttto\ShRztztttztz{t{trvkk3 *hhaztpvvtttztttzzztkttjj3 /nYdtvtzzzztztttttttptkkjU& :hTktzpjtzzrzpkzppppka]J&DwIkzvkttztvtppkkkakkJhwWjrjjvkppppkkkkaaka8 wxNkkdjkkkkkkkkadaaR8MzkkkqkkakaadaRR+#RkkzkkkadkkaRR(*|wJzdzakdd]]aR3# 5|akkkdkdk@'"#Dwek‘zvqq@2"b|ekvJ), hwWūü@/*w|lNV\\Zjz;*/|||||||||ee`N?G]JRq791||xxxuu[FLA76R@dq64xuuuuuh_wS_FF<37+6<0sshhfcbbXO_D99DOHDDw//???????@P(]VQyla}qfxqi|tmuj{ptv}{}|~ɩ{ѫxƬFݲlQή۰wcKįY~òwʵ޺}lѷ]ƶshܻĶй}˹kbӽÀýnûÍĈļп™xoƾėߌʄĢǿǕ{ç̃¹½ûɠ}Ȭļφ͖ʥЇƽɱʮ҉ǿϞԇҐՉ֊ԑͶҥՓ؋֔זٌٓլ۔ٜܕ٩ޘܠާܼޱ                                  9pŹţvXC4!    OŹX?      4O]ֲ9     /XddA4(C{ֲX!     RXX4, &* 9dwṿ]!  X]A!&(,((*2Xw{p{̤O  C]A&! & */,(,9dpvw{{ſ̿v2 XA4* !&*22/42Opppwp{ʠ?! X92/ !(/4229AXdppppw{̹O$ C224 &,299222O]dvpppw{{X4 22/&! 42299A2C]RdvdppwwwO 94* /4??2?LAOXRpdppuwpuO9(!,  CXX]]dddu{u{@2* $OXXdav]appw{uR9.!aaORR]Rjjjppppu{{p] vC?44$! X ORXRXaadjwww{w]] ,RXRL?42$ R   4OOUUUaajepv{w{{jOL&嘠R]XRRO90(!O!    2RRRRUUUUdRepw{{{wXX/v{pdORO22( &{U      XXX]XRaajLXUX]RddvepRL  $?X{]O29& w     RRROX]RRRa]a]LdR]LaLd] &CddR9&C2     9?ACRRRXd]jedejd]ejad! ! : ,Ov{wXC* {w     $((/AOROXdjpppevjjp   @oV0  (?OvX/      &*2ARRRpeppuep !!! [¶o@)  ,w4   ! ,9?Lapepp&&$ ~™h0 (&  *Ljaw(( &&&ɂM2    4??/,($?]pw (* &&&دzL#      OXdC9,!!*C,(&$$ دh?      !(9OXA4,!/*(*&!ܨh0      C*,*(&Eԍ^0       & $//(,(E޾z@        ,,2,*l¶ߨh.        4422,*lܨh       224,24ܾL         299229}دo:          ?22942¶ɯh%      ?2?92/əM       2?22?E¶¼o<    (?9A??MǸº¶¶`<   22L229S¶Ƕ  4CCA9?f¶¶ L?2CL2}¸Ƕ  L?RA24}Ƕ¶q CLCLCLǶ¶ǶG  OLAAC?Ƕ¶>  &LOLR@RǶ¶Ƕ¶Ƕ¶% ,OXLOCVy¶¶ºǶ¸Ǹ  9ROULLVǶ¶  ORXLOOqǶĺǶ   LXL]RXfyyǶǶǶǶb ]jLULOcyJ  LUULUR\yy1  jj]LUXyyy"  *ULLjULryyy  .]aaaUeryy  ?eaUUXSryy  OLaaaabryyn  ]jdjjRkiyyQ  jeuLpRmiyyy7  upjje]\r1 pjpjpagiyt  &ejejedZyyyy  4puwppaYyyt   2pewesYyyyty  Uwu{upsY÷ûyyyiH  LweaecYǸyyyryF uuepmYyyyig+ wua{Ngûøyri' wwwwuI_ȷ÷Ȼ÷yyy_Z  !wwRB_÷÷Ǹyyryyrig  2{e3rû÷Ƿ||yyrgY 4{wsBgû÷ǷǷy|y|yy|rrZN R{wxBgȻ÷Ǹûyy|y|yy|rrgYN Xm3_÷û÷yy||||r||rr_Y- \BtȻû||||y|yyrr|rrr_K+DP_÷ê|y||y||||r|KP' IY÷û||y|y||r|r|rrrBK !3Yêyy|||||||r||r_PK43rȻyyyyyyy|yy|||||r|r||rr_KB ?3têyyyy||||||rr|r|_|_=; OsB÷÷yy||y||||||r|||rt_tPB8jmBtȒy÷yy||||||r||grggtY3-mKȪt||||||t|r||g|ggttB3+ \Yyȷt||||||t|g|rrggYB3'  I_͐t÷÷r|||tt|g|g|grggtt33 &BtȪtt÷|||rttrt||gg|gYt33!  *3tȐtȷ÷ȷttr|t|||g|gtggtt36 !! ?3ђtttȷȷtt|ttt_tggtgtYY3;&&!! Ax3ѪtȷtttttttttttttY38( p=׷tȷȷȷȳrtttttttY3- ,&& u\B͒ȷȷȷȷttttP31&( $mYђȷȷtttB3'2(&& Y_ӪȻȷȪtttttB3,((*( Iڪtttt33(2((* 3᪪ȷt3;22/2 93ᷪ÷t3;4,,,*C3êmt384222LB䷜Ȫt3-294//jkYȢ÷Y314922 \3KrrìȜg32L294~c\II33333BPgirȳB32A2?2~~bc\PI333333KKgrtͳB6?2C29獍~bc\II3333333KPgrtѳ3IL2C29疖~~bc\IP3333333=KYttѷ38?4??瘘xb\T;I33333333=KYgtת3D9RL2瘘llbTNP;33333=333BPYgѪ31R9??瘘{{u{u[sfDDIP3333333333PYt3JLOLL瘘{{ww{{eveupujlsQQNIK33333333336Yg3OO@CC瘘wwewwpupwjpjpjejjjL[JWFFP;33333333ULLO瘘epu{vepeppjpjjjaaaLaLja[JQF5FOOCOO犊wueuejwjvpuepjdjaaaajRL]ULLURLOR{{{wwwwwewejjejeadaaaLdaL]aUUXOOOOwppppjjdjeaaajLUjLXaLLURppddd]]]]RXLRUULOXXXXRXX꪿?wwwup??wP??] _???????@( ýú{tکֳҸúٸ˺ܘİ™֍ۘݛʢٕٕ۟ܚޝޝܚڕ֍Ϣެ߬ܡהגב֎Ӊπ֪י؛ҋшσtúۭެӑ΄u½Ǿ߮Ǒ‰̕ћ׫׭߯Ϣþƿû( @|}}}~̾ľý̰Ž»Ű~rjz½xxzûɠںɵü|ҡɹڥIJܚ߾ڕޜ߷æx½ʸؑڕޜǓѿՍؑڕޜޜ˳•цՍؑڕܚޜܚڕīĻŚ֐҉ՍؑڕܚޜޜܚڕؑՍ{Ⱦ̒ܤ֐Ս֐ڕڕڙܚܚޜޜޜܚܚڕڕؑՍцz̒ܢԋ֐ؑؑڕڕڕڕڕڕؑؑՍԋц~xĹӑ؜Ս֐֐ؑؑؑ֐֐ՍՍ҉цЃwǻՕՕՍՍՍՍՍԋ҉҉цЃ~n½Ʃڤ֘҉҉ԋ҉҉҉ццЃ~~mƼǤ߰҉֘ܤэ҉ψцЃ͂~zḳӑ֘؜΅΅͂~}}g˛ܨڢՕ΅΅΅͂Ԭr̕ՕээԬrľќ߰ӑīľŖƈŁȀ}ψެڤǮ̺šǣ羂翄mu|э⵿֘ɽǻĹ÷ӺӺ۷޵zo_ļŽ(0`xxxxxxx¼½züľľľ½М¸ü¹Ľϸz{og{ogºƾ¹ĽĽxzrum}qiºƾ¹ƾƾºĺxxxxzr¸ĺƾƾѥãzxxx¸ƼƼӯź¸ۺūzxͻոxxx½ۺūxxzȚޝϭxxxzΗܙѥͻ~xxxӓۘޝ՝x؎ٔۘޝΗxԊ؎ٔۘޝޝÒxͻԊ؎֐ٔۘܙޝܙ˳xҽхԊ؎֐ٔۘܙޝޝۘٔêx¸ÒххԊ؎֐ٔۘܙޝޝܙۘٔ؎{xƼĺÒщхщԊՍ֐ٔٔۘܙޝޝޝܙۘۘٔ؎Ԋ{xȾƼƂݡԊщԊՍ֐ٔٔۘܙܙܙޝޝޝޝޝܙܙۘۘٔ֐؎ՍхxȾƂٞщԊՍ֐֐ٔٔۘۘܙܙܙܙܙܙܙܙܙۘۘٔٔٔ؎؎ԊԊ|z÷uוԊՍ֐֐ٔٔٔٔٔۘۘۘۘۘٔٔٔٔٔ֐؎ՍԊщхyø÷́ޭ֐ՍՍ֐֐֐ٔٔٔٔٔٔٔٔٔ֐֐ՍՍԊԊхх́ݶwĹã́ݡՍՍՍ֐֐֐֐֐֐֐֐֐֐ՍՍԊԊщхх́|ʩxǻà΅ٞՍՍՍՍՍՍՍՍՍՍՍԊԊԊххх́́u{ĺɽڡԊԊՍՍՍՍՍՍԊԊщщххх́́|nǼɽˆܩڡщщщщԊщщщщщххх΅́́||b˿ņޭщщщޭܩэщщщщψх΅΅́́|||byיщщڡڡщщψψ΅΅΅́́|||^|щщڡיψ΅΅΅΅́́|||`qґэۥґ΅΅΅́́́́t٭nͻ΅ڡґޭґψψψ΅΅uխsɦэٞܩґээщqêȾȞۥۥґґqī÷ĉ߱ۥjɦĉȍȄɃ́́ґڡ߱hɦɦŐĉy}}t΅ґܩuľ˿˿ɽġġ翄ui{ḱґٞj˿ɽɽǼǻĹĹ÷ռռ޺rfm޶|Ĺ÷ȿƼƼ帼¹º? ???????(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx~zxxxxxxxxxxxxxxxxxxx|¾zxxxxxxxxxZRN{txxxxxxþ}xxxxxxxypjxxxxxüſxxxxxxx)%#zsxxxyýĿƿ{xxxxx*'$zsxxxžýĿ;xxxxx~tnxz¼ýſι|xxxxaYTxļƿ¼ýſxxxyrĽƾ¼Ľſ̵zxx/+(ļŽƿüĽſںxxûļžƿ»üľſؼ}xƵúļŽƾǿ»üľƿнxxص¹ûļŽƿ»ļžƿźx̲vskwkcwkc{s¹úļŽƾǿºûĽžŽx̴skwkc|swkcwkcwkcwkcwkcskºûļŽǾºüŽƿƿxͿxwkcvn¶Ⱦumxldwkcwkcwkcwkcwkcsk¹úļŽƾǿûļŽƿú¹}u|phȼxx{tvn|qiwkcwkcwkcwkc{ogùĻżƽǿºüĽƾǿ¹ĻĿŽȼȼxxxxxxxqslymewkcwkctk¹Ļƽǿ¹ûļŽƾżȼȼxxxxxxxxx|uvn{ph{og¸úĻƽǿºĻżƾǿǿýżŽȼȼúxxxxxxxxxxxxymez¸¸¸¸¸¸¸¸¸¸¸ĺĻŻżżżù¸¸ºǿĻżȼȼxxxxxxxxxxxzrwkc¸ùùĺĺĺĺĺĺĺĺĺĺĺĺĺĺúƿŽŽȼȼxxxxxxxxxxxxyq¸ùŻŻƼƼƼƼƼƼƼƼżżżżǿƿýȼȼ÷|xxxxxxxxxxx{úĻƽƽǾǾǾǾǾǾǾǽ٪Ţõºxxxxxxxxxxxxùƽȿɿɿ׭~}}|¹ˬzxxxxxz}ǽĞӯ~~}||{zyúø÷÷ҢίŻ~}}|{zzyxxxxĻøҢȭ~}}|{{zyxxxxxxz~üxxݽ~~}||{zyyxxxxxxxxxxxx׺||{zzyxxxxxxxxxxxxy}ϴ{zyxxxxxxxxxxxxxxxxxx|ƮxxxxxxxxxxxxxxxxxxxxxܾĽxxxxxxxxxxxxxxxxxxxxxۼļ}xxxxxxxxxxxxxxxxxxxxx̛ߞҳxxxxxxxxxxxxxxxxxxxxxxЛߝ߻ȫxxxxxxxxxxxxxxxxxxxxxxxٙޜߝֱxxxxxxxxxxxxxxxxxxxxxxܗݚޜߞӫĶ|xxxxxxxxxxxxxxxxxܖݚޜߝߟޮɡxxxxxxxxxxxxxƵەݘݚߜߝԣxxxxxxxxмڔܗݘޚߜʙxxxxx™ړۖܗݙޚߜ⢊xxxxxǕْەۖܗݙޛߜԛxxxxx͒ؐړەۗܘݚޜߝȕxxxxxϐْؐړەۗܘݚޛߝߞ˵xxxxx֊׏ْؑڔەۗܘݚޛߝߞߝįxxxxxՈ؏ّْؐڔۖۗܙݚݜޝߞߜޛxxxxx˹Ԉ׍؏ّؐړڔۖۗܙݚݜޝߞߜޛݙxxxx̺Ԇ֌׍؏ْؐړەۖܘݙݚݛޝߞߟޛݙܗxxxxx•ӆՋ֌׎؏ْؐړەۖܘݙݚޛޜޞߟߝߜݙܗۖxxxxx”҅ՊՋ֍׎׏ْؑڔڕۗܘܙݚޛޜߞߜޛݚܖەčxxxxxɉӅԈՊ֌׍׎אْؑٓڕۖܘܙݚݛޜޝߞߝޜޛݙܘ۔ړڽxxxxx¸Ȉ҄ӈԉՋ֌׎׏ؐؑٓٔڕۖۗܘܚݛޜޝߞߞߝޜݚݙܘۖړّĬxxxxx¹¸{фӇӈԉՋ֌׎׏ّْؐڔڕږۗܘܚݛݜޝޞߟߞߝޜݛݚܘܗۖڔّ؏xxxxxúù¸y҄҆ӇԉԊՋ֌֎׏ؐؑٓڔڕۖۗܘܙܚݛݝޝޞߟߟߞޝݜݚܙܘۗۖڔّ؎׍}xxxxxĺúù¹¸ͻxу҄ӆӇԉԊՋ֍֎׏אْؑٔڕەۗܘܙܚݛݜݝޝޞߟߠߟߞޞޝݜݛݚܙۘۗڕڔٓ؏׍֋zxxxxŻĻĺù¹ѽxЂф҅҇ӈԉՊՋ֍֎׏אؑؒٔڔڕۖۗܘܙݛݛޜޜޝޞޟߠߞޝޜޛݚݚܙܘۖەڔړّ׍֋։xxxxxżŻĻĺúx֑уф҅ӇӈԉԊՋ֍׎׏ؐؑؒٓٔڕږۗۘܙܚݛݛޜޝޞޞߟߠߠߞߞޝޜޛݚݙܙܗܗۖڔړّْؐ֋ՉʆxxxxxĺƽƼżĻĺyާ֐҅҆ӇԈԊԋՌՍ֎׏ْؐؑٓٔڕڕږۗۘܙܚݛݛݜޝޝߞߟߟߠߟߟߞޝޝޜݛݚݚܙܘۗۖڕڔْٓؑؐ׏ՈԇᾂxxxxxǾǽƽƼżŻÇwިߩԋ҆ӇԉԊՋՌՍ֎׏אؑؒٓٔڕڕږۗۘۙܙܚݛݛݜݝޝޞߞߟߟߟߠߡߠߠߟߟޞޞޞޝޝݜݛݚܚܙܘۗۖږڕْٔؑؐ׏׏֍ԆӅ̮xxxxxȿȾǾǽƽż~zܡӉӇӉԊՋՌ֍֎֏אבؒؓٔٔڕږۗۗۘܙܙܚܚݛݜݜݝޝޞޞޟߟߟߟߠߠߠߠߠߠߠߠߠߠߠߠߠߟޟޞޞޝޝޝޜݜݛܛܚܙܙܘۗۗږڕڔْٓؑؐ׏׎֍֋ӄ҃ũ}xxxxxȿȾǾǽƽtyڜ҈ӉԊԋՌՍ֎֏אאؑؒؓٔٔڕږږۗۘܙܙܚݚݛݛݜݜݜݝݝޝޞޞޞޞޞߟߟߟߟߞߞߞߞޝޝޝޝޝޜݜݛݛݚݚܙܙܘۗۖۖڕڔڔْْؑؐ׏׎֍֌ԉтс|yyxxxɿȿǾǽi}הӉԊԋԌՍ֎֏֐אٕؑؒٓٔٔڕږڗۗۘۘܙܙܚܚݛݛݛݜݜݜݝݝݝݝݝݝݝݝݝݝݜݜݜݜݜݛݛݚݚܚܚܙܘۘۗۖڕڕڔْٔٓؑؐ׏׏֎֌ՋՊӆр|zzyxɿȿοg΀ߪՏԊԋՌՍ֍֎֏֐בؑؒٓٔٔڕڕږڗڗۘۘۙۙܙܚܚܚܛݛݛݛݛݛݛݛݛݛݛݛݛݛݚܚܚܚܙۙۙۘۗۗۖږڕڕٔٔٓؒؑאא׏֎֍ՌՋԊԉ҃~}|{zzy·iҌܡԍԋԌՍ֎֎֏֐בבٕٕؒؒؓٔږږۖۗۗۘۘۘۙۙۙܙܙܚܚܚܚܚܚܚܚܚܙܙܙܙܙܙܘۘۗۗږږڕڕٔٓٓؒؒؑؐ׏׎֍֍ՌՋՊԉӈс|z}|{{z··iҌڜԋՌՍՎՎ֏֐אבגٕٕؒؓؓٔٔږږږۗۗۗۘۘۘۘۘۙۙۙۙۙۘۘۘۘۘۘۗۗۗږږږڕڕڕٔٓٓؒؒؑؐ׏׏֎֍ՌՋՊԉԉӈӇ}yz~}||{¹ø÷·kҌؗԌՌՍՎՏ֏֐אבגٕٕٕٕؒؓؓٔٔږږږڗڗۗۗۗۗۗۗۗۗۗۗۗڗږږږڕٕٕٕٔٔؓؓؒؒבא׏֏֎ՎՍՌԋԊԉӈӇ҆҅{wݷy~}}|Ĺĸø÷··mיߩ֒ԌՍՎ֎֏֐֐֑בגגٕٕٕٖٖٖٖٖؓؓؔٔٔږږږږږږږږږږڕڕْٕٔٔٔٓٓؒؒؑאא֏֎֍֍ՌՋՋԊԉӈӇ҆҅҄vuɩz~~}źĹĹøø·soٞݤԌԍՎՎ֏֏֐֐בבבגגדٕٕٕٕٕٕٕٕٕٕٕؓؓؓٔٔٔٔٔٔٔؓؓؓؒؒؒבבא֏֏֎֎ՍՌՌԋԊԉӈӈ҇҆хфЃts¦{~ƺźŹĹĸørrٞڛՌՍՎՎՏ֏֐֐֑בגגגגדדדדؓؓؓؓؔؔٔٔٔٔٔٔؓؓؒؒؒבבבא֏֏֏֎֎֍ՍՌԋԋԊӉӈ҇҆҅хфуrq~ƻƺźŹĹĸYsݩؕՍՎՎՎ֏֏֐֐֑֑בגגגדגדגדדדדגגגגגגגגבבבאא֐֏֏֎ՎՍՍՌԌԋԊӉӉӈ҇҆҅хфЃЂ}poǻƻƻźźĹWyި֐ՎՎՎՏՏՏ֏֐֐אבבבבבגגגגגגגגבבבבבא֐֐֏֏֏ՎՎՍՍՌԌԋԊӊӉӈӈ҇҆ххфЃςρznmȼǼǻƻƺàWyܢԍՎՎՎՎՏՏՏՏ֐֐֐֐֐֐באאבבב֑֑֑֐֐֐֏֏֏ՏՎՎՍՍԌԋԋԊԊӉӉӈ҇҇҆цхЄЃςρπvlnùȽȼǼǻƻà\yٚԎՎՎՎՏՏՏ֏֏֏֏֏֏֏֐֐֐֏֏֏֏֏֏֏֏ՎՎՍՍՍԍԌԌԋԋԊӊӉ҈҈҇҇цхЄЃЃςρ΀sjpùɽȽȼǼǻZyדԍՍՎՎՎՎՏՏՏՏՏՏՏ֏֏֏ՏՏՏՎՎՎՎՍՍՍԌԌԋԋӊӊӊӊӉ҈҈҇чцЅЄЃσςρ΀~ngӭuƺɾɽȽȼȼdz֓ԍԍԎԎԎՎՎՎՎՎՎՎՎՎՎՎՎՎՎԎԍԍԍԍԌԌԋԋԋӊӊӉ҉҈҇ццххЄЃЂςρ΁΀~leͪvʿʾʾɽɽȽqdzӌӌӌӍԍԍԍԎԎԎԎԎԎԎԎԎՍՍՍՍԍԍԍԌԌԌԋӋӊӊ҉҉҈шччццЅЄЃσςρ΀~}dc}˿˿ʾʾɾɽjnьՒӌӌӌӌԌӌӍӍԍӍӍԍԍԍԍԍԍԍԍԌӌӌӋӋӋӋҊҊ҉҉҉҈шччцІЅЄЄσς΁΀΀~}|ba˿˿ʿʾɾUrԓުҋӋӌӌӌӌӌӌӍӌӍӌԌԌӌӌӌӌӌӌӌӋӋӋӋӊҊҊҊ҉҈шчччцхЅЄЄσςρ΁΀~}w__˿˿ʿʾO}ՕӎҋҋҋӌӌӌӌӌӌԏӌӌӌӌӌӌӌӌӌӌӌӋӋҊҊҊҊ҉҉҉шшччІІЅЄσσςς΁̀̀~}|t]\˿ȱO͂ڢڡҊҊҋҋҋҋҋҌҌݦݥԏӌӌӌӌӌӋӋӋӋӋҋҋҊҊ҉҉шшшЇІІІЅЄτσσ΂΁΁΀~~}|o[gƣU΄߯ҊҋҋҋҋҋҋҋӋٝڟҋҋҋҋҋҋҋҋҋҊҊщщщшшччЇІІЅυτσσ΂΂΁̀̀~}|{jYiƽĕ]χ֖ыҋҋҋҋҋҋҋ֖טҋҋҋҊҊҊҊҊҊщщшшшЈЇЇІІЅττσ΃΂΁΁̀~~}|{gWѪsź‡dЉޫъъыҋҋҋҋҋԏԑҋҋҋъъъщщщшшшЇЇЇІυυττσ΂΂΁̀̀~~}||_T˨vylъъъыыыҋҋҋӏܥӎҊҊҊъщщщшЈЇЇЇІІЅτττ΃΂́́́̀~~}|{]Rkrэ֗ыыыыыыьӏڢъъъщщщшшЇЇЇφυυτ΄΄΃΃͂́̀̀~~}|{QPdӐ߮ыыьььььӐ֗щщЉЉЈЈЈЇχχφυυ΄΄΃͂͂́́̀~}}|{OOO΅ӒыььььььӑԓЉЉЈЈЈχχφφφ΅΄΄΄̓͂́́̀~}}tOWͻOԔԔՖььььььӑޫэЉЉЈЈχχφφ΅΄΄̓̓͂́́́̀̀̀sO`ɦOՖՖܦҏҏҎҎҎҍӒۥэЈЈЈχχΆΆ΅΅΄΃̓͂͂͂͂́́́́nOٮnǾɦa֙ڤӒӑӑӑӑӐ؝؞ЈψψχχχφφΆ΅΅΅΅΄΄΄΃΃΃iOլsǾĉbל߰ԔԔԔԓԓԓۤ՗ЉЉЉЉЈЈЈψχχχχφφφΆ΅fOũĉr؞כՖՖՖՖՕ߰ӒъъъЊЊЊЉЉЉЉЉЈЈψχ]Olx١ܨ֚֙֙֙؝ݫӐььььыыыъъЊЊЊЉ]OlЉڤ߯לללכܨۦҏҎҎҎҍҍээьььыOOOӐۦٟ؟؟؞١ӑӐӐӐӐҏҏҎҎҎObO؞ݩڣڢڢۦלԒӒӒӑӑӑӑ΄OgʭOެެۥۥۥכԔԔԓԓԓ͂Oذvùɦ[߯߯ܨܨެ߯֙ՖՕՕzOԯ|ǾŐg߱߱߱ޫޫݫ֘֘sOƭƻĉUg̀̀ӓ֙؟߱߱߯ޮ٠pOɦĉllOOOOOagm̀̀ӓ֙ۥ߱߱bOʭɦƗĉllOOOOOOggt̀̀֙֙ۥ߱߱cYʭɦƗĉllOOOOOOUggz̀Ά֙֙ݫ߱OdʬȥƖÈkkOOOOOOOUgg̀̀ь֙֙OtǪƣĕjjOOOOOOOO[gg̀̀Ӓ؟ݬ߮Oܴz˿˿ʿʾɾɽɽȽŨĠ~iiOOOOOOOOOagm̀φ؟ݫOϳ˿ʿʾʾɾɽȽȼǼǻƻƺźźĹ¥߿徃|ihOOOOOOOOOOgg}ьԕ߰O̳˿˿ʾʾɾɽȽȼǼǼǻƻƺźŹĹĸø··Ӿ־ݼ㼁zhgOOOOOOOOOOUprэՖӒO˿˿ʿʾɾɽɽȽȼǼǻƻƺźŹĹĸø÷·¶ɿȿȾǾǽƽƼлӺںygfOOOOOOOO˿ʿʾʾɾɽȽȼǼǻƻƺźźĹĹøø··ȿȿǾǽƽƼżŻĻúù¹¸̷з׷߷}wv˿˿ʾʾɾɽȽȼǼǼǻƻƺźŹĹĸø··ɿȿȾǾƽƼżŻĻĺúù¸ȼǼǻƻƺźŹĹĸø÷·¶ɿȿȾǾǽƽƼŻĻĺúù¹¸Ĺøø··ȿȿǾǽƽƼżŻĻúù¹¸ɿȿȾǾƽƼżŻĻĺúù¸ŻĻĺúù¹¸??8????????????netsurf-2.9/libnsbmp-0.0.3/examples/ro.bmp0000664000175000017500000113060611031063543017251 0ustar vincevinceBM(  TTsss99111999Z99ZZc!Z999ZZZ9{9{{{ccc!!!JJJBBBZZBBBB))){{cc!cccc!ޜ{9ƄB{{{9{{ޜZZZBBޜ祥cc{9{{ƄƄޜZZBccZƄ{{Z{{ccBBccccB{ZZ                        "  "  !" ! !"!!!   "$""""    ""      $   "$ "" "" " $ !  ! $ $ " $$$ !!!! !!!   $ "    $ ! $   !"!" $ "!  ""    """   !!"$ $ $ !! !  ""$ !!! $" "$  !  ! !  !  !  !     !  " "  ! $!   !   !! !!  !!!   !! $!   !!   !   $ $! !!   "$"$   "$"$"$   "" " "  !$   $ ""   $! "" """ "   !"   ! $" $"  !" "$ ! """"!$   !  !" !  "$ ""  """  " !!    !!" !!!  !$! !!" !  """" """         $     $$$$ $  $$$ $ $     $    "" """$$"$$$$ ! $!!"""" "!!!!!  "!!!!!!$!!!!$!!!                               !!  "  ! ! !" "!!"!     "!$$  $ ! !"!! ""$" !!      $  $!$  "!"$!   $  $ $ "$ ! "$ !!"!!" "$ !!"    "  $ " "   ! !!$         """! $ ""   $!  $! "$  !!$      !"   ! !"" "  !  !          !  $$   ! !!    ! ! "!   !!        $!  !!$$    $  "         "  " "$"$    "$   "$ ""     " " $ ! "" !" ""$$""!"""""   ""  !   !" $"   !!!  !!!!!   ""!!!! ""!!   !!         "" """" !  ""           "$       " "$ $  $  $    !$ ""!!$$""$$$!!"   $$!$!!!!$! $! !!"!!!!$                  0)))))))))0))0)))   ))))0)00)0)0)0)    )))0))0)))))    )0)0)))0)00)    ))0)0)0)))    ))))))0))    ))0))))    )0))))    )))    0)    )  8 8   8 ??????????????                                                                                                                                                                                                                               K   >     >& &        *:*.-+ -.*:/:/8  B      **- -9/4.*-*  G   &    9*+ -48-/*-9.8  = &    94 -<-<-<-<-+ +4@ H 8@*  K   & &,0  - <-9  .-+ /+4+/8*  K &    D,   ,- .8,,/+ +/*-8,8   >  & &   P   - +4,+ 8/<++     &   & /)   8+ +A/8* 40   B &  & &   D0    . +//+ *   C &   &  ,        - 4. *   &   & &  & ,  / ,* *   &   &   /)     + 40- -/   &   & &  &  , . *  &   &  ,  .     & &  & &  @   * -*.H.-.*.7E    B     G>>77 24    5; 9 =;>77777>72'E9:       >77>>77G '<    ;     77777>7>'2' ,    G'  D,   7>>772 /0  GA ,  7777>>22  , GJ /0   77>77;'''2   , B      77>7;''      B     777; ''2A    B     >7>; '22.    B3          77;3 2''2<   B5;      B2''<   3; :    5   2'2'  3A      ''22    ;  J    = ''''2    5  E     '       3''''2'9    ;     3 2'A   3   3 2'''''''.D    ;          2E2<0       ,    5 ''<2''''    = '90    3  2 /  ; /0                                     '2'2'F                           5,                      3 2222'2                       F                                22',                                3        '2''          5;5 8/   3 ''2'2F  =35  A,   3= ''22'<,     ==:I0      535, <2''',                       ;3=.J,                          3=8ME2'',                              =35%6(%9.A@                             %#(% I<''                            #6#% 9<                                   %(#% I           ##% 9<J,          16#%@ F  %(# A<E     #6#4J,  ## MA    %#(% <@  %#6(%     1(6#            %##        %##1(%,        %((1#((%#6(%0,D      #6#%1((%%((%,@      ##1%(#%0,      %(6#%%(#%,/           #(1%##%0,       %#%#6#%       %((1%1(6#    ##1((#      %6#%#(#     ((%#6(1          #6(%1((1     %(6%#(#%%#(1      #6#1#1%#66(##%1%%%%11##((%         #6#16#%%#6#      %((#1%%1(1%1      #(%%6(#%661      %6%%((1%(%         %#(#%(6666(#(#(#(#######111111%%%1(%         1(##        %#61%1        #((            %#6(              1%%%%11111######(#(#(#%       #6666(#%        %#(##%1%%%%11###1      %1(6#                %1#(6(#       1#6(%             %#((%      1#66#      %#(1   1#6(#    %#((%    1#6#%      %#(1       1#61  %#((1                                             netsurf-2.9/libnsbmp-0.0.3/src/0000775000175000017500000000000011734430262015101 5ustar vincevincenetsurf-2.9/libnsbmp-0.0.3/src/libnsbmp.c0000664000175000017500000010217611502634203017054 0ustar vincevince/* * Copyright 2006 Richard Wilson * Copyright 2008 Sean Fox * * This file is part of NetSurf's libnsbmp, http://www.netsurf-browser.org/ * Licenced under the MIT License, * http://www.opensource.org/licenses/mit-license.php */ #include #include #include #include #include #include #include #include "utils/log.h" /* The functions provided by this file allow for the decoding of Microsoft's BMP and ICO image file formats. READING BMP FILES ================= To begin decoding a BMP, the caller should initialise a 'bmp_bitmap_callback_vt' structure with the appropriate values necessary to handle bitmap images. Next, a 'bmp_image' structure should be initialised by calling bmp_create(). This structure should then be passed to bmp_analyse() along with the BMP data to process and the size of this data. Once the analysis has begun, the decoder completes the width and height variables. To decode the image, the caller must use bmp_decode() which selects the proper decoding method based on the BMP info header and assigns the decoded bitmap image to the 'bitmap' member of the 'bmp_image' structure. The bitmap image is stored with 4 bytes-per-pixel in RGBA format. It should be noted that bmp_finalise() should always be called, even if the image was never decoded. It is also the responsibility of the caller to free 'bmp_data'. READING ICO FILES ================= To begin decoding an ICO, the caller should initialise a 'bmp_bitmap_callback_vt' structure with the appropriate values necessary to handle bitmap images. Next, an 'ico_collection' structure should be initialised by calling ico_create(). This structure should then be passed to ico_analyse() along with the ICO data to process and the size of this data. Once the analysis has begun, the decoder completes the width and height variables. Because ICO collections contain multiple bitmap images, the width and height will contain the values of the largest available image. The caller then obtains a BMP from the ICO collection by calling ico_find() with the requested width and height. To decode the image, the caller must use bmp_decode() which selects the proper decoding method based on the BMP info header and assigns the decoded bitmap image to the 'bitmap' member of the 'bmp_image' structure. The bitmap image is stored with 4 bytes-per-pixel in RGBA format. It should be noted that ico_finalise() should always be called, even if no images were decoded. Because ico_finalise() calls bmp_finalise() for each bitmap within the collection, the caller is not required to perform this function. However, it is the responsibility of the caller to free 'ico_data'. [dynis] - Tue 1st July 2008 */ /* squashes unused variable compiler warnings */ #define UNUSED(x) ((x)=(x)) /* BMP flags */ #define BMP_FILE_HEADER_SIZE 14 #define ICO_FILE_HEADER_SIZE 6 #define ICO_DIR_ENTRY_SIZE 16 static inline int8_t read_int8(uint8_t *data, unsigned int o) { return (int8_t) data[o]; } static inline uint8_t read_uint8(uint8_t *data, unsigned int o) { return (uint8_t) data[o]; } static inline int16_t read_int16(uint8_t *data, unsigned int o) { return (int16_t) (data[o] | (data[o+1] << 8)); } static inline uint16_t read_uint16(uint8_t *data, unsigned int o) { return (uint16_t) (data[o] | (data[o+1] << 8)); } static inline int32_t read_int32(uint8_t *data, unsigned int o) { return (int32_t) (data[o] | (data[o+1] << 8) | (data[o+2] << 16) | (data[o+3] << 24)); } static inline uint32_t read_uint32(uint8_t *data, unsigned int o) { return (uint32_t) (data[o] | (data[o+1] << 8) | (data[o+2] << 16) | (data[o+3] << 24)); } static bmp_result next_ico_image(ico_collection *ico, ico_image *image); static bmp_result bmp_analyse_header(bmp_image *bmp, unsigned char *data); static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes); static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes); static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes); static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes); static bmp_result bmp_decode_rle(bmp_image *bmp, uint8_t *data, int bytes, int size); static void bmp_invalidate(void *bitmap, void *private_word); /** Initialises necessary bmp_image members. */ void bmp_create(bmp_image *bmp, bmp_bitmap_callback_vt *bitmap_callbacks) { memset(bmp, 0, sizeof(bmp_image)); bmp->bitmap_callbacks = *bitmap_callbacks; } /** Initialises necessary ico_collection members. */ void ico_collection_create(ico_collection *ico, bmp_bitmap_callback_vt *bitmap_callbacks) { memset(ico, 0, sizeof(ico_collection)); ico->bitmap_callbacks = *bitmap_callbacks; } /** * Analyse a BMP prior to decoding. * * This function will scan the data provided and perform simple checks to * ensure the data is a valid BMP. * * This function must be called before bmp_decode() and sets up all the * relevant values in the bmp structure. * * \param bmp the BMP image to analyse * \return BMP_OK on success */ bmp_result bmp_analyse(bmp_image *bmp, size_t size, unsigned char *cdata) { uint8_t *data = (uint8_t *)cdata; /* ensure we aren't already initialised */ if (bmp->bitmap) return BMP_OK; /* initialize values */ bmp->buffer_size = size; bmp->bmp_data = data; /* standard 14-byte BMP file header is: * * +0 UINT16 File Type ('BM') * +2 UINT32 Size of File (in bytes) * +6 INT16 Reserved Field (1) * +8 INT16 Reserved Field (2) * +10 UINT32 Starting Position of Image Data (offset in bytes) */ if (bmp->buffer_size < BMP_FILE_HEADER_SIZE) return BMP_INSUFFICIENT_DATA; if ((data[0] != (uint8_t)'B') || (data[1] != (uint8_t)'M')) return BMP_DATA_ERROR; bmp->bitmap_offset = read_uint32(data, 10); data += BMP_FILE_HEADER_SIZE; /* boundary checking */ if (bmp->bitmap_offset >= size) return BMP_INSUFFICIENT_DATA; /* decode the BMP header */ return bmp_analyse_header(bmp, data); } /** * Analyse an ICO prior to decoding. * * This function will scan the data provided and perform simple checks to * ensure the data is a valid ICO. * * This function must be called before ico_find(). * * \param ico the ICO image to analyse * \return BMP_OK on success */ bmp_result ico_analyse(ico_collection *ico, size_t size, uint8_t *data) { uint16_t count, i; bmp_result result; int area, max_area = 0; /* ensure we aren't already initialised */ if (ico->first) return BMP_OK; /* initialize values */ ico->buffer_size = size; ico->ico_data = data; /* 6-byte ICO file header is: * * +0 INT16 Reserved (should be 0) * +2 UINT16 Type (1 for ICO, 2 for CUR) * +4 UINT16 Number of BMPs to follow */ if (ico->buffer_size < ICO_FILE_HEADER_SIZE) return BMP_INSUFFICIENT_DATA; // if (read_int16(data, 2) != 0x0000) // return BMP_DATA_ERROR; if (read_uint16(data, 2) != 0x0001) return BMP_DATA_ERROR; count = read_uint16(data, 4); if (count == 0) return BMP_DATA_ERROR; data += ICO_FILE_HEADER_SIZE; /* check if we have enough data for the directory */ if (ico->buffer_size < (uint32_t)(ICO_FILE_HEADER_SIZE + (ICO_DIR_ENTRY_SIZE * count))) return BMP_INSUFFICIENT_DATA; /* Decode the BMP files. * * 16-byte ICO directory entry is: * * +0 UINT8 Width (0 for 256 pixels) * +1 UINT8 Height (0 for 256 pixels) * +2 UINT8 Colour count (0 if more than 256 colours) * +3 INT8 Reserved (should be 0, but may not be) * +4 UINT16 Colour Planes (should be 0 or 1) * +6 UINT16 Bits Per Pixel * +8 UINT32 Size of BMP info header + bitmap data in bytes * +12 UINT32 Offset (points to the BMP info header, not the bitmap data) */ for (i = 0; i < count; i++) { ico_image *image; image = calloc(1, sizeof(ico_image)); if (!image) return BMP_INSUFFICIENT_MEMORY; result = next_ico_image(ico, image); if (result != BMP_OK) return result; image->bmp.width = read_uint8(data, 0); if (image->bmp.width == 0) image->bmp.width = 256; image->bmp.height = read_uint8(data, 1); if (image->bmp.height == 0) image->bmp.height = 256; image->bmp.buffer_size = read_uint32(data, 8); image->bmp.bmp_data = ico->ico_data + read_uint32(data, 12); image->bmp.ico = true; data += ICO_DIR_ENTRY_SIZE; /* Ensure that the bitmap data resides in the buffer */ if (image->bmp.bmp_data - ico->ico_data >= 0 && (uint32_t)(image->bmp.bmp_data - ico->ico_data) >= ico->buffer_size) return BMP_DATA_ERROR; /* Ensure that we have sufficient data to read the bitmap */ if (image->bmp.buffer_size - ICO_DIR_ENTRY_SIZE >= ico->buffer_size - (ico->ico_data - data)) return BMP_INSUFFICIENT_DATA; result = bmp_analyse_header(&image->bmp, image->bmp.bmp_data); if (result != BMP_OK) return result; /* adjust the size based on the images available */ area = image->bmp.width * image->bmp.height; if (area > max_area) { ico->width = image->bmp.width; ico->height = image->bmp.height; max_area = area; } } return BMP_OK; } /** * Allocates memory for the next BMP in an ICO collection * * Sets proper structure values * * \param ico the ICO collection to add the image to * \param image a pointer to the ICO image to be initialised */ static bmp_result next_ico_image(ico_collection *ico, ico_image *image) { bmp_create(&image->bmp, &ico->bitmap_callbacks); image->next = ico->first; ico->first = image; return BMP_OK; } static bmp_result bmp_analyse_header(bmp_image *bmp, uint8_t *data) { uint32_t header_size; uint32_t i; uint8_t j; int32_t width, height; uint8_t palette_size; unsigned int flags = 0; /* a variety of different bitmap headers can follow, depending * on the BMP variant. A full description of the various headers * can be found at * http://msdn.microsoft.com/en-us/library/ms532301(VS.85).aspx */ header_size = read_uint32(data, 0); if (bmp->buffer_size < (14 + header_size)) return BMP_INSUFFICIENT_DATA; if (header_size == 12) { /* the following header is for os/2 and windows 2.x and consists of: * * +0 UINT32 size of this header (in bytes) * +4 INT16 image width (in pixels) * +6 INT16 image height (in pixels) * +8 UINT16 number of colour planes (always 1) * +10 UINT16 number of bits per pixel */ width = read_int16(data, 4); height = read_int16(data, 6); if ((width <= 0) || (height == 0)) return BMP_DATA_ERROR; if (height < 0) { bmp->reversed = true; height = -height; } /* ICOs only support 256*256 resolutions * In the case of the ICO header, the height is actually the added * height of XOR-Bitmap and AND-Bitmap (double the visible height) * Technically we could remove this check and ICOs with bitmaps * of any size could be processed; this is to conform to the spec. */ if (bmp->ico) { if ((width > 256) || (height > 512)) { return BMP_DATA_ERROR; } else { bmp->width = width; bmp->height = height / 2; } } else { bmp->width = width; bmp->height = height; } if (read_uint16(data, 8) != 1) return BMP_DATA_ERROR; bmp->bpp = read_uint16(data, 10); /** * The bpp value should be in the range 1-32, but the only * values considered legal are: * RGB ENCODING: 1, 4, 8, 16, 24 and 32 */ if ((bmp->bpp != 1) && (bmp->bpp != 4) && (bmp->bpp != 8) && (bmp->bpp != 16) && (bmp->bpp != 24) && (bmp->bpp != 32)) return BMP_DATA_ERROR; bmp->colours = (1 << bmp->bpp); palette_size = 3; } else if (header_size < 40) { return BMP_DATA_ERROR; } else { /* the following header is for windows 3.x and onwards. it is a * minimum of 40 bytes and (as of Windows 95) a maximum of 108 bytes. * * +0 UINT32 size of this header (in bytes) * +4 INT32 image width (in pixels) * +8 INT32 image height (in pixels) * +12 UINT16 number of colour planes (always 1) * +14 UINT16 number of bits per pixel * +16 UINT32 compression methods used * +20 UINT32 size of bitmap (in bytes) * +24 UINT32 horizontal resolution (in pixels per meter) * +28 UINT32 vertical resolution (in pixels per meter) * +32 UINT32 number of colours in the image * +36 UINT32 number of important colours * +40 UINT32 mask identifying bits of red component * +44 UINT32 mask identifying bits of green component * +48 UINT32 mask identifying bits of blue component * +52 UINT32 mask identifying bits of alpha component * +56 UINT32 color space type * +60 UINT32 x coordinate of red endpoint * +64 UINT32 y coordinate of red endpoint * +68 UINT32 z coordinate of red endpoint * +72 UINT32 x coordinate of green endpoint * +76 UINT32 y coordinate of green endpoint * +80 UINT32 z coordinate of green endpoint * +84 UINT32 x coordinate of blue endpoint * +88 UINT32 y coordinate of blue endpoint * +92 UINT32 z coordinate of blue endpoint * +96 UINT32 gamma red coordinate scale value * +100 UINT32 gamma green coordinate scale value * +104 UINT32 gamma blue coordinate scale value */ width = read_int32(data, 4); height = read_int32(data, 8); if ((width <= 0) || (height == 0)) return BMP_DATA_ERROR; if (height < 0) { bmp->reversed = true; height = -height; } /* ICOs only support 256*256 resolutions * In the case of the ICO header, the height is actually the added * height of XOR-Bitmap and AND-Bitmap (double the visible height) * Technically we could remove this check and ICOs with bitmaps * of any size could be processed; this is to conform to the spec. */ if (bmp->ico) { if ((width > 256) || (height > 512)) { return BMP_DATA_ERROR; } else { bmp->width = width; bmp->height = height / 2; } } else { bmp->width = width; bmp->height = height; } if (read_uint16(data, 12) != 1) return BMP_DATA_ERROR; bmp->bpp = read_uint16(data, 14); if (bmp->bpp == 0) bmp->bpp = 8; bmp->encoding = read_uint32(data, 16); /** * The bpp value should be in the range 1-32, but the only * values considered legal are: * RGB ENCODING: 1, 4, 8, 16, 24 and 32 * RLE4 ENCODING: 4 * RLE8 ENCODING: 8 * BITFIELD ENCODING: 16 and 32 */ switch (bmp->encoding) { case BMP_ENCODING_RGB: if ((bmp->bpp != 1) && (bmp->bpp != 4) && (bmp->bpp != 8) && (bmp->bpp != 16) && (bmp->bpp != 24) && (bmp->bpp != 32)) return BMP_DATA_ERROR; break; case BMP_ENCODING_RLE8: if (bmp->bpp != 8) return BMP_DATA_ERROR; break; case BMP_ENCODING_RLE4: if (bmp->bpp != 4) return BMP_DATA_ERROR; break; case BMP_ENCODING_BITFIELDS: if ((bmp->bpp != 16) && (bmp->bpp != 32)) return BMP_DATA_ERROR; break; /* invalid encoding */ default: return BMP_DATA_ERROR; break; } /* Bitfield encoding means we have red, green, blue, and alpha masks. * Here we aquire the masks and determine the required bit shift to * align them in our 24-bit color 8-bit alpha format. */ if (bmp->encoding == BMP_ENCODING_BITFIELDS) { if (header_size == 40) { header_size += 12; if (bmp->buffer_size < (14 + header_size)) return BMP_INSUFFICIENT_DATA; for (i = 0; i < 3; i++) bmp->mask[i] = read_uint32(data, 40 + (i << 2)); } else { for (i = 0; i < 4; i++) bmp->mask[i] = read_uint32(data, 40 + (i << 2)); } for (i = 0; i < 4; i++) { if (bmp->mask[i] == 0) break; for (j = 31; j > 0; j--) if (bmp->mask[i] & (1 << j)) { if ((j - 7) > 0) bmp->mask[i] &= 0xff << (j - 7); else bmp->mask[i] &= 0xff >> (-(j - 7)); bmp->shift[i] = (i << 3) - (j - 7); break; } } } bmp->colours = read_uint32(data, 32); if (bmp->colours == 0) bmp->colours = (1 << bmp->bpp); palette_size = 4; } data += header_size; /* if there's no alpha mask, flag the bmp opaque */ if ((!bmp->ico) && (bmp->mask[3] == 0)) { flags |= BMP_OPAQUE; bmp->opaque = true; } /* we only have a palette for <16bpp */ if (bmp->bpp < 16) { /* we now have a series of palette entries of the format: * * +0 BYTE blue * +1 BYTE green * +2 BYTE red * * if the palette is from an OS/2 or Win2.x file then the entries * are padded with an extra byte. */ /* boundary checking */ if (bmp->buffer_size < (14 + header_size + ((uint64_t)4 * bmp->colours))) return BMP_INSUFFICIENT_DATA; /* create the colour table */ bmp->colour_table = (uint32_t *)malloc(bmp->colours * 4); if (!bmp->colour_table) return BMP_INSUFFICIENT_MEMORY; for (i = 0; i < bmp->colours; i++) { bmp->colour_table[i] = data[2] | (data[1] << 8) | (data[0] << 16); if (bmp->opaque) bmp->colour_table[i] |= (0xff << 24); data += palette_size; bmp->colour_table[i] = read_uint32((uint8_t *)&bmp->colour_table[i],0); } } /* create our bitmap */ flags |= BMP_NEW | BMP_CLEAR_MEMORY; bmp->bitmap = bmp->bitmap_callbacks.bitmap_create(bmp->width, bmp->height, flags); if (!bmp->bitmap) { if (bmp->colour_table) free(bmp->colour_table); bmp->colour_table = NULL; return BMP_INSUFFICIENT_MEMORY; } /* BMPs within ICOs don't have BMP file headers, so the image data should * always be right after the colour table. */ if (bmp->ico) bmp->bitmap_offset = (intptr_t)data - (intptr_t)bmp->bmp_data; bmp->bitmap_callbacks.bitmap_set_suspendable(bmp->bitmap, bmp, bmp_invalidate); return BMP_OK; } /** * Finds the closest BMP within an ICO collection * * This function finds the BMP with dimensions as close to a specified set * as possible from the images in the collection. * * \param ico the ICO collection to examine * \param width the preferred width (0 to use ICO header width) * \param height the preferred height (0 to use ICO header height) */ bmp_image *ico_find(ico_collection *ico, uint16_t width, uint16_t height) { bmp_image *bmp = NULL; ico_image *image; int x, y, cur, distance = (1 << 24); if (width == 0) width = ico->width; if (height == 0) height = ico->height; for (image = ico->first; image; image = image->next) { if ((image->bmp.width == width) && (image->bmp.height == height)) return &image->bmp; x = image->bmp.width - width; y = image->bmp.height - height; cur = (x * x) + (y * y); if (cur < distance) { distance = cur; bmp = &image->bmp; } } return bmp; } /** * Invalidates a BMP * * This function sets the BMP into a state such that the bitmap image data * can be released from memory. * * \param bmp the BMP image to invalidate */ static void bmp_invalidate(void *bitmap, void *private_word) { bmp_image *bmp = (bmp_image *)private_word; UNUSED(bitmap); bmp->decoded = false; } /** * Decode a BMP * * This function decodes the BMP data such that bmp->bitmap is a valid * image. The state of bmp->decoded is set to TRUE on exit such that it * can easily be identified which BMPs are in a fully decoded state. * * \param bmp the BMP image to decode * \return BMP_OK on success */ bmp_result bmp_decode(bmp_image *bmp) { uint8_t *data; uint32_t bytes; bmp_result result = BMP_OK; assert(bmp->bitmap); data = bmp->bmp_data + bmp->bitmap_offset; bytes = bmp->buffer_size - bmp->bitmap_offset; switch (bmp->encoding) { case BMP_ENCODING_RGB: if ((bmp->bpp == 24) || (bmp->bpp == 32)) result = bmp_decode_rgb24(bmp, &data, bytes); else if (bmp->bpp == 16) result = bmp_decode_rgb16(bmp, &data, bytes); else result = bmp_decode_rgb(bmp, &data, bytes); break; case BMP_ENCODING_RLE8: result = bmp_decode_rle(bmp, data, bytes, 8); break; case BMP_ENCODING_RLE4: result = bmp_decode_rle(bmp, data, bytes, 4); break; case BMP_ENCODING_BITFIELDS: if (bmp->bpp == 32) result = bmp_decode_rgb24(bmp, &data, bytes); else if (bmp->bpp == 16) result = bmp_decode_rgb16(bmp, &data, bytes); else return BMP_DATA_ERROR; } if ((!bmp->ico) || (result != BMP_OK)) return result; bytes = (uintptr_t)bmp->bmp_data + bmp->buffer_size - (uintptr_t)data; return bmp_decode_mask(bmp, data, bytes); } /** * Decode a BMP using "limited transparency" * * Bitmaps do not have native transparency support. However, there is a * "trick" that is used in some instances in which the first pixel of the * bitmap becomes the "transparency index". The decoding application can * replace this index with whatever background colour it chooses to * create the illusion of transparency. * * When to use transparency is at the discretion of the decoding * application. * * \param bmp the BMP image to decode * \param colour the colour to use as "transparent" * \return BMP_OK on success */ bmp_result bmp_decode_trans(bmp_image *bmp, uint32_t colour) { bmp->limited_trans = true; bmp->trans_colour = colour; return bmp_decode(bmp); } /** * Decode BMP data stored in 24bpp colour. * * \param bmp the BMP image to decode * \param start the data to decode, updated to last byte read on success * \param bytes the number of bytes of data available * \return BMP_OK on success * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; * in this case, the image may be partially viewable */ static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes) { uint8_t *top, *bottom, *end, *data; uint32_t *scanline; uint32_t x, y; uint32_t swidth, skip; intptr_t addr; uint8_t i; uint32_t word; data = *start; swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; skip = bmp->bpp >> 3; bmp->decoded = true; /* Determine transparent index */ if (bmp->limited_trans) { if ((data + skip) > end) return BMP_INSUFFICIENT_DATA; if (bmp->encoding == BMP_ENCODING_BITFIELDS) bmp->transparent_index = read_uint32(data, 0); else bmp->transparent_index = data[2] | (data[1] << 8) | (data[0] << 16); } for (y = 0; y < bmp->height; y++) { while (addr != (((intptr_t)data) & 3)) data++; if ((data + (skip * bmp->width)) > end) return BMP_INSUFFICIENT_DATA; if (bmp->reversed) scanline = (void *)(top + (y * swidth)); else scanline = (void *)(bottom - (y * swidth)); if (bmp->encoding == BMP_ENCODING_BITFIELDS) { for (x = 0; x < bmp->width; x++) { word = read_uint32(data, 0); for (i = 0; i < 4; i++) if (bmp->shift[i] > 0) scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]); else scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i])); /* 32-bit BMPs have alpha masks, but sometimes they're not utilized */ if (bmp->opaque) scanline[x] |= (0xff << 24); data += skip; scanline[x] = read_uint32((uint8_t *)&scanline[x],0); } } else { for (x = 0; x < bmp->width; x++) { scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16); if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index)) scanline[x] = bmp->trans_colour; if (bmp->opaque) scanline[x] |= (0xff << 24); data += skip; scanline[x] = read_uint32((uint8_t *)&scanline[x],0); } } } *start = data; return BMP_OK; } /** * Decode BMP data stored in 16bpp colour. * * \param bmp the BMP image to decode * \param start the data to decode, updated to last byte read on success * \param bytes the number of bytes of data available * \return BMP_OK on success * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; * in this case, the image may be partially viewable */ static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes) { uint8_t *top, *bottom, *end, *data; uint32_t *scanline; uint32_t x, y, swidth; intptr_t addr; uint8_t i; uint16_t word; data = *start; swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; bmp->decoded = true; /* Determine transparent index */ if (bmp->limited_trans) { if ((data + 2) > end) return BMP_INSUFFICIENT_DATA; bmp->transparent_index = read_uint16(data, 0); } for (y = 0; y < bmp->height; y++) { while (addr != (((intptr_t)data) & 3)) data += 2; if ((data + (2 * bmp->width)) > end) return BMP_INSUFFICIENT_DATA; if (bmp->reversed) scanline = (void *)(top + (y * swidth)); else scanline = (void *)(bottom - (y * swidth)); if (bmp->encoding == BMP_ENCODING_BITFIELDS) { for (x = 0; x < bmp->width; x++) { word = read_uint16(data, 0); if ((bmp->limited_trans) && (word == bmp->transparent_index)) scanline[x] = bmp->trans_colour; else { scanline[x] = 0; for (i = 0; i < 4; i++) if (bmp->shift[i] > 0) scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]); else scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i])); if (bmp->opaque) scanline[x] |= (0xff << 24); } data += 2; scanline[x] = read_uint32((uint8_t *)&scanline[x],0); } } else { for (x = 0; x < bmp->width; x++) { word = read_uint16(data, 0); if ((bmp->limited_trans) && (word == bmp->transparent_index)) scanline[x] = bmp->trans_colour; else { /* 16-bit RGB defaults to RGB555 */ scanline[x] = ((word & (31 << 0)) << 19) | ((word & (31 << 5)) << 6) | ((word & (31 << 10)) >> 7); } if (bmp->opaque) scanline[x] |= (0xff << 24); data += 2; scanline[x] = read_uint32((uint8_t *)&scanline[x],0); } } } *start = data; return BMP_OK; } /** * Decode BMP data stored with a palette and in 8bpp colour or less. * * \param bmp the BMP image to decode * \param start the data to decode, updated to last byte read on success * \param bytes the number of bytes of data available * \return BMP_OK on success * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; * in this case, the image may be partially viewable */ static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes) { uint8_t *top, *bottom, *end, *data; uint32_t *scanline; intptr_t addr; uint32_t x, y, swidth; uint8_t bit_shifts[8]; uint8_t ppb = 8 / bmp->bpp; uint8_t bit_mask = (1 << bmp->bpp) - 1; uint8_t cur_byte = 0, bit, i; for (i = 0; i < ppb; i++) bit_shifts[i] = 8 - ((i + 1) * bmp->bpp); data = *start; swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; bmp->decoded = true; /* Determine transparent index */ if (bmp->limited_trans) bmp->transparent_index = bmp->colour_table[(*data >> bit_shifts[0]) & bit_mask]; for (y = 0; y < bmp->height; y++) { while (addr != (((intptr_t)data) & 3)) data++; bit = 8; if ((data + (bmp->width / ppb)) > end) return BMP_INSUFFICIENT_DATA; if (bmp->reversed) scanline = (void *)(top + (y * swidth)); else scanline = (void *)(bottom - (y * swidth)); for (x = 0; x < bmp->width; x++) { if (bit >= ppb) { bit = 0; cur_byte = *data++; } scanline[x] = bmp->colour_table[(cur_byte >> bit_shifts[bit++]) & bit_mask]; if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index)) scanline[x] = bmp->trans_colour; } } *start = data; return BMP_OK; } /** * Decode a 1bpp mask for an ICO * * \param bmp the BMP image to decode * \param data the data to decode * \param bytes the number of bytes of data available * \return BMP_OK on success */ static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes) { uint8_t *top, *bottom, *end; uint32_t *scanline; intptr_t addr; uint32_t x, y, swidth; uint32_t cur_byte = 0; swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; for (y = 0; y < bmp->height; y++) { while (addr != (((intptr_t)data) & 3)) data++; if ((data + (bmp->width >> 3)) > end) return BMP_INSUFFICIENT_DATA; scanline = (void *)(bottom - (y * swidth)); for (x = 0; x < bmp->width; x++) { if ((x & 7) == 0) cur_byte = *data++; if ((cur_byte & 128) == 0) { scanline[x] = read_uint32((uint8_t *)&scanline[x], 0); scanline[x] |= (0xff << 24); scanline[x] = read_uint32((uint8_t *)&scanline[x], 0); } cur_byte = cur_byte << 1; } } return BMP_OK; } /** * Decode BMP data stored encoded in either RLE4 or RLE8. * * \param bmp the BMP image to decode * \param data the data to decode * \param bytes the number of bytes of data available * \param size the size of the RLE tokens (4 or 8) * \return BMP_OK on success * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; * in this case, the image may be partially viewable */ static bmp_result bmp_decode_rle(bmp_image *bmp, uint8_t *data, int bytes, int size) { uint8_t *top, *bottom, *end; uint32_t *scanline; uint32_t swidth; uint32_t i, length, pixels_left; uint32_t x = 0, y = 0, last_y = 0; uint32_t pixel = 0, pixel2; if (bmp->ico) return BMP_DATA_ERROR; swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width; top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); if (!top) return BMP_INSUFFICIENT_MEMORY; bottom = top + (uint64_t)swidth * (bmp->height - 1); end = data + bytes; bmp->decoded = true; do { if (data + 2 > end) return BMP_INSUFFICIENT_DATA; length = *data++; if (length == 0) { length = *data++; if (length == 0) { /* 00 - 00 means end of scanline */ x = 0; if (last_y == y) { if (++y > bmp->height) return BMP_DATA_ERROR; } last_y = y; } else if (length == 1) { /* 00 - 01 means end of RLE data */ return BMP_OK; } else if (length == 2) { /* 00 - 02 - XX - YY means move cursor */ if (data + 2 > end) return BMP_INSUFFICIENT_DATA; x += *data++; if (x >= bmp->width) return BMP_DATA_ERROR; y += *data++; if (y >= bmp->height) return BMP_DATA_ERROR; } else { /* 00 - NN means escape NN pixels */ if (bmp->reversed) { pixels_left = (y + 1) * bmp->width - x; scanline = (void *)(top + (y * swidth)); } else { pixels_left = (bmp->height - y + 1) * bmp->width - x; scanline = (void *)(bottom - (y * swidth)); } if (length > pixels_left) length = pixels_left; if (data + length > end) return BMP_INSUFFICIENT_DATA; /* the following code could be easily optimised by simply * checking the bounds on entry and using some simply copying * routines if so */ if (size == 8) { for (i = 0; i < length; i++) { if (x >= bmp->width) { x = 0; if (++y > bmp->height) return BMP_DATA_ERROR; scanline -= bmp->width; } scanline[x++] = bmp->colour_table[(int)*data++]; } } else { for (i = 0; i < length; i++) { if (x >= bmp->width) { x = 0; if (++y > bmp->height) return BMP_DATA_ERROR; scanline -= bmp->width; } if ((i & 1) == 0) { pixel = *data++; scanline[x++] = bmp->colour_table [pixel >> 4]; } else { scanline[x++] = bmp->colour_table [pixel & 0xf]; } } length = (length + 1) >> 1; } if ((length & 1) && (*data++ != 0x00)) return BMP_DATA_ERROR; } } else { /* NN means perform RLE for NN pixels */ if (bmp->reversed) { pixels_left = (y + 1) * bmp->width - x; scanline = (void *)(top + (y * swidth)); } else { pixels_left = (bmp->height - y + 1) * bmp->width - x; scanline = (void *)(bottom - (y * swidth)); } if (length > pixels_left) length = pixels_left; /* boundary checking */ if (data + 1 > end) return BMP_INSUFFICIENT_DATA; /* the following code could be easily optimised by simply * checking the bounds on entry and using some simply copying * routines if so */ if (size == 8) { pixel = bmp->colour_table[(int)*data++]; for (i = 0; i < length; i++) { if (x >= bmp->width) { x = 0; if (++y > bmp->height) return BMP_DATA_ERROR; scanline -= bmp->width; } scanline[x++] = pixel; } } else { pixel2 = *data++; pixel = bmp->colour_table[pixel2 >> 4]; pixel2 = bmp->colour_table[pixel2 & 0xf]; for (i = 0; i < length; i++) { if (x >= bmp->width) { x = 0; if (++y > bmp->height) return BMP_DATA_ERROR; scanline -= bmp->width; } if ((i & 1) == 0) scanline[x++] = pixel; else scanline[x++] = pixel2; } } } } while (data < end); return BMP_OK; } /** * Finalise a BMP prior to destruction. * * \param bmp the BMP image to finalise */ void bmp_finalise(bmp_image *bmp) { if (bmp->bitmap) bmp->bitmap_callbacks.bitmap_destroy(bmp->bitmap); bmp->bitmap = NULL; if (bmp->colour_table) free(bmp->colour_table); bmp->colour_table = NULL; } /** * Finalise an ICO prior to destruction. * * \param ico the ICO image to finalise */ void ico_finalise(ico_collection *ico) { ico_image *image; for (image = ico->first; image; image = image->next) bmp_finalise(&image->bmp); while (ico->first) { image = ico->first; ico->first = image->next; free(image); } } netsurf-2.9/libnsbmp-0.0.3/src/Makefile0000664000175000017500000000011511163547450016542 0ustar vincevince# Sources DIR_SOURCES := libnsbmp.c include build/makefiles/Makefile.subdir netsurf-2.9/libnsbmp-0.0.3/src/utils/0000775000175000017500000000000011734430262016241 5ustar vincevincenetsurf-2.9/libnsbmp-0.0.3/src/utils/log.h0000664000175000017500000000127111063177651017201 0ustar vincevince/* * Copyright 2003 James Bursa * Copyright 2004 John Tytgat * * This file is part of NetSurf, http://www.netsurf-browser.org/ * Licenced under the MIT License, * http://www.opensource.org/licenses/mit-license.php */ #include #ifndef _LIBNSBMP_LOG_H_ #define _LIBNSBMP_LOG_H_ #ifdef NDEBUG # define LOG(x) ((void) 0) #else # ifdef __GNUC__ # define LOG(x) do { printf x, fputc('\n', stdout)); } while (0) # elif defined(__CC_NORCROFT) # define LOG(x) do { printf x, fputc('\n', stdout)); } while (0) # else # define LOG(x) do { printf x, fputc('\n', stdout)); } while (0) # endif #endif #endif netsurf-2.9/libnsbmp-0.0.3/bin/0000775000175000017500000000000011734430262015062 5ustar vincevincenetsurf-2.9/libnsbmp-0.0.3/libnsbmp.pc.in0000664000175000017500000000034011173435205017045 0ustar vincevinceprefix=PREFIX exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: libnsbmp Description: Provides bmp loading and conversion Version: VERSION Libs: -L${libdir} -lnsbmp Cflags: -I${includedir}/ netsurf-2.9/libnsbmp-0.0.3/Makefile0000664000175000017500000000171711547273010015756 0ustar vincevince# Component settings COMPONENT := nsbmp COMPONENT_VERSION := 0.0.3 # Default to a static library COMPONENT_TYPE ?= lib-static # Setup the tooling include build/makefiles/Makefile.tools # Toolchain flags WARNFLAGS := -Wall -W -Wundef -Wpointer-arith -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ -Wmissing-declarations -Wnested-externs -pedantic # BeOS/Haiku standard library headers create warnings ifneq ($(TARGET),beos) WARNFLAGS := $(WARNFLAGS) -Werror endif CFLAGS := -D_BSD_SOURCE -I$(CURDIR)/include/ \ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS) ifneq ($(GCCVER),2) CFLAGS := $(CFLAGS) -std=c99 else # __inline__ is a GCCism CFLAGS := $(CFLAGS) -Dinline="__inline__" endif include build/makefiles/Makefile.top # Extra installation rules I := /include/ INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/libnsbmp.h INSTALL_ITEMS := $(INSTALL_ITEMS) /lib/pkgconfig:lib$(COMPONENT).pc.in INSTALL_ITEMS := $(INSTALL_ITEMS) /lib:$(OUTPUT) netsurf-2.9/libnsbmp-0.0.3/ico_display0000775000175000017500000000005011031340070016515 0ustar vincevinceset -e make bin/decode_ico $1 | display netsurf-2.9/libnsbmp-0.0.3/COPYING0000664000175000017500000000210711060174664015350 0ustar vincevinceCopyright (C) 2006 Richard Wilson Copyright (C) 2008 Sean Fox Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. netsurf-2.9/libnsbmp-0.0.3/bmp_display0000775000175000017500000000005011031063543016530 0ustar vincevinceset -e make bin/decode_bmp $1 | display netsurf-2.9/libnsbmp-0.0.3/build/0000775000175000017500000000000011734430264015413 5ustar vincevincenetsurf-2.9/libnsbmp-0.0.3/build/makefiles/0000775000175000017500000000000011734430265017354 5ustar vincevincenetsurf-2.9/libnsbmp-0.0.3/build/makefiles/Makefile.top0000664000175000017500000004232311537116272021621 0ustar vincevince# Top-level Makefile fragment # # Expected inputs: # # BUILD Type of build to perform: # release - Release build # debug - Debug build # COMPONENT Name of the component (sans leading "lib" iff a library) # COMPONENT_VERSION Component version number (x.y.z) # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # TARGET Target platform identifier # # Optional inputs: # # BUILDDIR Directory to build into (defaults to # build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE)) # CC_CAN_BUILD_AND_DEP Flag whether $(CC) is capable of calculating dependency # information at the same time as compiling sources. # Set to "yes" if it can. # DESTDIR Sandboxed FS root (e.g. for packaging) # HOST Host platform identifier # REQUIRED_PKGS List of required pkg-config packages # # The client may also override all toolchain settings, including: # # ARFLAGS Archiver flags for the current compilation # CFLAGS C compiler flags for the current compilation # CXXFLAGS C++ compiler flags for the current compilation # LDFLAGS Linker flags for the current compilation # # TESTCFLAGS Any test-specific CFLAGS # TESTCXXFLAGS Any test-specific CXXFLAGS # TESTLDFLAGS Any test-specific LDFLAGS # # TESTRUNNER Test runner invocation command # The test runner takes a command line in the form # # # Targets provided: # # all Default target. Builds component using current settings # test Build and run test suite, using current settings. # coverage Determine test suite coverage (requires lcov) # profile Build with profiling support enabled (requires gprof) # docs Produce documentation (requires doxygen) # clean Clean the build # distclean Remove distribution files, too # install Install component into prefix. # uninstall Remove component from prefix. # # Variables provided: # # major-version Extracts the major version (x) from COMPONENT_VERSION # minor-version Extracts the minor version (y) from COMPONENT_VERSION # patch-version Extracts the patch version (z) from COMPONENT_VERSION # OUTPUT Path + filename of build target ############################################################################### # Sanity checks ############################################################################### # Name of component must be defined by client ifeq ($(COMPONENT),) $(error COMPONENT not defined) endif # As must the version ifeq ($(COMPONENT_VERSION),) $(error COMPONENT_VERSION not defined) endif # As must the component type ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not defined) endif # Target platform must be defined by the client ifeq ($(TARGET),) $(error TARGET not defined) endif # Build type, too ifeq ($(BUILD),) $(error BUILD not defined) endif ############################################################################## # Makefile variables ############################################################################## Q ?= @ VQ ?= @ ############################################################################## # Exported variables (also OUTPUT, further down) ############################################################################## major-version := $(word 1,$(subst ., ,$(COMPONENT_VERSION))) minor-version := $(word 2,$(subst ., ,$(COMPONENT_VERSION))) patch-version := $(word 3,$(subst ., ,$(COMPONENT_VERSION))) ############################################################################## # Build environment ############################################################################## # Build directory BUILDDIR ?= build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE) # Build tree subdirs COVERAGEDIR := $(BUILDDIR)/coverage DOCDIR := $(BUILDDIR)/docs # Determine if we want to build testcases ifeq ($(MAKECMDGOALS),test) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),profile) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),coverage) WANT_TEST := yes else WANT_TEST := no endif # List of items to delete on clean CLEAN_ITEMS := # List of items to delete on distclean DISTCLEAN_ITEMS := # List of items to build for testing TEST_ITEMS := # List of targets to run for testing TEST_TARGETS := # List of targets which are prerequisites for running tests TEST_PREREQS := # List of items to (un)install INSTALL_ITEMS := # List of targets to run before building $(OBJECT) PRE_TARGETS := # List of targets to run after building $(OBJECT) POST_TARGETS := # Source files SOURCES := # Include configuration Makefile fragment -include Makefile.config # Set the default target (before including any children) __default: all # Include Makefile fragments in subdirectories define do_include DIR := $$(dir $(1)) include $(1) endef MAKE_INCLUDES := $(wildcard */Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Calculate objects to build OBJECTS := $(addprefix $(BUILDDIR)/,$(filter %.o, \ $(subst /,_,$(subst .c,.o,$(SOURCES))) \ $(subst /,_,$(subst .cpp,.o,$(SOURCES))) \ $(subst /,_,$(subst .cmhg,.o,$(SOURCES))) \ $(subst /,_,$(subst .s,.o,$(SOURCES))))) bin_for_test = $(addprefix $(BUILDDIR)/,$(firstword $(subst :, ,$(ITEM)))) TEST_BINARIES := $(foreach ITEM,$(TEST_ITEMS),$(bin_for_test)) # Determine if we're building any C++ sources ifneq ($(filter %.cpp,$(SOURCES)),) CXX_IN_BUILD := yes else CXX_IN_BUILD := no endif # Determine the output filename ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) ifeq ($(findstring lib-shared,$(COMPONENT_TYPE)),lib-shared) SHAREDLIBNAME := lib$(COMPONENT)$(LIBEXT) SONAME := $(SHAREDLIBNAME).$(major-version) OUTPUT := $(BUILDDIR)/$(SHAREDLIBNAME).$(COMPONENT_VERSION) else OUTPUT := $(BUILDDIR)/lib$(COMPONENT)$(LIBEXT) endif else OUTPUT := $(BUILDDIR)/$(COMPONENT)$(EXEEXT) endif ############################################################################### # Build targets ############################################################################### .PHONY: all test coverage profile docs clean distclean install uninstall \ __default __precov __partial_clean __postshared ifeq ($(COMPONENT_TYPE),lib-shared) POST_TARGETS := __postshared $(POST_TARGETS) __postshared: $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SONAME) $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SHAREDLIBNAME) endif # Default target all: $(PRE_TARGETS) $(OUTPUT) $(POST_TARGETS) # Build and execute testsuite test: all $(TEST_PREREQS) $(TEST_BINARIES) $(TEST_TARGETS) $(VQ)$(ECHO) $(ECHOFLAGS) " TEST: Testing complete" # Compute coverage __precov: __partial_clean $(Q)$(LCOV) --directory . --zerocounters coverage: __precov test $(Q)$(LCOV) --directory $(BUILDDIR) --base-directory $(CURDIR) \ --capture --output-file $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(LCOV) --extract $(COVERAGEDIR)/$(COMPONENT)_tmp.info \ "$(CURDIR)/src*" -o $(COVERAGEDIR)/$(COMPONENT).info $(Q)$(RM) $(RMFLAGS) $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(GENHTML) -o $(COVERAGEDIR) --num-spaces 2 \ $(COVERAGEDIR)/$(COMPONENT).info # Build for profiling profile: __partial_clean test # Compile documentation docs: $(BUILDDIR)/stamp $(Q)$(DOXYGEN) build/Doxyfile # Clean build tree __partial_clean: -$(Q)$(RM) $(RMFLAGS) $(CLEAN_ITEMS) -$(Q)$(RM) $(RMFLAGS) gmon.out -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.d) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcda) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcno) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.o) clean: __partial_clean -$(Q)$(RM) $(RMFLAGS) -r build/docs -$(Q)$(RM) $(RMFLAGS) -r $(BUILDDIR) # Remove auto-generated non-build-tree items distclean: clean -$(Q)$(RM) $(RMFLAGS) $(DISTCLEAN_ITEMS) # The installation target, and associated canned command sequences. # For reference, the syntax of INSTALL_ITEMS is: # # :[';']* # # We also permit a trailing ';' in the file list. __comma := , __empty := __space := $(empty) $(empty) __required = $(if $(REQUIRED_PKGS),Requires: $(subst $(__space),$(__comma) ,$(strip $(REQUIRED_PKGS))),) # Install a pkg-config control file ($1) to the specified location ($2) define install_pkgconfig $(Q)$(ECHO) $(ECHOFLAGS) "sed -e... $1 >$(BUILDDIR)/$(1:.in=)" $(Q)$(SED) \ -e 's#PREFIX#$(PREFIX)#' \ -e 's#MAJOR#$(major-version)#' \ -e 's#MINOR#$(minor-version)#' \ -e 's#PATCH#$(patch-version)#' \ -e 's#VERSION#$(COMPONENT_VERSION)#' \ -e 's#REQUIRED#$(__required)#' \ $1 >$(BUILDDIR)/$(1:.in=) $(INSTALL) $(INSTALLFLAGS) -m 644 $(BUILDDIR)/$(1:.in=) \ $2/$(1:.in=) endef # TODO: Is this scheme portable? define install_shared_lib $(INSTALL) $(INSTALLFLAGS) -m 755 $1 $2/$(notdir $1) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SONAME) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SHAREDLIBNAME) endef # Install a file ($1) to the specified location ($2) define install_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(call install_pkgconfig,$1,$2), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call install_shared_lib,$1,$2), \ $(INSTALL) $(INSTALLFLAGS) -m 644 $1 $2))) endef # Install a list of files ($2) to the specified location ($1) # We create the installation location if it doesn't already exist define install_to_dest $(Q)$(MKDIR) $(MKDIRFLAGS) $(DESTDIR)$(PREFIX)$1 $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call install_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef install: all $(foreach ITEM,$(INSTALL_ITEMS), \ $(call install_to_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) # Uninstallation # TODO: Work out how to safely remove symlinks define uninstall_shared_lib $(RM) $(RMFLAGS) $2/$(notdir $1).$(COMPONENT_VERSION) endef # Uninstall a file ($1) from the specified location ($2) define uninstall_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(RM) $(RMFLAGS) $2/$(1:.pc.in=.pc), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call uninstall_shared_lib,$1,$2), \ $(RM) $(RMFLAGS) $2/$(notdir $1)))) endef # Uninstall a list of files ($2) from the specified location ($1) # TODO: Come up with a safe way of removing directories, too define uninstall_from_dest $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call uninstall_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef uninstall: $(foreach ITEM,$(INSTALL_ITEMS), \ $(call uninstall_from_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) ############################################################################### # Actual rules ############################################################################### $(BUILDDIR)/stamp: $(Q)$(MKDIR) $(MKDIRFLAGS) $(BUILDDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(COVERAGEDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(DOCDIR) $(Q)$(TOUCH) $(TOUCHFLAGS) $(BUILDDIR)/stamp $(OUTPUT): $(BUILDDIR)/stamp $(OBJECTS) ifeq ($(COMPONENT_TYPE),lib-static) $(VQ)$(ECHO) $(ECHOFLAGS) " AR: $@" $(Q)$(RM) $(RMFLAGS) $@ $(Q)$(AR) $(ARFLAGS) $@ $(OBJECTS) else $(VQ)$(ECHO) $(ECHOFLAGS) " LINK: $@" ifeq ($(CXX_IN_BUILD),yes) $(Q)$(CXX) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) else $(Q)$(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) endif endif ############################################################################### # Autogenerated, implied rules ############################################################################### DEPFILES := BUILDFILES := ifeq ($(CC_CAN_BUILD_AND_DEP),yes) # C compiler can compile and dep simultaneously define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else ifeq ($(CC_CANNOT_DEP),yes) # C compiler cannot calculate dependencies define dep_c endef define dep_cxx endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else # C compiler must calculate dependencies first, then compile (default) define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CC) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CXX) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef endif endif define build_cmhg ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " CMHG: $1" $$(Q)$$(CMHG) $$(CMHGFLAGS) $1 -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_s ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) "ASSEMBLE: $1" $$(Q)$$(CC) $$($3) $1 -c -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef BUILDCFLAGS = $(CFLAGS) $(SHAREDCFLAGS) BUILDCXXFLAGS = $(CXXFLAGS) $(SHAREDCXXFLAGS) BUILDASFLAGS = $(ASFLAGS) $(SHAREDCFLAGS) # Generate dependency rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),BUILDCXXFLAGS))) # Generate compilation rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),BUILDCXXFLAGS))) $(eval $(foreach SOURCE,$(filter %.cmhg,$(SOURCES)), \ $(call build_cmhg,$(SOURCE),$(subst /,_,$(SOURCE:.cmhg=.o))))) $(eval $(foreach SOURCE,$(filter %.s,$(SOURCES)), \ $(call build_s,$(SOURCE),$(subst /,_,$(SOURCE:.s=.o)),BUILDASFLAGS))) # Similarly for test sources ifeq ($(WANT_TEST),yes) ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) TESTLIB := $(OUTPUT) TESTLDFLAGS += -L$(BUILDDIR)/ -l$(COMPONENT) endif TESTCFLAGS := $(CFLAGS) $(TESTCFLAGS) TESTCXXFLAGS += $(CXXFLAGS) TESTLDFLAGS += $(LDFLAGS) define link_test $2: $($3) $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " LINK: $2" ifeq ($$(CXX_IN_BUILD),yes) $$(Q)$$(CXX) -o $$@ $1 $$($4) else $$(Q)$$(CC) -o $$@ $1 $$($4) endif endef srcs_for_test = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) objs_for_test = $(addprefix $(BUILDDIR)/, \ $(subst /,_,$(addsuffix .o,$(basename $(srcs_for_test))))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(call link_test,$(objs_for_test),$(bin_for_test),TESTLIB,TESTLDFLAGS))) endif # Include dependency makefiles ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) -include $(sort $(DEPFILES)) endif netsurf-2.9/libnsbmp-0.0.3/build/makefiles/Makefile.clang0000664000175000017500000000232611545435603022103 0ustar vincevince# Clang-specific toolchain setup # We assume that we're using a standard GCC/binutils environment, as well # as clang being mostly GCC-compatible on the command line CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### CC_CAN_BUILD_AND_DEP ?= yes netsurf-2.9/libnsbmp-0.0.3/build/makefiles/Makefile.norcroft0000664000175000017500000000220311545435603022645 0ustar vincevince# Norcroft specific toolchain setup CCDEF := -D CCOPT := -Otime CCNOOPT := CCDBG := -g CCINC := -I CCLIB := -L # TODO: Norcroft CC cannot do assembler as C CCAS := CCSHR := CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g LDSHR := ARFLG := -c # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) $(error Coverage is not supported with Norcroft) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) $(error Profile is not supported with Norcroft) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -zM CXXFLAGS := $(CXXFLAGS) -zM LDFLAGS := $(LDFLAGS) -zM endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. CC_CANNOT_DEP := yes netsurf-2.9/libnsbmp-0.0.3/build/makefiles/Makefile.gcc0000664000175000017500000000457011545435603021556 0ustar vincevince# GCC specific toolchain setup # We assume that we're using a standard GCC/binutils environment CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions for various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="__attribute__((aligned))" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) COVCFLAGS ?= -fprofile-arcs -ftest-coverage COVCXXFLAGS ?= -fprofile-arcs -ftest-coverage COVLDFLAGS ?= -lgcov CFLAGS := $(CFLAGS) $(COVCFLAGS) CXXFLAGS := $(CXXFLAGS) $(COVCXXFLAGS) LDFLAGS := $(LDFLAGS) $(COVLDFLAGS) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) PROFCFLAGS ?= -pg PROFCXXFLAGS ?= -pg PROFLDFLAGS ?= -pg CFLAGS := $(CFLAGS) $(PROFCFLAGS) CXXFLAGS := $(CXXFLAGS) $(PROFCXXFLAGS) LDFLAGS := $(LDFLAGS) $(PROFLDFLAGS) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -mmodule CXXFLAGS := $(CXXFLAGS) -mmodule LDFLAGS := $(LDFLAGS) -mmodule endif ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CC_CAN_BUILD_AND_DEP := no CC_CANNOT_DEP := yes CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. ccvsn := $(shell $(CC) -dumpversion) # ccvsn = x.y.z GCCVER := $(word 1,$(subst ., ,$(ccvsn))) # GCCVER = x # If the major version (x, above) is not 2, then assume build & dep. # This will break if using a version of GCC < 2, but that's unlikely. ifneq ($(GCCVER),2) CC_CAN_BUILD_AND_DEP ?= yes endif netsurf-2.9/libnsbmp-0.0.3/build/makefiles/Makefile.pkgconfig0000664000175000017500000000426511476474557023010 0ustar vincevince# General purpose pkg-config macros # Determine if a package is available # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_available ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package availability) endif ifeq ($$(shell $$(PKGCONFIG) --exists $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Retrieve the version of a package # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif $(1) := $$(shell $$(PKGCONFIG) --version $(2)) endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number define pkg_config_package_min_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number # 4: Highest accepted version number define pkg_config_package_compare_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) ifeq ($$(shell $$(PKGCONFIG) --max-version=$(4) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif else $(1) := no endif endef # Add package to compiler/linker flags # 1: Name of package to add details of # 2: CFLAGS variable to extend, or none # 3: LDFLAGS variable to extend, or none define pkg_config_package_add_flags ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifneq ($(2),) $(2) := $$($(2)) $$(shell $$(PKGCONFIG) --cflags $(1)) endif ifneq ($(3),) $(3) := $$($(3)) $$(shell $$(PKGCONFIG) --libs $(1)) endif endef netsurf-2.9/libnsbmp-0.0.3/build/makefiles/Makefile.subdir0000664000175000017500000000741711165262413022310 0ustar vincevince# Child makefile fragment # # Inputs (reset on exit) # # DIR_SOURCES List of source files in this directory # DIR_TEST_ITEMS List of test items in this directory # DIR_INSTALL_ITEMS Items to install in form :; # # Toolchain is provided by top-level makefile # # Variables provided by top-level makefile # # BUILDDIR The location of the build tree root # COMPONENT The name of the component # CURDIR The location of the source tree root # EXPORTDIR The location of the export directory # WANT_TEST Whether to build testcases # # do_include Canned command sequence to include a child makefile # # Variables provided by parent makefile: # # DIR The name of the directory we're in, relative to CURDIR # # Variables we can manipulate: # # CLEAN_ITEMS The list of items to remove for "make clean" # DISTCLEAN_ITEMS The list of items to remove for "make distclean" # TEST_ITEMS The list of items to build for "make test" # TEST_TARGETS The list of target names to run for "make test" # INSTALL_ITEMS The list of items to (un)install # # SOURCES The list of sources to build for $(COMPONENT) # # Plus anything from the toolchain # Push parent directory onto the directory stack sp := $(sp).x dirstack_$(sp) := $(d) d := $(DIR) # Sources SRCS_$(d) := $(DIR_SOURCES) TEST_ITEMS_$(d) := INSTALL_ITEMS_$(d) := # Append to sources for component SOURCES := $(SOURCES) $(addprefix $(d), $(SRCS_$(d))) # Test sources ifeq ($(WANT_TEST),yes) ifneq ($(DIR_TEST_ITEMS),) # Extract the binary name from the ITEM binary = $(subst /,_,$(addprefix $(d),$(firstword $(subst :, ,$(ITEM))))) # Extract the list of sources from the ITEM sources = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) # We can't simply use the output of foreach here, # as it space separates its output, which kinda defeats the point. define append_test_src TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d))$1; endef define append_test TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d)) $1: $$(eval $$(foreach TSRC,$2, \ $$(call append_test_src,$$(addprefix $$(d),$$(TSRC))))) endef # Append test items, prepending $(d) to each source file $(eval $(foreach ITEM,$(DIR_TEST_ITEMS), \ $(call append_test,$(binary),$(sources)))) TEST_ITEMS := $(TEST_ITEMS) $(TEST_ITEMS_$(d)) TEST_TARGETS := $(TEST_TARGETS) test_$(d) # Extract the binary name from the TEST binary_name = $(firstword $(subst :, ,$(TEST))) # Target for tests in this directory test_$(d): $(d) $(addprefix $(BUILDDIR)/, \ $(foreach TEST,$(TEST_ITEMS_$(d)),$(binary_name))) $(Q)$(SHAREDLDPATH) $(TESTRUNNER) $(BUILDDIR) \ $(CURDIR)/$< $(subst /,_,$<) $(EXEEXT) endif endif # Install items ifneq ($(DIR_INSTALL_ITEMS),) # Extract the destination directory from the variable dest_dir = $(firstword $(subst :, ,$(ITEM))) # Extract the list of files to install files = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) define append_install_file INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d))$1; endef define append_install_item INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d)) $1: $$(eval $$(foreach FILE,$2, \ $$(call append_install_file,$$(addprefix $$(d),$$(FILE))))) endef # Append items to install (along with install location), prepending $(d) # to each item in the file list $(eval $(foreach ITEM,$(DIR_INSTALL_ITEMS), \ $(call append_install_item,$(dest_dir),$(files)))) INSTALL_ITEMS := $(INSTALL_ITEMS) $(INSTALL_ITEMS_$(d)) endif # Reset the inputs DIR_SOURCES := DIR_TEST_ITEMS := DIR_INSTALL_ITEMS := # Now include any children we may have MAKE_INCLUDES := $(wildcard $(d)*/Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Pop off the directory stack d := $(dirstack_$(sp)) sp := $(basename $(sp)) netsurf-2.9/libnsbmp-0.0.3/build/makefiles/Makefile.tools0000664000175000017500000003224511537136047022163 0ustar vincevince# Tools Makefile fragment # # Expected inputs: # # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # # Optional inputs: # # BUILD Type of build to perform: # release - Release build (default) # debug - Debug build # OPTCFLAGS Optional C compiler flags for $(BUILD) # OPTCXXFLAGS Optional C++ compiler flags for $(BUILD) # OPTLDFLAGS Optional linker flags for $(BUILD) # TARGET Target platform (defaults to host) # PREFIX Absolute installation path prefix # (defaults to /usr/local) # ############################################################################### # Sanity checks ############################################################################### ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not set) endif # Default build to release ifeq ($(BUILD),) BUILD := release endif ############################################################################### # Host/target platform detection ############################################################################### # Autodetect host if necessary ifeq ($(HOST),) HOST := $(shell uname -s) endif # Simple host sanitisation ifeq ($(HOST),) # Don't ask HOST := riscos else ifeq ($(HOST),RISC OS) HOST := riscos endif ifeq ($(HOST),BeOS) HOST := beos endif ifeq ($(HOST),Haiku) HOST := haiku endif ifeq ($(HOST),AmigaOS) HOST := amiga endif ifeq ($(findstring MINGW,$(HOST)),MINGW) HOST := windows endif endif ifeq ($(TARGET),) # Default target to host. Please add exceptions as required. TARGET := $(HOST) ifeq ($(HOST),haiku) # This isn't necessarily correct -- they have differences. However, in the # general case, this will work. If there are differences that are actually # important wrt the target platform (as opposed to the build host) then # we'll just have to introduce a haiku target, too. TARGET := beos endif endif # Sanitise HOST and TARGET # TODO: Ideally, we want the equivalent of s/[^A-Za-z0-9]/_/g here HOST := $(subst .,_,$(subst -,_,$(subst /,_,$(HOST)))) TARGET := $(subst .,_,$(subst -,_,$(subst /,_,$(TARGET)))) # Now setup our tooling ifeq ($(TARGET),riscos) ifeq ($(HOST),riscos) # Building on native RISC OS GCCSDK_INSTALL_ENV ?= CC__ := gcc CXX__ := g++ CMHG ?= cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= # On certain versions of RISC OS (<>4 || kernel < 8.75), # the kernel will clean up the current redirection on # OS_Exit, including closing the associated file handles. # This is problematic for UnixLib, as it's invariably using # those filehandles in a pipe between parent and child processes. # This affects us as, anywhere where we shell out and want to # capture the output of the child process may fail. # Fortunately, if we know the child process is built against # UnixLib, then we also know that it won't call OS_Exit when it # exits, instead returning directly to our exit handler (and thus # preserving the redirection). This only works, however, if the # child application is specified using its absolute path, or # found in Run$Path. In the case of Perl, it does not appear in # Run$Path, so we must invoke it using its absolute path so that # the SharedUnixLibrary successfully detects it as a child process. PERL ?= .bin.perl # This is nasty, but needed because $(CURDIR) will # contain colons, and thus confuse make mightily $(shell SetMacro Alias$$$(COMPONENT)pwd Set %0 :|$$CSD>|mUnset Alias$$$(COMPONENT)pwd) $(shell $(COMPONENT)pwd $(COMPONENT)$$Dir) CURDIR := <$(COMPONENT)$$Dir> else # Cross compiling for RISC OS ifeq ($(origin GCCSDK_INSTALL_ENV),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/env),) GCCSDK_INSTALL_ENV := /opt/netsurf/arm-unknown-riscos/env else GCCSDK_INSTALL_ENV := /home/riscos/env endif endif ifeq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/cross/bin),) GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-unknown-riscos/cross/bin else GCCSDK_INSTALL_CROSSBIN := /home/riscos/cross/bin endif endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) CMHG ?= PATH="$(GCCSDK_INSTALL_CROSSBIN):$(PATH)" $(GCCSDK_INSTALL_CROSSBIN)/cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/share/pkgconfig" pkg-config ifneq ($(COMPONENT_TYPE),riscos-module) ifeq ($(origin CC),default) ifneq ($(findstring arm-unknown-riscos-gcc,$(CC__)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif else ifneq ($(findstring arm-unknown-riscos-gcc,$(CC)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif endif else EXEEXT := ,ffa endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib CMHGFLAGS := -p -tgcc -32bit -apcs 3/32/nonreent/fpe2/noswst/nofpr/nofp # Default prefix PREFIX ?= $(GCCSDK_INSTALL_ENV) endif # BeOS-like targets ifeq ($(TARGET),beos) ifeq ($(HOST),beos) # Building on BeOS CC__ := gcc # No pkg-config PKGCONFIG ?= # Default prefix BEOS_INSTALL_ENV ?= /boot/home/config else ifeq ($(HOST),haiku) # Building on Haiku # Default prefix BEOS_INSTALL_ENV ?= /boot/common else # TODO: more sensible default BEOS_INSTALL_ENV ?= /home/jmb/haiku/env BEOS_INSTALL_CROSSBIN ?= /home/jmb/haiku/haiku/generated/cross-tools/bin CC__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*g++) AR__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*ar) PKGCONFIG := PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/share/pkgconfig" pkg-config endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -I$(BEOS_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -I$(BEOS_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(BEOS_INSTALL_ENV)/lib PREFIX ?= $(BEOS_INSTALL_ENV) endif # Windows ifeq ($(TARGET),windows) ifeq ($(HOST),windows) # Building on Windows CC__ := gcc CXX__ := g++ AR__ := ar PKGCONFIG ?= else # Cross compiling for Windows -- assumes mingw toolchain MINGW_INSTALL_ENV ?= /usr/local/mingw CC__ := i586-mingw32msvc-gcc CXX__ := i586-mingw32msvc-g++ AR__ := i586-mingw32msvc-ar PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(MINGW_INSTALL_ENV)/lib # Default prefix PREFIX ?= $(MINGW_INSTALL_ENV) endif # AmigaOS (3/4; m68k/ppc: we can treat them identically) ifeq ($(findstring amiga,$(TARGET)),amiga) ifeq ($(findstring amiga,$(HOST)),amiga) # Building on AmigaOS # Nothing to do, as we assume the default tooling works else # Cross compiling for AmigaOS ifeq ($(TARGET),amigaos3) GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-unknown-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-unknown-amigaos/cross/bin else GCCSDK_INSTALL_ENV ?= /opt/netsurf/ppc-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/ppc-amigaos/cross/bin endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib PREFIX ?= $(GCCSDK_INSTALL_ENV) endif endif # Default prefix PREFIX ?= /usr/local ############################################################################### # Tool defaults ############################################################################### CP ?= cp DOXYGEN ?= doxygen ECHO ?= echo GENHTML ?= genhtml ifeq ($(HOST),$(TARGET)) HOST_CC ?= $(CC) HOST_CXX ?= $(CXX) else HOST_CC ?= cc HOST_CXX ?= c++ endif INSTALL ?= install LCOV ?= lcov LN ?= ln MAKE ?= make MKDIR ?= mkdir MKDIRFLAGS ?= -p MV ?= mv PERL ?= perl PKGCONFIG ?= PKG_CONFIG_PATH="$(PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)" pkg-config GREP ?= grep SED ?= sed TOUCH ?= touch XSLTPROC ?= xsltproc ############################################################################### # Override defaulted tools ############################################################################### # CC ifeq ($(findstring ccc-analyzer,$(CC)),ccc-analyzer) # We're being invoked by scan-build, so export # the compiler we would have used such that # scan-build works with cross-compilation. # There's no need to do this if we would have # used the default compiler. ifdef CC__ export CCC_CC := $(CC__) endif else # Only set CC if it's not already set in the # environment and we have a value for it. # Otherwise, leave it to be defaulted. ifeq ($(origin CC),default) ifdef CC__ CC := $(CC__) endif endif endif # CXX ifeq ($(origin CXX),default) ifdef CXX__ CXX := $(CXX__) endif endif # AR ifeq ($(origin AR),default) ifdef AR__ AR := $(AR__) endif endif ############################################################################### # Auto-detect the toolchain ############################################################################### # Check for GCC first, as that's most likely # TODO: Using shell redirection like this probably hurts portability ccspecs := $(shell $(CC) -dumpspecs 2>&1) ifeq ($(findstring libgcc,$(ccspecs)),libgcc) # Looks like GCC toolchain := gcc else # Not GCC, so enquire further ccvsn := $(shell $(CC) --version 2>&1) ifeq ($(ccvsn),) # Version string is blank ifeq ($(HOST),riscos) # For some reason we never see the output of SCL apps, so might be # Norcroft. However it might also be a GCC linked against a buggy # UnixLib. # TODO: Something more useful than blindly assuming GCC. ccvsn := GCC # ccvsn := Norcroft endif endif # "Norcroft ..." ifeq ($(word 1,$(ccvsn)),Norcroft) toolchain := norcroft endif # "GCC ..." ifeq ($(word 1,$(ccvsn)),GCC) toolchain := gcc endif # "clang ..." ifeq ($(word 1,$(ccvsn)),clang) toolchain := clang endif ifeq ($(word 1,$(ccvsn)),Apple) ifeq ($(word 2,$(ccvsn)),clang) # Apple clang toolchain := clang endif endif endif ifeq ($(toolchain),) $(error Unable to detect toolchain) endif # TODO: It would be nice to avoid this hard-coded path include build/makefiles/Makefile.$(toolchain) ############################################################################### # Default assembler/compiler/linker/archiver flags ############################################################################### ifeq ($(BUILD),release) OPTCFLAGS ?= $(CCDEF)NDEBUG $(CCOPT) OPTCXXFLAGS ?= $(CXXDEF)NDEBUG $(CXXOPT) else OPTCFLAGS ?= $(CCDBG) $(CCNOOPT) $(CCDEF)DEBUG OPTCXXFLAGS ?= $(CXXDBG) $(CXXNOOPT) $(CXXDEF)DEBUG OPTLDFLAGS ?= $(LDDBG) endif ifeq ($(origin ARFLAGS),default) ARFLAGS := $(ARFLG) endif # TODO: This assumes that the C compiler can cope with assembler ASFLAGS ?= $(CCAS) CFLAGS := $(CFLAGS) $(OPTCFLAGS) $(CCDEF)BUILD_TARGET_$(TARGET) $(CCDEF)BUILD_HOST_$(HOST) CXXFLAGS := $(CXXFLAGS) $(OPTCXXFLAGS) \ $(CXXDEF)BUILD_TARGET_$(TARGET) $(CXXDEF)BUILD_HOST_$(HOST) ASFLAGS := $(ASFLAGS) $(CFLAGS) LDFLAGS := $(LDFLAGS) $(OPTLDFLAGS) ############################################################################### # lib-shared defaults ############################################################################### # Default library extension ifeq ($(COMPONENT_TYPE),lib-static) LIBEXT ?= .a else LIBEXT ?= .so endif # If we're building a shared library, modify the flags appropriately ifeq ($(COMPONENT_TYPE),lib-shared) # Default CFLAGS/LDFLAGS for shared libraries SHAREDCFLAGS ?= $(CCSHR) $(CCDEF)PIC SHAREDCXXFLAGS ?= $(CXXSHR) $(CCDEF)PIC SHAREDLDFLAGS ?= $(LDSHR) SHAREDLDPATH ?= LD_LIBRARY_PATH="$(BUILDDIR):$(LD_LIBRARY_PATH)" endif ################################################################################ # Package config macros ################################################################################ include build/makefiles/Makefile.pkgconfig netsurf-2.9/librufl-0.0.1/0000775000175000017500000000000011734430311014134 5ustar vincevincenetsurf-2.9/librufl-0.0.1/include/0000775000175000017500000000000011734430311015557 5ustar vincevincenetsurf-2.9/librufl-0.0.1/include/rufl.h0000664000175000017500000001106611321135473016707 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2006 James Bursa */ #ifndef RUFL_H #define RUFL_H #include #include #include "oslib/os.h" /** Return code for RUfl functions. */ typedef enum { /** Success. */ rufl_OK, /** Failure: memory was exhausted. */ rufl_OUT_OF_MEMORY, /** Failure: Font Manager error; details in rufl_fm_error. */ rufl_FONT_MANAGER_ERROR, /** Failure: no font with this name exists. */ rufl_FONT_NOT_FOUND, /** Failure: file input / output error: details in errno. */ rufl_IO_ERROR, /** Failure: file input unexpected eof. */ rufl_IO_EOF, } rufl_code; /** Font weight and slant. Normal weight is 400, 700 gives the "Bold" weight of * fonts. */ typedef enum { rufl_WEIGHT_100 = 1, rufl_WEIGHT_200 = 2, rufl_WEIGHT_300 = 3, rufl_WEIGHT_400 = 4, rufl_WEIGHT_500 = 5, rufl_WEIGHT_600 = 6, rufl_WEIGHT_700 = 7, rufl_WEIGHT_800 = 8, rufl_WEIGHT_900 = 9, rufl_SLANTED = 0x100, } rufl_style; /** rufl_paint flags */ #define rufl_BLEND_FONT 0x01 /** Last Font Manager error. */ extern os_error *rufl_fm_error; /** List of available font families. */ extern const char **rufl_family_list; /** Number of entries in rufl_family_list. */ extern unsigned int rufl_family_list_entries; /** Menu of font families. */ extern void *rufl_family_menu; /* Callbacks used by rufl_decompose_glyph */ typedef int (*rufl_move_to_func)(os_coord *to, void *user); typedef int (*rufl_line_to_func)(os_coord *to, void *user); typedef int (*rufl_cubic_to_func)(os_coord *control1, os_coord *control2, os_coord *to, void *user); struct rufl_decomp_funcs { rufl_move_to_func move_to; rufl_line_to_func line_to; rufl_cubic_to_func cubic_to; }; /** * Initialise RUfl. * * All available fonts are scanned. May take some time. */ rufl_code rufl_init(void); /** * Render Unicode text. */ rufl_code rufl_paint(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int x, int y, unsigned int flags); /** * Measure the width of Unicode text. */ rufl_code rufl_width(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int *width); /** * Find where in a string a x coordinate falls. */ rufl_code rufl_x_to_offset(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int click_x, size_t *char_offset, int *actual_x); /** * Find the prefix of a string that will fit in a specified width. */ rufl_code rufl_split(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int width, size_t *char_offset, int *actual_x); /** Type of callback function for rufl_paint_callback(). */ typedef void (*rufl_callback_t)(void *context, const char *font_name, unsigned int font_size, const char *s8, unsigned short *s16, unsigned int n, int x, int y); /** * Render text, but call a callback instead of each call to Font_Paint. */ rufl_code rufl_paint_callback(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int x, int y, rufl_callback_t callback, void *context); /** * Decompose a glyph to a path. */ rufl_code rufl_decompose_glyph(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, struct rufl_decomp_funcs *funcs, void *user); /** * Read metrics for a font */ rufl_code rufl_font_metrics(const char *font_family, rufl_style font_style, os_box *bbox, int *xkern, int *ykern, int *italic, int *ascent, int *descent, int *xheight, int *cap_height, signed char *uline_position, unsigned char *uline_thickness); /** * Read metrics for a glyph */ rufl_code rufl_glyph_metrics(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int *x_bearing, int *y_bearing, int *width, int *height, int *x_advance, int *y_advance); /** * Determine the maximum bounding box of a font. */ rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, unsigned int font_size, int *bbox); /** * Dump the internal library state to stdout. */ void rufl_dump_state(void); /** * Clear the internal font handle cache. * * Call this function on mode changes or output redirection changes. */ void rufl_invalidate_cache(void); /** * Free all resources used by the library. */ void rufl_quit(void); #endif netsurf-2.9/librufl-0.0.1/librufl.pc.in0000664000175000017500000000032611321135473016530 0ustar vincevinceprefix=PREFIX exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: librufl Description: RISC OS Unicode font library Version: VERSION Libs: -L${libdir} -lrufl Cflags: -I${includedir} netsurf-2.9/librufl-0.0.1/python/0000775000175000017500000000000011734430311015455 5ustar vincevincenetsurf-2.9/librufl-0.0.1/python/Mk.old0000664000175000017500000000106311321135473016527 0ustar vincevince# compiling on RISC OS using Norcroft CC = cc CFLAGS = -fn -ecz -wap -IOSLib: -DNDEBUG LD = link LDFLAGS = -aof LIBS = OSLib:o.oslib32 MKDLK = makedlk SOURCE += strfuncs.c OBJS = $(SOURCE:.c=.o) EXEEXT = all: librufl.a rufl/pyd rufl_test rufl_chars librufl.a: $(OBJS) $(LD) $(LDFLAGS) -o $@ $(OBJS) o.ruflmodule: ruflmodule.o librufl.a $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) ruflmodule.o: ruflmodule.c $(CC) -fn -wp -IPyInc:Include,PyInc:RISCOS,TCPIPLibs:,OSLib: -c $@ $< rufl/pyd: o.ruflmodule $(MKDLK) -s .RISCOS.s.linktab -o $< -d $@ -e initrufl netsurf-2.9/librufl-0.0.1/python/ruflmodule.c0000664000175000017500000001162211321135473020004 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2006 James Bursa */ /* Python module for RUfl. */ #include "Python.h" #include "rufl.h" static char pyrufl_paint__doc__[] = "paint(font_family, font_style, font_size, string, x, y, flags)\n\n" "Render Unicode text." ; static PyObject * pyrufl_paint(PyObject *self /* Not used */, PyObject *args) { const char *font_family; rufl_style font_style; unsigned int font_size; const char *string; int length; int x; int y; unsigned int flags; if (!PyArg_ParseTuple(args, "siIs#iiI", &font_family, &font_style, &font_size, &string, &length, &x, &y, &flags)) return NULL; rufl_paint(font_family, font_style, font_size, string, length, x, y, flags); Py_INCREF(Py_None); return Py_None; } static char pyrufl_width__doc__[] = "width(font_family, font_style, font_size, string)\n\n" "Return the width of Unicode text." ; static PyObject * pyrufl_width(PyObject *self /* Not used */, PyObject *args) { const char *font_family; rufl_style font_style; unsigned int font_size; const char *string; int length; int width = 0; if (!PyArg_ParseTuple(args, "siIs#", &font_family, &font_style, &font_size, &string, &length)) return NULL; rufl_width(font_family, font_style, font_size, string, length, &width); return PyInt_FromLong(width); } static char pyrufl_x_to_offset__doc__[] = "x_to_offset(font_family, font_style, font_size, string, click_x)\n\n" "Return a pair of the character offset in string that click_x falls,\n" "and the actual x coordinate for that character offset." ; static PyObject * pyrufl_x_to_offset(PyObject *self /* Not used */, PyObject *args) { const char *font_family; rufl_style font_style; unsigned int font_size; const char *string; int length; int click_x; size_t char_offset = 0; int actual_x = 0; if (!PyArg_ParseTuple(args, "siIs#i", &font_family, &font_style, &font_size, &string, &length, &click_x)) return NULL; rufl_x_to_offset(font_family, font_style, font_size, string, length, click_x, &char_offset, &actual_x); return Py_BuildValue("ii", (int) char_offset, actual_x); } static char pyrufl_split__doc__[] = "split(font_family, font_style, font_size, string, width)\n\n" "Return a pair of the character offset in string that fits in width,\n" "and the actual x coordinate for that character offset." ; static PyObject * pyrufl_split(PyObject *self /* Not used */, PyObject *args) { const char *font_family; rufl_style font_style; unsigned int font_size; const char *string; int length; int width; size_t char_offset = 0; int actual_x = 0; if (!PyArg_ParseTuple(args, "siIs#i", &font_family, &font_style, &font_size, &string, &length, &width)) return NULL; rufl_split(font_family, font_style, font_size, string, length, width, &char_offset, &actual_x); return Py_BuildValue("ii", (int) char_offset, actual_x); } static char pyrufl_invalidate_cache__doc__[] = "invalidate_cache()\n\n" "Clear the internal font handle cache.\n" "Call this function on mode changes or output redirection changes." ; static PyObject * pyrufl_invalidate_cache(PyObject *self /* Not used */, PyObject *args) { if (!PyArg_ParseTuple(args, "")) return NULL; rufl_invalidate_cache(); Py_INCREF(Py_None); return Py_None; } /* List of methods defined in the module */ static struct PyMethodDef pyrufl_methods[] = { {"paint", (PyCFunction)pyrufl_paint, METH_VARARGS, pyrufl_paint__doc__}, {"width", (PyCFunction)pyrufl_width, METH_VARARGS, pyrufl_width__doc__}, {"x_to_offset", (PyCFunction)pyrufl_x_to_offset, METH_VARARGS, pyrufl_x_to_offset__doc__}, {"split", (PyCFunction)pyrufl_split, METH_VARARGS, pyrufl_split__doc__}, {"invalidate_cache", (PyCFunction)pyrufl_invalidate_cache, METH_VARARGS, pyrufl_invalidate_cache__doc__}, {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ }; /* Initialization function for the module (*must* be called initrufl) */ static char pyrufl_module_documentation[] = "This module provides access to the RISC OS Unicode font library\n" "All string parameters must be in UTF-8." ; void initrufl(void) { PyObject *module; rufl_code code; code = rufl_init(); if (code != rufl_OK) Py_FatalError("rufl_init() failed"); Py_AtExit(rufl_quit); /* Create the module and add the functions */ module = Py_InitModule4("rufl", pyrufl_methods, pyrufl_module_documentation, (PyObject *) NULL, PYTHON_API_VERSION); /* Add some symbolic constants to the module */ PyModule_AddIntConstant(module, "regular", rufl_REGULAR); PyModule_AddIntConstant(module, "slanted", rufl_SLANTED); PyModule_AddIntConstant(module, "bold", rufl_BOLD); PyModule_AddIntConstant(module, "bold_slanted", rufl_BOLD_SLANTED); PyModule_AddIntConstant(module, "blend", rufl_BLEND_FONT); /* Check for errors */ if (PyErr_Occurred()) Py_FatalError("can't initialize module rufl"); } netsurf-2.9/librufl-0.0.1/src/0000775000175000017500000000000011734430311014723 5ustar vincevincenetsurf-2.9/librufl-0.0.1/src/strfuncs.c0000664000175000017500000000120011321135473016732 0ustar vincevince#include #include #include #include "strfuncs.h" char *strdup(const char *s) { size_t len = strlen(s); char *new = malloc(len + 1); if (!new) return 0; memcpy(new, s, len); new[len] = '\0'; return new; } char *strndup(const char *s, size_t n) { size_t len = strlen(s); if (n < len) len = n; char *new = malloc(len + 1); if (!new) return 0; memcpy(new, s, len); new[len] = '\0'; return new; } int strcasecmp(const char *s1, const char *s2) { int i; while ((i = tolower(*s1)) && i == tolower(*s2)) s1++, s2++; return ((unsigned char) tolower(*s1) - (unsigned char) tolower(*s2)); } netsurf-2.9/librufl-0.0.1/src/rufl_character_set_test.c0000664000175000017500000000150111321135473021765 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2005 James Bursa */ #include "rufl_internal.h" /** * Test if a character set contains a character. * * \param charset character set * \param c character code * \return true if present, false if absent */ bool rufl_character_set_test(struct rufl_character_set *charset, unsigned int c) { unsigned int block = c >> 8; unsigned int byte = (c >> 3) & 31; unsigned int bit = c & 7; if (256 <= block) return false; if (charset->index[block] == BLOCK_EMPTY) return false; else if (charset->index[block] == BLOCK_FULL) return true; else { unsigned char z = charset->block[charset->index[block]][byte]; return z & (1 << bit); } } netsurf-2.9/librufl-0.0.1/src/rufl_metrics.c0000664000175000017500000002041511321135473017572 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2005 John-Mark Bell */ #include #include #include #include "oslib/font.h" #include "rufl_internal.h" static int rufl_unicode_map_search_cmp(const void *keyval, const void *datum); /** * Read a font's metrics (sized for a 1pt font) */ rufl_code rufl_font_metrics(const char *font_family, rufl_style font_style, os_box *bbox, int *xkern, int *ykern, int *italic, int *ascent, int *descent, int *xheight, int *cap_height, signed char *uline_position, unsigned char *uline_thickness) { unsigned int font; font_f f; int misc_size; font_metrics_misc_info *misc_info; rufl_code code; code = rufl_find_font_family(font_family, font_style, &font, NULL, NULL); if (code != rufl_OK) return code; code = rufl_find_font(font, 16 /* 1pt */, NULL, &f); if (code != rufl_OK) return code; rufl_fm_error = xfont_read_font_metrics(f, 0, 0, 0, 0, 0, 0, 0, 0, 0, &misc_size, 0); if (rufl_fm_error) { LOG("xfont_read_font_metrics: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } if (misc_size == 0) { LOG("no miscellaneous information in metrics for %s", rufl_font_list[font].identifier); /** \todo better error code */ return rufl_FONT_NOT_FOUND; } misc_info = (font_metrics_misc_info *)malloc(misc_size); if (!misc_info) return rufl_OUT_OF_MEMORY; rufl_fm_error = xfont_read_font_metrics(f, 0, 0, 0, misc_info, 0, 0, 0, 0, 0, 0, 0); if (rufl_fm_error) { LOG("xfont_read_font_metrics: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); free(misc_info); return rufl_FONT_MANAGER_ERROR; } /* and fill in output */ if (bbox) { bbox->x0 = misc_info->x0; bbox->y0 = misc_info->y0; bbox->x1 = misc_info->x1; bbox->y1 = misc_info->y1; } if (xkern) (*xkern) = misc_info->xkern; if (ykern) (*ykern) = misc_info->ykern; if (italic) (*italic) = misc_info->italic_correction; if (ascent) (*ascent) = misc_info->ascender; if (descent) (*descent) = misc_info->descender; if (xheight) (*xheight) = misc_info->xheight; if (cap_height) (*cap_height) = misc_info->cap_height; if (uline_position) (*uline_position) = misc_info->underline_position; if (uline_thickness) (*uline_thickness) = misc_info->underline_thickness; free(misc_info); return rufl_OK; } /** * Read a glyph's metrics */ rufl_code rufl_glyph_metrics(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int *x_bearing, int *y_bearing, int *width, int *height, int *x_advance, int *y_advance) { const char *font_encoding = NULL; unsigned int font, font1, u; unsigned short u1[2]; struct rufl_character_set *charset; struct rufl_unicode_map_entry *umap_entry = NULL; font_f f; rufl_code code; font_scan_block block; font_string_flags flags; int xa, ya; /* Find font family containing glyph */ code = rufl_find_font_family(font_family, font_style, &font, NULL, &charset); if (code != rufl_OK) return code; rufl_utf8_read(string, length, u); if (charset && rufl_character_set_test(charset, u)) font1 = font; else if (u < 0x10000) font1 = rufl_substitution_table[u]; else font1 = rufl_CACHE_CORPUS; /* Old font managers need the font encoding, too */ if (rufl_old_font_manager && font1 != rufl_CACHE_CORPUS) { unsigned int i; unsigned short u16 = (unsigned short) u; for (i = 0; i < rufl_font_list[font1].num_umaps; i++) { struct rufl_unicode_map *map = rufl_font_list[font1].umap + i; umap_entry = bsearch(&u16, map->map, map->entries, sizeof map->map[0], rufl_unicode_map_search_cmp); if (umap_entry) { font_encoding = map->encoding; break; } } assert(umap_entry != NULL); } code = rufl_find_font(font1, font_size, font_encoding, &f); if (code != rufl_OK) return code; /* * Glyph Metrics for horizontal text: * * ^ x0 x1 * | Xbearing : x0 - oX * | +-----+-------- y1 Ybearing : y1 - oY * | | | Xadvance : aX - oX * | | | Yadvance : 0 * o---|-----|---a--> Glyph width : x1 - x0 * | | | Glyph height : y1 - y0 * | +-----+-------- y0 Right side bearing: aX - x1 * | * * The rectangle (x0,y0),(x1,y1) is the glyph bounding box. * * Glyph Metrics for vertical text: * * -------o---------> * y1--+--|--+ Xbearing : x0 - oX * | | | Ybearing : oY - y1 * | | | Xadvance : 0 * | | | Yadvance : aY - oY * | | | Glyph width : x1 - x0 * y0--+-----+ Glyph height : y1 - y0 * ------a----------- Right side bearing: N/A * x0 v x1 * * The rectangle (x0,y0),(x1,y1) is the glyph bounding box. * * * In order to extract the information we want from the * Font Manager, a little bit of hackery is required. * * Firstly, we can take the origin as being (0,0). This is an * arbitrary choice but makes the maths simpler. * * Secondly, the bounding box returned by Font_CharBBox / * Font_ScanString / Font_StringBBox represents the ink area of * the glyph (i.e. the smallest box needed to contain all the * glyph path segments). This means that, for glyphs with no * displayed content (such as a space), the bounding box will be 0. * These SWIs therefore allow us to retrieve the (x0,y0),(x1,y1) * coordinates marked in the diagrams above. * * Finally, we need to retrieve the glyph advance distance. This is * returned in R3/R4 on exit from Font_ScanString (providing bit 17 * of the flags word on entry is clear). It is important to note, * however, that the height will be returned as 0 for fonts with no * Yadvance values in the font data file. Therefore, in order to * achieve vertical layout of text, further work will be needed * (We're also ignoring the fact that the X coordinates of all * values will be in the wrong place and the Y coordinates will have * the wrong sign due to the differing definitions of the Y axis for * horizontal and vertical text.) * * Note that all values (that we're interested in, at least) * returned by the SWIs mentioned above are in _millipoints_. */ block.space.x = block.space.y = 0; block.letter.x = block.letter.y = 0; block.split_char = -1; flags = font_GIVEN_BLOCK | font_GIVEN_LENGTH | font_GIVEN_FONT | font_RETURN_BBOX; u1[0] = (unsigned short)u; u1[1] = 0; if (font1 == rufl_CACHE_CORPUS) { /* Fallback Glyph */ /** \todo implement this properly */ xa = 1000 * font_size; ya = 0; block.bbox.x0 = block.bbox.y0 = 0; block.bbox.x1 = block.bbox.y1 = xa; } else if (rufl_old_font_manager) { /* Old Font Manager */ char s[2]; /* We found the correct umap entry when * looking for the font encoding */ s[0] = umap_entry->c; s[1] = 0; rufl_fm_error = xfont_scan_string(f, s, flags, 0x7fffffff, 0x7fffffff, &block, 0, 1, 0, &xa, &ya, 0); if (rufl_fm_error) { LOG("xfont_scan_string: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } } else { /* UCS Font Manager */ rufl_fm_error = xfont_scan_string(f, (const char *)u1, flags | font_GIVEN16_BIT, 0x7fffffff, 0x7fffffff, &block, 0, 2, 0, &xa, &ya, 0); if (rufl_fm_error) { LOG("xfont_scan_string: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } } /** \todo handle vertical text */ if (x_bearing) (*x_bearing) = block.bbox.x0; if (y_bearing) (*y_bearing) = block.bbox.y1; if (width) (*width) = block.bbox.x1 - block.bbox.x0; if (height) (*height) = block.bbox.y1 - block.bbox.y0; if (x_advance) (*x_advance) = xa; if (y_advance) (*y_advance) = ya; return rufl_OK; } int rufl_unicode_map_search_cmp(const void *keyval, const void *datum) { const unsigned short *key = keyval; const struct rufl_unicode_map_entry *entry = datum; if (*key < entry->u) return -1; else if (entry->u < *key) return 1; return 0; } netsurf-2.9/librufl-0.0.1/src/rufl_decompose.c0000664000175000017500000000734011321135473020104 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2005 John-Mark Bell */ #include #include #include "oslib/font.h" #include "rufl_internal.h" /** * Process a Draw path object * * \param path Pointer to path block * \param funcs Struct of callback functions * \param user User pointer to be passed to callbacks * \return Pointer to word after this path, or NULL to terminate processing */ static int *process_path(int *path, struct rufl_decomp_funcs *funcs, void *user) { /* skip forward to style entry */ path += 9; /* skip dash pattern */ if (path[0] & (1<<7)) path += path[2] + 2; /* and move to start of path components */ path++; while (path[0] != 0) { switch (path[0]) { case 2: /* Move to */ if (funcs->move_to((os_coord *)(path + 1), user)) return NULL; path += 3; break; case 5: /* Close path */ path++; break; case 6: /* Cubic Bezier to */ if (funcs->cubic_to((os_coord *)(path + 1), (os_coord *)(path + 3), (os_coord *)(path + 5), user)) return NULL; path += 7; break; case 8: /* Line to */ if (funcs->line_to((os_coord *)(path + 1), user)) return NULL; path += 3; break; default: /* Anything else is broken */ assert(0); } } /* + 1 to account for tag 0 - end of path */ return path + 1; } rufl_code rufl_decompose_glyph(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t len, struct rufl_decomp_funcs *funcs, void *user) { int *buf, *p, *ep; int buf_size; char *buf_end; rufl_code err; /* Get required buffer size */ rufl_fm_error = xfont_switch_output_to_buffer( font_NO_OUTPUT | font_ADD_HINTS, (byte *)8, 0); if (rufl_fm_error) { LOG("xfont_switch_output_to_buffer: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } err = rufl_paint(font_family, font_style, font_size, string, len, 0, 0, rufl_BLEND_FONT); if (err) { /* reset font redirection - too bad if this fails */ xfont_switch_output_to_buffer(0, 0, 0); return err; } rufl_fm_error = xfont_switch_output_to_buffer(0, NULL, &buf_end); if (rufl_fm_error) { LOG("xfont_switch_output_to_buffer: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } buf_size = buf_end - (char *)NULL; /* Allocate and initialise buffer */ buf = malloc(buf_size); if (!buf) { LOG("Failed to allocate decompose buffer of size %i", buf_size); return rufl_OUT_OF_MEMORY; } buf[0] = 0; buf[1] = buf_size - 8; /* Populate buffer */ rufl_fm_error = xfont_switch_output_to_buffer( font_ADD_HINTS, (byte *)buf, 0); if (rufl_fm_error) { LOG("xfont_switch_output_to_buffer: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); free(buf); return rufl_FONT_MANAGER_ERROR; } err = rufl_paint(font_family, font_style, font_size, string, len, 0, 0, rufl_BLEND_FONT); if (err) { /* reset font redirection - too bad if this fails */ xfont_switch_output_to_buffer(0, 0, 0); free(buf); return err; } rufl_fm_error = xfont_switch_output_to_buffer(0, 0, &buf_end); if (rufl_fm_error) { LOG("xfont_switch_output_to_buffer: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); free(buf); return rufl_FONT_MANAGER_ERROR; } ep = (int *)(void *)buf_end; /* Parse buffer, calling callbacks as required */ for (p = buf; p < ep;) { if (p[0] != 2) { LOG("Object type %d not known", p[0]); break; } p = process_path(p, funcs, user); /* Have the callbacks asked for us to stop? */ if (p == NULL) break; } free(buf); return rufl_OK; } netsurf-2.9/librufl-0.0.1/src/Glyphs0000664000175000017500000015703511321135473016132 0ustar vincevince# # Name: Adobe Glyph List # Table version: 1.2 # Date: 22 Oct 1998 # # Description: # # The Adobe Glyph List (AGL) list relates Unicode values (UVs) to glyph # names, and should be used only as described in the document "Unicode and # Glyph Names," at # http://www.adobe.com/supportservice/devrelations/typeforum/unicodegn.html . # # The glyph name to UV relation is one to many. 12 glyph names are mapped to # two UVs each; each UV has a separate entry. All other glyph names are # mapped to one UV each. # # The Unicode Standard version 2.1 is used for all UVs outside of the Private # Use area, except for 4 entries (see Revision History for 1.2 below). # # There are 1051 entries in this list, 171 of which are in the Corporate Use # subarea (CUS). Refer to the document "Unicode Corporate Use Subarea as used # by Adobe Systems," at # http://www.adobe.com/supportservice/devrelations/typeforum/corporateuse.txt # for compatibility decompositions for these characters, and to the document # "Unicode and Glyph Names" for more information the CUS. # # Format: Semicolon-delimited fields: # # (1) Standard UV or CUS UV. (4 uppercase hexadecimal digits) # # (2) Glyph name. (upper- and lowercase letters, digits) # # (3) Character names: Unicode character names for standard UVs, and # descriptive names for CUS UVs. (uppercase letters, hyphen, space) # # (4) [optional] Comment. A comment of "Duplicate" indicates one of two # UVs of a double-mapping. It is the UV that may be given a uni # override, or the UV that is in the CUS, as described in the document # "Unicode and Glyph Names." # # The entries are sorted by glyph name in increasing ASCII order; entries # with the same glyph name are sorted in decreasing priority order. # # Lines starting with "#" are comments; blank lines should be ignored. # # Revision History: # # 1.2 [22 Oct 1998] # # Some Central European glyph names were remapped and the glyph "dotlessj" # was added. Some entries in the table below have not changed but are # included to provide a complete context for other glyphs that have been # remapped or double-mapped. "-" means that the entry for that UV does not # exist in the AGL. # # -------- ---------------------- ---------------- -------------- # UV Character name AGL 1.1 AGL 1.2 # (shortened) glyph name glyph name # -------- ---------------------- ---------------- -------------- # 015E/F S/s with cedilla S/scommaaccent S/scedilla # 0162/3 T/t with cedilla T/tcommaaccent T/tcommaaccent # 0218/9 S/s with comma below - S/scommaaccent # 021A/B T/t with comma below - T/tcommaaccent # 1E9E/F S/s with comma below S/scedilla - # F6C1/2 S/s with cedilla S/scedilla S/scedilla # F6BE dotless j - dotlessj # -------- ---------------------- ---------------- -------------- # # The characters at U+1E9E/F in AGL 1.1, LATIN CAPITAL/SMALL LETTER S WITH # COMMA BELOW, which are proposed new characters (see (b) in the notes for # AGL 1.1 below), have since been reassigned by the Unicode Standard to new # proposed values of U+0218/9. These characters, as well as U+021A/B, LATIN # CAPITAL/SMALL LETTER T WITH COMMA BELOW, are not in the Unicode Standard # 2.1. # # Entries with the same glyph name are now sorted in decreasing priority # order instead of in increasing UV order. # # 1.1 [24 Nov 1997] # # a. The "Euro" glyph's UV assignment is changed from U+20A0 (EURO-CURRENCY # SIGN) to U+20AC (EURO SIGN). While U+20AC is not defined in the # Unicode Standard 2.0, it has been accepted by the Unicode Technical # Committee for the next version of the Standard; it has not yet passed # the ISO approval process as of 7 November '97. # # b. Glyphs "Scedilla" and "scedilla", which were assigned in the Corporate # Use Subarea in AGL 1.0, are now additionally mapped to U+1E9E and # U+1E9F respectively. These two UVs share the same Unicode approval # status as the Euro glyph (see a. above). # # c. The "fraction" glyph is now additionally mapped to U+2215, to match # Windows Glyph List 4. # # d. The descriptive name for glyph "onefitted", in the Corporate Use # subarea, is changed from "TABULAR DIGIT ONE" to "PROPORTIONAL DIGIT # ONE". # # 1.0 [17 Jul 1997] Original version # 0041;A;LATIN CAPITAL LETTER A 00C6;AE;LATIN CAPITAL LETTER AE 01FC;AEacute;LATIN CAPITAL LETTER AE WITH ACUTE F7E6;AEsmall;LATIN SMALL CAPITAL LETTER AE 00C1;Aacute;LATIN CAPITAL LETTER A WITH ACUTE F7E1;Aacutesmall;LATIN SMALL CAPITAL LETTER A WITH ACUTE 0102;Abreve;LATIN CAPITAL LETTER A WITH BREVE 00C2;Acircumflex;LATIN CAPITAL LETTER A WITH CIRCUMFLEX F7E2;Acircumflexsmall;LATIN SMALL CAPITAL LETTER A WITH CIRCUMFLEX F6C9;Acute;CAPITAL ACUTE ACCENT F7B4;Acutesmall;SMALL CAPITAL ACUTE ACCENT 00C4;Adieresis;LATIN CAPITAL LETTER A WITH DIAERESIS F7E4;Adieresissmall;LATIN SMALL CAPITAL LETTER A WITH DIAERESIS 00C0;Agrave;LATIN CAPITAL LETTER A WITH GRAVE F7E0;Agravesmall;LATIN SMALL CAPITAL LETTER A WITH GRAVE 0391;Alpha;GREEK CAPITAL LETTER ALPHA 0386;Alphatonos;GREEK CAPITAL LETTER ALPHA WITH TONOS 0100;Amacron;LATIN CAPITAL LETTER A WITH MACRON 0104;Aogonek;LATIN CAPITAL LETTER A WITH OGONEK 00C5;Aring;LATIN CAPITAL LETTER A WITH RING ABOVE 01FA;Aringacute;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE F7E5;Aringsmall;LATIN SMALL CAPITAL LETTER A WITH RING ABOVE F761;Asmall;LATIN SMALL CAPITAL LETTER A 00C3;Atilde;LATIN CAPITAL LETTER A WITH TILDE F7E3;Atildesmall;LATIN SMALL CAPITAL LETTER A WITH TILDE 0042;B;LATIN CAPITAL LETTER B 0392;Beta;GREEK CAPITAL LETTER BETA F6F4;Brevesmall;SMALL CAPITAL BREVE F762;Bsmall;LATIN SMALL CAPITAL LETTER B 0043;C;LATIN CAPITAL LETTER C 0106;Cacute;LATIN CAPITAL LETTER C WITH ACUTE F6CA;Caron;CAPITAL CARON F6F5;Caronsmall;SMALL CAPITAL CARON 010C;Ccaron;LATIN CAPITAL LETTER C WITH CARON 00C7;Ccedilla;LATIN CAPITAL LETTER C WITH CEDILLA F7E7;Ccedillasmall;LATIN SMALL CAPITAL LETTER C WITH CEDILLA 0108;Ccircumflex;LATIN CAPITAL LETTER C WITH CIRCUMFLEX 010A;Cdotaccent;LATIN CAPITAL LETTER C WITH DOT ABOVE F7B8;Cedillasmall;SMALL CAPITAL CEDILLA 03A7;Chi;GREEK CAPITAL LETTER CHI F6F6;Circumflexsmall;SMALL CAPITAL MODIFIER LETTER CIRCUMFLEX ACCENT F763;Csmall;LATIN SMALL CAPITAL LETTER C 0044;D;LATIN CAPITAL LETTER D 010E;Dcaron;LATIN CAPITAL LETTER D WITH CARON 0110;Dcroat;LATIN CAPITAL LETTER D WITH STROKE 2206;Delta;INCREMENT 0394;Delta;GREEK CAPITAL LETTER DELTA;Duplicate F6CB;Dieresis;CAPITAL DIAERESIS F6CC;DieresisAcute;CAPITAL DIAERESIS ACUTE ACCENT F6CD;DieresisGrave;CAPITAL DIAERESIS GRAVE ACCENT F7A8;Dieresissmall;SMALL CAPITAL DIAERESIS F6F7;Dotaccentsmall;SMALL CAPITAL DOT ABOVE F764;Dsmall;LATIN SMALL CAPITAL LETTER D 0045;E;LATIN CAPITAL LETTER E 00C9;Eacute;LATIN CAPITAL LETTER E WITH ACUTE F7E9;Eacutesmall;LATIN SMALL CAPITAL LETTER E WITH ACUTE 0114;Ebreve;LATIN CAPITAL LETTER E WITH BREVE 011A;Ecaron;LATIN CAPITAL LETTER E WITH CARON 00CA;Ecircumflex;LATIN CAPITAL LETTER E WITH CIRCUMFLEX F7EA;Ecircumflexsmall;LATIN SMALL CAPITAL LETTER E WITH CIRCUMFLEX 00CB;Edieresis;LATIN CAPITAL LETTER E WITH DIAERESIS F7EB;Edieresissmall;LATIN SMALL CAPITAL LETTER E WITH DIAERESIS 0116;Edotaccent;LATIN CAPITAL LETTER E WITH DOT ABOVE 00C8;Egrave;LATIN CAPITAL LETTER E WITH GRAVE F7E8;Egravesmall;LATIN SMALL CAPITAL LETTER E WITH GRAVE 0112;Emacron;LATIN CAPITAL LETTER E WITH MACRON 014A;Eng;LATIN CAPITAL LETTER ENG 0118;Eogonek;LATIN CAPITAL LETTER E WITH OGONEK 0395;Epsilon;GREEK CAPITAL LETTER EPSILON 0388;Epsilontonos;GREEK CAPITAL LETTER EPSILON WITH TONOS F765;Esmall;LATIN SMALL CAPITAL LETTER E 0397;Eta;GREEK CAPITAL LETTER ETA 0389;Etatonos;GREEK CAPITAL LETTER ETA WITH TONOS 00D0;Eth;LATIN CAPITAL LETTER ETH F7F0;Ethsmall;LATIN SMALL CAPITAL LETTER ETH 20AC;Euro;EURO SIGN 0046;F;LATIN CAPITAL LETTER F F766;Fsmall;LATIN SMALL CAPITAL LETTER F 0047;G;LATIN CAPITAL LETTER G 0393;Gamma;GREEK CAPITAL LETTER GAMMA 011E;Gbreve;LATIN CAPITAL LETTER G WITH BREVE 01E6;Gcaron;LATIN CAPITAL LETTER G WITH CARON 011C;Gcircumflex;LATIN CAPITAL LETTER G WITH CIRCUMFLEX 0122;Gcommaaccent;LATIN CAPITAL LETTER G WITH CEDILLA 0120;Gdotaccent;LATIN CAPITAL LETTER G WITH DOT ABOVE F6CE;Grave;CAPITAL GRAVE ACCENT F760;Gravesmall;SMALL CAPITAL GRAVE ACCENT F767;Gsmall;LATIN SMALL CAPITAL LETTER G 0048;H;LATIN CAPITAL LETTER H 25CF;H18533;BLACK CIRCLE 25AA;H18543;BLACK SMALL SQUARE 25AB;H18551;WHITE SMALL SQUARE 25A1;H22073;WHITE SQUARE 0126;Hbar;LATIN CAPITAL LETTER H WITH STROKE 0124;Hcircumflex;LATIN CAPITAL LETTER H WITH CIRCUMFLEX F768;Hsmall;LATIN SMALL CAPITAL LETTER H F6CF;Hungarumlaut;CAPITAL DOUBLE ACUTE ACCENT F6F8;Hungarumlautsmall;SMALL CAPITAL DOUBLE ACUTE ACCENT 0049;I;LATIN CAPITAL LETTER I 0132;IJ;LATIN CAPITAL LIGATURE IJ 00CD;Iacute;LATIN CAPITAL LETTER I WITH ACUTE F7ED;Iacutesmall;LATIN SMALL CAPITAL LETTER I WITH ACUTE 012C;Ibreve;LATIN CAPITAL LETTER I WITH BREVE 00CE;Icircumflex;LATIN CAPITAL LETTER I WITH CIRCUMFLEX F7EE;Icircumflexsmall;LATIN SMALL CAPITAL LETTER I WITH CIRCUMFLEX 00CF;Idieresis;LATIN CAPITAL LETTER I WITH DIAERESIS F7EF;Idieresissmall;LATIN SMALL CAPITAL LETTER I WITH DIAERESIS 0130;Idotaccent;LATIN CAPITAL LETTER I WITH DOT ABOVE 2111;Ifraktur;BLACK-LETTER CAPITAL I 00CC;Igrave;LATIN CAPITAL LETTER I WITH GRAVE F7EC;Igravesmall;LATIN SMALL CAPITAL LETTER I WITH GRAVE 012A;Imacron;LATIN CAPITAL LETTER I WITH MACRON 012E;Iogonek;LATIN CAPITAL LETTER I WITH OGONEK 0399;Iota;GREEK CAPITAL LETTER IOTA 03AA;Iotadieresis;GREEK CAPITAL LETTER IOTA WITH DIALYTIKA 038A;Iotatonos;GREEK CAPITAL LETTER IOTA WITH TONOS F769;Ismall;LATIN SMALL CAPITAL LETTER I 0128;Itilde;LATIN CAPITAL LETTER I WITH TILDE 004A;J;LATIN CAPITAL LETTER J 0134;Jcircumflex;LATIN CAPITAL LETTER J WITH CIRCUMFLEX F76A;Jsmall;LATIN SMALL CAPITAL LETTER J 004B;K;LATIN CAPITAL LETTER K 039A;Kappa;GREEK CAPITAL LETTER KAPPA 0136;Kcommaaccent;LATIN CAPITAL LETTER K WITH CEDILLA F76B;Ksmall;LATIN SMALL CAPITAL LETTER K 004C;L;LATIN CAPITAL LETTER L F6BF;LL;LATIN CAPITAL LETTER LL 0139;Lacute;LATIN CAPITAL LETTER L WITH ACUTE 039B;Lambda;GREEK CAPITAL LETTER LAMDA 013D;Lcaron;LATIN CAPITAL LETTER L WITH CARON 013B;Lcommaaccent;LATIN CAPITAL LETTER L WITH CEDILLA 013F;Ldot;LATIN CAPITAL LETTER L WITH MIDDLE DOT 0141;Lslash;LATIN CAPITAL LETTER L WITH STROKE F6F9;Lslashsmall;LATIN SMALL CAPITAL LETTER L WITH STROKE F76C;Lsmall;LATIN SMALL CAPITAL LETTER L 004D;M;LATIN CAPITAL LETTER M F6D0;Macron;CAPITAL MACRON F7AF;Macronsmall;SMALL CAPITAL MACRON F76D;Msmall;LATIN SMALL CAPITAL LETTER M 039C;Mu;GREEK CAPITAL LETTER MU 004E;N;LATIN CAPITAL LETTER N 0143;Nacute;LATIN CAPITAL LETTER N WITH ACUTE 0147;Ncaron;LATIN CAPITAL LETTER N WITH CARON 0145;Ncommaaccent;LATIN CAPITAL LETTER N WITH CEDILLA F76E;Nsmall;LATIN SMALL CAPITAL LETTER N 00D1;Ntilde;LATIN CAPITAL LETTER N WITH TILDE F7F1;Ntildesmall;LATIN SMALL CAPITAL LETTER N WITH TILDE 039D;Nu;GREEK CAPITAL LETTER NU 004F;O;LATIN CAPITAL LETTER O 0152;OE;LATIN CAPITAL LIGATURE OE F6FA;OEsmall;LATIN SMALL CAPITAL LIGATURE OE 00D3;Oacute;LATIN CAPITAL LETTER O WITH ACUTE F7F3;Oacutesmall;LATIN SMALL CAPITAL LETTER O WITH ACUTE 014E;Obreve;LATIN CAPITAL LETTER O WITH BREVE 00D4;Ocircumflex;LATIN CAPITAL LETTER O WITH CIRCUMFLEX F7F4;Ocircumflexsmall;LATIN SMALL CAPITAL LETTER O WITH CIRCUMFLEX 00D6;Odieresis;LATIN CAPITAL LETTER O WITH DIAERESIS F7F6;Odieresissmall;LATIN SMALL CAPITAL LETTER O WITH DIAERESIS F6FB;Ogoneksmall;SMALL CAPITAL OGONEK 00D2;Ograve;LATIN CAPITAL LETTER O WITH GRAVE F7F2;Ogravesmall;LATIN SMALL CAPITAL LETTER O WITH GRAVE 01A0;Ohorn;LATIN CAPITAL LETTER O WITH HORN 0150;Ohungarumlaut;LATIN CAPITAL LETTER O WITH DOUBLE ACUTE 014C;Omacron;LATIN CAPITAL LETTER O WITH MACRON 2126;Omega;OHM SIGN 03A9;Omega;GREEK CAPITAL LETTER OMEGA;Duplicate 038F;Omegatonos;GREEK CAPITAL LETTER OMEGA WITH TONOS 039F;Omicron;GREEK CAPITAL LETTER OMICRON 038C;Omicrontonos;GREEK CAPITAL LETTER OMICRON WITH TONOS 00D8;Oslash;LATIN CAPITAL LETTER O WITH STROKE 01FE;Oslashacute;LATIN CAPITAL LETTER O WITH STROKE AND ACUTE F7F8;Oslashsmall;LATIN SMALL CAPITAL LETTER O WITH STROKE F76F;Osmall;LATIN SMALL CAPITAL LETTER O 00D5;Otilde;LATIN CAPITAL LETTER O WITH TILDE F7F5;Otildesmall;LATIN SMALL CAPITAL LETTER O WITH TILDE 0050;P;LATIN CAPITAL LETTER P 03A6;Phi;GREEK CAPITAL LETTER PHI 03A0;Pi;GREEK CAPITAL LETTER PI 03A8;Psi;GREEK CAPITAL LETTER PSI F770;Psmall;LATIN SMALL CAPITAL LETTER P 0051;Q;LATIN CAPITAL LETTER Q F771;Qsmall;LATIN SMALL CAPITAL LETTER Q 0052;R;LATIN CAPITAL LETTER R 0154;Racute;LATIN CAPITAL LETTER R WITH ACUTE 0158;Rcaron;LATIN CAPITAL LETTER R WITH CARON 0156;Rcommaaccent;LATIN CAPITAL LETTER R WITH CEDILLA 211C;Rfraktur;BLACK-LETTER CAPITAL R 03A1;Rho;GREEK CAPITAL LETTER RHO F6FC;Ringsmall;SMALL CAPITAL RING ABOVE F772;Rsmall;LATIN SMALL CAPITAL LETTER R 0053;S;LATIN CAPITAL LETTER S 250C;SF010000;BOX DRAWINGS LIGHT DOWN AND RIGHT 2514;SF020000;BOX DRAWINGS LIGHT UP AND RIGHT 2510;SF030000;BOX DRAWINGS LIGHT DOWN AND LEFT 2518;SF040000;BOX DRAWINGS LIGHT UP AND LEFT 253C;SF050000;BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL 252C;SF060000;BOX DRAWINGS LIGHT DOWN AND HORIZONTAL 2534;SF070000;BOX DRAWINGS LIGHT UP AND HORIZONTAL 251C;SF080000;BOX DRAWINGS LIGHT VERTICAL AND RIGHT 2524;SF090000;BOX DRAWINGS LIGHT VERTICAL AND LEFT 2500;SF100000;BOX DRAWINGS LIGHT HORIZONTAL 2502;SF110000;BOX DRAWINGS LIGHT VERTICAL 2561;SF190000;BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE 2562;SF200000;BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE 2556;SF210000;BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE 2555;SF220000;BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE 2563;SF230000;BOX DRAWINGS DOUBLE VERTICAL AND LEFT 2551;SF240000;BOX DRAWINGS DOUBLE VERTICAL 2557;SF250000;BOX DRAWINGS DOUBLE DOWN AND LEFT 255D;SF260000;BOX DRAWINGS DOUBLE UP AND LEFT 255C;SF270000;BOX DRAWINGS UP DOUBLE AND LEFT SINGLE 255B;SF280000;BOX DRAWINGS UP SINGLE AND LEFT DOUBLE 255E;SF360000;BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE 255F;SF370000;BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE 255A;SF380000;BOX DRAWINGS DOUBLE UP AND RIGHT 2554;SF390000;BOX DRAWINGS DOUBLE DOWN AND RIGHT 2569;SF400000;BOX DRAWINGS DOUBLE UP AND HORIZONTAL 2566;SF410000;BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL 2560;SF420000;BOX DRAWINGS DOUBLE VERTICAL AND RIGHT 2550;SF430000;BOX DRAWINGS DOUBLE HORIZONTAL 256C;SF440000;BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL 2567;SF450000;BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE 2568;SF460000;BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE 2564;SF470000;BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE 2565;SF480000;BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE 2559;SF490000;BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE 2558;SF500000;BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE 2552;SF510000;BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE 2553;SF520000;BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE 256B;SF530000;BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE 256A;SF540000;BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE 015A;Sacute;LATIN CAPITAL LETTER S WITH ACUTE 0160;Scaron;LATIN CAPITAL LETTER S WITH CARON F6FD;Scaronsmall;LATIN SMALL CAPITAL LETTER S WITH CARON 015E;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA F6C1;Scedilla;LATIN CAPITAL LETTER S WITH CEDILLA;Duplicate 015C;Scircumflex;LATIN CAPITAL LETTER S WITH CIRCUMFLEX 0218;Scommaaccent;LATIN CAPITAL LETTER S WITH COMMA BELOW 03A3;Sigma;GREEK CAPITAL LETTER SIGMA F773;Ssmall;LATIN SMALL CAPITAL LETTER S 0054;T;LATIN CAPITAL LETTER T 03A4;Tau;GREEK CAPITAL LETTER TAU 0166;Tbar;LATIN CAPITAL LETTER T WITH STROKE 0164;Tcaron;LATIN CAPITAL LETTER T WITH CARON 0162;Tcommaaccent;LATIN CAPITAL LETTER T WITH CEDILLA 021A;Tcommaaccent;LATIN CAPITAL LETTER T WITH COMMA BELOW;Duplicate 0398;Theta;GREEK CAPITAL LETTER THETA 00DE;Thorn;LATIN CAPITAL LETTER THORN F7FE;Thornsmall;LATIN SMALL CAPITAL LETTER THORN F6FE;Tildesmall;SMALL CAPITAL SMALL TILDE F774;Tsmall;LATIN SMALL CAPITAL LETTER T 0055;U;LATIN CAPITAL LETTER U 00DA;Uacute;LATIN CAPITAL LETTER U WITH ACUTE F7FA;Uacutesmall;LATIN SMALL CAPITAL LETTER U WITH ACUTE 016C;Ubreve;LATIN CAPITAL LETTER U WITH BREVE 00DB;Ucircumflex;LATIN CAPITAL LETTER U WITH CIRCUMFLEX F7FB;Ucircumflexsmall;LATIN SMALL CAPITAL LETTER U WITH CIRCUMFLEX 00DC;Udieresis;LATIN CAPITAL LETTER U WITH DIAERESIS F7FC;Udieresissmall;LATIN SMALL CAPITAL LETTER U WITH DIAERESIS 00D9;Ugrave;LATIN CAPITAL LETTER U WITH GRAVE F7F9;Ugravesmall;LATIN SMALL CAPITAL LETTER U WITH GRAVE 01AF;Uhorn;LATIN CAPITAL LETTER U WITH HORN 0170;Uhungarumlaut;LATIN CAPITAL LETTER U WITH DOUBLE ACUTE 016A;Umacron;LATIN CAPITAL LETTER U WITH MACRON 0172;Uogonek;LATIN CAPITAL LETTER U WITH OGONEK 03A5;Upsilon;GREEK CAPITAL LETTER UPSILON 03D2;Upsilon1;GREEK UPSILON WITH HOOK SYMBOL 03AB;Upsilondieresis;GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA 038E;Upsilontonos;GREEK CAPITAL LETTER UPSILON WITH TONOS 016E;Uring;LATIN CAPITAL LETTER U WITH RING ABOVE F775;Usmall;LATIN SMALL CAPITAL LETTER U 0168;Utilde;LATIN CAPITAL LETTER U WITH TILDE 0056;V;LATIN CAPITAL LETTER V F776;Vsmall;LATIN SMALL CAPITAL LETTER V 0057;W;LATIN CAPITAL LETTER W 1E82;Wacute;LATIN CAPITAL LETTER W WITH ACUTE 0174;Wcircumflex;LATIN CAPITAL LETTER W WITH CIRCUMFLEX 1E84;Wdieresis;LATIN CAPITAL LETTER W WITH DIAERESIS 1E80;Wgrave;LATIN CAPITAL LETTER W WITH GRAVE F777;Wsmall;LATIN SMALL CAPITAL LETTER W 0058;X;LATIN CAPITAL LETTER X 039E;Xi;GREEK CAPITAL LETTER XI F778;Xsmall;LATIN SMALL CAPITAL LETTER X 0059;Y;LATIN CAPITAL LETTER Y 00DD;Yacute;LATIN CAPITAL LETTER Y WITH ACUTE F7FD;Yacutesmall;LATIN SMALL CAPITAL LETTER Y WITH ACUTE 0176;Ycircumflex;LATIN CAPITAL LETTER Y WITH CIRCUMFLEX 0178;Ydieresis;LATIN CAPITAL LETTER Y WITH DIAERESIS F7FF;Ydieresissmall;LATIN SMALL CAPITAL LETTER Y WITH DIAERESIS 1EF2;Ygrave;LATIN CAPITAL LETTER Y WITH GRAVE F779;Ysmall;LATIN SMALL CAPITAL LETTER Y 005A;Z;LATIN CAPITAL LETTER Z 0179;Zacute;LATIN CAPITAL LETTER Z WITH ACUTE 017D;Zcaron;LATIN CAPITAL LETTER Z WITH CARON F6FF;Zcaronsmall;LATIN SMALL CAPITAL LETTER Z WITH CARON 017B;Zdotaccent;LATIN CAPITAL LETTER Z WITH DOT ABOVE 0396;Zeta;GREEK CAPITAL LETTER ZETA F77A;Zsmall;LATIN SMALL CAPITAL LETTER Z 0061;a;LATIN SMALL LETTER A 00E1;aacute;LATIN SMALL LETTER A WITH ACUTE 0103;abreve;LATIN SMALL LETTER A WITH BREVE 00E2;acircumflex;LATIN SMALL LETTER A WITH CIRCUMFLEX 00B4;acute;ACUTE ACCENT 0301;acutecomb;COMBINING ACUTE ACCENT 00E4;adieresis;LATIN SMALL LETTER A WITH DIAERESIS 00E6;ae;LATIN SMALL LETTER AE 01FD;aeacute;LATIN SMALL LETTER AE WITH ACUTE 2015;afii00208;HORIZONTAL BAR 0410;afii10017;CYRILLIC CAPITAL LETTER A 0411;afii10018;CYRILLIC CAPITAL LETTER BE 0412;afii10019;CYRILLIC CAPITAL LETTER VE 0413;afii10020;CYRILLIC CAPITAL LETTER GHE 0414;afii10021;CYRILLIC CAPITAL LETTER DE 0415;afii10022;CYRILLIC CAPITAL LETTER IE 0401;afii10023;CYRILLIC CAPITAL LETTER IO 0416;afii10024;CYRILLIC CAPITAL LETTER ZHE 0417;afii10025;CYRILLIC CAPITAL LETTER ZE 0418;afii10026;CYRILLIC CAPITAL LETTER I 0419;afii10027;CYRILLIC CAPITAL LETTER SHORT I 041A;afii10028;CYRILLIC CAPITAL LETTER KA 041B;afii10029;CYRILLIC CAPITAL LETTER EL 041C;afii10030;CYRILLIC CAPITAL LETTER EM 041D;afii10031;CYRILLIC CAPITAL LETTER EN 041E;afii10032;CYRILLIC CAPITAL LETTER O 041F;afii10033;CYRILLIC CAPITAL LETTER PE 0420;afii10034;CYRILLIC CAPITAL LETTER ER 0421;afii10035;CYRILLIC CAPITAL LETTER ES 0422;afii10036;CYRILLIC CAPITAL LETTER TE 0423;afii10037;CYRILLIC CAPITAL LETTER U 0424;afii10038;CYRILLIC CAPITAL LETTER EF 0425;afii10039;CYRILLIC CAPITAL LETTER HA 0426;afii10040;CYRILLIC CAPITAL LETTER TSE 0427;afii10041;CYRILLIC CAPITAL LETTER CHE 0428;afii10042;CYRILLIC CAPITAL LETTER SHA 0429;afii10043;CYRILLIC CAPITAL LETTER SHCHA 042A;afii10044;CYRILLIC CAPITAL LETTER HARD SIGN 042B;afii10045;CYRILLIC CAPITAL LETTER YERU 042C;afii10046;CYRILLIC CAPITAL LETTER SOFT SIGN 042D;afii10047;CYRILLIC CAPITAL LETTER E 042E;afii10048;CYRILLIC CAPITAL LETTER YU 042F;afii10049;CYRILLIC CAPITAL LETTER YA 0490;afii10050;CYRILLIC CAPITAL LETTER GHE WITH UPTURN 0402;afii10051;CYRILLIC CAPITAL LETTER DJE 0403;afii10052;CYRILLIC CAPITAL LETTER GJE 0404;afii10053;CYRILLIC CAPITAL LETTER UKRAINIAN IE 0405;afii10054;CYRILLIC CAPITAL LETTER DZE 0406;afii10055;CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I 0407;afii10056;CYRILLIC CAPITAL LETTER YI 0408;afii10057;CYRILLIC CAPITAL LETTER JE 0409;afii10058;CYRILLIC CAPITAL LETTER LJE 040A;afii10059;CYRILLIC CAPITAL LETTER NJE 040B;afii10060;CYRILLIC CAPITAL LETTER TSHE 040C;afii10061;CYRILLIC CAPITAL LETTER KJE 040E;afii10062;CYRILLIC CAPITAL LETTER SHORT U F6C4;afii10063;CYRILLIC SMALL LETTER GHE VARIANT F6C5;afii10064;CYRILLIC SMALL LETTER BE VARIANT 0430;afii10065;CYRILLIC SMALL LETTER A 0431;afii10066;CYRILLIC SMALL LETTER BE 0432;afii10067;CYRILLIC SMALL LETTER VE 0433;afii10068;CYRILLIC SMALL LETTER GHE 0434;afii10069;CYRILLIC SMALL LETTER DE 0435;afii10070;CYRILLIC SMALL LETTER IE 0451;afii10071;CYRILLIC SMALL LETTER IO 0436;afii10072;CYRILLIC SMALL LETTER ZHE 0437;afii10073;CYRILLIC SMALL LETTER ZE 0438;afii10074;CYRILLIC SMALL LETTER I 0439;afii10075;CYRILLIC SMALL LETTER SHORT I 043A;afii10076;CYRILLIC SMALL LETTER KA 043B;afii10077;CYRILLIC SMALL LETTER EL 043C;afii10078;CYRILLIC SMALL LETTER EM 043D;afii10079;CYRILLIC SMALL LETTER EN 043E;afii10080;CYRILLIC SMALL LETTER O 043F;afii10081;CYRILLIC SMALL LETTER PE 0440;afii10082;CYRILLIC SMALL LETTER ER 0441;afii10083;CYRILLIC SMALL LETTER ES 0442;afii10084;CYRILLIC SMALL LETTER TE 0443;afii10085;CYRILLIC SMALL LETTER U 0444;afii10086;CYRILLIC SMALL LETTER EF 0445;afii10087;CYRILLIC SMALL LETTER HA 0446;afii10088;CYRILLIC SMALL LETTER TSE 0447;afii10089;CYRILLIC SMALL LETTER CHE 0448;afii10090;CYRILLIC SMALL LETTER SHA 0449;afii10091;CYRILLIC SMALL LETTER SHCHA 044A;afii10092;CYRILLIC SMALL LETTER HARD SIGN 044B;afii10093;CYRILLIC SMALL LETTER YERU 044C;afii10094;CYRILLIC SMALL LETTER SOFT SIGN 044D;afii10095;CYRILLIC SMALL LETTER E 044E;afii10096;CYRILLIC SMALL LETTER YU 044F;afii10097;CYRILLIC SMALL LETTER YA 0491;afii10098;CYRILLIC SMALL LETTER GHE WITH UPTURN 0452;afii10099;CYRILLIC SMALL LETTER DJE 0453;afii10100;CYRILLIC SMALL LETTER GJE 0454;afii10101;CYRILLIC SMALL LETTER UKRAINIAN IE 0455;afii10102;CYRILLIC SMALL LETTER DZE 0456;afii10103;CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I 0457;afii10104;CYRILLIC SMALL LETTER YI 0458;afii10105;CYRILLIC SMALL LETTER JE 0459;afii10106;CYRILLIC SMALL LETTER LJE 045A;afii10107;CYRILLIC SMALL LETTER NJE 045B;afii10108;CYRILLIC SMALL LETTER TSHE 045C;afii10109;CYRILLIC SMALL LETTER KJE 045E;afii10110;CYRILLIC SMALL LETTER SHORT U 040F;afii10145;CYRILLIC CAPITAL LETTER DZHE 0462;afii10146;CYRILLIC CAPITAL LETTER YAT 0472;afii10147;CYRILLIC CAPITAL LETTER FITA 0474;afii10148;CYRILLIC CAPITAL LETTER IZHITSA F6C6;afii10192;CYRILLIC SMALL LETTER DE VARIANT 045F;afii10193;CYRILLIC SMALL LETTER DZHE 0463;afii10194;CYRILLIC SMALL LETTER YAT 0473;afii10195;CYRILLIC SMALL LETTER FITA 0475;afii10196;CYRILLIC SMALL LETTER IZHITSA F6C7;afii10831;CYRILLIC SMALL LETTER PE VARIANT F6C8;afii10832;CYRILLIC SMALL LETTER TE VARIANT 04D9;afii10846;CYRILLIC SMALL LETTER SCHWA 200E;afii299;LEFT-TO-RIGHT MARK 200F;afii300;RIGHT-TO-LEFT MARK 200D;afii301;ZERO WIDTH JOINER 066A;afii57381;ARABIC PERCENT SIGN 060C;afii57388;ARABIC COMMA 0660;afii57392;ARABIC-INDIC DIGIT ZERO 0661;afii57393;ARABIC-INDIC DIGIT ONE 0662;afii57394;ARABIC-INDIC DIGIT TWO 0663;afii57395;ARABIC-INDIC DIGIT THREE 0664;afii57396;ARABIC-INDIC DIGIT FOUR 0665;afii57397;ARABIC-INDIC DIGIT FIVE 0666;afii57398;ARABIC-INDIC DIGIT SIX 0667;afii57399;ARABIC-INDIC DIGIT SEVEN 0668;afii57400;ARABIC-INDIC DIGIT EIGHT 0669;afii57401;ARABIC-INDIC DIGIT NINE 061B;afii57403;ARABIC SEMICOLON 061F;afii57407;ARABIC QUESTION MARK 0621;afii57409;ARABIC LETTER HAMZA 0622;afii57410;ARABIC LETTER ALEF WITH MADDA ABOVE 0623;afii57411;ARABIC LETTER ALEF WITH HAMZA ABOVE 0624;afii57412;ARABIC LETTER WAW WITH HAMZA ABOVE 0625;afii57413;ARABIC LETTER ALEF WITH HAMZA BELOW 0626;afii57414;ARABIC LETTER YEH WITH HAMZA ABOVE 0627;afii57415;ARABIC LETTER ALEF 0628;afii57416;ARABIC LETTER BEH 0629;afii57417;ARABIC LETTER TEH MARBUTA 062A;afii57418;ARABIC LETTER TEH 062B;afii57419;ARABIC LETTER THEH 062C;afii57420;ARABIC LETTER JEEM 062D;afii57421;ARABIC LETTER HAH 062E;afii57422;ARABIC LETTER KHAH 062F;afii57423;ARABIC LETTER DAL 0630;afii57424;ARABIC LETTER THAL 0631;afii57425;ARABIC LETTER REH 0632;afii57426;ARABIC LETTER ZAIN 0633;afii57427;ARABIC LETTER SEEN 0634;afii57428;ARABIC LETTER SHEEN 0635;afii57429;ARABIC LETTER SAD 0636;afii57430;ARABIC LETTER DAD 0637;afii57431;ARABIC LETTER TAH 0638;afii57432;ARABIC LETTER ZAH 0639;afii57433;ARABIC LETTER AIN 063A;afii57434;ARABIC LETTER GHAIN 0640;afii57440;ARABIC TATWEEL 0641;afii57441;ARABIC LETTER FEH 0642;afii57442;ARABIC LETTER QAF 0643;afii57443;ARABIC LETTER KAF 0644;afii57444;ARABIC LETTER LAM 0645;afii57445;ARABIC LETTER MEEM 0646;afii57446;ARABIC LETTER NOON 0648;afii57448;ARABIC LETTER WAW 0649;afii57449;ARABIC LETTER ALEF MAKSURA 064A;afii57450;ARABIC LETTER YEH 064B;afii57451;ARABIC FATHATAN 064C;afii57452;ARABIC DAMMATAN 064D;afii57453;ARABIC KASRATAN 064E;afii57454;ARABIC FATHA 064F;afii57455;ARABIC DAMMA 0650;afii57456;ARABIC KASRA 0651;afii57457;ARABIC SHADDA 0652;afii57458;ARABIC SUKUN 0647;afii57470;ARABIC LETTER HEH 06A4;afii57505;ARABIC LETTER VEH 067E;afii57506;ARABIC LETTER PEH 0686;afii57507;ARABIC LETTER TCHEH 0698;afii57508;ARABIC LETTER JEH 06AF;afii57509;ARABIC LETTER GAF 0679;afii57511;ARABIC LETTER TTEH 0688;afii57512;ARABIC LETTER DDAL 0691;afii57513;ARABIC LETTER RREH 06BA;afii57514;ARABIC LETTER NOON GHUNNA 06D2;afii57519;ARABIC LETTER YEH BARREE 06D5;afii57534;ARABIC LETTER AE 20AA;afii57636;NEW SHEQEL SIGN 05BE;afii57645;HEBREW PUNCTUATION MAQAF 05C3;afii57658;HEBREW PUNCTUATION SOF PASUQ 05D0;afii57664;HEBREW LETTER ALEF 05D1;afii57665;HEBREW LETTER BET 05D2;afii57666;HEBREW LETTER GIMEL 05D3;afii57667;HEBREW LETTER DALET 05D4;afii57668;HEBREW LETTER HE 05D5;afii57669;HEBREW LETTER VAV 05D6;afii57670;HEBREW LETTER ZAYIN 05D7;afii57671;HEBREW LETTER HET 05D8;afii57672;HEBREW LETTER TET 05D9;afii57673;HEBREW LETTER YOD 05DA;afii57674;HEBREW LETTER FINAL KAF 05DB;afii57675;HEBREW LETTER KAF 05DC;afii57676;HEBREW LETTER LAMED 05DD;afii57677;HEBREW LETTER FINAL MEM 05DE;afii57678;HEBREW LETTER MEM 05DF;afii57679;HEBREW LETTER FINAL NUN 05E0;afii57680;HEBREW LETTER NUN 05E1;afii57681;HEBREW LETTER SAMEKH 05E2;afii57682;HEBREW LETTER AYIN 05E3;afii57683;HEBREW LETTER FINAL PE 05E4;afii57684;HEBREW LETTER PE 05E5;afii57685;HEBREW LETTER FINAL TSADI 05E6;afii57686;HEBREW LETTER TSADI 05E7;afii57687;HEBREW LETTER QOF 05E8;afii57688;HEBREW LETTER RESH 05E9;afii57689;HEBREW LETTER SHIN 05EA;afii57690;HEBREW LETTER TAV FB2A;afii57694;HEBREW LETTER SHIN WITH SHIN DOT FB2B;afii57695;HEBREW LETTER SHIN WITH SIN DOT FB4B;afii57700;HEBREW LETTER VAV WITH HOLAM FB1F;afii57705;HEBREW LIGATURE YIDDISH YOD YOD PATAH 05F0;afii57716;HEBREW LIGATURE YIDDISH DOUBLE VAV 05F1;afii57717;HEBREW LIGATURE YIDDISH VAV YOD 05F2;afii57718;HEBREW LIGATURE YIDDISH DOUBLE YOD FB35;afii57723;HEBREW LETTER VAV WITH DAGESH 05B4;afii57793;HEBREW POINT HIRIQ 05B5;afii57794;HEBREW POINT TSERE 05B6;afii57795;HEBREW POINT SEGOL 05BB;afii57796;HEBREW POINT QUBUTS 05B8;afii57797;HEBREW POINT QAMATS 05B7;afii57798;HEBREW POINT PATAH 05B0;afii57799;HEBREW POINT SHEVA 05B2;afii57800;HEBREW POINT HATAF PATAH 05B1;afii57801;HEBREW POINT HATAF SEGOL 05B3;afii57802;HEBREW POINT HATAF QAMATS 05C2;afii57803;HEBREW POINT SIN DOT 05C1;afii57804;HEBREW POINT SHIN DOT 05B9;afii57806;HEBREW POINT HOLAM 05BC;afii57807;HEBREW POINT DAGESH OR MAPIQ 05BD;afii57839;HEBREW POINT METEG 05BF;afii57841;HEBREW POINT RAFE 05C0;afii57842;HEBREW PUNCTUATION PASEQ 02BC;afii57929;MODIFIER LETTER APOSTROPHE 2105;afii61248;CARE OF 2113;afii61289;SCRIPT SMALL L 2116;afii61352;NUMERO SIGN 202C;afii61573;POP DIRECTIONAL FORMATTING 202D;afii61574;LEFT-TO-RIGHT OVERRIDE 202E;afii61575;RIGHT-TO-LEFT OVERRIDE 200C;afii61664;ZERO WIDTH NON-JOINER 066D;afii63167;ARABIC FIVE POINTED STAR 02BD;afii64937;MODIFIER LETTER REVERSED COMMA 00E0;agrave;LATIN SMALL LETTER A WITH GRAVE 2135;aleph;ALEF SYMBOL 03B1;alpha;GREEK SMALL LETTER ALPHA 03AC;alphatonos;GREEK SMALL LETTER ALPHA WITH TONOS 0101;amacron;LATIN SMALL LETTER A WITH MACRON 0026;ampersand;AMPERSAND F726;ampersandsmall;SMALL CAPITAL AMPERSAND 2220;angle;ANGLE 2329;angleleft;LEFT-POINTING ANGLE BRACKET 232A;angleright;RIGHT-POINTING ANGLE BRACKET 0387;anoteleia;GREEK ANO TELEIA 0105;aogonek;LATIN SMALL LETTER A WITH OGONEK 2248;approxequal;ALMOST EQUAL TO 00E5;aring;LATIN SMALL LETTER A WITH RING ABOVE 01FB;aringacute;LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE 2194;arrowboth;LEFT RIGHT ARROW 21D4;arrowdblboth;LEFT RIGHT DOUBLE ARROW 21D3;arrowdbldown;DOWNWARDS DOUBLE ARROW 21D0;arrowdblleft;LEFTWARDS DOUBLE ARROW 21D2;arrowdblright;RIGHTWARDS DOUBLE ARROW 21D1;arrowdblup;UPWARDS DOUBLE ARROW 2193;arrowdown;DOWNWARDS ARROW F8E7;arrowhorizex;HORIZONTAL ARROW EXTENDER 2190;arrowleft;LEFTWARDS ARROW 2192;arrowright;RIGHTWARDS ARROW 2191;arrowup;UPWARDS ARROW 2195;arrowupdn;UP DOWN ARROW 21A8;arrowupdnbse;UP DOWN ARROW WITH BASE F8E6;arrowvertex;VERTICAL ARROW EXTENDER 005E;asciicircum;CIRCUMFLEX ACCENT 007E;asciitilde;TILDE 002A;asterisk;ASTERISK 2217;asteriskmath;ASTERISK OPERATOR F6E9;asuperior;SUPERSCRIPT LATIN SMALL LETTER A 0040;at;COMMERCIAL AT 00E3;atilde;LATIN SMALL LETTER A WITH TILDE 0062;b;LATIN SMALL LETTER B 005C;backslash;REVERSE SOLIDUS 007C;bar;VERTICAL LINE 03B2;beta;GREEK SMALL LETTER BETA 2588;block;FULL BLOCK F8F4;braceex;CURLY BRACKET EXTENDER 007B;braceleft;LEFT CURLY BRACKET F8F3;braceleftbt;LEFT CURLY BRACKET BOTTOM F8F2;braceleftmid;LEFT CURLY BRACKET MID F8F1;bracelefttp;LEFT CURLY BRACKET TOP 007D;braceright;RIGHT CURLY BRACKET F8FE;bracerightbt;RIGHT CURLY BRACKET BOTTOM F8FD;bracerightmid;RIGHT CURLY BRACKET MID F8FC;bracerighttp;RIGHT CURLY BRACKET TOP 005B;bracketleft;LEFT SQUARE BRACKET F8F0;bracketleftbt;LEFT SQUARE BRACKET BOTTOM F8EF;bracketleftex;LEFT SQUARE BRACKET EXTENDER F8EE;bracketlefttp;LEFT SQUARE BRACKET TOP 005D;bracketright;RIGHT SQUARE BRACKET F8FB;bracketrightbt;RIGHT SQUARE BRACKET BOTTOM F8FA;bracketrightex;RIGHT SQUARE BRACKET EXTENDER F8F9;bracketrighttp;RIGHT SQUARE BRACKET TOP 02D8;breve;BREVE 00A6;brokenbar;BROKEN BAR F6EA;bsuperior;SUPERSCRIPT LATIN SMALL LETTER B 2022;bullet;BULLET 0063;c;LATIN SMALL LETTER C 0107;cacute;LATIN SMALL LETTER C WITH ACUTE 02C7;caron;CARON 21B5;carriagereturn;DOWNWARDS ARROW WITH CORNER LEFTWARDS 010D;ccaron;LATIN SMALL LETTER C WITH CARON 00E7;ccedilla;LATIN SMALL LETTER C WITH CEDILLA 0109;ccircumflex;LATIN SMALL LETTER C WITH CIRCUMFLEX 010B;cdotaccent;LATIN SMALL LETTER C WITH DOT ABOVE 00B8;cedilla;CEDILLA 00A2;cent;CENT SIGN F6DF;centinferior;SUBSCRIPT CENT SIGN F7A2;centoldstyle;OLDSTYLE CENT SIGN F6E0;centsuperior;SUPERSCRIPT CENT SIGN 03C7;chi;GREEK SMALL LETTER CHI 25CB;circle;WHITE CIRCLE 2297;circlemultiply;CIRCLED TIMES 2295;circleplus;CIRCLED PLUS 02C6;circumflex;MODIFIER LETTER CIRCUMFLEX ACCENT 2663;club;BLACK CLUB SUIT 003A;colon;COLON 20A1;colonmonetary;COLON SIGN 002C;comma;COMMA F6C3;commaaccent;COMMA BELOW F6E1;commainferior;SUBSCRIPT COMMA F6E2;commasuperior;SUPERSCRIPT COMMA 2245;congruent;APPROXIMATELY EQUAL TO 00A9;copyright;COPYRIGHT SIGN F8E9;copyrightsans;COPYRIGHT SIGN SANS SERIF F6D9;copyrightserif;COPYRIGHT SIGN SERIF 00A4;currency;CURRENCY SIGN F6D1;cyrBreve;CAPITAL CYRILLIC BREVE F6D2;cyrFlex;CAPITAL CYRILLIC CIRCUMFLEX F6D4;cyrbreve;CYRILLIC BREVE F6D5;cyrflex;CYRILLIC CIRCUMFLEX 0064;d;LATIN SMALL LETTER D 2020;dagger;DAGGER 2021;daggerdbl;DOUBLE DAGGER F6D3;dblGrave;CAPITAL DOUBLE GRAVE ACCENT F6D6;dblgrave;DOUBLE GRAVE ACCENT 010F;dcaron;LATIN SMALL LETTER D WITH CARON 0111;dcroat;LATIN SMALL LETTER D WITH STROKE 00B0;degree;DEGREE SIGN 03B4;delta;GREEK SMALL LETTER DELTA 2666;diamond;BLACK DIAMOND SUIT 00A8;dieresis;DIAERESIS F6D7;dieresisacute;DIAERESIS ACUTE ACCENT F6D8;dieresisgrave;DIAERESIS GRAVE ACCENT 0385;dieresistonos;GREEK DIALYTIKA TONOS 00F7;divide;DIVISION SIGN 2593;dkshade;DARK SHADE 2584;dnblock;LOWER HALF BLOCK 0024;dollar;DOLLAR SIGN F6E3;dollarinferior;SUBSCRIPT DOLLAR SIGN F724;dollaroldstyle;OLDSTYLE DOLLAR SIGN F6E4;dollarsuperior;SUPERSCRIPT DOLLAR SIGN 20AB;dong;DONG SIGN 02D9;dotaccent;DOT ABOVE 0323;dotbelowcomb;COMBINING DOT BELOW 0131;dotlessi;LATIN SMALL LETTER DOTLESS I F6BE;dotlessj;LATIN SMALL LETTER DOTLESS J 22C5;dotmath;DOT OPERATOR F6EB;dsuperior;SUPERSCRIPT LATIN SMALL LETTER D 0065;e;LATIN SMALL LETTER E 00E9;eacute;LATIN SMALL LETTER E WITH ACUTE 0115;ebreve;LATIN SMALL LETTER E WITH BREVE 011B;ecaron;LATIN SMALL LETTER E WITH CARON 00EA;ecircumflex;LATIN SMALL LETTER E WITH CIRCUMFLEX 00EB;edieresis;LATIN SMALL LETTER E WITH DIAERESIS 0117;edotaccent;LATIN SMALL LETTER E WITH DOT ABOVE 00E8;egrave;LATIN SMALL LETTER E WITH GRAVE 0038;eight;DIGIT EIGHT 2088;eightinferior;SUBSCRIPT EIGHT F738;eightoldstyle;OLDSTYLE DIGIT EIGHT 2078;eightsuperior;SUPERSCRIPT EIGHT 2208;element;ELEMENT OF 2026;ellipsis;HORIZONTAL ELLIPSIS 0113;emacron;LATIN SMALL LETTER E WITH MACRON 2014;emdash;EM DASH 2205;emptyset;EMPTY SET 2013;endash;EN DASH 014B;eng;LATIN SMALL LETTER ENG 0119;eogonek;LATIN SMALL LETTER E WITH OGONEK 03B5;epsilon;GREEK SMALL LETTER EPSILON 03AD;epsilontonos;GREEK SMALL LETTER EPSILON WITH TONOS 003D;equal;EQUALS SIGN 2261;equivalence;IDENTICAL TO 212E;estimated;ESTIMATED SYMBOL F6EC;esuperior;SUPERSCRIPT LATIN SMALL LETTER E 03B7;eta;GREEK SMALL LETTER ETA 03AE;etatonos;GREEK SMALL LETTER ETA WITH TONOS 00F0;eth;LATIN SMALL LETTER ETH 0021;exclam;EXCLAMATION MARK 203C;exclamdbl;DOUBLE EXCLAMATION MARK 00A1;exclamdown;INVERTED EXCLAMATION MARK F7A1;exclamdownsmall;SMALL CAPITAL INVERTED EXCLAMATION MARK F721;exclamsmall;SMALL CAPITAL EXCLAMATION MARK 2203;existential;THERE EXISTS 0066;f;LATIN SMALL LETTER F 2640;female;FEMALE SIGN FB00;ff;LATIN SMALL LIGATURE FF FB03;ffi;LATIN SMALL LIGATURE FFI FB04;ffl;LATIN SMALL LIGATURE FFL FB01;fi;LATIN SMALL LIGATURE FI 2012;figuredash;FIGURE DASH 25A0;filledbox;BLACK SQUARE 25AC;filledrect;BLACK RECTANGLE 0035;five;DIGIT FIVE 215D;fiveeighths;VULGAR FRACTION FIVE EIGHTHS 2085;fiveinferior;SUBSCRIPT FIVE F735;fiveoldstyle;OLDSTYLE DIGIT FIVE 2075;fivesuperior;SUPERSCRIPT FIVE FB02;fl;LATIN SMALL LIGATURE FL 0192;florin;LATIN SMALL LETTER F WITH HOOK 0034;four;DIGIT FOUR 2084;fourinferior;SUBSCRIPT FOUR F734;fouroldstyle;OLDSTYLE DIGIT FOUR 2074;foursuperior;SUPERSCRIPT FOUR 2044;fraction;FRACTION SLASH 2215;fraction;DIVISION SLASH;Duplicate 20A3;franc;FRENCH FRANC SIGN 0067;g;LATIN SMALL LETTER G 03B3;gamma;GREEK SMALL LETTER GAMMA 011F;gbreve;LATIN SMALL LETTER G WITH BREVE 01E7;gcaron;LATIN SMALL LETTER G WITH CARON 011D;gcircumflex;LATIN SMALL LETTER G WITH CIRCUMFLEX 0123;gcommaaccent;LATIN SMALL LETTER G WITH CEDILLA 0121;gdotaccent;LATIN SMALL LETTER G WITH DOT ABOVE 00DF;germandbls;LATIN SMALL LETTER SHARP S 2207;gradient;NABLA 0060;grave;GRAVE ACCENT 0300;gravecomb;COMBINING GRAVE ACCENT 003E;greater;GREATER-THAN SIGN 2265;greaterequal;GREATER-THAN OR EQUAL TO 00AB;guillemotleft;LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 00BB;guillemotright;RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 2039;guilsinglleft;SINGLE LEFT-POINTING ANGLE QUOTATION MARK 203A;guilsinglright;SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 0068;h;LATIN SMALL LETTER H 0127;hbar;LATIN SMALL LETTER H WITH STROKE 0125;hcircumflex;LATIN SMALL LETTER H WITH CIRCUMFLEX 2665;heart;BLACK HEART SUIT 0309;hookabovecomb;COMBINING HOOK ABOVE 2302;house;HOUSE 02DD;hungarumlaut;DOUBLE ACUTE ACCENT 002D;hyphen;HYPHEN-MINUS 00AD;hyphen;SOFT HYPHEN;Duplicate F6E5;hypheninferior;SUBSCRIPT HYPHEN-MINUS F6E6;hyphensuperior;SUPERSCRIPT HYPHEN-MINUS 0069;i;LATIN SMALL LETTER I 00ED;iacute;LATIN SMALL LETTER I WITH ACUTE 012D;ibreve;LATIN SMALL LETTER I WITH BREVE 00EE;icircumflex;LATIN SMALL LETTER I WITH CIRCUMFLEX 00EF;idieresis;LATIN SMALL LETTER I WITH DIAERESIS 00EC;igrave;LATIN SMALL LETTER I WITH GRAVE 0133;ij;LATIN SMALL LIGATURE IJ 012B;imacron;LATIN SMALL LETTER I WITH MACRON 221E;infinity;INFINITY 222B;integral;INTEGRAL 2321;integralbt;BOTTOM HALF INTEGRAL F8F5;integralex;INTEGRAL EXTENDER 2320;integraltp;TOP HALF INTEGRAL 2229;intersection;INTERSECTION 25D8;invbullet;INVERSE BULLET 25D9;invcircle;INVERSE WHITE CIRCLE 263B;invsmileface;BLACK SMILING FACE 012F;iogonek;LATIN SMALL LETTER I WITH OGONEK 03B9;iota;GREEK SMALL LETTER IOTA 03CA;iotadieresis;GREEK SMALL LETTER IOTA WITH DIALYTIKA 0390;iotadieresistonos;GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS 03AF;iotatonos;GREEK SMALL LETTER IOTA WITH TONOS F6ED;isuperior;SUPERSCRIPT LATIN SMALL LETTER I 0129;itilde;LATIN SMALL LETTER I WITH TILDE 006A;j;LATIN SMALL LETTER J 0135;jcircumflex;LATIN SMALL LETTER J WITH CIRCUMFLEX 006B;k;LATIN SMALL LETTER K 03BA;kappa;GREEK SMALL LETTER KAPPA 0137;kcommaaccent;LATIN SMALL LETTER K WITH CEDILLA 0138;kgreenlandic;LATIN SMALL LETTER KRA 006C;l;LATIN SMALL LETTER L 013A;lacute;LATIN SMALL LETTER L WITH ACUTE 03BB;lambda;GREEK SMALL LETTER LAMDA 013E;lcaron;LATIN SMALL LETTER L WITH CARON 013C;lcommaaccent;LATIN SMALL LETTER L WITH CEDILLA 0140;ldot;LATIN SMALL LETTER L WITH MIDDLE DOT 003C;less;LESS-THAN SIGN 2264;lessequal;LESS-THAN OR EQUAL TO 258C;lfblock;LEFT HALF BLOCK 20A4;lira;LIRA SIGN F6C0;ll;LATIN SMALL LETTER LL 2227;logicaland;LOGICAL AND 00AC;logicalnot;NOT SIGN 2228;logicalor;LOGICAL OR 017F;longs;LATIN SMALL LETTER LONG S 25CA;lozenge;LOZENGE 0142;lslash;LATIN SMALL LETTER L WITH STROKE F6EE;lsuperior;SUPERSCRIPT LATIN SMALL LETTER L 2591;ltshade;LIGHT SHADE 006D;m;LATIN SMALL LETTER M 00AF;macron;MACRON 02C9;macron;MODIFIER LETTER MACRON;Duplicate 2642;male;MALE SIGN 2212;minus;MINUS SIGN 2032;minute;PRIME F6EF;msuperior;SUPERSCRIPT LATIN SMALL LETTER M 00B5;mu;MICRO SIGN 03BC;mu;GREEK SMALL LETTER MU;Duplicate 00D7;multiply;MULTIPLICATION SIGN 266A;musicalnote;EIGHTH NOTE 266B;musicalnotedbl;BEAMED EIGHTH NOTES 006E;n;LATIN SMALL LETTER N 0144;nacute;LATIN SMALL LETTER N WITH ACUTE 0149;napostrophe;LATIN SMALL LETTER N PRECEDED BY APOSTROPHE 0148;ncaron;LATIN SMALL LETTER N WITH CARON 0146;ncommaaccent;LATIN SMALL LETTER N WITH CEDILLA 0039;nine;DIGIT NINE 2089;nineinferior;SUBSCRIPT NINE F739;nineoldstyle;OLDSTYLE DIGIT NINE 2079;ninesuperior;SUPERSCRIPT NINE 2209;notelement;NOT AN ELEMENT OF 2260;notequal;NOT EQUAL TO 2284;notsubset;NOT A SUBSET OF 207F;nsuperior;SUPERSCRIPT LATIN SMALL LETTER N 00F1;ntilde;LATIN SMALL LETTER N WITH TILDE 03BD;nu;GREEK SMALL LETTER NU 0023;numbersign;NUMBER SIGN 006F;o;LATIN SMALL LETTER O 00F3;oacute;LATIN SMALL LETTER O WITH ACUTE 014F;obreve;LATIN SMALL LETTER O WITH BREVE 00F4;ocircumflex;LATIN SMALL LETTER O WITH CIRCUMFLEX 00F6;odieresis;LATIN SMALL LETTER O WITH DIAERESIS 0153;oe;LATIN SMALL LIGATURE OE 02DB;ogonek;OGONEK 00F2;ograve;LATIN SMALL LETTER O WITH GRAVE 01A1;ohorn;LATIN SMALL LETTER O WITH HORN 0151;ohungarumlaut;LATIN SMALL LETTER O WITH DOUBLE ACUTE 014D;omacron;LATIN SMALL LETTER O WITH MACRON 03C9;omega;GREEK SMALL LETTER OMEGA 03D6;omega1;GREEK PI SYMBOL 03CE;omegatonos;GREEK SMALL LETTER OMEGA WITH TONOS 03BF;omicron;GREEK SMALL LETTER OMICRON 03CC;omicrontonos;GREEK SMALL LETTER OMICRON WITH TONOS 0031;one;DIGIT ONE 2024;onedotenleader;ONE DOT LEADER 215B;oneeighth;VULGAR FRACTION ONE EIGHTH F6DC;onefitted;PROPORTIONAL DIGIT ONE 00BD;onehalf;VULGAR FRACTION ONE HALF 2081;oneinferior;SUBSCRIPT ONE F731;oneoldstyle;OLDSTYLE DIGIT ONE 00BC;onequarter;VULGAR FRACTION ONE QUARTER 00B9;onesuperior;SUPERSCRIPT ONE 2153;onethird;VULGAR FRACTION ONE THIRD 25E6;openbullet;WHITE BULLET 00AA;ordfeminine;FEMININE ORDINAL INDICATOR 00BA;ordmasculine;MASCULINE ORDINAL INDICATOR 221F;orthogonal;RIGHT ANGLE 00F8;oslash;LATIN SMALL LETTER O WITH STROKE 01FF;oslashacute;LATIN SMALL LETTER O WITH STROKE AND ACUTE F6F0;osuperior;SUPERSCRIPT LATIN SMALL LETTER O 00F5;otilde;LATIN SMALL LETTER O WITH TILDE 0070;p;LATIN SMALL LETTER P 00B6;paragraph;PILCROW SIGN 0028;parenleft;LEFT PARENTHESIS F8ED;parenleftbt;LEFT PAREN BOTTOM F8EC;parenleftex;LEFT PAREN EXTENDER 208D;parenleftinferior;SUBSCRIPT LEFT PARENTHESIS 207D;parenleftsuperior;SUPERSCRIPT LEFT PARENTHESIS F8EB;parenlefttp;LEFT PAREN TOP 0029;parenright;RIGHT PARENTHESIS F8F8;parenrightbt;RIGHT PAREN BOTTOM F8F7;parenrightex;RIGHT PAREN EXTENDER 208E;parenrightinferior;SUBSCRIPT RIGHT PARENTHESIS 207E;parenrightsuperior;SUPERSCRIPT RIGHT PARENTHESIS F8F6;parenrighttp;RIGHT PAREN TOP 2202;partialdiff;PARTIAL DIFFERENTIAL 0025;percent;PERCENT SIGN 002E;period;FULL STOP 00B7;periodcentered;MIDDLE DOT 2219;periodcentered;BULLET OPERATOR;Duplicate F6E7;periodinferior;SUBSCRIPT FULL STOP F6E8;periodsuperior;SUPERSCRIPT FULL STOP 22A5;perpendicular;UP TACK 2030;perthousand;PER MILLE SIGN 20A7;peseta;PESETA SIGN 03C6;phi;GREEK SMALL LETTER PHI 03D5;phi1;GREEK PHI SYMBOL 03C0;pi;GREEK SMALL LETTER PI 002B;plus;PLUS SIGN 00B1;plusminus;PLUS-MINUS SIGN 211E;prescription;PRESCRIPTION TAKE 220F;product;N-ARY PRODUCT 2282;propersubset;SUBSET OF 2283;propersuperset;SUPERSET OF 221D;proportional;PROPORTIONAL TO 03C8;psi;GREEK SMALL LETTER PSI 0071;q;LATIN SMALL LETTER Q 003F;question;QUESTION MARK 00BF;questiondown;INVERTED QUESTION MARK F7BF;questiondownsmall;SMALL CAPITAL INVERTED QUESTION MARK F73F;questionsmall;SMALL CAPITAL QUESTION MARK 0022;quotedbl;QUOTATION MARK 201E;quotedblbase;DOUBLE LOW-9 QUOTATION MARK 201C;quotedblleft;LEFT DOUBLE QUOTATION MARK 201D;quotedblright;RIGHT DOUBLE QUOTATION MARK 2018;quoteleft;LEFT SINGLE QUOTATION MARK 201B;quotereversed;SINGLE HIGH-REVERSED-9 QUOTATION MARK 2019;quoteright;RIGHT SINGLE QUOTATION MARK 201A;quotesinglbase;SINGLE LOW-9 QUOTATION MARK 0027;quotesingle;APOSTROPHE 0072;r;LATIN SMALL LETTER R 0155;racute;LATIN SMALL LETTER R WITH ACUTE 221A;radical;SQUARE ROOT F8E5;radicalex;RADICAL EXTENDER 0159;rcaron;LATIN SMALL LETTER R WITH CARON 0157;rcommaaccent;LATIN SMALL LETTER R WITH CEDILLA 2286;reflexsubset;SUBSET OF OR EQUAL TO 2287;reflexsuperset;SUPERSET OF OR EQUAL TO 00AE;registered;REGISTERED SIGN F8E8;registersans;REGISTERED SIGN SANS SERIF F6DA;registerserif;REGISTERED SIGN SERIF 2310;revlogicalnot;REVERSED NOT SIGN 03C1;rho;GREEK SMALL LETTER RHO 02DA;ring;RING ABOVE F6F1;rsuperior;SUPERSCRIPT LATIN SMALL LETTER R 2590;rtblock;RIGHT HALF BLOCK F6DD;rupiah;RUPIAH SIGN 0073;s;LATIN SMALL LETTER S 015B;sacute;LATIN SMALL LETTER S WITH ACUTE 0161;scaron;LATIN SMALL LETTER S WITH CARON 015F;scedilla;LATIN SMALL LETTER S WITH CEDILLA F6C2;scedilla;LATIN SMALL LETTER S WITH CEDILLA;Duplicate 015D;scircumflex;LATIN SMALL LETTER S WITH CIRCUMFLEX 0219;scommaaccent;LATIN SMALL LETTER S WITH COMMA BELOW 2033;second;DOUBLE PRIME 00A7;section;SECTION SIGN 003B;semicolon;SEMICOLON 0037;seven;DIGIT SEVEN 215E;seveneighths;VULGAR FRACTION SEVEN EIGHTHS 2087;seveninferior;SUBSCRIPT SEVEN F737;sevenoldstyle;OLDSTYLE DIGIT SEVEN 2077;sevensuperior;SUPERSCRIPT SEVEN 2592;shade;MEDIUM SHADE 03C3;sigma;GREEK SMALL LETTER SIGMA 03C2;sigma1;GREEK SMALL LETTER FINAL SIGMA 223C;similar;TILDE OPERATOR 0036;six;DIGIT SIX 2086;sixinferior;SUBSCRIPT SIX F736;sixoldstyle;OLDSTYLE DIGIT SIX 2076;sixsuperior;SUPERSCRIPT SIX 002F;slash;SOLIDUS 263A;smileface;WHITE SMILING FACE 0020;space;SPACE 00A0;space;NO-BREAK SPACE;Duplicate 2660;spade;BLACK SPADE SUIT F6F2;ssuperior;SUPERSCRIPT LATIN SMALL LETTER S 00A3;sterling;POUND SIGN 220B;suchthat;CONTAINS AS MEMBER 2211;summation;N-ARY SUMMATION 263C;sun;WHITE SUN WITH RAYS 0074;t;LATIN SMALL LETTER T 03C4;tau;GREEK SMALL LETTER TAU 0167;tbar;LATIN SMALL LETTER T WITH STROKE 0165;tcaron;LATIN SMALL LETTER T WITH CARON 0163;tcommaaccent;LATIN SMALL LETTER T WITH CEDILLA 021B;tcommaaccent;LATIN SMALL LETTER T WITH COMMA BELOW;Duplicate 2234;therefore;THEREFORE 03B8;theta;GREEK SMALL LETTER THETA 03D1;theta1;GREEK THETA SYMBOL 00FE;thorn;LATIN SMALL LETTER THORN 0033;three;DIGIT THREE 215C;threeeighths;VULGAR FRACTION THREE EIGHTHS 2083;threeinferior;SUBSCRIPT THREE F733;threeoldstyle;OLDSTYLE DIGIT THREE 00BE;threequarters;VULGAR FRACTION THREE QUARTERS F6DE;threequartersemdash;THREE QUARTERS EM DASH 00B3;threesuperior;SUPERSCRIPT THREE 02DC;tilde;SMALL TILDE 0303;tildecomb;COMBINING TILDE 0384;tonos;GREEK TONOS 2122;trademark;TRADE MARK SIGN F8EA;trademarksans;TRADE MARK SIGN SANS SERIF F6DB;trademarkserif;TRADE MARK SIGN SERIF 25BC;triagdn;BLACK DOWN-POINTING TRIANGLE 25C4;triaglf;BLACK LEFT-POINTING POINTER 25BA;triagrt;BLACK RIGHT-POINTING POINTER 25B2;triagup;BLACK UP-POINTING TRIANGLE F6F3;tsuperior;SUPERSCRIPT LATIN SMALL LETTER T 0032;two;DIGIT TWO 2025;twodotenleader;TWO DOT LEADER 2082;twoinferior;SUBSCRIPT TWO F732;twooldstyle;OLDSTYLE DIGIT TWO 00B2;twosuperior;SUPERSCRIPT TWO 2154;twothirds;VULGAR FRACTION TWO THIRDS 0075;u;LATIN SMALL LETTER U 00FA;uacute;LATIN SMALL LETTER U WITH ACUTE 016D;ubreve;LATIN SMALL LETTER U WITH BREVE 00FB;ucircumflex;LATIN SMALL LETTER U WITH CIRCUMFLEX 00FC;udieresis;LATIN SMALL LETTER U WITH DIAERESIS 00F9;ugrave;LATIN SMALL LETTER U WITH GRAVE 01B0;uhorn;LATIN SMALL LETTER U WITH HORN 0171;uhungarumlaut;LATIN SMALL LETTER U WITH DOUBLE ACUTE 016B;umacron;LATIN SMALL LETTER U WITH MACRON 005F;underscore;LOW LINE 2017;underscoredbl;DOUBLE LOW LINE 222A;union;UNION 2200;universal;FOR ALL 0173;uogonek;LATIN SMALL LETTER U WITH OGONEK 2580;upblock;UPPER HALF BLOCK 03C5;upsilon;GREEK SMALL LETTER UPSILON 03CB;upsilondieresis;GREEK SMALL LETTER UPSILON WITH DIALYTIKA 03B0;upsilondieresistonos;GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS 03CD;upsilontonos;GREEK SMALL LETTER UPSILON WITH TONOS 016F;uring;LATIN SMALL LETTER U WITH RING ABOVE 0169;utilde;LATIN SMALL LETTER U WITH TILDE 0076;v;LATIN SMALL LETTER V 0077;w;LATIN SMALL LETTER W 1E83;wacute;LATIN SMALL LETTER W WITH ACUTE 0175;wcircumflex;LATIN SMALL LETTER W WITH CIRCUMFLEX 1E85;wdieresis;LATIN SMALL LETTER W WITH DIAERESIS 2118;weierstrass;SCRIPT CAPITAL P 1E81;wgrave;LATIN SMALL LETTER W WITH GRAVE 0078;x;LATIN SMALL LETTER X 03BE;xi;GREEK SMALL LETTER XI 0079;y;LATIN SMALL LETTER Y 00FD;yacute;LATIN SMALL LETTER Y WITH ACUTE 0177;ycircumflex;LATIN SMALL LETTER Y WITH CIRCUMFLEX 00FF;ydieresis;LATIN SMALL LETTER Y WITH DIAERESIS 00A5;yen;YEN SIGN 1EF3;ygrave;LATIN SMALL LETTER Y WITH GRAVE 007A;z;LATIN SMALL LETTER Z 017A;zacute;LATIN SMALL LETTER Z WITH ACUTE 017E;zcaron;LATIN SMALL LETTER Z WITH CARON 017C;zdotaccent;LATIN SMALL LETTER Z WITH DOT ABOVE 0030;zero;DIGIT ZERO 2080;zeroinferior;SUBSCRIPT ZERO F730;zerooldstyle;OLDSTYLE DIGIT ZERO 2070;zerosuperior;SUPERSCRIPT ZERO 03B6;zeta;GREEK SMALL LETTER ZETA # # Name: ITC Zapf Dingbats encoding, Unicode values, and # glyph names # Table version: 1.0 # Date: 17 July 1997 # # Version of ITC Zapf Dingbats: # # ITC Zapf Dingbats (PostScript FontName: ZapfDingbats) contains 202 # of the 379 glyphs in PCL Zapf Dingbats. # # Versions of ZapfDingbats previous to 002.000 do not encode 14 out of the # 202 available glyphs in their PostScript encoding (though these 14 glyphs # can be accessed on the Macintosh due to the FOND's reencoding of the # glyphs). ZapfDingbats version 002.000 encodes all of the 202 glyphs in its # PostScript encoding. # # Unicode encoding of ZapfDingbats: # # The 188 glyphs in the PostScript encoding of versions of ZapfDingbats # previous to 002.000 have regular Unicode values (160 in the Dingbats block # and 28 in other blocks). The remaining 14 glyphs have been assigned # Unicode values in the Corporate Use subarea, and coincide exactly with # Apple's MacOS Dingbats assignments in that area. # # Format: Four tab-separated columns: # # (1) The PostScript encoding. (2 uppercase hexadecimal digits) # 202 code points are defined. # Source: Adobe Systems. # # (2) The Unicode value. (4 uppercase hexadecimal digits) # The 14 glyphs at code points 0x80-8D have Corporate Use subarea # values. # Source: ftp://unicode.org/pub/UNIX/MAPPINGS/VENDORS/APPLE/DINGBAT.TXT # [as of 25 February 1997] # # (3) The glyph name. (upper- and lowercase letters, digits) # Source: Adobe Systems. # # (4) The Unicode 2.0 character name. (uppercase letters, hyphen, space) # Source: The Unicode Standard, Version 2.0 # # The 14 Corporate Use subarea glyphs obviously don't have a # Unicode 2.0 character name. A descriptive name (in lowercase # letters) taken from the source for (2) above is used instead. # # The entries are in PostScript encoding order. # # Lines starting with "#" are comments; blank lines are to be ignored. # 0020;space;SPACE 2701;a1;UPPER BLADE SCISSORS 2702;a2;BLACK SCISSORS 2703;a202;LOWER BLADE SCISSORS 2704;a3;WHITE SCISSORS 260E;a4;BLACK TELEPHONE 2706;a5;TELEPHONE LOCATION SIGN 2707;a119;TAPE DRIVE 2708;a118;AIRPLANE 2709;a117;ENVELOPE 261B;a11;BLACK RIGHT POINTING INDEX 261E;a12;WHITE RIGHT POINTING INDEX 270C;a13;VICTORY HAND 270D;a14;WRITING HAND 270E;a15;LOWER RIGHT PENCIL 270F;a16;PENCIL 2710;a105;UPPER RIGHT PENCIL 2711;a17;WHITE NIB 2712;a18;BLACK NIB 2713;a19;CHECK MARK 2714;a20;HEAVY CHECK MARK 2715;a21;MULTIPLICATION X 2716;a22;HEAVY MULTIPLICATION X 2717;a23;BALLOT X 2718;a24;HEAVY BALLOT X 2719;a25;OUTLINED GREEK CROSS 271A;a26;HEAVY GREEK CROSS 271B;a27;OPEN CENTRE CROSS 271C;a28;HEAVY OPEN CENTRE CROSS 271D;a6;LATIN CROSS 271E;a7;SHADOWED WHITE LATIN CROSS 271F;a8;OUTLINED LATIN CROSS 2720;a9;MALTESE CROSS 2721;a10;STAR OF DAVID 2722;a29;FOUR TEARDROP-SPOKED ASTERISK 2723;a30;FOUR BALLOON-SPOKED ASTERISK 2724;a31;HEAVY FOUR BALLOON-SPOKED ASTERISK 2725;a32;FOUR CLUB-SPOKED ASTERISK 2726;a33;BLACK FOUR POINTED STAR 2727;a34;WHITE FOUR POINTED STAR 2605;a35;BLACK STAR 2729;a36;STRESS OUTLINED WHITE STAR 272A;a37;CIRCLED WHITE STAR 272B;a38;OPEN CENTRE BLACK STAR 272C;a39;BLACK CENTRE WHITE STAR 272D;a40;OUTLINED BLACK STAR 272E;a41;HEAVY OUTLINED BLACK STAR 272F;a42;PINWHEEL STAR 2730;a43;SHADOWED WHITE STAR 2731;a44;HEAVY ASTERISK 2732;a45;OPEN CENTRE ASTERISK 2733;a46;EIGHT SPOKED ASTERISK 2734;a47;EIGHT POINTED BLACK STAR 2735;a48;EIGHT POINTED PINWHEEL STAR 2736;a49;SIX POINTED BLACK STAR 2737;a50;EIGHT POINTED RECTILINEAR BLACK STAR 2738;a51;HEAVY EIGHT POINTED RECTILINEAR BLACK STAR 2739;a52;TWELVE POINTED BLACK STAR 273A;a53;SIXTEEN POINTED ASTERISK 273B;a54;TEARDROP-SPOKED ASTERISK 273C;a55;OPEN CENTRE TEARDROP-SPOKED ASTERISK 273D;a56;HEAVY TEARDROP-SPOKED ASTERISK 273E;a57;SIX PETALLED BLACK AND WHITE FLORETTE 273F;a58;BLACK FLORETTE 2740;a59;WHITE FLORETTE 2741;a60;EIGHT PETALLED OUTLINED BLACK FLORETTE 2742;a61;CIRCLED OPEN CENTRE EIGHT POINTED STAR 2743;a62;HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK 2744;a63;SNOWFLAKE 2745;a64;TIGHT TRIFOLIATE SNOWFLAKE 2746;a65;HEAVY CHEVRON SNOWFLAKE 2747;a66;SPARKLE 2748;a67;HEAVY SPARKLE 2749;a68;BALLOON-SPOKED ASTERISK 274A;a69;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK 274B;a70;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK 25CF;a71;BLACK CIRCLE 274D;a72;SHADOWED WHITE CIRCLE 25A0;a73;BLACK SQUARE 274F;a74;LOWER RIGHT DROP-SHADOWED WHITE SQUARE 2750;a203;UPPER RIGHT DROP-SHADOWED WHITE SQUARE 2751;a75;LOWER RIGHT SHADOWED WHITE SQUARE 2752;a204;UPPER RIGHT SHADOWED WHITE SQUARE 25B2;a76;BLACK UP-POINTING TRIANGLE 25BC;a77;BLACK DOWN-POINTING TRIANGLE 25C6;a78;BLACK DIAMOND 2756;a79;BLACK DIAMOND MINUS WHITE X 25D7;a81;RIGHT HALF BLACK CIRCLE 2758;a82;LIGHT VERTICAL BAR 2759;a83;MEDIUM VERTICAL BAR 275A;a84;HEAVY VERTICAL BAR 275B;a97;HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT 275C;a98;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT 275D;a99;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT 275E;a100;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT F8D7;a89;MEDIUM LEFT PARENTHESIS ORNAMENT F8D8;a90;MEDIUM RIGHT PARENTHESIS ORNAMENT F8D9;a93;MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT F8DA;a94;MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT F8DB;a91;MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT F8DC;a92;MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT F8DD;a205;HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT F8DE;a85;HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT F8DF;a206;HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT F8E0;a86;HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT F8E1;a87;LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT F8E2;a88;LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT F8E3;a95;MEDIUM LEFT CURLY BRACKET ORNAMENT F8E4;a96;MEDIUM RIGHT CURLY BRACKET ORNAMENT 2761;a101;CURVED STEM PARAGRAPH SIGN ORNAMENT 2762;a102;HEAVY EXCLAMATION MARK ORNAMENT 2763;a103;HEAVY HEART EXCLAMATION MARK ORNAMENT 2764;a104;HEAVY BLACK HEART 2765;a106;ROTATED HEAVY BLACK HEART BULLET 2766;a107;FLORAL HEART 2767;a108;ROTATED FLORAL HEART BULLET 2663;a112;BLACK CLUB SUIT 2666;a111;BLACK DIAMOND SUIT 2665;a110;BLACK HEART SUIT 2660;a109;BLACK SPADE SUIT 2460;a120;CIRCLED DIGIT ONE 2461;a121;CIRCLED DIGIT TWO 2462;a122;CIRCLED DIGIT THREE 2463;a123;CIRCLED DIGIT FOUR 2464;a124;CIRCLED DIGIT FIVE 2465;a125;CIRCLED DIGIT SIX 2466;a126;CIRCLED DIGIT SEVEN 2467;a127;CIRCLED DIGIT EIGHT 2468;a128;CIRCLED DIGIT NINE 2469;a129;CIRCLED NUMBER TEN 2776;a130;DINGBAT NEGATIVE CIRCLED DIGIT ONE 2777;a131;DINGBAT NEGATIVE CIRCLED DIGIT TWO 2778;a132;DINGBAT NEGATIVE CIRCLED DIGIT THREE 2779;a133;DINGBAT NEGATIVE CIRCLED DIGIT FOUR 277A;a134;DINGBAT NEGATIVE CIRCLED DIGIT FIVE 277B;a135;DINGBAT NEGATIVE CIRCLED DIGIT SIX 277C;a136;DINGBAT NEGATIVE CIRCLED DIGIT SEVEN 277D;a137;DINGBAT NEGATIVE CIRCLED DIGIT EIGHT 277E;a138;DINGBAT NEGATIVE CIRCLED DIGIT NINE 277F;a139;DINGBAT NEGATIVE CIRCLED NUMBER TEN 2780;a140;DINGBAT CIRCLED SANS-SERIF DIGIT ONE 2781;a141;DINGBAT CIRCLED SANS-SERIF DIGIT TWO 2782;a142;DINGBAT CIRCLED SANS-SERIF DIGIT THREE 2783;a143;DINGBAT CIRCLED SANS-SERIF DIGIT FOUR 2784;a144;DINGBAT CIRCLED SANS-SERIF DIGIT FIVE 2785;a145;DINGBAT CIRCLED SANS-SERIF DIGIT SIX 2786;a146;DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN 2787;a147;DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT 2788;a148;DINGBAT CIRCLED SANS-SERIF DIGIT NINE 2789;a149;DINGBAT CIRCLED SANS-SERIF NUMBER TEN 278A;a150;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE 278B;a151;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO 278C;a152;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE 278D;a153;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR 278E;a154;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE 278F;a155;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX 2790;a156;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN 2791;a157;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT 2792;a158;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE 2793;a159;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN 2794;a160;HEAVY WIDE-HEADED RIGHTWARDS ARROW 2192;a161;RIGHTWARDS ARROW 2194;a163;LEFT RIGHT ARROW 2195;a164;UP DOWN ARROW 2798;a196;HEAVY SOUTH EAST ARROW 2799;a165;HEAVY RIGHTWARDS ARROW 279A;a192;HEAVY NORTH EAST ARROW 279B;a166;DRAFTING POINT RIGHTWARDS ARROW 279C;a167;HEAVY ROUND-TIPPED RIGHTWARDS ARROW 279D;a168;TRIANGLE-HEADED RIGHTWARDS ARROW 279E;a169;HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW 279F;a170;DASHED TRIANGLE-HEADED RIGHTWARDS ARROW 27A0;a171;HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW 27A1;a172;BLACK RIGHTWARDS ARROW 27A2;a173;THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD 27A3;a162;THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD 27A4;a174;BLACK RIGHTWARDS ARROWHEAD 27A5;a175;HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW 27A6;a176;HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW 27A7;a177;SQUAT BLACK RIGHTWARDS ARROW 27A8;a178;HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW 27A9;a179;RIGHT-SHADED WHITE RIGHTWARDS ARROW 27AA;a193;LEFT-SHADED WHITE RIGHTWARDS ARROW 27AB;a180;BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW 27AC;a199;FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW 27AD;a181;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW 27AE;a200;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW 27AF;a182;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW 27B1;a201;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW 27B2;a183;CIRCLED HEAVY WHITE RIGHTWARDS ARROW 27B3;a184;WHITE-FEATHERED RIGHTWARDS ARROW 27B4;a197;BLACK-FEATHERED SOUTH EAST ARROW 27B5;a185;BLACK-FEATHERED RIGHTWARDS ARROW 27B6;a194;BLACK-FEATHERED NORTH EAST ARROW 27B7;a198;HEAVY BLACK-FEATHERED SOUTH EAST ARROW 27B8;a186;HEAVY BLACK-FEATHERED RIGHTWARDS ARROW 27B9;a195;HEAVY BLACK-FEATHERED NORTH EAST ARROW 27BA;a187;TEARDROP-BARBED RIGHTWARDS ARROW 27BB;a188;HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW 27BC;a189;WEDGE-TAILED RIGHTWARDS ARROW 27BD;a190;HEAVY WEDGE-TAILED RIGHTWARDS ARROW 27BE;a191;OPEN-OUTLINED RIGHTWARDS ARROW netsurf-2.9/librufl-0.0.1/src/rufl_init.c0000664000175000017500000012151211321135473017067 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2006 James Bursa */ #define _GNU_SOURCE /* for strndup */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rufl_internal.h" struct rufl_font_list_entry *rufl_font_list = 0; size_t rufl_font_list_entries = 0; const char **rufl_family_list = 0; unsigned int rufl_family_list_entries = 0; struct rufl_family_map_entry *rufl_family_map = 0; os_error *rufl_fm_error = 0; void *rufl_family_menu = 0; unsigned short *rufl_substitution_table = 0; struct rufl_cache_entry rufl_cache[rufl_CACHE_SIZE]; int rufl_cache_time = 0; bool rufl_old_font_manager = false; wimp_w rufl_status_w = 0; char rufl_status_buffer[80]; /** An entry in rufl_weight_table. */ struct rufl_weight_table_entry { const char *name; unsigned int weight; }; /** Map from font name part to font weight. Must be case-insensitive sorted by * name. */ const struct rufl_weight_table_entry rufl_weight_table[] = { { "Black", 9 }, { "Bold", 7 }, { "Book", 3 }, { "Demi", 6 }, { "DemiBold", 6 }, { "Extra", 8 }, { "ExtraBlack", 9 }, { "ExtraBold", 8 }, { "ExtraLight", 1 }, { "Heavy", 8 }, { "Light", 2 }, { "Medium", 5 }, { "Regular", 4 }, { "Semi", 6 }, { "SemiBold", 6 }, { "SemiLight", 3 }, { "UltraBlack", 9 }, { "UltraBold", 9 }, }; static rufl_code rufl_init_font_list(void); static rufl_code rufl_init_add_font(const char *identifier, const char *local_name); static int rufl_weight_table_cmp(const void *keyval, const void *datum); static rufl_code rufl_init_scan_font(unsigned int font); static rufl_code rufl_init_scan_font_no_enumerate(unsigned int font); static bool rufl_is_space(unsigned int u); static rufl_code rufl_init_scan_font_old(unsigned int font_index); static rufl_code rufl_init_scan_font_in_encoding(const char *font_name, const char *encoding, struct rufl_character_set *charset, struct rufl_unicode_map *umap, unsigned int *last); static rufl_code rufl_init_read_encoding(font_f font, struct rufl_unicode_map *umap); static int rufl_glyph_map_cmp(const void *keyval, const void *datum); static int rufl_unicode_map_cmp(const void *z1, const void *z2); static rufl_code rufl_init_substitution_table(void); static rufl_code rufl_save_cache(void); static rufl_code rufl_load_cache(void); static int rufl_font_list_cmp(const void *keyval, const void *datum); static rufl_code rufl_init_family_menu(void); static void rufl_init_status_open(void); static void rufl_init_status(const char *status, float progress); static void rufl_init_status_close(void); /** * Initialise RUfl. * * All available fonts are scanned. May take some time. */ rufl_code rufl_init(void) { bool rufl_broken_font_enumerate_characters = false; unsigned int changes = 0; unsigned int i; int fm_version; rufl_code code; font_f font; os_colour old_sand, old_glass; if (rufl_font_list_entries) /* already initialized */ return rufl_OK; xhourglass_on(); rufl_init_status_open(); /* determine if the font manager supports Unicode */ rufl_fm_error = xfont_find_font("Homerton.Medium\\EUTF8", 160, 160, 0, 0, &font, 0, 0); if (rufl_fm_error) { if (rufl_fm_error->errnum == error_FONT_ENCODING_NOT_FOUND) { rufl_old_font_manager = true; } else { LOG("xfont_find_font: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); rufl_quit(); xhourglass_off(); return rufl_FONT_MANAGER_ERROR; } } else { /* New font manager; see if character enumeration works */ int next; rufl_fm_error = xfont_enumerate_characters(font, 0, &next, NULL); /* Broken if SWI fails or it doesn't return 0x20 as the first * character to process. Font Managers earlier than 3.64 have * a bug that means they do not return the first available * range of characters in a font. We detect this by asking * for the first character in Homerton.Medium, which we know * is 0x20 (i.e. space). If the value returned is not this, * then we assume the font manager is broken and fall back to * the old code which is significantly slower. */ if (rufl_fm_error || next != 0x20) rufl_broken_font_enumerate_characters = true; xfont_lose_font(font); } LOG("%s font manager", rufl_old_font_manager ? "old" : "new"); /* test if the font manager supports background blending */ rufl_fm_error = xfont_cache_addr(&fm_version, 0, 0); if (rufl_fm_error) return rufl_FONT_MANAGER_ERROR; if (fm_version >= 335) rufl_can_background_blend = true; code = rufl_init_font_list(); if (code != rufl_OK) { rufl_quit(); xhourglass_off(); return code; } LOG("%zu faces, %u families", rufl_font_list_entries, rufl_family_list_entries); code = rufl_load_cache(); if (code != rufl_OK) { LOG("rufl_load_cache: 0x%x", code); rufl_quit(); xhourglass_off(); return code; } xhourglass_leds(1, 0, 0); for (i = 0; i != rufl_font_list_entries; i++) { if (rufl_font_list[i].charset) { /* character set loaded from cache */ continue; } LOG("scanning %u \"%s\"", i, rufl_font_list[i].identifier); xhourglass_percentage(100 * i / rufl_font_list_entries); rufl_init_status(rufl_font_list[i].identifier, (float) i / rufl_font_list_entries); if (rufl_old_font_manager) code = rufl_init_scan_font_old(i); else if (rufl_broken_font_enumerate_characters) code = rufl_init_scan_font_no_enumerate(i); else code = rufl_init_scan_font(i); if (code != rufl_OK) { LOG("rufl_init_scan_font: 0x%x", code); rufl_quit(); xhourglass_off(); return code; } changes++; } xhourglass_leds(2, 0, 0); xhourglass_colours(0x0000ff, 0x00ffff, &old_sand, &old_glass); code = rufl_init_substitution_table(); if (code != rufl_OK) { LOG("rufl_init_substitution_table: 0x%x", code); rufl_quit(); xhourglass_off(); return code; } xhourglass_colours(old_sand, old_glass, 0, 0); if (changes) { LOG("%u new charsets", changes); xhourglass_leds(3, 0, 0); code = rufl_save_cache(); if (code != rufl_OK) { LOG("rufl_save_cache: 0x%x", code); rufl_quit(); xhourglass_off(); return code; } } for (i = 0; i != rufl_CACHE_SIZE; i++) rufl_cache[i].font = rufl_CACHE_NONE; code = rufl_init_family_menu(); if (code != rufl_OK) { LOG("rufl_init_substitution_table: 0x%x", code); rufl_quit(); xhourglass_off(); return code; } rufl_init_status_close(); xhourglass_off(); return rufl_OK; } /** * Build list of font in rufl_font_list and list of font families * in rufl_family_list. */ rufl_code rufl_init_font_list(void) { rufl_code code; font_list_context context = 0; char identifier[80], local_name[80]; while (context != -1) { /* read identifier */ rufl_fm_error = xfont_list_fonts((byte *)identifier, font_RETURN_FONT_NAME | font_RETURN_LOCAL_FONT_NAME | context, sizeof identifier, (byte *)local_name, sizeof local_name, 0, &context, 0, 0); if (rufl_fm_error) { LOG("xfont_list_fonts: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } if (context == -1) break; code = rufl_init_add_font(identifier, local_name); if (code != rufl_OK) return code; } return rufl_OK; } rufl_code rufl_init_add_font(const char *identifier, const char *local_name) { int size; struct rufl_font_list_entry *font_list; char *dot; const char **family_list; const char *family, *part; unsigned int weight = 0; unsigned int slant = 0; bool special = false; struct rufl_family_map_entry *family_map; unsigned int i; struct rufl_weight_table_entry *entry; /* Check that: * a) it's not a RiScript generated font * b) it's not a TeX font */ /* Read required buffer size */ rufl_fm_error = xosfscontrol_canonicalise_path(identifier, 0, "Font$Path", 0, 0, &size); if (rufl_fm_error) { LOG("xosfscontrol_canonicalise_path(\"%s\", ...): 0x%x: %s", identifier, rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_OK; } /* size is -(space required - 1) so negate and add 1 */ size = -size + 1; /* Create buffer and canonicalise path */ char fullpath[size]; rufl_fm_error = xosfscontrol_canonicalise_path(identifier, fullpath, "Font$Path", 0, size, 0); if (rufl_fm_error) { LOG("xosfscontrol_canonicalise_path(\"%s\", ...): 0x%x: %s", identifier, rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_OK; } /* LOG("%s", fullpath); */ if (strstr(fullpath, "RiScript") || strstr(fullpath, "!TeXFonts")) /* Ignore this font */ return rufl_OK; /* add identifier to rufl_font_list */ font_list = realloc(rufl_font_list, sizeof rufl_font_list[0] * (rufl_font_list_entries + 1)); if (!font_list) return rufl_OUT_OF_MEMORY; rufl_font_list = font_list; rufl_font_list[rufl_font_list_entries].identifier = strdup(identifier); if (!rufl_font_list[rufl_font_list_entries].identifier) return rufl_OUT_OF_MEMORY; rufl_font_list[rufl_font_list_entries].charset = 0; rufl_font_list[rufl_font_list_entries].umap = 0; rufl_font_list_entries++; /* determine family, weight, and slant */ dot = strchr(local_name, '.'); family = local_name; if (dot) *dot = 0; while (dot) { part = dot + 1; dot = strchr(part, '.'); if (dot) *dot = 0; if (strcasecmp(part, "Italic") == 0 || strcasecmp(part, "Oblique") == 0) { slant = 1; continue; } entry = bsearch(part, rufl_weight_table, sizeof rufl_weight_table / sizeof rufl_weight_table[0], sizeof rufl_weight_table[0], rufl_weight_table_cmp); if (entry) weight = entry->weight; else special = true; /* unknown weight or style */ } if (!weight) weight = 4; weight--; if (rufl_family_list_entries == 0 || strcasecmp(family, rufl_family_list[rufl_family_list_entries - 1]) != 0) { /* new family */ family_list = realloc(rufl_family_list, sizeof rufl_family_list[0] * (rufl_family_list_entries + 1)); if (!family_list) return rufl_OUT_OF_MEMORY; rufl_family_list = family_list; family_map = realloc(rufl_family_map, sizeof rufl_family_map[0] * (rufl_family_list_entries + 1)); if (!family_map) return rufl_OUT_OF_MEMORY; rufl_family_map = family_map; family = strdup(family); if (!family) return rufl_OUT_OF_MEMORY; rufl_family_list[rufl_family_list_entries] = family; for (i = 0; i != 9; i++) rufl_family_map[rufl_family_list_entries].font[i][0] = rufl_family_map[rufl_family_list_entries].font[i][1] = NO_FONT; rufl_family_list_entries++; } struct rufl_family_map_entry *e = &rufl_family_map[rufl_family_list_entries - 1]; /* prefer fonts with no unknown weight or style in their name, so that, * for example, Alps.Light takes priority over Alps.Cond.Light */ if (e->font[weight][slant] == NO_FONT || !special) e->font[weight][slant] = rufl_font_list_entries - 1; rufl_font_list[rufl_font_list_entries - 1].family = rufl_family_list_entries - 1; rufl_font_list[rufl_font_list_entries - 1].weight = weight; rufl_font_list[rufl_font_list_entries - 1].slant = slant; return rufl_OK; } int rufl_weight_table_cmp(const void *keyval, const void *datum) { const char *key = keyval; const struct rufl_weight_table_entry *entry = datum; return strcasecmp(key, entry->name); } /** * Scan a font for available characters. */ rufl_code rufl_init_scan_font(unsigned int font_index) { char font_name[80]; int x_out, y_out; unsigned int byte, bit; unsigned int last_used = 0; unsigned int string[2] = { 0, 0 }; unsigned int u, next; struct rufl_character_set *charset; struct rufl_character_set *charset2; font_f font; font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } }; /*LOG("font %u \"%s\"", font_index, rufl_font_list[font_index].identifier);*/ charset = calloc(1, sizeof *charset); if (!charset) return rufl_OUT_OF_MEMORY; for (u = 0; u != 256; u++) charset->index[u] = BLOCK_EMPTY; snprintf(font_name, sizeof font_name, "%s\\EUTF8", rufl_font_list[font_index].identifier); rufl_fm_error = xfont_find_font(font_name, 160, 160, 0, 0, &font, 0, 0); if (rufl_fm_error) { LOG("xfont_find_font(\"%s\"): 0x%x: %s", font_name, rufl_fm_error->errnum, rufl_fm_error->errmess); free(charset); return rufl_OK; } /* Scan through mapped characters */ for (u = 0; u != (unsigned int) -1; u = next) { unsigned int internal; rufl_fm_error = xfont_enumerate_characters(font, u, (int *) &next, (int *) &internal); if (rufl_fm_error) { LOG("xfont_enumerate_characters: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); xfont_lose_font(font); free(charset); return rufl_OK; } /* Skip DELETE and C0/C1 controls */ if (u < 0x0020 || (0x007f <= u && u <= 0x009f)) continue; /* Skip astral characters */ if (u > 0xffff) continue; /* Skip unmapped characters */ if (internal == (unsigned int) -1) continue; if (u % 0x200 == 0) rufl_init_status(0, 0); /* Character is mapped, let's see if it's really there */ string[0] = u; rufl_fm_error = xfont_scan_string(font, (char *) string, font_RETURN_BBOX | font_GIVEN32_BIT | font_GIVEN_FONT | font_GIVEN_LENGTH | font_GIVEN_BLOCK, 0x7fffffff, 0x7fffffff, &block, 0, 4, 0, &x_out, &y_out, 0); if (rufl_fm_error) break; if (block.bbox.x0 == 0x20000000) { /* absent (no definition) */ } else if (x_out == 0 && y_out == 0 && block.bbox.x0 == 0 && block.bbox.y0 == 0 && block.bbox.x1 == 0 && block.bbox.y1 == 0) { /* absent (empty) */ } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 && block.bbox.x1 == 0 && block.bbox.y1 == 0 && !rufl_is_space(u)) { /* absent (space but not a space character - some * fonts do this) */ } else { /* present */ if (charset->index[u >> 8] == BLOCK_EMPTY) { charset->index[u >> 8] = last_used; last_used++; if (last_used == 254) /* too many characters */ break; } byte = (u >> 3) & 31; bit = u & 7; charset->block[charset->index[u >> 8]][byte] |= 1 << bit; } } xfont_lose_font(font); if (rufl_fm_error) { free(charset); LOG("xfont_scan_string: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } /* Determine which blocks are full, and mark them as such */ for (u = 0; u != 256; u++) { if (charset->index[u] == BLOCK_EMPTY) continue; bit = 0xff; for (byte = 0; byte != 32; byte++) bit &= charset->block[u][byte]; if (bit == 0xff) { /* Block is full */ charset->index[u] = BLOCK_FULL; for (byte = 0; byte != 32; byte++) charset->block[u][byte] = 0; } } /* shrink-wrap */ charset->size = offsetof(struct rufl_character_set, block) + 32 * last_used; charset2 = realloc(charset, charset->size); if (!charset2) { free(charset); return rufl_OUT_OF_MEMORY; } rufl_font_list[font_index].charset = charset; return rufl_OK; } /** * Scan a font for available characters (version without character enumeration) */ rufl_code rufl_init_scan_font_no_enumerate(unsigned int font_index) { char font_name[80]; int x_out, y_out; unsigned int byte, bit; unsigned int block_count = 0; unsigned int last_used = 0; unsigned int string[2] = { 0, 0 }; unsigned int u; struct rufl_character_set *charset; struct rufl_character_set *charset2; font_f font; font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } }; /*LOG("font %u \"%s\"", font_index, rufl_font_list[font_index].identifier);*/ charset = calloc(1, sizeof *charset); if (!charset) return rufl_OUT_OF_MEMORY; snprintf(font_name, sizeof font_name, "%s\\EUTF8", rufl_font_list[font_index].identifier); rufl_fm_error = xfont_find_font(font_name, 160, 160, 0, 0, &font, 0, 0); if (rufl_fm_error) { LOG("xfont_find_font(\"%s\"): 0x%x: %s", font_name, rufl_fm_error->errnum, rufl_fm_error->errmess); free(charset); return rufl_OK; } /* scan through all characters */ for (u = 0x0020; u != 0x10000; u++) { if (u == 0x007f) { /* skip DELETE and C1 controls */ u = 0x009f; continue; } if (u % 0x200 == 0) rufl_init_status(0, 0); string[0] = u; rufl_fm_error = xfont_scan_string(font, (char *) string, font_RETURN_BBOX | font_GIVEN32_BIT | font_GIVEN_FONT | font_GIVEN_LENGTH | font_GIVEN_BLOCK, 0x7fffffff, 0x7fffffff, &block, 0, 4, 0, &x_out, &y_out, 0); if (rufl_fm_error) break; if (block.bbox.x0 == 0x20000000) { /* absent (no definition) */ } else if (x_out == 0 && y_out == 0 && block.bbox.x0 == 0 && block.bbox.y0 == 0 && block.bbox.x1 == 0 && block.bbox.y1 == 0) { /* absent (empty) */ } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 && block.bbox.x1 == 0 && block.bbox.y1 == 0 && !rufl_is_space(u)) { /* absent (space but not a space character - some * fonts do this) */ } else { /* present */ byte = (u >> 3) & 31; bit = u & 7; charset->block[last_used][byte] |= 1 << bit; block_count++; } if ((u + 1) % 256 == 0) { /* end of block */ if (block_count == 0) charset->index[u >> 8] = BLOCK_EMPTY; else if (block_count == 256) { charset->index[u >> 8] = BLOCK_FULL; for (byte = 0; byte != 32; byte++) charset->block[last_used][byte] = 0; } else { charset->index[u >> 8] = last_used; last_used++; if (last_used == 254) /* too many characters */ break; } block_count = 0; } } xfont_lose_font(font); if (rufl_fm_error) { free(charset); LOG("xfont_scan_string: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } /* shrink-wrap */ charset->size = offsetof(struct rufl_character_set, block) + 32 * last_used; charset2 = realloc(charset, charset->size); if (!charset2) { free(charset); return rufl_OUT_OF_MEMORY; } rufl_font_list[font_index].charset = charset; return rufl_OK; } /** * A character is one of the Unicode space characters. */ bool rufl_is_space(unsigned int u) { return u == 0x0020 || u == 0x00a0 || (0x2000 <= u && u <= 0x200b) || u == 0x202f || u == 0x3000; } /** * Scan a font for available characters (old font manager version). */ rufl_code rufl_init_scan_font_old(unsigned int font_index) { const char *font_name = rufl_font_list[font_index].identifier; struct rufl_character_set *charset; struct rufl_character_set *charset2; struct rufl_unicode_map *umap = NULL; unsigned int num_umaps = 0; unsigned int i; unsigned int last_used = 0; rufl_code code; font_list_context context = 0; char encoding[80]; /*LOG("font %u \"%s\"", font_index, font_name);*/ charset = calloc(1, sizeof *charset); if (!charset) return rufl_OUT_OF_MEMORY; for (i = 0; i != 256; i++) charset->index[i] = BLOCK_EMPTY; /* Firstly, search through available encodings (Symbol fonts fail) */ while (context != -1) { struct rufl_unicode_map *temp; rufl_fm_error = xfont_list_fonts((byte *) encoding, font_RETURN_FONT_NAME | 0x400000 /* Return encoding name, instead */ | context, sizeof(encoding), NULL, 0, NULL, &context, NULL, NULL); if (rufl_fm_error) { LOG("xfont_list_fonts: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); free(charset); for (i = 0; i < num_umaps; i++) free((umap + i)->encoding); free(umap); return rufl_FONT_MANAGER_ERROR; } if (context == -1) break; temp = realloc(umap, (num_umaps + 1) * sizeof *umap); if (!temp) { free(charset); for (i = 0; i < num_umaps; i++) free((umap + i)->encoding); free(umap); return rufl_OUT_OF_MEMORY; } memset(temp + num_umaps, 0, sizeof *umap); umap = temp; num_umaps++; code = rufl_init_scan_font_in_encoding(font_name, encoding, charset, umap + (num_umaps - 1), &last_used); if (code != rufl_OK) { /* Not finding the font isn't fatal */ if (code != rufl_FONT_MANAGER_ERROR || (rufl_fm_error->errnum != error_FONT_NOT_FOUND && rufl_fm_error->errnum != error_FILE_NOT_FOUND)) { free(charset); for (i = 0; i < num_umaps; i++) free((umap + i)->encoding); free(umap); return code; } /* Ensure we reuse the currently allocated umap */ num_umaps--; } else { /* If this mapping is identical to an existing one, * then we can discard it */ for (i = 0; i != num_umaps - 1; i++) { const struct rufl_unicode_map *a = (umap + i); const struct rufl_unicode_map *b = (umap + num_umaps - 1); if (a->entries == b->entries && memcmp(a->map, b->map, sizeof a->map) == 0) { /* Found identical map; discard */ num_umaps--; break; } } } } if (num_umaps == 0) { /* This is a symbol font and can only be used * without an encoding */ struct rufl_unicode_map *temp; temp = realloc(umap, (num_umaps + 1) * sizeof *umap); if (!temp) { free(charset); free(umap); return rufl_OUT_OF_MEMORY; } memset(temp + num_umaps, 0, sizeof *umap); umap = temp; num_umaps++; code = rufl_init_scan_font_in_encoding(font_name, NULL, charset, umap, &last_used); if (code != rufl_OK) { /* Not finding the font isn't fatal */ if (code != rufl_FONT_MANAGER_ERROR || (rufl_fm_error->errnum != error_FONT_NOT_FOUND && rufl_fm_error->errnum != error_FILE_NOT_FOUND)) { free(charset); for (i = 0; i < num_umaps; i++) free((umap + i)->encoding); free(umap); return code; } num_umaps--; } } /* shrink-wrap */ charset->size = offsetof(struct rufl_character_set, block) + 32 * last_used; charset2 = realloc(charset, charset->size); if (!charset2) { for (i = 0; i < num_umaps; i++) free((umap + i)->encoding); free(umap); free(charset); return rufl_OUT_OF_MEMORY; } rufl_font_list[font_index].charset = charset; rufl_font_list[font_index].umap = umap; rufl_font_list[font_index].num_umaps = num_umaps; return rufl_OK; } /** * Helper function for rufl_init_scan_font_old. * Scans the given font using the given font encoding (or none, if NULL) */ rufl_code rufl_init_scan_font_in_encoding(const char *font_name, const char *encoding, struct rufl_character_set *charset, struct rufl_unicode_map *umap, unsigned int *last) { char string[2] = { 0, 0 }; int x_out, y_out; unsigned int byte, bit; unsigned int i; unsigned int last_used = *last; unsigned int u; rufl_code code; font_f font; font_scan_block block = { { 0, 0 }, { 0, 0 }, -1, { 0, 0, 0, 0 } }; char buf[80]; if (encoding) snprintf(buf, sizeof buf, "%s\\E%s", font_name, encoding); else snprintf(buf, sizeof buf, "%s", font_name); rufl_fm_error = xfont_find_font(buf, 160, 160, 0, 0, &font, 0, 0); if (rufl_fm_error) { LOG("xfont_find_font(\"%s\"): 0x%x: %s", buf, rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } code = rufl_init_read_encoding(font, umap); if (code != rufl_OK) { xfont_lose_font(font); return code; } for (i = 0; i != umap->entries; i++) { u = umap->map[i].u; string[0] = umap->map[i].c; rufl_fm_error = xfont_scan_string(font, (char *) string, font_RETURN_BBOX | font_GIVEN_FONT | font_GIVEN_LENGTH | font_GIVEN_BLOCK, 0x7fffffff, 0x7fffffff, &block, 0, 1, 0, &x_out, &y_out, 0); if (rufl_fm_error) break; if (block.bbox.x0 == 0x20000000) { /* absent (no definition) */ } else if (x_out == 0 && y_out == 0 && block.bbox.x0 == 0 && block.bbox.y0 == 0 && block.bbox.x1 == 0 && block.bbox.y1 == 0) { /* absent (empty) */ } else if (block.bbox.x0 == 0 && block.bbox.y0 == 0 && block.bbox.x1 == 0 && block.bbox.y1 == 0 && !rufl_is_space(u)) { /* absent (space but not a space character - some * fonts do this) */ } else { /* present */ if (charset->index[u >> 8] == BLOCK_EMPTY) { charset->index[u >> 8] = last_used; last_used++; if (last_used == 254) /* too many characters */ break; } byte = (u >> 3) & 31; bit = u & 7; charset->block[charset->index[u >> 8]][byte] |= 1 << bit; } } xfont_lose_font(font); if (rufl_fm_error) { LOG("xfont_scan_string: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } if (encoding) { umap->encoding = strdup(encoding); if (!umap->encoding) return rufl_OUT_OF_MEMORY; } *last = last_used; return rufl_OK; } /** * Parse an encoding file and fill in a rufl_unicode_map. */ rufl_code rufl_init_read_encoding(font_f font, struct rufl_unicode_map *umap) { unsigned int u = 0; unsigned int i = 0; int c; int n; char filename[200]; char s[200]; struct rufl_glyph_map_entry *entry; FILE *fp; rufl_fm_error = xfont_read_encoding_filename(font, filename, sizeof filename, 0); if (rufl_fm_error) { LOG("xfont_read_encoding_filename: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } fp = fopen(filename, "r"); if (!fp) /* many "symbol" fonts have no encoding file: assume Latin 1 */ fp = fopen("Resources:$.Fonts.Encodings.Latin1", "r"); if (!fp) return rufl_IO_ERROR; while (!feof(fp) && u != 256) { c = fgetc(fp); if (c == '%') { /* comment line */ fgets(s, sizeof s, fp); } else if (c == '/') { /* character definition */ if (i++ < 32) continue; n = fscanf(fp, "%100s", s); if (n != 1) break; entry = bsearch(s, rufl_glyph_map, rufl_glyph_map_size, sizeof rufl_glyph_map[0], rufl_glyph_map_cmp); if (entry) { /* may be more than one unicode for the glyph * sentinels stop overshooting array */ while (strcmp(s, (entry - 1)->glyph_name) == 0) entry--; for (; strcmp(s, entry->glyph_name) == 0; entry++) { umap->map[u].u = entry->u; umap->map[u].c = i - 1; u++; if (u == 256) break; } } } } if (fclose(fp) == EOF) return rufl_IO_ERROR; /* sort by unicode */ qsort(umap->map, u, sizeof umap->map[0], rufl_unicode_map_cmp); umap->entries = u; return rufl_OK; } int rufl_glyph_map_cmp(const void *keyval, const void *datum) { const char *key = keyval; const struct rufl_glyph_map_entry *entry = datum; return strcmp(key, entry->glyph_name); } int rufl_unicode_map_cmp(const void *z1, const void *z2) { const struct rufl_unicode_map_entry *entry1 = z1; const struct rufl_unicode_map_entry *entry2 = z2; if (entry1->u < entry2->u) return -1; else if (entry2->u < entry1->u) return 1; return 0; } /** * Construct the font substitution table. */ rufl_code rufl_init_substitution_table(void) { unsigned char z; unsigned int i; unsigned int block, byte, bit; unsigned int u; unsigned int index; const struct rufl_character_set *charset; rufl_substitution_table = malloc(65536 * sizeof rufl_substitution_table[0]); if (!rufl_substitution_table) { LOG("malloc(%zu) failed", 65536 * sizeof rufl_substitution_table[0]); return rufl_OUT_OF_MEMORY; } for (u = 0; u != 0x10000; u++) rufl_substitution_table[u] = NOT_AVAILABLE; for (i = 0; i != rufl_font_list_entries; i++) { charset = rufl_font_list[i].charset; if (!charset) continue; for (block = 0; block != 256; block++) { if (charset->index[block] == BLOCK_EMPTY) continue; if (charset->index[block] == BLOCK_FULL) { for (u = block << 8; u != (block << 8) + 256; u++) { if (rufl_substitution_table[u] == NOT_AVAILABLE) rufl_substitution_table[u] = i; } continue; } index = charset->index[block]; for (byte = 0; byte != 32; byte++) { z = charset->block[index][byte]; if (z == 0) continue; u = (block << 8) | (byte << 3); for (bit = 0; bit != 8; bit++, u++) { if (rufl_substitution_table[u] == NOT_AVAILABLE && z & (1 << bit)) rufl_substitution_table[u] = i; } } } } return rufl_OK; } /** * Save character sets to cache. */ rufl_code rufl_save_cache(void) { unsigned int i; const unsigned int version = rufl_CACHE_VERSION; size_t len; FILE *fp; fp = fopen(rufl_CACHE, "wb"); if (!fp) { LOG("fopen: 0x%x: %s", errno, strerror(errno)); return rufl_OK; } /* cache format version */ if (fwrite(&version, sizeof version, 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } /* font manager type flag */ if (fwrite(&rufl_old_font_manager, sizeof rufl_old_font_manager, 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } for (i = 0; i != rufl_font_list_entries; i++) { if (!rufl_font_list[i].charset) continue; /* length of font identifier */ len = strlen(rufl_font_list[i].identifier); if (fwrite(&len, sizeof len, 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } /* font identifier */ if (fwrite(rufl_font_list[i].identifier, len, 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } /* character set */ if (fwrite(rufl_font_list[i].charset, rufl_font_list[i].charset->size, 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } /* unicode map */ if (rufl_old_font_manager) { unsigned int j; if (fwrite(&rufl_font_list[i].num_umaps, sizeof rufl_font_list[i].num_umaps, 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } for (j = 0; j < rufl_font_list[i].num_umaps; j++) { const struct rufl_unicode_map *umap = rufl_font_list[i].umap + j; len = umap->encoding ? strlen(umap->encoding) : 0; if (fwrite(&len, sizeof len, 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } if (umap->encoding) { if (fwrite(umap->encoding, len, 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } } if (fwrite(&umap->entries, sizeof umap->entries, 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } if (fwrite(umap->map, umap->entries * sizeof(struct rufl_unicode_map_entry), 1, fp) != 1) { LOG("fwrite: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } } } } if (fclose(fp) == EOF) { LOG("fclose: 0x%x: %s", errno, strerror(errno)); return rufl_OK; } LOG("%u charsets saved", i); return rufl_OK; } /** * Load character sets from cache. */ rufl_code rufl_load_cache(void) { unsigned int version; unsigned int i = 0; bool old_font_manager; char *identifier; size_t len, size; FILE *fp; struct rufl_font_list_entry *entry; struct rufl_character_set *charset; struct rufl_unicode_map *umap = NULL; unsigned int num_umaps = 0; fp = fopen(rufl_CACHE, "rb"); if (!fp) { LOG("fopen: 0x%x: %s", errno, strerror(errno)); return rufl_OK; } /* cache format version */ if (fread(&version, sizeof version, 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } if (version != rufl_CACHE_VERSION) { /* incompatible cache format */ LOG("cache version %u (now %u)", version, rufl_CACHE_VERSION); fclose(fp); return rufl_OK; } /* font manager type flag */ if (fread(&old_font_manager, sizeof old_font_manager, 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); fclose(fp); return rufl_OK; } if (old_font_manager != rufl_old_font_manager) { /* font manager type has changed */ LOG("font manager %u (now %u)", old_font_manager, rufl_old_font_manager); fclose(fp); return rufl_OK; } while (!feof(fp)) { /* length of font identifier */ if (fread(&len, sizeof len, 1, fp) != 1) { /* eof at this point simply means that the whole cache * file has been loaded */ if (!feof(fp)) LOG("fread: 0x%x: %s", errno, strerror(errno)); break; } identifier = malloc(len + 1); if (!identifier) { LOG("malloc(%zu) failed", len + 1); fclose(fp); return rufl_OUT_OF_MEMORY; } /* font identifier */ if (fread(identifier, len, 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); free(identifier); break; } identifier[len] = 0; /* character set */ if (fread(&size, sizeof size, 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); free(identifier); break; } charset = malloc(size); if (!charset) { LOG("malloc(%zu) failed", size); free(identifier); fclose(fp); return rufl_OUT_OF_MEMORY; } charset->size = size; if (fread(charset->index, size - sizeof size, 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); free(charset); free(identifier); break; } /* unicode map */ if (rufl_old_font_manager) { rufl_code code = rufl_OK; unsigned int entry; /* Number of maps */ if (fread(&num_umaps, sizeof num_umaps, 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); free(charset); free(identifier); break; } umap = calloc(num_umaps, sizeof *umap); if (!umap) { LOG("malloc(%zu) failed", sizeof *umap); free(charset); free(identifier); fclose(fp); return rufl_OUT_OF_MEMORY; } /* Load them */ for (entry = 0; entry < num_umaps; entry++) { struct rufl_unicode_map *map = umap + entry; if (fread(&len, sizeof(len), 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); break; } if (len > 0) { map->encoding = malloc(len + 1); if (!map->encoding) { LOG("malloc(%zu) failed", len + 1); code = rufl_OUT_OF_MEMORY; break; } if (fread(map->encoding, len, 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); break; } map->encoding[len] = 0; } if (fread(&map->entries, sizeof(map->entries), 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); break; } if (fread(map->map, map->entries * sizeof(struct rufl_unicode_map_entry), 1, fp) != 1) { if (feof(fp)) LOG("fread: %s", "unexpected eof"); else LOG("fread: 0x%x: %s", errno, strerror(errno)); break; } } /* Clean up if loading failed */ if (entry != num_umaps) { for (num_umaps = 0; num_umaps <= entry; num_umaps++) { struct rufl_unicode_map *map = umap + num_umaps; free(map->encoding); } free(umap); free(charset); free(identifier); if (code != rufl_OK) return code; break; } } /* put in rufl_font_list */ entry = lfind(identifier, rufl_font_list, &rufl_font_list_entries, sizeof rufl_font_list[0], rufl_font_list_cmp); if (entry) { entry->charset = charset; entry->umap = umap; entry->num_umaps = num_umaps; i++; } else { LOG("\"%s\" not in font list", identifier); while (num_umaps > 0) { struct rufl_unicode_map *map = umap + num_umaps - 1; free(map->encoding); num_umaps--; } free(umap); free(charset); } free(identifier); } fclose(fp); LOG("%u charsets loaded", i); return rufl_OK; } int rufl_font_list_cmp(const void *keyval, const void *datum) { const char *key = keyval; const struct rufl_font_list_entry *entry = datum; return strcasecmp(key, entry->identifier); } /** * Create a menu of font families. */ rufl_code rufl_init_family_menu(void) { wimp_menu *menu; unsigned int i; menu = malloc(wimp_SIZEOF_MENU(rufl_family_list_entries)); if (!menu) return rufl_OUT_OF_MEMORY; menu->title_data.indirected_text.text = (char *) "Fonts"; menu->title_fg = wimp_COLOUR_BLACK; menu->title_bg = wimp_COLOUR_LIGHT_GREY; menu->work_fg = wimp_COLOUR_BLACK; menu->work_bg = wimp_COLOUR_WHITE; menu->width = 200; menu->height = wimp_MENU_ITEM_HEIGHT; menu->gap = wimp_MENU_ITEM_GAP; for (i = 0; i != rufl_family_list_entries; i++) { menu->entries[i].menu_flags = 0; menu->entries[i].sub_menu = wimp_NO_SUB_MENU; menu->entries[i].icon_flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); menu->entries[i].data.indirected_text.text = (char *) rufl_family_list[i]; menu->entries[i].data.indirected_text.validation = (char *) -1; menu->entries[i].data.indirected_text.size = strlen(rufl_family_list[i]); } menu->entries[0].menu_flags = wimp_MENU_TITLE_INDIRECTED; menu->entries[i - 1].menu_flags |= wimp_MENU_LAST; rufl_family_menu = menu; return rufl_OK; } /** * Create and open the init status window. */ void rufl_init_status_open(void) { int xeig_factor, yeig_factor, xwind_limit, ywind_limit, width, height; wimp_t task; osbool window_task; wimp_WINDOW(4) window = { { 0, 0, 0, 0 }, 0, 0, wimp_TOP, wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_NEW_FORMAT, wimp_COLOUR_BLACK, wimp_COLOUR_LIGHT_GREY, wimp_COLOUR_BLACK, wimp_COLOUR_VERY_LIGHT_GREY, wimp_COLOUR_DARK_GREY, wimp_COLOUR_LIGHT_GREY, wimp_COLOUR_CREAM, 0, { 0, -128, 800, 0 }, 0, 0, 0, 0, 0, { "" }, 4, { { { 12, -56, 788, -12 }, wimp_ICON_TEXT | wimp_ICON_HCENTRED | wimp_ICON_VCENTRED | wimp_ICON_INDIRECTED | wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT | wimp_COLOUR_VERY_LIGHT_GREY <errnum, error->errmess); return; } if (!task) return; /* not a Wimp task */ error = xtaskwindowtaskinfo_window_task(&window_task); if (error) { LOG("xtaskwindowtaskinfo_window_task: 0x%x: %s", error->errnum, error->errmess); return; } if (window_task) return; /* in a TaskWindow */ xwimp_create_window((const wimp_window *) &window, &rufl_status_w); state.w = rufl_status_w; xwimp_get_window_state(&state); xwimp_open_window((wimp_open *) (void *) &state); } /** * Update the status window and multitask. */ void rufl_init_status(const char *status, float progress) { wimp_block block; static os_t last_t = 0; os_t t; if (!rufl_status_w) return; if (status) { strncpy(rufl_status_buffer, status, sizeof rufl_status_buffer); rufl_status_buffer[sizeof rufl_status_buffer - 1] = 0; xwimp_set_icon_state(rufl_status_w, 3, 0, 0); } if (progress) xwimp_resize_icon(rufl_status_w, 2, 16, -112, 16 + 768 * progress, -68); xos_read_monotonic_time(&t); if (last_t == t) return; xwimp_poll(wimp_QUEUE_REDRAW | wimp_MASK_LEAVING | wimp_MASK_ENTERING | wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_MASK_MESSAGE | wimp_MASK_RECORDED | wimp_MASK_ACKNOWLEDGE, &block, 0, 0); last_t = t; } /** * Close and delete the status window. */ void rufl_init_status_close(void) { if (!rufl_status_w) return; xwimp_delete_window(rufl_status_w); rufl_status_w = 0; } netsurf-2.9/librufl-0.0.1/src/rufl_invalidate_cache.c0000664000175000017500000000113111321135473021361 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2005 James Bursa */ #include "oslib/font.h" #include "rufl_internal.h" /** * Clear the internal font handle cache. * * Call this function on mode changes or output redirection changes. */ void rufl_invalidate_cache(void) { unsigned int i; for (i = 0; i != rufl_CACHE_SIZE; i++) { if (rufl_cache[i].font != rufl_CACHE_NONE) { xfont_lose_font(rufl_cache[i].f); rufl_cache[i].font = rufl_CACHE_NONE; } } } netsurf-2.9/librufl-0.0.1/src/rufl_internal.h0000664000175000017500000001435011321135473017746 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2006 James Bursa */ #include #include "oslib/font.h" #include "rufl.h" #ifdef __CC_NORCROFT #include "strfuncs.h" #endif /** The available characters in a font. The range which can be represented is * 0x0000 to 0xffff. The size of the structure is 4 + 256 + 32 * blocks. A * typical * 200 glyph font might have characters in 10 blocks, giving 580 * bytes. The maximum possible size of the structure is 8388 bytes. Note that * since two index values are reserved, fonts with 65280-65024 glyphs may be * unrepresentable, if there are no full blocks. This is unlikely. The primary * aim of this structure is to make lookup fast. */ struct rufl_character_set { /** Size of structure / bytes. */ size_t size; /** Index table. Each entry represents a block of 256 characters, so * i[k] refers to characters [256*k, 256*(k+1)). The value is either * BLOCK_EMPTY, BLOCK_FULL, or an offset into the block table. */ unsigned char index[256]; /** The block has no characters present. */ # define BLOCK_EMPTY 254 /** All characters in the block are present. */ # define BLOCK_FULL 255 /** Block table. Each entry is a 256-bit bitmap indicating which * characters in the block are present and absent. */ unsigned char block[254][32]; }; /** Part of struct rufl_unicode_map. */ struct rufl_unicode_map_entry { /** Unicode value. */ unsigned short u; /** Corresponding character. */ unsigned char c; }; /** Old font manager: mapping from Unicode to character code. This is simply * an array sorted by Unicode value, suitable for bsearch(). If a font has * support for multiple encodings, then it will have multiple unicode maps. * The encoding field contains the name of the encoding to pass to the * font manager. This will be NULL if the font is a Symbol font. */ struct rufl_unicode_map { /** Corresponding encoding name */ char *encoding; /** Number of valid entries in map. */ unsigned int entries; /** Map from Unicode to character code. */ struct rufl_unicode_map_entry map[256]; }; /** An entry in rufl_font_list. */ struct rufl_font_list_entry { /** Font identifier (name). */ char *identifier; /** Character set of font. */ struct rufl_character_set *charset; /** Number of Unicode mapping tables */ unsigned int num_umaps; /** Mappings from Unicode to character code. */ struct rufl_unicode_map *umap; /** Family that this font belongs to (index in rufl_family_list and * rufl_family_map). */ unsigned int family; /** Font weight (0 to 8). */ unsigned int weight; /** Font slant (0 or 1). */ unsigned int slant; }; /** List of all available fonts. */ extern struct rufl_font_list_entry *rufl_font_list; /** Number of entries in rufl_font_list. */ extern size_t rufl_font_list_entries; /** An entry in rufl_family_map. */ struct rufl_family_map_entry { /** This style does not exist in this family. */ # define NO_FONT UINT_MAX /** Map from weight and slant to index in rufl_font_list, or NO_FONT. */ unsigned int font[9][2]; }; /** Map from font family to fonts, rufl_family_list_entries entries. */ extern struct rufl_family_map_entry *rufl_family_map; /** No font contains this character. */ #define NOT_AVAILABLE 65535 /** Font substitution table. */ extern unsigned short *rufl_substitution_table; /** Number of slots in recent-use cache. This is the maximum number of RISC OS * font handles that will be used at any time by the library. */ #define rufl_CACHE_SIZE 10 /** An entry in rufl_cache. */ struct rufl_cache_entry { /** Font number (index in rufl_font_list), or rufl_CACHE_*. */ unsigned int font; /** No font cached in this slot. */ #define rufl_CACHE_NONE UINT_MAX /** Font for rendering hex substitutions in this slot. */ #define rufl_CACHE_CORPUS (UINT_MAX - 1) /** Font size. */ unsigned int size; /** Font encoding */ const char *encoding; /** Value of rufl_cache_time when last used. */ unsigned int last_used; /** RISC OS font handle. */ font_f f; }; /** Cache of rufl_CACHE_SIZE most recently used font handles. */ extern struct rufl_cache_entry rufl_cache[rufl_CACHE_SIZE]; /** Counter for measuring age of cache entries. */ extern int rufl_cache_time; /** Font manager does not support Unicode. */ extern bool rufl_old_font_manager; /** Font manager supports background blending */ extern bool rufl_can_background_blend; rufl_code rufl_find_font_family(const char *family, rufl_style font_style, unsigned int *font, unsigned int *slanted, struct rufl_character_set **charset); rufl_code rufl_find_font(unsigned int font, unsigned int font_size, const char *encoding, font_f *fhandle); bool rufl_character_set_test(struct rufl_character_set *charset, unsigned int c); #define rufl_utf8_read(s, l, u) \ if (4 <= l && ((s[0] & 0xf8) == 0xf0) && ((s[1] & 0xc0) == 0x80) && \ ((s[2] & 0xc0) == 0x80) && ((s[3] & 0xc0) == 0x80)) { \ u = ((s[0] & 0x7) << 18) | ((s[1] & 0x3f) << 12) | \ ((s[2] & 0x3f) << 6) | (s[3] & 0x3f); \ s += 4; l -= 4; \ } else if (3 <= l && ((s[0] & 0xf0) == 0xe0) && \ ((s[1] & 0xc0) == 0x80) && \ ((s[2] & 0xc0) == 0x80)) { \ u = ((s[0] & 0xf) << 12) | ((s[1] & 0x3f) << 6) | \ (s[2] & 0x3f); \ s += 3; l -= 3; \ } else if (2 <= l && ((s[0] & 0xe0) == 0xc0) && \ ((s[1] & 0xc0) == 0x80)) { \ u = ((s[0] & 0x3f) << 6) | (s[1] & 0x3f); \ s += 2; l -= 2; \ } else if ((s[0] & 0x80) == 0) { \ u = s[0]; \ s++; l--; \ } else { \ u = 0xfffd; \ s++; l--; \ } #define rufl_CACHE ".RUfl_cache" #define rufl_CACHE_VERSION 3 struct rufl_glyph_map_entry { const char *glyph_name; unsigned short u; }; extern const struct rufl_glyph_map_entry rufl_glyph_map[]; extern const size_t rufl_glyph_map_size; #ifndef NDEBUG #ifdef __CC_NORCROFT #define __PRETTY_FUNCTION__ __func__ #endif #define LOG(format, ...) (fprintf(stderr, __FILE__ " %s %i: ", \ __PRETTY_FUNCTION__, __LINE__), fprintf(stderr, format, \ __VA_ARGS__), fprintf(stderr, "\n")) #else #define LOG(format, ...) ((void) 0) #endif netsurf-2.9/librufl-0.0.1/src/strfuncs.h0000664000175000017500000000021211321135473016741 0ustar vincevince#include char *strdup(const char *s); char *strndup(const char *s, size_t n); int strcasecmp(const char *s1, const char *s2); netsurf-2.9/librufl-0.0.1/src/rufl_quit.c0000664000175000017500000000202211321135473017100 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2006 James Bursa */ #include #include "oslib/font.h" #include "rufl_internal.h" /** * Free all resources used by the library. */ void rufl_quit(void) { unsigned int i; if (!rufl_font_list) return; for (i = 0; i != rufl_font_list_entries; i++) { free(rufl_font_list[i].identifier); free(rufl_font_list[i].charset); } free(rufl_font_list); rufl_font_list = 0; for (i = 0; i != rufl_family_list_entries; i++) free((void *) rufl_family_list[i]); free(rufl_family_list); free(rufl_family_map); rufl_family_list = 0; for (i = 0; i != rufl_CACHE_SIZE; i++) { if (rufl_cache[i].font != rufl_CACHE_NONE) { xfont_lose_font(rufl_cache[i].f); rufl_cache[i].font = rufl_CACHE_NONE; } } free(rufl_family_menu); rufl_family_menu = 0; free(rufl_substitution_table); rufl_substitution_table = 0; } netsurf-2.9/librufl-0.0.1/src/Makefile0000664000175000017500000000072711510173503016370 0ustar vincevince# Sources DIR_SOURCES := rufl_character_set_test.c rufl_decompose.c rufl_dump_state.c \ rufl_find.c rufl_init.c rufl_invalidate_cache.c \ rufl_metrics.c rufl_paint.c rufl_quit.c ifeq ($(toolchain),norcroft) DIR_SOURCES := $(DIR_SOURCES) strfuncs.c endif SOURCES := $(SOURCES) $(BUILDDIR)/rufl_glyph_map.c $(BUILDDIR)/rufl_glyph_map.c: src/Glyphs $(VQ)$(ECHO) "MKGLYPHS: $<" $(Q)$(PERL) build/tools/makeglyphs < $< > $@ include build/makefiles/Makefile.subdir netsurf-2.9/librufl-0.0.1/src/rufl_find.c0000664000175000017500000001154011321135473017043 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2005 James Bursa * Copyright 2005 John-Mark Bell */ #include #include #include #include #include #include "rufl_internal.h" static int rufl_family_list_cmp(const void *keyval, const void *datum); static rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size, const char *encoding, font_f f); /** * Find a font family. */ rufl_code rufl_find_font_family(const char *font_family, rufl_style font_style, unsigned int *font, unsigned int *slanted, struct rufl_character_set **charset) { const char **family; unsigned int f; unsigned int weight, slant, used_weight; unsigned int search_direction; family = bsearch(font_family, rufl_family_list, rufl_family_list_entries, sizeof rufl_family_list[0], rufl_family_list_cmp); if (!family) return rufl_FONT_NOT_FOUND; weight = (font_style & 0xf) - 1; assert(weight <= 8); slant = font_style & rufl_SLANTED ? 1 : 0; struct rufl_family_map_entry *e = &rufl_family_map[family - rufl_family_list]; used_weight = weight; if (weight <= 2) search_direction = -1; else search_direction = +1; while (1) { if (e->font[used_weight][slant] != NO_FONT) { /* the weight and slant is available */ f = e->font[used_weight][slant]; break; } if (e->font[used_weight][1 - slant] != NO_FONT) { /* slanted, and non-slanted weight exists, or vv. */ f = e->font[used_weight][1 - slant]; break; } if (used_weight == 0) { /* searched down without finding a weight: search up */ used_weight = weight + 1; search_direction = +1; } else if (used_weight == 8) { /* searched up without finding a weight: search down */ used_weight = weight - 1; search_direction = -1; } else { /* try the next weight in the current direction */ used_weight += search_direction; } } if (font) (*font) = f; if (slanted) (*slanted) = slant; if (charset) (*charset) = rufl_font_list[f].charset; return rufl_OK; } /** * Find a sized font, placing in the cache if necessary. */ rufl_code rufl_find_font(unsigned int font, unsigned int font_size, const char *encoding, font_f *fhandle) { font_f f; char font_name[80]; unsigned int i; rufl_code code; assert(fhandle != NULL); for (i = 0; i != rufl_CACHE_SIZE; i++) { /* Comparing pointers for the encoding is fine, as the * encoding string passed to us is either: * * a) NULL * or b) statically allocated * or c) resides in the font's umap, which is constant * for the lifetime of the application. */ if (rufl_cache[i].font == font && rufl_cache[i].size == font_size && rufl_cache[i].encoding == encoding) break; } if (i != rufl_CACHE_SIZE) { /* found in cache */ f = rufl_cache[i].f; rufl_cache[i].last_used = rufl_cache_time++; } else { /* not found */ if (font == rufl_CACHE_CORPUS) { if (encoding) snprintf(font_name, sizeof font_name, "Corpus.Medium\\E%s", encoding); else snprintf(font_name, sizeof font_name, "Corpus.Medium"); } else { if (encoding) snprintf(font_name, sizeof font_name, "%s\\E%s", rufl_font_list[font].identifier, encoding); else snprintf(font_name, sizeof font_name, "%s", rufl_font_list[font].identifier); } rufl_fm_error = xfont_find_font(font_name, font_size, font_size, 0, 0, &f, 0, 0); if (rufl_fm_error) { LOG("xfont_find_font: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } /* place in cache */ code = rufl_place_in_cache(font, font_size, encoding, f); if (code != rufl_OK) return code; } (*fhandle) = f; return rufl_OK; } int rufl_family_list_cmp(const void *keyval, const void *datum) { const char *key = keyval; const char * const *entry = datum; return strcasecmp(key, *entry); } /** * Place a font into the recent-use cache, making space if necessary. */ rufl_code rufl_place_in_cache(unsigned int font, unsigned int font_size, const char *encoding, font_f f) { unsigned int i; unsigned int max_age = 0; unsigned int evict = 0; for (i = 0; i != rufl_CACHE_SIZE; i++) { if (rufl_cache[i].font == rufl_CACHE_NONE) { evict = i; break; } else if (max_age < rufl_cache_time - rufl_cache[i].last_used) { max_age = rufl_cache_time - rufl_cache[i].last_used; evict = i; } } if (rufl_cache[evict].font != rufl_CACHE_NONE) { rufl_fm_error = xfont_lose_font(rufl_cache[evict].f); if (rufl_fm_error) return rufl_FONT_MANAGER_ERROR; } rufl_cache[evict].font = font; rufl_cache[evict].size = font_size; rufl_cache[evict].encoding = encoding; rufl_cache[evict].f = f; rufl_cache[evict].last_used = rufl_cache_time++; return rufl_OK; } netsurf-2.9/librufl-0.0.1/src/rufl_paint.c0000664000175000017500000003763311321135473017251 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2006 James Bursa */ #include #include #include #include #include #include "oslib/font.h" #include "rufl_internal.h" typedef enum { rufl_PAINT, rufl_WIDTH, rufl_X_TO_OFFSET, rufl_SPLIT, rufl_PAINT_CALLBACK, rufl_FONT_BBOX } rufl_action; #define rufl_PROCESS_CHUNK 200 bool rufl_can_background_blend = false; static const os_trfm trfm_oblique = { { { 65536, 0 }, { 13930, 65536 }, { 0, 0 } } }; static rufl_code rufl_process(rufl_action action, const char *font_family, rufl_style font_style, unsigned int font_size, const char *string0, size_t length, int x, int y, unsigned int flags, int *width, int click_x, size_t *char_offset, int *actual_x, rufl_callback_t callback, void *context); static rufl_code rufl_process_span(rufl_action action, unsigned short *s, unsigned int n, unsigned int font, unsigned int font_size, unsigned int slant, int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context); static rufl_code rufl_process_span_old(rufl_action action, unsigned short *s, unsigned int n, unsigned int font, unsigned int font_size, unsigned int slant, int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context); static int rufl_unicode_map_search_cmp(const void *keyval, const void *datum); static rufl_code rufl_process_not_available(rufl_action action, unsigned short *s, unsigned int n, unsigned int font_size, int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context); /** * Render Unicode text. */ rufl_code rufl_paint(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int x, int y, unsigned int flags) { return rufl_process(rufl_PAINT, font_family, font_style, font_size, string, length, x, y, flags, 0, 0, 0, 0, 0, 0); } /** * Measure the width of Unicode text. */ rufl_code rufl_width(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int *width) { return rufl_process(rufl_WIDTH, font_family, font_style, font_size, string, length, 0, 0, 0, width, 0, 0, 0, 0, 0); } /** * Find the nearest character boundary in a string to where an x coordinate * falls. */ rufl_code rufl_x_to_offset(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int click_x, size_t *char_offset, int *actual_x) { return rufl_process(rufl_X_TO_OFFSET, font_family, font_style, font_size, string, length, 0, 0, 0, 0, click_x, char_offset, actual_x, 0, 0); } /** * Find the prefix of a string that will fit in a specified width. */ rufl_code rufl_split(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int width, size_t *char_offset, int *actual_x) { return rufl_process(rufl_SPLIT, font_family, font_style, font_size, string, length, 0, 0, 0, 0, width, char_offset, actual_x, 0, 0); } /** * Render text, but call a callback instead of each call to Font_Paint. */ rufl_code rufl_paint_callback(const char *font_family, rufl_style font_style, unsigned int font_size, const char *string, size_t length, int x, int y, rufl_callback_t callback, void *context) { return rufl_process(rufl_PAINT_CALLBACK, font_family, font_style, font_size, string, length, x, y, 0, 0, 0, 0, 0, callback, context); } /** * Determine the maximum bounding box of a font. */ rufl_code rufl_font_bbox(const char *font_family, rufl_style font_style, unsigned int font_size, int *bbox) { return rufl_process(rufl_FONT_BBOX, font_family, font_style, font_size, 0, 0, 0, 0, 0, bbox, 0, 0, 0, 0, 0); } /** * Render, measure, or split Unicode text. */ rufl_code rufl_process(rufl_action action, const char *font_family, rufl_style font_style, unsigned int font_size, const char *string0, size_t length, int x, int y, unsigned int flags, int *width, int click_x, size_t *char_offset, int *actual_x, rufl_callback_t callback, void *context) { unsigned short s[rufl_PROCESS_CHUNK]; unsigned int font; unsigned int font0, font1; unsigned int n; unsigned int u; size_t offset; size_t offset_u; size_t offset_map[rufl_PROCESS_CHUNK]; unsigned int slant; const char *string = string0; struct rufl_character_set *charset; rufl_code code; assert(action == rufl_PAINT || (action == rufl_WIDTH && width) || (action == rufl_X_TO_OFFSET && char_offset && actual_x) || (action == rufl_SPLIT && char_offset && actual_x) || (action == rufl_PAINT_CALLBACK && callback) || (action == rufl_FONT_BBOX && width)); if ((flags & rufl_BLEND_FONT) && !rufl_can_background_blend) { /* unsuitable FM => clear blending bit */ flags &= ~rufl_BLEND_FONT; } if (length == 0 && action != rufl_FONT_BBOX) { if (action == rufl_WIDTH) *width = 0; else if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { *char_offset = 0; *actual_x = 0; } return rufl_OK; } if ((action == rufl_X_TO_OFFSET || action == rufl_SPLIT) && click_x <= 0) { *char_offset = 0; *actual_x = 0; return rufl_OK; } code = rufl_find_font_family(font_family, font_style, &font, &slant, &charset); if (code != rufl_OK) return code; if (action == rufl_FONT_BBOX) { if (rufl_old_font_manager) code = rufl_process_span_old(action, 0, 0, font, font_size, slant, width, 0, 0, 0, 0, 0, 0); else code = rufl_process_span(action, 0, 0, font, font_size, slant, width, 0, 0, 0, 0, 0, 0); return code; } offset_u = 0; rufl_utf8_read(string, length, u); if (u <= 0x001f || (0x007f <= u && u <= 0x009f)) font1 = NOT_AVAILABLE; else if (charset && rufl_character_set_test(charset, u)) font1 = font; else if (u < 0x10000) font1 = rufl_substitution_table[u]; else font1 = NOT_AVAILABLE; do { s[0] = u; offset_map[0] = offset_u; n = 1; font0 = font1; /* invariant: s[0..n) is in font font0 */ while (0 < length && n < rufl_PROCESS_CHUNK && font1 == font0) { offset_u = string - string0; rufl_utf8_read(string, length, u); s[n] = u; offset_map[n] = offset_u; if (u <= 0x001f || (0x007f <= u && u <= 0x009f)) font1 = NOT_AVAILABLE; else if (charset && rufl_character_set_test(charset, u)) font1 = font; else if (u < 0x10000) font1 = rufl_substitution_table[u]; else font1 = NOT_AVAILABLE; if (font1 == font0) n++; } if (n == rufl_PROCESS_CHUNK) n--; s[n] = 0; offset_map[n] = offset_u; if (length == 0 && font1 == font0) offset_map[n] = string - string0; if (font0 == NOT_AVAILABLE) code = rufl_process_not_available(action, s, n, font_size, &x, y, flags, click_x, &offset, callback, context); else if (rufl_old_font_manager) code = rufl_process_span_old(action, s, n, font0, font_size, slant, &x, y, flags, click_x, &offset, callback, context); else code = rufl_process_span(action, s, n, font0, font_size, slant, &x, y, flags, click_x, &offset, callback, context); if ((action == rufl_X_TO_OFFSET || action == rufl_SPLIT) && (offset < n || click_x < x)) break; if (code != rufl_OK) return code; } while (!(length == 0 && font1 == font0)); if (action == rufl_WIDTH) *width = x; else if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { *char_offset = offset_map[offset]; *actual_x = x; } return rufl_OK; } /** * Render a string of characters from a single RISC OS font. */ rufl_code rufl_process_span(rufl_action action, unsigned short *s, unsigned int n, unsigned int font, unsigned int font_size, unsigned int slant, int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context) { unsigned short *split_point; int x_out, y_out; unsigned int i; char font_name[80]; bool oblique = slant && !rufl_font_list[font].slant; font_f f; rufl_code code; code = rufl_find_font(font, font_size, "UTF8", &f); if (code != rufl_OK) return code; if (action == rufl_FONT_BBOX) { rufl_fm_error = xfont_read_info(f, &x[0], &x[1], &x[2], &x[3]); if (rufl_fm_error) return rufl_FONT_MANAGER_ERROR; return rufl_OK; } if (action == rufl_PAINT) { /* paint span */ rufl_fm_error = xfont_paint(f, (const char *) s, font_OS_UNITS | (oblique ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | font_GIVEN16_BIT | ((flags & rufl_BLEND_FONT) ? font_BLEND_FONT : 0), *x, y, 0, &trfm_oblique, n * 2); if (rufl_fm_error) { LOG("xfont_paint: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); for (i = 0; i != n; i++) fprintf(stderr, "0x%x ", s[i]); fprintf(stderr, " (%u)\n", n); return rufl_FONT_MANAGER_ERROR; } } else if (action == rufl_PAINT_CALLBACK) { snprintf(font_name, sizeof font_name, "%s\\EUTF8", rufl_font_list[font].identifier); callback(context, font_name, font_size, 0, s, n, *x, y); } /* increment x by width of span */ if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { rufl_fm_error = xfont_scan_string(f, (const char *) s, font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | font_GIVEN16_BIT | ((action == rufl_X_TO_OFFSET) ? font_RETURN_CARET_POS : 0), (click_x - *x) * 400, 0x7fffffff, 0, 0, n * 2, (char **)(void *)&split_point, &x_out, &y_out, 0); *offset = split_point - s; } else { rufl_fm_error = xfont_scan_string(f, (const char *) s, font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | font_GIVEN16_BIT, 0x7fffffff, 0x7fffffff, 0, 0, n * 2, 0, &x_out, &y_out, 0); } if (rufl_fm_error) { LOG("xfont_scan_string: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } *x += x_out / 400; return rufl_OK; } /** * Render a string of characters from a single RISC OS font (old font manager * version). */ rufl_code rufl_process_span_old(rufl_action action, unsigned short *s, unsigned int n, unsigned int font, unsigned int font_size, unsigned int slant, int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context) { char s2[rufl_PROCESS_CHUNK]; char *split_point; int x_out, y_out; unsigned int i; bool oblique = slant && !rufl_font_list[font].slant; font_f f; rufl_code code; if (action == rufl_FONT_BBOX) { /* Don't need encoding for bounding box */ code = rufl_find_font(font, font_size, NULL, &f); if (code != rufl_OK) return code; rufl_fm_error = xfont_read_info(f, &x[0], &x[1], &x[2], &x[3]); if (rufl_fm_error) { LOG("xfont_read_info: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } return rufl_OK; } if (offset) *offset = 0; /* Process the span in map-coherent chunks */ do { struct rufl_unicode_map *map = NULL; struct rufl_unicode_map_entry *entry = NULL; unsigned int j; i = 0; /* Find map for first character */ for (j = 0; j < rufl_font_list[font].num_umaps; j++) { map = rufl_font_list[font].umap + j; entry = bsearch(&s[i], map->map, map->entries, sizeof map->map[0], rufl_unicode_map_search_cmp); if (entry) break; } assert(map != NULL); assert(entry != NULL); /* Collect characters: s[0..i) use map */ do { entry = bsearch(&s[i], map->map, map->entries, sizeof map->map[0], rufl_unicode_map_search_cmp); if (entry) s2[i++] = entry->c; } while (i != n && entry != NULL); s2[i] = 0; code = rufl_find_font(font, font_size, map->encoding, &f); if (code != rufl_OK) return code; if (action == rufl_PAINT) { /* paint span */ /* call Font_SetFont to work around broken PS printer * driver, which doesn't use the font handle from * Font_Paint */ rufl_fm_error = xfont_set_font(f); if (rufl_fm_error) { LOG("xfont_set_font: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } rufl_fm_error = xfont_paint(f, s2, font_OS_UNITS | (oblique ? font_GIVEN_TRFM : 0) | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | ((flags & rufl_BLEND_FONT) ? font_BLEND_FONT : 0), *x, y, 0, &trfm_oblique, i); if (rufl_fm_error) { LOG("xfont_paint: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } } else if (action == rufl_PAINT_CALLBACK) { char font_name[80]; if (map->encoding) snprintf(font_name, sizeof font_name, "%s\\E%s", rufl_font_list[font].identifier, map->encoding); else snprintf(font_name, sizeof font_name, "%s", rufl_font_list[font].identifier); callback(context, font_name, font_size, s2, 0, i, *x, y); } /* increment x by width of span */ if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { rufl_fm_error = xfont_scan_string(f, s2, font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | ((action == rufl_X_TO_OFFSET) ? font_RETURN_CARET_POS : 0), (click_x - *x) * 400, 0x7fffffff, 0, 0, i, &split_point, &x_out, &y_out, 0); *offset += split_point - s2; } else { rufl_fm_error = xfont_scan_string(f, s2, font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN, 0x7fffffff, 0x7fffffff, 0, 0, i, 0, &x_out, &y_out, 0); } if (rufl_fm_error) { LOG("xfont_scan_string: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess); return rufl_FONT_MANAGER_ERROR; } *x += x_out / 400; /* Now update s and n for the next chunk */ s += i; n -= i; } while (n != 0); return rufl_OK; } int rufl_unicode_map_search_cmp(const void *keyval, const void *datum) { const unsigned short *key = keyval; const struct rufl_unicode_map_entry *entry = datum; if (*key < entry->u) return -1; else if (entry->u < *key) return 1; return 0; } /** * Render a string of characters not available in any font as their hex code. */ rufl_code rufl_process_not_available(rufl_action action, unsigned short *s, unsigned int n, unsigned int font_size, int *x, int y, unsigned int flags, int click_x, size_t *offset, rufl_callback_t callback, void *context) { char missing[] = "0000"; int dx = 7 * font_size / 64; int top_y = y + 5 * font_size / 64; unsigned int i; font_f f; rufl_code code; if (action == rufl_WIDTH) { *x += n * dx; return rufl_OK; } else if (action == rufl_X_TO_OFFSET || action == rufl_SPLIT) { if (click_x - *x < (int) (n * dx)) *offset = (click_x - *x) / dx; else *offset = n; *x += *offset * dx; return rufl_OK; } code = rufl_find_font(rufl_CACHE_CORPUS, font_size / 2, "Latin1", &f); if (code != rufl_OK) return code; for (i = 0; i != n; i++) { missing[0] = "0123456789abcdef"[(s[i] >> 12) & 0xf]; missing[1] = "0123456789abcdef"[(s[i] >> 8) & 0xf]; missing[2] = "0123456789abcdef"[(s[i] >> 4) & 0xf]; missing[3] = "0123456789abcdef"[(s[i] >> 0) & 0xf]; /* first two characters in top row */ if (action == rufl_PAINT) { rufl_fm_error = xfont_paint(f, missing, font_OS_UNITS | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | ((flags & rufl_BLEND_FONT) ? font_BLEND_FONT : 0), *x, top_y, 0, 0, 2); if (rufl_fm_error) return rufl_FONT_MANAGER_ERROR; } else { callback(context, "Corpus.Medium\\ELatin1", font_size / 2, missing, 0, 2, *x, top_y); } /* last two characters underneath */ if (action == rufl_PAINT) { rufl_fm_error = xfont_paint(f, missing + 2, font_OS_UNITS | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | ((flags & rufl_BLEND_FONT) ? font_BLEND_FONT : 0), *x, y, 0, 0, 2); if (rufl_fm_error) return rufl_FONT_MANAGER_ERROR; } else { callback(context, "Corpus.Medium\\ELatin1", font_size / 2, missing + 2, 0, 2, *x, y); } *x += dx; } return rufl_OK; } netsurf-2.9/librufl-0.0.1/src/rufl_dump_state.c0000664000175000017500000000567511321135473020304 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2006 James Bursa */ #include #include "rufl_internal.h" static void rufl_dump_character_set(struct rufl_character_set *charset); static void rufl_dump_unicode_map(struct rufl_unicode_map *umap); static void rufl_dump_substitution_table(void); /** * Dump the internal library state to stdout. */ void rufl_dump_state(void) { unsigned int i, j; printf("rufl_font_list:\n"); for (i = 0; i != rufl_font_list_entries; i++) { printf(" %u \"%s\"\n", i, rufl_font_list[i].identifier); if (rufl_font_list[i].charset) { printf(" "); rufl_dump_character_set(rufl_font_list[i].charset); printf("\n"); } else { printf(" (no charset table)\n"); } if (rufl_font_list[i].umap) { for (j = 0; j < rufl_font_list[i].num_umaps; j++) { struct rufl_unicode_map *map = rufl_font_list[i].umap + j; printf(" "); rufl_dump_unicode_map(map); printf("\n"); } } } printf("rufl_family_list:\n"); for (i = 0; i != rufl_family_list_entries; i++) { printf(" %u \"%s\"\n", i, rufl_family_list[i]); for (j = 0; j != 9; j++) { struct rufl_family_map_entry *e = &rufl_family_map[i]; printf(" %u ", j); if (e->font[j][0] == NO_FONT) printf("- "); else printf("\"%s\" ", rufl_font_list[e->font[j][0]]. identifier); if (e->font[j][1] == NO_FONT) printf("- "); else printf("\"%s\" ", rufl_font_list[e->font[j][1]]. identifier); printf("\n"); } } printf("rufl_substitution_table:\n"); rufl_dump_substitution_table(); } /** * Dump a representation of a character set to stdout. * * \param charset character set to print */ void rufl_dump_character_set(struct rufl_character_set *charset) { unsigned int u, t; u = 0; while (u != 0x10000) { while (u != 0x10000 && !rufl_character_set_test(charset, u)) u++; if (u != 0x10000) { if (!rufl_character_set_test(charset, u + 1)) { printf("%x ", u); u++; } else { t = u; while (rufl_character_set_test(charset, u)) u++; printf("%x-%x ", t, u - 1); } } } } /** * Dump a representation of a unicode map to stdout. * * \param umap unicode map to print */ void rufl_dump_unicode_map(struct rufl_unicode_map *umap) { unsigned int i; if (umap->encoding) printf("%s: ", umap->encoding); for (i = 0; i != umap->entries; i++) printf("%x:%x ", umap->map[i].u, umap->map[i].c); } /** * Dump a representation of the substitution table to stdout. */ void rufl_dump_substitution_table(void) { unsigned int font; unsigned int u, t; u = 0; while (u != 0x10000) { t = u; font = rufl_substitution_table[t]; while (u != 0x10000 && font == rufl_substitution_table[u]) u++; if (font != NOT_AVAILABLE) printf(" %x-%x => %u \"%s\"\n", t, u - 1, font, rufl_font_list[font].identifier); } } netsurf-2.9/librufl-0.0.1/test/0000775000175000017500000000000011734430311015113 5ustar vincevincenetsurf-2.9/librufl-0.0.1/test/rufl_test.c0000664000175000017500000000725611321135473017303 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2006 James Bursa */ #include #include #include #include "rufl.h" static void try(rufl_code code, const char *context); static int move_to(os_coord *to, void *user); static int line_to(os_coord *to, void *user); static int cubic_to(os_coord *control1, os_coord *control2, os_coord *to, void *user); static void callback(void *context, const char *font_name, unsigned int font_size, const char *s8, unsigned short *s16, unsigned int n, int x, int y); int main(void) { char utf8_test[] = "Hello, world! ὕαλον " "Uherské Hradiště. 𐀀"; int width; size_t char_offset; int x; int actual_x; struct rufl_decomp_funcs funcs = { move_to, line_to, cubic_to }; int bbox[4]; try(rufl_init(), "rufl_init"); rufl_dump_state(); try(rufl_paint("NewHall", rufl_WEIGHT_400, 240, utf8_test, sizeof utf8_test - 1, 1200, 1000, 0), "rufl_paint"); try(rufl_width("NewHall", rufl_WEIGHT_400, 240, utf8_test, sizeof utf8_test - 1, &width), "rufl_width"); printf("width: %i\n", width); for (x = 0; x < width + 100; x += 100) { try(rufl_x_to_offset("NewHall", rufl_WEIGHT_400, 240, utf8_test, sizeof utf8_test - 1, x, &char_offset, &actual_x), "rufl_x_to_offset"); printf("x to offset: %i -> %i %zi \"%s\"\n", x, actual_x, char_offset, utf8_test + char_offset); try(rufl_split("NewHall", rufl_WEIGHT_400, 240, utf8_test, sizeof utf8_test - 1, x, &char_offset, &actual_x), "rufl_split"); printf("split: %i -> %i %zi \"%s\"\n", x, actual_x, char_offset, utf8_test + char_offset); } try(rufl_decompose_glyph("Homerton", rufl_WEIGHT_400, 1280, "A", 1, &funcs, 0), "rufl_decompose_glyph"); try(rufl_paint_callback("NewHall", rufl_WEIGHT_400, 240, utf8_test, sizeof utf8_test - 1, 1200, 1000, callback, 0), "rufl_paint_callback"); try(rufl_font_bbox("NewHall", rufl_WEIGHT_400, 240, bbox), "rufl_font_bbox"); printf("bbox: %i %i %i %i\n", bbox[0], bbox[1], bbox[2], bbox[3]); rufl_quit(); return 0; } void try(rufl_code code, const char *context) { if (code == rufl_OK) return; else if (code == rufl_OUT_OF_MEMORY) printf("error: %s: out of memory\n", context); else if (code == rufl_FONT_MANAGER_ERROR) printf("error: %s: Font Manager error %x %s\n", context, rufl_fm_error->errnum, rufl_fm_error->errmess); else if (code == rufl_FONT_NOT_FOUND) printf("error: %s: font not found\n", context); else if (code == rufl_IO_ERROR) printf("error: %s: io error: %i %s\n", context, errno, strerror(errno)); else if (code == rufl_IO_EOF) printf("error: %s: eof\n", context); else printf("error: %s: unknown error\n", context); rufl_quit(); exit(1); } int move_to(os_coord *to, void *user) { (void) user; printf("Move to (%d,%d)\n", to->x, to->y); return 0; } int line_to(os_coord *to, void *user) { (void) user; printf("Line to (%d,%d)\n", to->x, to->y); return 0; } int cubic_to(os_coord *control1, os_coord *control2, os_coord *to, void *user) { (void) user; printf("Bezier to (%d,%d),(%d,%d),(%d,%d)\n", control1->x, control1->y, control2->x, control2->y, to->x, to->y); return 0; } void callback(void *context, const char *font_name, unsigned int font_size, const char *s8, unsigned short *s16, unsigned int n, int x, int y) { (void) context; printf("callback: \"%s\", %u, ", font_name, font_size); if (s8) printf("s8 \"%.*s\" ", n, s8); else { printf("s16 \""); for (unsigned int i = 0; i != n; i++) printf("%x ", (unsigned int) s16[i]); printf("\" "); } printf("%i %i\n", x, y); } netsurf-2.9/librufl-0.0.1/test/rufl_chars.c0000664000175000017500000002006711321135473017417 0ustar vincevince/* * This file is part of RUfl * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license * Copyright 2006 James Bursa */ #include #include #include #include #include #include "oslib/colourtrans.h" #include "oslib/wimp.h" #include "rufl.h" unsigned int font = 0; unsigned int weight = rufl_WEIGHT_400; bool italic = false; static rufl_code redraw(int x, int y, int y0, int y1); static void try(rufl_code code, const char *context); static void die(const char *error); int main(void) { unsigned int i; bool quit = false; const wimp_MESSAGE_LIST(2) messages = { { message_MODE_CHANGE, message_QUIT } }; wimp_t task; wimp_menu *menu; struct wimp_window_base window = { { 400, 400, 1700, 1200 }, 0, 0, wimp_TOP, wimp_WINDOW_MOVEABLE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_TOGGLE_ICON | wimp_WINDOW_VSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_NEW_FORMAT, wimp_COLOUR_BLACK, wimp_COLOUR_LIGHT_GREY, wimp_COLOUR_BLACK, wimp_COLOUR_WHITE, wimp_COLOUR_DARK_GREY, wimp_COLOUR_MID_LIGHT_GREY, wimp_COLOUR_CREAM, 0, { 0, -81928, 1300, 0 }, wimp_ICON_TEXT | wimp_ICON_HCENTRED, 0, 0, 2, 1, { "RUfl Chars" }, 0 }; wimp_w w; wimp_window_state state; wimp_block block; wimp_event_no event; wimp_pointer pointer; osbool more; os_error *error; rufl_code code = rufl_OK; error = xwimp_initialise(wimp_VERSION_RO3, "RUfl Chars", (const wimp_message_list *) (const void *) &messages, 0, &task); if (error) { printf("error: xwimp_initialise: 0x%x: %s\n", error->errnum, error->errmess); exit(1); } try(rufl_init(), "rufl_init"); menu = malloc(wimp_SIZEOF_MENU(10 + rufl_family_list_entries)); if (!menu) die("Out of memory"); strcpy(menu->title_data.text, "Fonts"); menu->title_fg = wimp_COLOUR_BLACK; menu->title_bg = wimp_COLOUR_LIGHT_GREY; menu->work_fg = wimp_COLOUR_RED; menu->work_bg = wimp_COLOUR_WHITE; menu->width = 200; menu->height = wimp_MENU_ITEM_HEIGHT; menu->gap = wimp_MENU_ITEM_GAP; for (i = 0; i != 10; i++) { menu->entries[i].menu_flags = 0; menu->entries[i].sub_menu = wimp_NO_SUB_MENU; menu->entries[i].icon_flags = wimp_ICON_TEXT | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); strcpy(menu->entries[i].data.text, "100"); menu->entries[i].data.text[0] = '1' + i; } menu->entries[9].menu_flags = wimp_MENU_SEPARATE; menu->entries[9].sub_menu = wimp_NO_SUB_MENU; menu->entries[9].icon_flags = wimp_ICON_TEXT | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); strcpy(menu->entries[9].data.text, "Italic"); for (i = 0; i != rufl_family_list_entries; i++) { menu->entries[10 + i].menu_flags = 0; menu->entries[10 + i].sub_menu = wimp_NO_SUB_MENU; menu->entries[10 + i].icon_flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) | (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT); menu->entries[10 + i].data.indirected_text.text = (char *) rufl_family_list[i]; menu->entries[10 + i].data.indirected_text.validation = (char *) -1; menu->entries[10 + i].data.indirected_text.size = strlen(rufl_family_list[i]); } menu->entries[3].menu_flags |= wimp_MENU_TICKED; menu->entries[10].menu_flags |= wimp_MENU_TICKED; menu->entries[i + 9].menu_flags |= wimp_MENU_LAST; error = xwimp_create_window((wimp_window *) &window, &w); if (error) die(error->errmess); state.w = w; error = xwimp_get_window_state(&state); if (error) die(error->errmess); error = xwimp_open_window((wimp_open *) (void *) &state); if (error) die(error->errmess); while (!quit) { error = xwimp_poll(wimp_MASK_NULL, &block, 0, &event); if (error) die(error->errmess); switch (event) { case wimp_REDRAW_WINDOW_REQUEST: error = xwimp_redraw_window(&block.redraw, &more); if (error) die(error->errmess); xcolourtrans_set_font_colours(0, os_COLOUR_WHITE, os_COLOUR_BLACK, 14, 0, 0, 0); while (more) { code = redraw(block.redraw.box.x0 - block.redraw.xscroll, block.redraw.box.y1 - block.redraw.yscroll, block.redraw.box.y1 - block.redraw.yscroll - block.redraw.clip.y1, block.redraw.box.y1 - block.redraw.yscroll - block.redraw.clip.y0); error = xwimp_get_rectangle(&block.redraw, &more); if (error) die(error->errmess); } try(code, "redraw"); break; case wimp_OPEN_WINDOW_REQUEST: error = xwimp_open_window(&block.open); if (error) die(error->errmess); break; case wimp_CLOSE_WINDOW_REQUEST: quit = true; break; case wimp_MOUSE_CLICK: if (block.pointer.buttons == wimp_CLICK_MENU) { error = xwimp_create_menu(menu, block.pointer.pos.x - 64, block.pointer.pos.y); if (error) die(error->errmess); } break; case wimp_MENU_SELECTION: error = xwimp_get_pointer_info(&pointer); if (error) die(error->errmess); if (block.selection.items[0] <= 8) { menu->entries[weight - 1].menu_flags ^= wimp_MENU_TICKED; weight = block.selection.items[0] + 1; menu->entries[weight - 1].menu_flags ^= wimp_MENU_TICKED; } else if (block.selection.items[0] == 9) { italic = !italic; menu->entries[9].menu_flags ^= wimp_MENU_TICKED; } else { menu->entries[10 + font].menu_flags ^= wimp_MENU_TICKED; font = block.selection.items[0] - 10; menu->entries[10 + font].menu_flags ^= wimp_MENU_TICKED; } error = xwimp_force_redraw(w, window.extent.x0, window.extent.y0, window.extent.x1, window.extent.y1); if (error) die(error->errmess); if (pointer.buttons == wimp_CLICK_ADJUST) { error = xwimp_create_menu(menu, pointer.pos.x - 64, pointer.pos.y); if (error) die(error->errmess); } break; case wimp_USER_MESSAGE: case wimp_USER_MESSAGE_RECORDED: switch (block.message.action) { case message_QUIT: quit = true; break; case message_MODE_CHANGE: rufl_invalidate_cache(); break; } break; } } /* try(rufl_paint("NewHall.Medium", 240, utf8_test, sizeof utf8_test - 1, */ /* 1200, 1200), "rufl_paint"); */ xwimp_close_down(task); rufl_quit(); return 0; } rufl_code redraw(int x, int y, int y0, int y1) { char s[10]; unsigned int l; unsigned int u; rufl_code code; rufl_style style = weight | (italic ? rufl_SLANTED : 0); for (u = y0 / 40 * 32; (int) u != (y1 / 40 + 1) * 32; u++) { if (u <= 0x7f) s[0] = u, l = 1; else if (u <= 0x7ff) s[0] = 0xc0 | (u >> 6), s[1] = 0x80 | (u & 0x3f), l = 2; else if (u <= 0xffff) s[0] = 0xe0 | (u >> 12), s[1] = 0x80 | ((u >> 6) & 0x3f), s[2] = 0x80 | (u & 0x3f), l = 3; else break; s[l] = 0; code = rufl_paint(rufl_family_list[font], style, 240, s, l, x + 10 + 40 * (u % 32), y - 40 - 40 * (u / 32), 0); if (code != rufl_OK) return code; } return rufl_OK; } void try(rufl_code code, const char *context) { char s[200]; if (code == rufl_OK) return; else if (code == rufl_OUT_OF_MEMORY) snprintf(s, sizeof s, "error: %s: out of memory\n", context); else if (code == rufl_FONT_MANAGER_ERROR) snprintf(s, sizeof s, "error: %s: Font Manager error %x %s\n", context, rufl_fm_error->errnum, rufl_fm_error->errmess); else if (code == rufl_FONT_NOT_FOUND) snprintf(s, sizeof s, "error: %s: font not found\n", context); else if (code == rufl_IO_ERROR) snprintf(s, sizeof s, "error: %s: io error: %i %s\n", context, errno, strerror(errno)); else if (code == rufl_IO_EOF) snprintf(s, sizeof s, "error: %s: eof\n", context); else snprintf(s, sizeof s, "error: %s: unknown error\n", context); die(s); } void die(const char *error) { os_error warn_error; warn_error.errnum = 1; strncpy(warn_error.errmess, error, sizeof warn_error.errmess - 1); warn_error.errmess[sizeof warn_error.errmess - 1] = '\0'; xwimp_report_error(&warn_error, wimp_ERROR_BOX_OK_ICON, "RUfl Chars", 0); rufl_quit(); exit(EXIT_FAILURE); } netsurf-2.9/librufl-0.0.1/test/Makefile0000664000175000017500000000016111321135473016554 0ustar vincevince# Tests DIR_TEST_ITEMS := rufl_test:rufl_test.c rufl_chars:rufl_chars.c include build/makefiles/Makefile.subdir netsurf-2.9/librufl-0.0.1/Makefile0000664000175000017500000000226111321135473015600 0ustar vincevince# Component settings COMPONENT := rufl COMPONENT_VERSION := 0.0.1 # Default to a static library COMPONENT_TYPE ?= lib-static # Setup the tooling include build/makefiles/Makefile.tools TESTRUNNER := $(ECHO) # Toolchain flags WARNFLAGS := -Wall -W -Wundef -Wpointer-arith -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ -Wmissing-declarations -Wnested-externs -pedantic # BeOS/Haiku/AmigaOS4 standard library headers create warnings ifneq ($(TARGET),beos) ifneq ($(TARGET),AmigaOS) WARNFLAGS := $(WARNFLAGS) -Werror endif endif CFLAGS := -I$(CURDIR)/include/ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS) ifneq ($(GCCVER),2) CFLAGS := $(CFLAGS) -std=c99 else # __inline__ is a GCCism CFLAGS := $(CFLAGS) -Dinline="__inline__" endif # OSLib ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) ifeq ($(TARGET),riscos) CFLAGS := $(CFLAGS) -I$(PREFIX)/include LDFLAGS := $(LDFLAGS) -lOSLib32 endif endif include build/makefiles/Makefile.top # Extra installation rules I := /include INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/rufl.h INSTALL_ITEMS := $(INSTALL_ITEMS) /lib/pkgconfig:lib$(COMPONENT).pc.in INSTALL_ITEMS := $(INSTALL_ITEMS) /lib:$(OUTPUT) netsurf-2.9/librufl-0.0.1/.cvsignore0000664000175000017500000000002710357312561016141 0ustar vincevince*,ff8 rufl_glyph_map.c netsurf-2.9/librufl-0.0.1/build/0000775000175000017500000000000011734430313015235 5ustar vincevincenetsurf-2.9/librufl-0.0.1/build/makefiles/0000775000175000017500000000000011734430313017175 5ustar vincevincenetsurf-2.9/librufl-0.0.1/build/makefiles/Makefile.top0000664000175000017500000004232311537116272021450 0ustar vincevince# Top-level Makefile fragment # # Expected inputs: # # BUILD Type of build to perform: # release - Release build # debug - Debug build # COMPONENT Name of the component (sans leading "lib" iff a library) # COMPONENT_VERSION Component version number (x.y.z) # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # TARGET Target platform identifier # # Optional inputs: # # BUILDDIR Directory to build into (defaults to # build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE)) # CC_CAN_BUILD_AND_DEP Flag whether $(CC) is capable of calculating dependency # information at the same time as compiling sources. # Set to "yes" if it can. # DESTDIR Sandboxed FS root (e.g. for packaging) # HOST Host platform identifier # REQUIRED_PKGS List of required pkg-config packages # # The client may also override all toolchain settings, including: # # ARFLAGS Archiver flags for the current compilation # CFLAGS C compiler flags for the current compilation # CXXFLAGS C++ compiler flags for the current compilation # LDFLAGS Linker flags for the current compilation # # TESTCFLAGS Any test-specific CFLAGS # TESTCXXFLAGS Any test-specific CXXFLAGS # TESTLDFLAGS Any test-specific LDFLAGS # # TESTRUNNER Test runner invocation command # The test runner takes a command line in the form # # # Targets provided: # # all Default target. Builds component using current settings # test Build and run test suite, using current settings. # coverage Determine test suite coverage (requires lcov) # profile Build with profiling support enabled (requires gprof) # docs Produce documentation (requires doxygen) # clean Clean the build # distclean Remove distribution files, too # install Install component into prefix. # uninstall Remove component from prefix. # # Variables provided: # # major-version Extracts the major version (x) from COMPONENT_VERSION # minor-version Extracts the minor version (y) from COMPONENT_VERSION # patch-version Extracts the patch version (z) from COMPONENT_VERSION # OUTPUT Path + filename of build target ############################################################################### # Sanity checks ############################################################################### # Name of component must be defined by client ifeq ($(COMPONENT),) $(error COMPONENT not defined) endif # As must the version ifeq ($(COMPONENT_VERSION),) $(error COMPONENT_VERSION not defined) endif # As must the component type ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not defined) endif # Target platform must be defined by the client ifeq ($(TARGET),) $(error TARGET not defined) endif # Build type, too ifeq ($(BUILD),) $(error BUILD not defined) endif ############################################################################## # Makefile variables ############################################################################## Q ?= @ VQ ?= @ ############################################################################## # Exported variables (also OUTPUT, further down) ############################################################################## major-version := $(word 1,$(subst ., ,$(COMPONENT_VERSION))) minor-version := $(word 2,$(subst ., ,$(COMPONENT_VERSION))) patch-version := $(word 3,$(subst ., ,$(COMPONENT_VERSION))) ############################################################################## # Build environment ############################################################################## # Build directory BUILDDIR ?= build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE) # Build tree subdirs COVERAGEDIR := $(BUILDDIR)/coverage DOCDIR := $(BUILDDIR)/docs # Determine if we want to build testcases ifeq ($(MAKECMDGOALS),test) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),profile) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),coverage) WANT_TEST := yes else WANT_TEST := no endif # List of items to delete on clean CLEAN_ITEMS := # List of items to delete on distclean DISTCLEAN_ITEMS := # List of items to build for testing TEST_ITEMS := # List of targets to run for testing TEST_TARGETS := # List of targets which are prerequisites for running tests TEST_PREREQS := # List of items to (un)install INSTALL_ITEMS := # List of targets to run before building $(OBJECT) PRE_TARGETS := # List of targets to run after building $(OBJECT) POST_TARGETS := # Source files SOURCES := # Include configuration Makefile fragment -include Makefile.config # Set the default target (before including any children) __default: all # Include Makefile fragments in subdirectories define do_include DIR := $$(dir $(1)) include $(1) endef MAKE_INCLUDES := $(wildcard */Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Calculate objects to build OBJECTS := $(addprefix $(BUILDDIR)/,$(filter %.o, \ $(subst /,_,$(subst .c,.o,$(SOURCES))) \ $(subst /,_,$(subst .cpp,.o,$(SOURCES))) \ $(subst /,_,$(subst .cmhg,.o,$(SOURCES))) \ $(subst /,_,$(subst .s,.o,$(SOURCES))))) bin_for_test = $(addprefix $(BUILDDIR)/,$(firstword $(subst :, ,$(ITEM)))) TEST_BINARIES := $(foreach ITEM,$(TEST_ITEMS),$(bin_for_test)) # Determine if we're building any C++ sources ifneq ($(filter %.cpp,$(SOURCES)),) CXX_IN_BUILD := yes else CXX_IN_BUILD := no endif # Determine the output filename ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) ifeq ($(findstring lib-shared,$(COMPONENT_TYPE)),lib-shared) SHAREDLIBNAME := lib$(COMPONENT)$(LIBEXT) SONAME := $(SHAREDLIBNAME).$(major-version) OUTPUT := $(BUILDDIR)/$(SHAREDLIBNAME).$(COMPONENT_VERSION) else OUTPUT := $(BUILDDIR)/lib$(COMPONENT)$(LIBEXT) endif else OUTPUT := $(BUILDDIR)/$(COMPONENT)$(EXEEXT) endif ############################################################################### # Build targets ############################################################################### .PHONY: all test coverage profile docs clean distclean install uninstall \ __default __precov __partial_clean __postshared ifeq ($(COMPONENT_TYPE),lib-shared) POST_TARGETS := __postshared $(POST_TARGETS) __postshared: $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SONAME) $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SHAREDLIBNAME) endif # Default target all: $(PRE_TARGETS) $(OUTPUT) $(POST_TARGETS) # Build and execute testsuite test: all $(TEST_PREREQS) $(TEST_BINARIES) $(TEST_TARGETS) $(VQ)$(ECHO) $(ECHOFLAGS) " TEST: Testing complete" # Compute coverage __precov: __partial_clean $(Q)$(LCOV) --directory . --zerocounters coverage: __precov test $(Q)$(LCOV) --directory $(BUILDDIR) --base-directory $(CURDIR) \ --capture --output-file $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(LCOV) --extract $(COVERAGEDIR)/$(COMPONENT)_tmp.info \ "$(CURDIR)/src*" -o $(COVERAGEDIR)/$(COMPONENT).info $(Q)$(RM) $(RMFLAGS) $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(GENHTML) -o $(COVERAGEDIR) --num-spaces 2 \ $(COVERAGEDIR)/$(COMPONENT).info # Build for profiling profile: __partial_clean test # Compile documentation docs: $(BUILDDIR)/stamp $(Q)$(DOXYGEN) build/Doxyfile # Clean build tree __partial_clean: -$(Q)$(RM) $(RMFLAGS) $(CLEAN_ITEMS) -$(Q)$(RM) $(RMFLAGS) gmon.out -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.d) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcda) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcno) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.o) clean: __partial_clean -$(Q)$(RM) $(RMFLAGS) -r build/docs -$(Q)$(RM) $(RMFLAGS) -r $(BUILDDIR) # Remove auto-generated non-build-tree items distclean: clean -$(Q)$(RM) $(RMFLAGS) $(DISTCLEAN_ITEMS) # The installation target, and associated canned command sequences. # For reference, the syntax of INSTALL_ITEMS is: # # :[';']* # # We also permit a trailing ';' in the file list. __comma := , __empty := __space := $(empty) $(empty) __required = $(if $(REQUIRED_PKGS),Requires: $(subst $(__space),$(__comma) ,$(strip $(REQUIRED_PKGS))),) # Install a pkg-config control file ($1) to the specified location ($2) define install_pkgconfig $(Q)$(ECHO) $(ECHOFLAGS) "sed -e... $1 >$(BUILDDIR)/$(1:.in=)" $(Q)$(SED) \ -e 's#PREFIX#$(PREFIX)#' \ -e 's#MAJOR#$(major-version)#' \ -e 's#MINOR#$(minor-version)#' \ -e 's#PATCH#$(patch-version)#' \ -e 's#VERSION#$(COMPONENT_VERSION)#' \ -e 's#REQUIRED#$(__required)#' \ $1 >$(BUILDDIR)/$(1:.in=) $(INSTALL) $(INSTALLFLAGS) -m 644 $(BUILDDIR)/$(1:.in=) \ $2/$(1:.in=) endef # TODO: Is this scheme portable? define install_shared_lib $(INSTALL) $(INSTALLFLAGS) -m 755 $1 $2/$(notdir $1) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SONAME) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SHAREDLIBNAME) endef # Install a file ($1) to the specified location ($2) define install_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(call install_pkgconfig,$1,$2), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call install_shared_lib,$1,$2), \ $(INSTALL) $(INSTALLFLAGS) -m 644 $1 $2))) endef # Install a list of files ($2) to the specified location ($1) # We create the installation location if it doesn't already exist define install_to_dest $(Q)$(MKDIR) $(MKDIRFLAGS) $(DESTDIR)$(PREFIX)$1 $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call install_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef install: all $(foreach ITEM,$(INSTALL_ITEMS), \ $(call install_to_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) # Uninstallation # TODO: Work out how to safely remove symlinks define uninstall_shared_lib $(RM) $(RMFLAGS) $2/$(notdir $1).$(COMPONENT_VERSION) endef # Uninstall a file ($1) from the specified location ($2) define uninstall_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(RM) $(RMFLAGS) $2/$(1:.pc.in=.pc), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call uninstall_shared_lib,$1,$2), \ $(RM) $(RMFLAGS) $2/$(notdir $1)))) endef # Uninstall a list of files ($2) from the specified location ($1) # TODO: Come up with a safe way of removing directories, too define uninstall_from_dest $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call uninstall_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef uninstall: $(foreach ITEM,$(INSTALL_ITEMS), \ $(call uninstall_from_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) ############################################################################### # Actual rules ############################################################################### $(BUILDDIR)/stamp: $(Q)$(MKDIR) $(MKDIRFLAGS) $(BUILDDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(COVERAGEDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(DOCDIR) $(Q)$(TOUCH) $(TOUCHFLAGS) $(BUILDDIR)/stamp $(OUTPUT): $(BUILDDIR)/stamp $(OBJECTS) ifeq ($(COMPONENT_TYPE),lib-static) $(VQ)$(ECHO) $(ECHOFLAGS) " AR: $@" $(Q)$(RM) $(RMFLAGS) $@ $(Q)$(AR) $(ARFLAGS) $@ $(OBJECTS) else $(VQ)$(ECHO) $(ECHOFLAGS) " LINK: $@" ifeq ($(CXX_IN_BUILD),yes) $(Q)$(CXX) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) else $(Q)$(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) endif endif ############################################################################### # Autogenerated, implied rules ############################################################################### DEPFILES := BUILDFILES := ifeq ($(CC_CAN_BUILD_AND_DEP),yes) # C compiler can compile and dep simultaneously define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else ifeq ($(CC_CANNOT_DEP),yes) # C compiler cannot calculate dependencies define dep_c endef define dep_cxx endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else # C compiler must calculate dependencies first, then compile (default) define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CC) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CXX) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef endif endif define build_cmhg ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " CMHG: $1" $$(Q)$$(CMHG) $$(CMHGFLAGS) $1 -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_s ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) "ASSEMBLE: $1" $$(Q)$$(CC) $$($3) $1 -c -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef BUILDCFLAGS = $(CFLAGS) $(SHAREDCFLAGS) BUILDCXXFLAGS = $(CXXFLAGS) $(SHAREDCXXFLAGS) BUILDASFLAGS = $(ASFLAGS) $(SHAREDCFLAGS) # Generate dependency rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),BUILDCXXFLAGS))) # Generate compilation rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),BUILDCXXFLAGS))) $(eval $(foreach SOURCE,$(filter %.cmhg,$(SOURCES)), \ $(call build_cmhg,$(SOURCE),$(subst /,_,$(SOURCE:.cmhg=.o))))) $(eval $(foreach SOURCE,$(filter %.s,$(SOURCES)), \ $(call build_s,$(SOURCE),$(subst /,_,$(SOURCE:.s=.o)),BUILDASFLAGS))) # Similarly for test sources ifeq ($(WANT_TEST),yes) ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) TESTLIB := $(OUTPUT) TESTLDFLAGS += -L$(BUILDDIR)/ -l$(COMPONENT) endif TESTCFLAGS := $(CFLAGS) $(TESTCFLAGS) TESTCXXFLAGS += $(CXXFLAGS) TESTLDFLAGS += $(LDFLAGS) define link_test $2: $($3) $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " LINK: $2" ifeq ($$(CXX_IN_BUILD),yes) $$(Q)$$(CXX) -o $$@ $1 $$($4) else $$(Q)$$(CC) -o $$@ $1 $$($4) endif endef srcs_for_test = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) objs_for_test = $(addprefix $(BUILDDIR)/, \ $(subst /,_,$(addsuffix .o,$(basename $(srcs_for_test))))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(call link_test,$(objs_for_test),$(bin_for_test),TESTLIB,TESTLDFLAGS))) endif # Include dependency makefiles ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) -include $(sort $(DEPFILES)) endif netsurf-2.9/librufl-0.0.1/build/makefiles/Makefile.clang0000664000175000017500000000232611545435603021732 0ustar vincevince# Clang-specific toolchain setup # We assume that we're using a standard GCC/binutils environment, as well # as clang being mostly GCC-compatible on the command line CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### CC_CAN_BUILD_AND_DEP ?= yes netsurf-2.9/librufl-0.0.1/build/makefiles/Makefile.norcroft0000664000175000017500000000220311545435603022474 0ustar vincevince# Norcroft specific toolchain setup CCDEF := -D CCOPT := -Otime CCNOOPT := CCDBG := -g CCINC := -I CCLIB := -L # TODO: Norcroft CC cannot do assembler as C CCAS := CCSHR := CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g LDSHR := ARFLG := -c # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) $(error Coverage is not supported with Norcroft) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) $(error Profile is not supported with Norcroft) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -zM CXXFLAGS := $(CXXFLAGS) -zM LDFLAGS := $(LDFLAGS) -zM endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. CC_CANNOT_DEP := yes netsurf-2.9/librufl-0.0.1/build/makefiles/Makefile.gcc0000664000175000017500000000457011545435603021405 0ustar vincevince# GCC specific toolchain setup # We assume that we're using a standard GCC/binutils environment CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions for various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="__attribute__((aligned))" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) COVCFLAGS ?= -fprofile-arcs -ftest-coverage COVCXXFLAGS ?= -fprofile-arcs -ftest-coverage COVLDFLAGS ?= -lgcov CFLAGS := $(CFLAGS) $(COVCFLAGS) CXXFLAGS := $(CXXFLAGS) $(COVCXXFLAGS) LDFLAGS := $(LDFLAGS) $(COVLDFLAGS) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) PROFCFLAGS ?= -pg PROFCXXFLAGS ?= -pg PROFLDFLAGS ?= -pg CFLAGS := $(CFLAGS) $(PROFCFLAGS) CXXFLAGS := $(CXXFLAGS) $(PROFCXXFLAGS) LDFLAGS := $(LDFLAGS) $(PROFLDFLAGS) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -mmodule CXXFLAGS := $(CXXFLAGS) -mmodule LDFLAGS := $(LDFLAGS) -mmodule endif ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CC_CAN_BUILD_AND_DEP := no CC_CANNOT_DEP := yes CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. ccvsn := $(shell $(CC) -dumpversion) # ccvsn = x.y.z GCCVER := $(word 1,$(subst ., ,$(ccvsn))) # GCCVER = x # If the major version (x, above) is not 2, then assume build & dep. # This will break if using a version of GCC < 2, but that's unlikely. ifneq ($(GCCVER),2) CC_CAN_BUILD_AND_DEP ?= yes endif netsurf-2.9/librufl-0.0.1/build/makefiles/Makefile.pkgconfig0000664000175000017500000000426511476474557022637 0ustar vincevince# General purpose pkg-config macros # Determine if a package is available # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_available ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package availability) endif ifeq ($$(shell $$(PKGCONFIG) --exists $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Retrieve the version of a package # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif $(1) := $$(shell $$(PKGCONFIG) --version $(2)) endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number define pkg_config_package_min_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number # 4: Highest accepted version number define pkg_config_package_compare_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) ifeq ($$(shell $$(PKGCONFIG) --max-version=$(4) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif else $(1) := no endif endef # Add package to compiler/linker flags # 1: Name of package to add details of # 2: CFLAGS variable to extend, or none # 3: LDFLAGS variable to extend, or none define pkg_config_package_add_flags ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifneq ($(2),) $(2) := $$($(2)) $$(shell $$(PKGCONFIG) --cflags $(1)) endif ifneq ($(3),) $(3) := $$($(3)) $$(shell $$(PKGCONFIG) --libs $(1)) endif endef netsurf-2.9/librufl-0.0.1/build/makefiles/Makefile.subdir0000664000175000017500000000741711165262413022137 0ustar vincevince# Child makefile fragment # # Inputs (reset on exit) # # DIR_SOURCES List of source files in this directory # DIR_TEST_ITEMS List of test items in this directory # DIR_INSTALL_ITEMS Items to install in form :; # # Toolchain is provided by top-level makefile # # Variables provided by top-level makefile # # BUILDDIR The location of the build tree root # COMPONENT The name of the component # CURDIR The location of the source tree root # EXPORTDIR The location of the export directory # WANT_TEST Whether to build testcases # # do_include Canned command sequence to include a child makefile # # Variables provided by parent makefile: # # DIR The name of the directory we're in, relative to CURDIR # # Variables we can manipulate: # # CLEAN_ITEMS The list of items to remove for "make clean" # DISTCLEAN_ITEMS The list of items to remove for "make distclean" # TEST_ITEMS The list of items to build for "make test" # TEST_TARGETS The list of target names to run for "make test" # INSTALL_ITEMS The list of items to (un)install # # SOURCES The list of sources to build for $(COMPONENT) # # Plus anything from the toolchain # Push parent directory onto the directory stack sp := $(sp).x dirstack_$(sp) := $(d) d := $(DIR) # Sources SRCS_$(d) := $(DIR_SOURCES) TEST_ITEMS_$(d) := INSTALL_ITEMS_$(d) := # Append to sources for component SOURCES := $(SOURCES) $(addprefix $(d), $(SRCS_$(d))) # Test sources ifeq ($(WANT_TEST),yes) ifneq ($(DIR_TEST_ITEMS),) # Extract the binary name from the ITEM binary = $(subst /,_,$(addprefix $(d),$(firstword $(subst :, ,$(ITEM))))) # Extract the list of sources from the ITEM sources = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) # We can't simply use the output of foreach here, # as it space separates its output, which kinda defeats the point. define append_test_src TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d))$1; endef define append_test TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d)) $1: $$(eval $$(foreach TSRC,$2, \ $$(call append_test_src,$$(addprefix $$(d),$$(TSRC))))) endef # Append test items, prepending $(d) to each source file $(eval $(foreach ITEM,$(DIR_TEST_ITEMS), \ $(call append_test,$(binary),$(sources)))) TEST_ITEMS := $(TEST_ITEMS) $(TEST_ITEMS_$(d)) TEST_TARGETS := $(TEST_TARGETS) test_$(d) # Extract the binary name from the TEST binary_name = $(firstword $(subst :, ,$(TEST))) # Target for tests in this directory test_$(d): $(d) $(addprefix $(BUILDDIR)/, \ $(foreach TEST,$(TEST_ITEMS_$(d)),$(binary_name))) $(Q)$(SHAREDLDPATH) $(TESTRUNNER) $(BUILDDIR) \ $(CURDIR)/$< $(subst /,_,$<) $(EXEEXT) endif endif # Install items ifneq ($(DIR_INSTALL_ITEMS),) # Extract the destination directory from the variable dest_dir = $(firstword $(subst :, ,$(ITEM))) # Extract the list of files to install files = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) define append_install_file INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d))$1; endef define append_install_item INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d)) $1: $$(eval $$(foreach FILE,$2, \ $$(call append_install_file,$$(addprefix $$(d),$$(FILE))))) endef # Append items to install (along with install location), prepending $(d) # to each item in the file list $(eval $(foreach ITEM,$(DIR_INSTALL_ITEMS), \ $(call append_install_item,$(dest_dir),$(files)))) INSTALL_ITEMS := $(INSTALL_ITEMS) $(INSTALL_ITEMS_$(d)) endif # Reset the inputs DIR_SOURCES := DIR_TEST_ITEMS := DIR_INSTALL_ITEMS := # Now include any children we may have MAKE_INCLUDES := $(wildcard $(d)*/Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Pop off the directory stack d := $(dirstack_$(sp)) sp := $(basename $(sp)) netsurf-2.9/librufl-0.0.1/build/makefiles/Makefile.tools0000664000175000017500000003224511537136047022012 0ustar vincevince# Tools Makefile fragment # # Expected inputs: # # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # # Optional inputs: # # BUILD Type of build to perform: # release - Release build (default) # debug - Debug build # OPTCFLAGS Optional C compiler flags for $(BUILD) # OPTCXXFLAGS Optional C++ compiler flags for $(BUILD) # OPTLDFLAGS Optional linker flags for $(BUILD) # TARGET Target platform (defaults to host) # PREFIX Absolute installation path prefix # (defaults to /usr/local) # ############################################################################### # Sanity checks ############################################################################### ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not set) endif # Default build to release ifeq ($(BUILD),) BUILD := release endif ############################################################################### # Host/target platform detection ############################################################################### # Autodetect host if necessary ifeq ($(HOST),) HOST := $(shell uname -s) endif # Simple host sanitisation ifeq ($(HOST),) # Don't ask HOST := riscos else ifeq ($(HOST),RISC OS) HOST := riscos endif ifeq ($(HOST),BeOS) HOST := beos endif ifeq ($(HOST),Haiku) HOST := haiku endif ifeq ($(HOST),AmigaOS) HOST := amiga endif ifeq ($(findstring MINGW,$(HOST)),MINGW) HOST := windows endif endif ifeq ($(TARGET),) # Default target to host. Please add exceptions as required. TARGET := $(HOST) ifeq ($(HOST),haiku) # This isn't necessarily correct -- they have differences. However, in the # general case, this will work. If there are differences that are actually # important wrt the target platform (as opposed to the build host) then # we'll just have to introduce a haiku target, too. TARGET := beos endif endif # Sanitise HOST and TARGET # TODO: Ideally, we want the equivalent of s/[^A-Za-z0-9]/_/g here HOST := $(subst .,_,$(subst -,_,$(subst /,_,$(HOST)))) TARGET := $(subst .,_,$(subst -,_,$(subst /,_,$(TARGET)))) # Now setup our tooling ifeq ($(TARGET),riscos) ifeq ($(HOST),riscos) # Building on native RISC OS GCCSDK_INSTALL_ENV ?= CC__ := gcc CXX__ := g++ CMHG ?= cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= # On certain versions of RISC OS (<>4 || kernel < 8.75), # the kernel will clean up the current redirection on # OS_Exit, including closing the associated file handles. # This is problematic for UnixLib, as it's invariably using # those filehandles in a pipe between parent and child processes. # This affects us as, anywhere where we shell out and want to # capture the output of the child process may fail. # Fortunately, if we know the child process is built against # UnixLib, then we also know that it won't call OS_Exit when it # exits, instead returning directly to our exit handler (and thus # preserving the redirection). This only works, however, if the # child application is specified using its absolute path, or # found in Run$Path. In the case of Perl, it does not appear in # Run$Path, so we must invoke it using its absolute path so that # the SharedUnixLibrary successfully detects it as a child process. PERL ?= .bin.perl # This is nasty, but needed because $(CURDIR) will # contain colons, and thus confuse make mightily $(shell SetMacro Alias$$$(COMPONENT)pwd Set %0 :|$$CSD>|mUnset Alias$$$(COMPONENT)pwd) $(shell $(COMPONENT)pwd $(COMPONENT)$$Dir) CURDIR := <$(COMPONENT)$$Dir> else # Cross compiling for RISC OS ifeq ($(origin GCCSDK_INSTALL_ENV),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/env),) GCCSDK_INSTALL_ENV := /opt/netsurf/arm-unknown-riscos/env else GCCSDK_INSTALL_ENV := /home/riscos/env endif endif ifeq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/cross/bin),) GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-unknown-riscos/cross/bin else GCCSDK_INSTALL_CROSSBIN := /home/riscos/cross/bin endif endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) CMHG ?= PATH="$(GCCSDK_INSTALL_CROSSBIN):$(PATH)" $(GCCSDK_INSTALL_CROSSBIN)/cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/share/pkgconfig" pkg-config ifneq ($(COMPONENT_TYPE),riscos-module) ifeq ($(origin CC),default) ifneq ($(findstring arm-unknown-riscos-gcc,$(CC__)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif else ifneq ($(findstring arm-unknown-riscos-gcc,$(CC)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif endif else EXEEXT := ,ffa endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib CMHGFLAGS := -p -tgcc -32bit -apcs 3/32/nonreent/fpe2/noswst/nofpr/nofp # Default prefix PREFIX ?= $(GCCSDK_INSTALL_ENV) endif # BeOS-like targets ifeq ($(TARGET),beos) ifeq ($(HOST),beos) # Building on BeOS CC__ := gcc # No pkg-config PKGCONFIG ?= # Default prefix BEOS_INSTALL_ENV ?= /boot/home/config else ifeq ($(HOST),haiku) # Building on Haiku # Default prefix BEOS_INSTALL_ENV ?= /boot/common else # TODO: more sensible default BEOS_INSTALL_ENV ?= /home/jmb/haiku/env BEOS_INSTALL_CROSSBIN ?= /home/jmb/haiku/haiku/generated/cross-tools/bin CC__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*g++) AR__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*ar) PKGCONFIG := PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/share/pkgconfig" pkg-config endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -I$(BEOS_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -I$(BEOS_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(BEOS_INSTALL_ENV)/lib PREFIX ?= $(BEOS_INSTALL_ENV) endif # Windows ifeq ($(TARGET),windows) ifeq ($(HOST),windows) # Building on Windows CC__ := gcc CXX__ := g++ AR__ := ar PKGCONFIG ?= else # Cross compiling for Windows -- assumes mingw toolchain MINGW_INSTALL_ENV ?= /usr/local/mingw CC__ := i586-mingw32msvc-gcc CXX__ := i586-mingw32msvc-g++ AR__ := i586-mingw32msvc-ar PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(MINGW_INSTALL_ENV)/lib # Default prefix PREFIX ?= $(MINGW_INSTALL_ENV) endif # AmigaOS (3/4; m68k/ppc: we can treat them identically) ifeq ($(findstring amiga,$(TARGET)),amiga) ifeq ($(findstring amiga,$(HOST)),amiga) # Building on AmigaOS # Nothing to do, as we assume the default tooling works else # Cross compiling for AmigaOS ifeq ($(TARGET),amigaos3) GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-unknown-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-unknown-amigaos/cross/bin else GCCSDK_INSTALL_ENV ?= /opt/netsurf/ppc-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/ppc-amigaos/cross/bin endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib PREFIX ?= $(GCCSDK_INSTALL_ENV) endif endif # Default prefix PREFIX ?= /usr/local ############################################################################### # Tool defaults ############################################################################### CP ?= cp DOXYGEN ?= doxygen ECHO ?= echo GENHTML ?= genhtml ifeq ($(HOST),$(TARGET)) HOST_CC ?= $(CC) HOST_CXX ?= $(CXX) else HOST_CC ?= cc HOST_CXX ?= c++ endif INSTALL ?= install LCOV ?= lcov LN ?= ln MAKE ?= make MKDIR ?= mkdir MKDIRFLAGS ?= -p MV ?= mv PERL ?= perl PKGCONFIG ?= PKG_CONFIG_PATH="$(PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)" pkg-config GREP ?= grep SED ?= sed TOUCH ?= touch XSLTPROC ?= xsltproc ############################################################################### # Override defaulted tools ############################################################################### # CC ifeq ($(findstring ccc-analyzer,$(CC)),ccc-analyzer) # We're being invoked by scan-build, so export # the compiler we would have used such that # scan-build works with cross-compilation. # There's no need to do this if we would have # used the default compiler. ifdef CC__ export CCC_CC := $(CC__) endif else # Only set CC if it's not already set in the # environment and we have a value for it. # Otherwise, leave it to be defaulted. ifeq ($(origin CC),default) ifdef CC__ CC := $(CC__) endif endif endif # CXX ifeq ($(origin CXX),default) ifdef CXX__ CXX := $(CXX__) endif endif # AR ifeq ($(origin AR),default) ifdef AR__ AR := $(AR__) endif endif ############################################################################### # Auto-detect the toolchain ############################################################################### # Check for GCC first, as that's most likely # TODO: Using shell redirection like this probably hurts portability ccspecs := $(shell $(CC) -dumpspecs 2>&1) ifeq ($(findstring libgcc,$(ccspecs)),libgcc) # Looks like GCC toolchain := gcc else # Not GCC, so enquire further ccvsn := $(shell $(CC) --version 2>&1) ifeq ($(ccvsn),) # Version string is blank ifeq ($(HOST),riscos) # For some reason we never see the output of SCL apps, so might be # Norcroft. However it might also be a GCC linked against a buggy # UnixLib. # TODO: Something more useful than blindly assuming GCC. ccvsn := GCC # ccvsn := Norcroft endif endif # "Norcroft ..." ifeq ($(word 1,$(ccvsn)),Norcroft) toolchain := norcroft endif # "GCC ..." ifeq ($(word 1,$(ccvsn)),GCC) toolchain := gcc endif # "clang ..." ifeq ($(word 1,$(ccvsn)),clang) toolchain := clang endif ifeq ($(word 1,$(ccvsn)),Apple) ifeq ($(word 2,$(ccvsn)),clang) # Apple clang toolchain := clang endif endif endif ifeq ($(toolchain),) $(error Unable to detect toolchain) endif # TODO: It would be nice to avoid this hard-coded path include build/makefiles/Makefile.$(toolchain) ############################################################################### # Default assembler/compiler/linker/archiver flags ############################################################################### ifeq ($(BUILD),release) OPTCFLAGS ?= $(CCDEF)NDEBUG $(CCOPT) OPTCXXFLAGS ?= $(CXXDEF)NDEBUG $(CXXOPT) else OPTCFLAGS ?= $(CCDBG) $(CCNOOPT) $(CCDEF)DEBUG OPTCXXFLAGS ?= $(CXXDBG) $(CXXNOOPT) $(CXXDEF)DEBUG OPTLDFLAGS ?= $(LDDBG) endif ifeq ($(origin ARFLAGS),default) ARFLAGS := $(ARFLG) endif # TODO: This assumes that the C compiler can cope with assembler ASFLAGS ?= $(CCAS) CFLAGS := $(CFLAGS) $(OPTCFLAGS) $(CCDEF)BUILD_TARGET_$(TARGET) $(CCDEF)BUILD_HOST_$(HOST) CXXFLAGS := $(CXXFLAGS) $(OPTCXXFLAGS) \ $(CXXDEF)BUILD_TARGET_$(TARGET) $(CXXDEF)BUILD_HOST_$(HOST) ASFLAGS := $(ASFLAGS) $(CFLAGS) LDFLAGS := $(LDFLAGS) $(OPTLDFLAGS) ############################################################################### # lib-shared defaults ############################################################################### # Default library extension ifeq ($(COMPONENT_TYPE),lib-static) LIBEXT ?= .a else LIBEXT ?= .so endif # If we're building a shared library, modify the flags appropriately ifeq ($(COMPONENT_TYPE),lib-shared) # Default CFLAGS/LDFLAGS for shared libraries SHAREDCFLAGS ?= $(CCSHR) $(CCDEF)PIC SHAREDCXXFLAGS ?= $(CXXSHR) $(CCDEF)PIC SHAREDLDFLAGS ?= $(LDSHR) SHAREDLDPATH ?= LD_LIBRARY_PATH="$(BUILDDIR):$(LD_LIBRARY_PATH)" endif ################################################################################ # Package config macros ################################################################################ include build/makefiles/Makefile.pkgconfig netsurf-2.9/librufl-0.0.1/build/tools/0000775000175000017500000000000011734430310016372 5ustar vincevincenetsurf-2.9/librufl-0.0.1/build/tools/makeglyphs0000775000175000017500000000123111321135473020465 0ustar vincevince#!/usr/bin/perl -W %name = (); print "#include \n"; print "#include \"rufl_internal.h\"\n"; print "const struct rufl_glyph_map_entry rufl_glyph_map[] = {\n"; print "\t{\" \", 0}, /* sentinel */\n"; while (<>) { if (/^([0-9A-F]{4});([a-zA-Z0-9]+);/) { $name{"$1:$2"} = 1; } } @glyph = (); while (($un, ) = each %name) { ($u, $n) = split ':', $un; push @glyph, [$n, $u]; } foreach $z (sort {$$a[0] cmp $$b[0] or $$a[1] cmp $$b[1]} @glyph) { print "\t{\"$$z[0]\", 0x$$z[1]},\n"; } print "\t{\"~\", 0} /* sentinel */\n"; print "};\n"; print "const size_t rufl_glyph_map_size = sizeof rufl_glyph_map /\n"; print " sizeof rufl_glyph_map[0];\n"; netsurf-2.9/libsvgtiny-0.0.2/0000775000175000017500000000000011734430273014677 5ustar vincevincenetsurf-2.9/libsvgtiny-0.0.2/include/0000775000175000017500000000000011734430273016322 5ustar vincevincenetsurf-2.9/libsvgtiny-0.0.2/include/svgtiny.h0000664000175000017500000000307611317521106020175 0ustar vincevince/* * This file is part of Libsvgtiny * Licensed under the MIT License, * http://opensource.org/licenses/mit-license.php * Copyright 2008 James Bursa */ #ifndef SVGTINY_H #define SVGTINY_H #include typedef int svgtiny_colour; #define svgtiny_TRANSPARENT 0x1000000 #ifdef __riscos__ #define svgtiny_RGB(r, g, b) ((b) << 16 | (g) << 8 | (r)) #define svgtiny_RED(c) ((c) & 0xff) #define svgtiny_GREEN(c) (((c) >> 8) & 0xff) #define svgtiny_BLUE(c) (((c) >> 16) & 0xff) #else #define svgtiny_RGB(r, g, b) ((r) << 16 | (g) << 8 | (b)) #define svgtiny_RED(c) (((c) >> 16) & 0xff) #define svgtiny_GREEN(c) (((c) >> 8) & 0xff) #define svgtiny_BLUE(c) ((c) & 0xff) #endif struct svgtiny_shape { float *path; unsigned int path_length; char *text; float text_x, text_y; svgtiny_colour fill; svgtiny_colour stroke; int stroke_width; }; struct svgtiny_diagram { int width, height; struct svgtiny_shape *shape; unsigned int shape_count; unsigned short error_line; const char *error_message; }; typedef enum { svgtiny_OK, svgtiny_OUT_OF_MEMORY, svgtiny_LIBXML_ERROR, svgtiny_NOT_SVG, svgtiny_SVG_ERROR } svgtiny_code; enum { svgtiny_PATH_MOVE, svgtiny_PATH_CLOSE, svgtiny_PATH_LINE, svgtiny_PATH_BEZIER }; struct svgtiny_named_color { const char *name; svgtiny_colour color; }; struct svgtiny_diagram *svgtiny_create(void); svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram, const char *buffer, size_t size, const char *url, int width, int height); void svgtiny_free(struct svgtiny_diagram *svg); #endif netsurf-2.9/libsvgtiny-0.0.2/examples/0000775000175000017500000000000011734430273016515 5ustar vincevincenetsurf-2.9/libsvgtiny-0.0.2/examples/svgtiny_display_x11.c0000664000175000017500000002154411322440701022576 0ustar vincevince/* * This file is part of Libsvgtiny * Licensed under the MIT License, * http://opensource.org/licenses/mit-license.php * Copyright 2009-2010 James Bursa */ /* * This example loads an SVG using libsvgtiny and then displays it in an X11 * window using cairo. * * Functions of interest for libsvgtiny use are: * main() - loads an SVG using svgtiny_create() and svgtiny_parse() * event_diagram_expose() - renders the SVG by stepping through the shapes * * Compile using: * gcc -g -W -Wall -o svgtiny_display_x11 svgtiny_display_x11.c \ * `pkg-config --cflags --libs libsvgtiny cairo` -lX11 */ #include #include #include #include #include #include #include #include #include #include #include #include #include "svgtiny.h" struct svgtiny_diagram *diagram; Display *display; Window diagram_window; Atom wm_protocols_atom, wm_delete_window_atom; char *svg_path; float scale = 1.0; bool quit = false; void gui_init(void); void gui_quit(void); void update_window_title(void); void gui_poll(void); void event_diagram_key_press(XKeyEvent *key_event); void event_diagram_expose(const XExposeEvent *expose_event); void render_path(cairo_t *cr, float scale, struct svgtiny_shape *path); void die(const char *message); /** * Main program. */ int main(int argc, char *argv[]) { FILE *fd; struct stat sb; char *buffer; size_t size; size_t n; svgtiny_code code; if (argc != 2) { fprintf(stderr, "Usage: %s FILE\n", argv[0]); return 1; } svg_path = argv[1]; /* load file into memory buffer */ fd = fopen(svg_path, "rb"); if (!fd) { perror(svg_path); return 1; } if (stat(svg_path, &sb)) { perror(svg_path); return 1; } size = sb.st_size; buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %lld bytes\n", (long long) size); return 1; } n = fread(buffer, 1, size, fd); if (n != size) { perror(svg_path); return 1; } fclose(fd); /* create svgtiny object */ diagram = svgtiny_create(); if (!diagram) { fprintf(stderr, "svgtiny_create failed\n"); return 1; } /* parse */ code = svgtiny_parse(diagram, buffer, size, svg_path, 1000, 1000); if (code != svgtiny_OK) { fprintf(stderr, "svgtiny_parse failed: "); switch (code) { case svgtiny_OUT_OF_MEMORY: fprintf(stderr, "svgtiny_OUT_OF_MEMORY"); break; case svgtiny_LIBXML_ERROR: fprintf(stderr, "svgtiny_LIBXML_ERROR"); break; case svgtiny_NOT_SVG: fprintf(stderr, "svgtiny_NOT_SVG"); break; case svgtiny_SVG_ERROR: fprintf(stderr, "svgtiny_SVG_ERROR: line %i: %s", diagram->error_line, diagram->error_message); break; default: fprintf(stderr, "unknown svgtiny_code %i", code); break; } fprintf(stderr, "\n"); } free(buffer); /*printf("viewbox 0 0 %u %u\n", diagram->width, diagram->height);*/ gui_init(); while (!quit) { gui_poll(); } gui_quit(); svgtiny_free(diagram); return 0; } /** * Initialize X11 interface. */ void gui_init(void) { display = XOpenDisplay(NULL); if (!display) die("XOpenDisplay failed: is DISPLAY set?"); diagram_window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, diagram->width, diagram->height, 0, 0, 0); update_window_title(); XMapWindow(display, diagram_window); XSelectInput(display, diagram_window, KeyPressMask | ButtonPressMask | ExposureMask | StructureNotifyMask); wm_protocols_atom = XInternAtom(display, "WM_PROTOCOLS", False); wm_delete_window_atom = XInternAtom(display, "WM_DELETE_WINDOW", False); XSetWMProtocols(display, diagram_window, &wm_delete_window_atom, 1); } /** * Free X11 interface. */ void gui_quit(void) { XCloseDisplay(display); } /** * Update window title to show current state. */ void update_window_title(void) { char title[100]; char *svg_path_copy; char *base_name; svg_path_copy = strdup(svg_path); if (!svg_path_copy) { fprintf(stderr, "out of memory\n"); return; } base_name = basename(svg_path_copy); snprintf(title, sizeof title, "%s (%i%%) - svgtiny", base_name, (int) roundf(scale * 100.0)); XStoreName(display, diagram_window, title); free(svg_path_copy); } /** * Handle an X11 event. */ void gui_poll(void) { XEvent event; XNextEvent(display, &event); switch (event.type) { case KeyPress: if (event.xkey.window == diagram_window) { event_diagram_key_press(&event.xkey); } break; case Expose: if (event.xexpose.window == diagram_window) { event_diagram_expose(&event.xexpose); } break; case ClientMessage: if (event.xclient.message_type == wm_protocols_atom && event.xclient.format == 32 && (Atom) event.xclient.data.l[0] == wm_delete_window_atom) quit = true; break; default: /*printf("unknown event %i\n", event.type);*/ break; } } /** * Handle an X11 KeyPress event in the diagram window. */ void event_diagram_key_press(XKeyEvent *key_event) { KeySym key_sym; float new_scale = scale; unsigned int width, height; key_sym = XLookupKeysym(key_event, 0); switch (key_sym) { case XK_q: case XK_Escape: quit = true; break; case XK_minus: case XK_KP_Subtract: new_scale -= 0.1; break; case XK_equal: case XK_plus: case XK_KP_Add: new_scale += 0.1; break; case XK_1: case XK_KP_Multiply: case XK_KP_1: new_scale = 1; break; case XK_2: case XK_KP_2: new_scale = 2; break; default: break; } if (new_scale < 0.1) new_scale = 0.1; else if (5 < new_scale) new_scale = 5; if (new_scale == scale) return; scale = new_scale; width = diagram->width * scale; height = diagram->height * scale; if (width < 400) width = 400; if (height < 400) height = 400; XResizeWindow(display, diagram_window, width, height); XClearArea(display, diagram_window, 0, 0, 0, 0, True); update_window_title(); } /** * Handle an X11 Expose event of the diagram window. */ void event_diagram_expose(const XExposeEvent *expose_event) { cairo_surface_t *surface; cairo_t *cr; cairo_status_t status; unsigned int i; if (expose_event->count != 0) return; surface = cairo_xlib_surface_create(display, diagram_window, DefaultVisual(display, DefaultScreen(display)), diagram->width * scale, diagram->height * scale); if (!surface) { fprintf(stderr, "cairo_xlib_surface_create failed\n"); return; } cr = cairo_create(surface); status = cairo_status(cr); if (status != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "cairo_create failed: %s\n", cairo_status_to_string(status)); cairo_destroy(cr); cairo_surface_destroy(surface); return; } cairo_set_source_rgb(cr, 1, 1, 1); cairo_paint(cr); for (i = 0; i != diagram->shape_count; i++) { if (diagram->shape[i].path) { render_path(cr, scale, &diagram->shape[i]); } else if (diagram->shape[i].text) { cairo_set_source_rgb(cr, svgtiny_RED(diagram->shape[i].stroke) / 255.0, svgtiny_GREEN(diagram->shape[i].stroke) / 255.0, svgtiny_BLUE(diagram->shape[i].stroke) / 255.0); cairo_move_to(cr, scale * diagram->shape[i].text_x, scale * diagram->shape[i].text_y); cairo_show_text(cr, diagram->shape[i].text); } } status = cairo_status(cr); if (status != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "cairo error: %s\n", cairo_status_to_string(status)); cairo_destroy(cr); cairo_surface_destroy(surface); return; } cairo_destroy(cr); cairo_surface_destroy(surface); } /** * Render an svgtiny path using cairo. */ void render_path(cairo_t *cr, float scale, struct svgtiny_shape *path) { unsigned int j; cairo_new_path(cr); for (j = 0; j != path->path_length; ) { switch ((int) path->path[j]) { case svgtiny_PATH_MOVE: cairo_move_to(cr, scale * path->path[j + 1], scale * path->path[j + 2]); j += 3; break; case svgtiny_PATH_CLOSE: cairo_close_path(cr); j += 1; break; case svgtiny_PATH_LINE: cairo_line_to(cr, scale * path->path[j + 1], scale * path->path[j + 2]); j += 3; break; case svgtiny_PATH_BEZIER: cairo_curve_to(cr, scale * path->path[j + 1], scale * path->path[j + 2], scale * path->path[j + 3], scale * path->path[j + 4], scale * path->path[j + 5], scale * path->path[j + 6]); j += 7; break; default: printf("error "); j += 1; } } if (path->fill != svgtiny_TRANSPARENT) { cairo_set_source_rgb(cr, svgtiny_RED(path->fill) / 255.0, svgtiny_GREEN(path->fill) / 255.0, svgtiny_BLUE(path->fill) / 255.0); cairo_fill_preserve(cr); } if (path->stroke != svgtiny_TRANSPARENT) { cairo_set_source_rgb(cr, svgtiny_RED(path->stroke) / 255.0, svgtiny_GREEN(path->stroke) / 255.0, svgtiny_BLUE(path->stroke) / 255.0); cairo_set_line_width(cr, scale * path->stroke_width); cairo_stroke_preserve(cr); } } /** * Exit with fatal error. */ void die(const char *message) { fprintf(stderr, "%s\n", message); exit(1); } netsurf-2.9/libsvgtiny-0.0.2/src/0000775000175000017500000000000011734430273015466 5ustar vincevincenetsurf-2.9/libsvgtiny-0.0.2/src/svgtiny_list.c0000664000175000017500000000503211244445005020363 0ustar vincevince/* * This file is part of Libsvgtiny * Licensed under the MIT License, * http://opensource.org/licenses/mit-license.php * Copyright 2008 James Bursa */ /** * A svgtiny_list is a managed array of objects. It grows in chunks to reduce * calls to realloc(), but keeps wasted space low. */ #include #include "svgtiny.h" #include "svgtiny_internal.h" struct svgtiny_list { unsigned int size; /* number of slots used */ unsigned int allocated; /* number of slots allocated (>= size) */ size_t item_size; /* size of each slot / bytes */ char *items; /* array of slots */ }; /** * Create an empty svgtiny_list. */ struct svgtiny_list *svgtiny_list_create(size_t item_size) { struct svgtiny_list *list = malloc(sizeof *list); if (!list) return 0; list->size = 0; list->allocated = 0; list->item_size = item_size; list->items = 0; return list; } /** * Return the number of objects in a list. */ unsigned int svgtiny_list_size(struct svgtiny_list *list) { return list->size; } /** * Set the number of objects in a list. If the size is increased, the new * objects are not initialized in any way. * * The allocation size formula is taken from Python's list: * http://svn.python.org/view/python/trunk/Objects/listobject.c?view=markup * * Objects may have moved after this call. Use svgtiny_list_get() to get new * pointers. */ svgtiny_code svgtiny_list_resize(struct svgtiny_list *list, unsigned int new_size) { unsigned int new_allocated; void *new_items; if (new_size <= list->allocated) { list->size = new_size; return svgtiny_OK; } new_allocated = (new_size >> 3) + (new_size < 9 ? 3 : 6) + new_size; if (new_size == 0) new_allocated = 0; new_items = realloc(list->items, new_allocated * list->item_size); if (!new_items) return svgtiny_OUT_OF_MEMORY; list->size = new_size; list->allocated = new_allocated; list->items = new_items; return svgtiny_OK; } /** * Return a pointer to an object in a list. */ void *svgtiny_list_get(struct svgtiny_list *list, unsigned int i) { assert(i < list->size); return (void *) (list->items + i * list->item_size); } /** * Add space for one object to a list and return a pointer to it. */ void *svgtiny_list_push(struct svgtiny_list *list) { svgtiny_code code; code = svgtiny_list_resize(list, list->size + 1); if (code != svgtiny_OK) return 0; return svgtiny_list_get(list, list->size - 1); } /** * Free an entire list. */ void svgtiny_list_free(struct svgtiny_list *list) { free(list->items); free(list); } netsurf-2.9/libsvgtiny-0.0.2/src/colors.gperf0000664000175000017500000001366611244445005020023 0ustar vincevince/* * This file is part of Libsvgtiny * Licensed under the MIT License, * http://opensource.org/licenses/mit-license.php * Copyright 2008 James Bursa */ %language=ANSI-C %struct-type %switch=1 %define hash-function-name svgtiny_color_hash %define lookup-function-name svgtiny_color_lookup %readonly-tables %{ #include #include "svgtiny.h" #include "svgtiny_internal.h" %} struct svgtiny_named_color; %% aliceblue, svgtiny_RGB(240, 248, 255) antiquewhite, svgtiny_RGB(250, 235, 215) aqua, svgtiny_RGB( 0, 255, 255) aquamarine, svgtiny_RGB(127, 255, 212) azure, svgtiny_RGB(240, 255, 255) beige, svgtiny_RGB(245, 245, 220) bisque, svgtiny_RGB(255, 228, 196) black, svgtiny_RGB( 0, 0, 0) blanchedalmond, svgtiny_RGB(255, 235, 205) blue, svgtiny_RGB( 0, 0, 255) blueviolet, svgtiny_RGB(138, 43, 226) brown, svgtiny_RGB(165, 42, 42) burlywood, svgtiny_RGB(222, 184, 135) cadetblue, svgtiny_RGB( 95, 158, 160) chartreuse, svgtiny_RGB(127, 255, 0) chocolate, svgtiny_RGB(210, 105, 30) coral, svgtiny_RGB(255, 127, 80) cornflowerblue, svgtiny_RGB(100, 149, 237) cornsilk, svgtiny_RGB(255, 248, 220) crimson, svgtiny_RGB(220, 20, 60) cyan, svgtiny_RGB( 0, 255, 255) darkblue, svgtiny_RGB( 0, 0, 139) darkcyan, svgtiny_RGB( 0, 139, 139) darkgoldenrod, svgtiny_RGB(184, 134, 11) darkgray, svgtiny_RGB(169, 169, 169) darkgreen, svgtiny_RGB( 0, 100, 0) darkgrey, svgtiny_RGB(169, 169, 169) darkkhaki, svgtiny_RGB(189, 183, 107) darkmagenta, svgtiny_RGB(139, 0, 139) darkolivegreen, svgtiny_RGB( 85, 107, 47) darkorange, svgtiny_RGB(255, 140, 0) darkorchid, svgtiny_RGB(153, 50, 204) darkred, svgtiny_RGB(139, 0, 0) darksalmon, svgtiny_RGB(233, 150, 122) darkseagreen, svgtiny_RGB(143, 188, 143) darkslateblue, svgtiny_RGB( 72, 61, 139) darkslategray, svgtiny_RGB( 47, 79, 79) darkslategrey, svgtiny_RGB( 47, 79, 79) darkturquoise, svgtiny_RGB( 0, 206, 209) darkviolet, svgtiny_RGB(148, 0, 211) deeppink, svgtiny_RGB(255, 20, 147) deepskyblue, svgtiny_RGB( 0, 191, 255) dimgray, svgtiny_RGB(105, 105, 105) dimgrey, svgtiny_RGB(105, 105, 105) dodgerblue, svgtiny_RGB( 30, 144, 255) firebrick, svgtiny_RGB(178, 34, 34) floralwhite, svgtiny_RGB(255, 250, 240) forestgreen, svgtiny_RGB( 34, 139, 34) fuchsia, svgtiny_RGB(255, 0, 255) gainsboro, svgtiny_RGB(220, 220, 220) ghostwhite, svgtiny_RGB(248, 248, 255) gold, svgtiny_RGB(255, 215, 0) goldenrod, svgtiny_RGB(218, 165, 32) gray, svgtiny_RGB(128, 128, 128) grey, svgtiny_RGB(128, 128, 128) green, svgtiny_RGB( 0, 128, 0) greenyellow, svgtiny_RGB(173, 255, 47) honeydew, svgtiny_RGB(240, 255, 240) hotpink, svgtiny_RGB(255, 105, 180) indianred, svgtiny_RGB(205, 92, 92) indigo, svgtiny_RGB( 75, 0, 130) ivory, svgtiny_RGB(255, 255, 240) khaki, svgtiny_RGB(240, 230, 140) lavender, svgtiny_RGB(230, 230, 250) lavenderblush, svgtiny_RGB(255, 240, 245) lawngreen, svgtiny_RGB(124, 252, 0) lemonchiffon, svgtiny_RGB(255, 250, 205) lightblue, svgtiny_RGB(173, 216, 230) lightcoral, svgtiny_RGB(240, 128, 128) lightcyan, svgtiny_RGB(224, 255, 255) lightgoldenrodyellow, svgtiny_RGB(250, 250, 210) lightgray, svgtiny_RGB(211, 211, 211) lightgreen, svgtiny_RGB(144, 238, 144) lightgrey, svgtiny_RGB(211, 211, 211) lightpink, svgtiny_RGB(255, 182, 193) lightsalmon, svgtiny_RGB(255, 160, 122) lightseagreen, svgtiny_RGB( 32, 178, 170) lightskyblue, svgtiny_RGB(135, 206, 250) lightslategray, svgtiny_RGB(119, 136, 153) lightslategrey, svgtiny_RGB(119, 136, 153) lightsteelblue, svgtiny_RGB(176, 196, 222) lightyellow, svgtiny_RGB(255, 255, 224) lime, svgtiny_RGB( 0, 255, 0) limegreen, svgtiny_RGB( 50, 205, 50) linen, svgtiny_RGB(250, 240, 230) magenta, svgtiny_RGB(255, 0, 255) maroon, svgtiny_RGB(128, 0, 0) mediumaquamarine, svgtiny_RGB(102, 205, 170) mediumblue, svgtiny_RGB( 0, 0, 205) mediumorchid, svgtiny_RGB(186, 85, 211) mediumpurple, svgtiny_RGB(147, 112, 219) mediumseagreen, svgtiny_RGB( 60, 179, 113) mediumslateblue, svgtiny_RGB(123, 104, 238) mediumspringgreen, svgtiny_RGB( 0, 250, 154) mediumturquoise, svgtiny_RGB( 72, 209, 204) mediumvioletred, svgtiny_RGB(199, 21, 133) midnightblue, svgtiny_RGB( 25, 25, 112) mintcream, svgtiny_RGB(245, 255, 250) mistyrose, svgtiny_RGB(255, 228, 225) moccasin, svgtiny_RGB(255, 228, 181) navajowhite, svgtiny_RGB(255, 222, 173) navy, svgtiny_RGB( 0, 0, 128) oldlace, svgtiny_RGB(253, 245, 230) olive, svgtiny_RGB(128, 128, 0) olivedrab, svgtiny_RGB(107, 142, 35) orange, svgtiny_RGB(255, 165, 0) orangered, svgtiny_RGB(255, 69, 0) orchid, svgtiny_RGB(218, 112, 214) palegoldenrod, svgtiny_RGB(238, 232, 170) palegreen, svgtiny_RGB(152, 251, 152) paleturquoise, svgtiny_RGB(175, 238, 238) palevioletred, svgtiny_RGB(219, 112, 147) papayawhip, svgtiny_RGB(255, 239, 213) peachpuff, svgtiny_RGB(255, 218, 185) peru, svgtiny_RGB(205, 133, 63) pink, svgtiny_RGB(255, 192, 203) plum, svgtiny_RGB(221, 160, 221) powderblue, svgtiny_RGB(176, 224, 230) purple, svgtiny_RGB(128, 0, 128) red, svgtiny_RGB(255, 0, 0) rosybrown, svgtiny_RGB(188, 143, 143) royalblue, svgtiny_RGB( 65, 105, 225) saddlebrown, svgtiny_RGB(139, 69, 19) salmon, svgtiny_RGB(250, 128, 114) sandybrown, svgtiny_RGB(244, 164, 96) seagreen, svgtiny_RGB( 46, 139, 87) seashell, svgtiny_RGB(255, 245, 238) sienna, svgtiny_RGB(160, 82, 45) silver, svgtiny_RGB(192, 192, 192) skyblue, svgtiny_RGB(135, 206, 235) slateblue, svgtiny_RGB(106, 90, 205) slategray, svgtiny_RGB(112, 128, 144) slategrey, svgtiny_RGB(112, 128, 144) snow, svgtiny_RGB(255, 250, 250) springgreen, svgtiny_RGB( 0, 255, 127) steelblue, svgtiny_RGB( 70, 130, 180) tan, svgtiny_RGB(210, 180, 140) teal, svgtiny_RGB( 0, 128, 128) thistle, svgtiny_RGB(216, 191, 216) tomato, svgtiny_RGB(255, 99, 71) turquoise, svgtiny_RGB( 64, 224, 208) violet, svgtiny_RGB(238, 130, 238) wheat, svgtiny_RGB(245, 222, 179) white, svgtiny_RGB(255, 255, 255) whitesmoke, svgtiny_RGB(245, 245, 245) yellow, svgtiny_RGB(255, 255, 0) yellowgreen, svgtiny_RGB(154, 205, 50) netsurf-2.9/libsvgtiny-0.0.2/src/svgtiny_gradient.c0000664000175000017500000004340211506674214021217 0ustar vincevince/* * This file is part of Libsvgtiny * Licensed under the MIT License, * http://opensource.org/licenses/mit-license.php * Copyright 2008 James Bursa */ #include #include #include #include "svgtiny.h" #include "svgtiny_internal.h" #undef GRADIENT_DEBUG static svgtiny_code svgtiny_parse_linear_gradient(xmlNode *linear, struct svgtiny_parse_state *state); static float svgtiny_parse_gradient_offset(const char *s); static void svgtiny_path_bbox(float *p, unsigned int n, float *x0, float *y0, float *x1, float *y1); static void svgtiny_invert_matrix(float *m, float *inv); /** * Find a gradient by id and parse it. */ void svgtiny_find_gradient(const char *id, struct svgtiny_parse_state *state) { xmlNode *gradient; fprintf(stderr, "svgtiny_find_gradient: id \"%s\"\n", id); state->linear_gradient_stop_count = 0; state->gradient_x1 = "0%"; state->gradient_y1 = "0%"; state->gradient_x2 = "100%"; state->gradient_y2 = "0%"; state->gradient_user_space_on_use = false; state->gradient_transform.a = 1; state->gradient_transform.b = 0; state->gradient_transform.c = 0; state->gradient_transform.d = 1; state->gradient_transform.e = 0; state->gradient_transform.f = 0; gradient = svgtiny_find_element_by_id( (xmlNode *) state->document, id); fprintf(stderr, "gradient %p\n", (void *) gradient); if (!gradient) { fprintf(stderr, "gradient \"%s\" not found\n", id); return; } fprintf(stderr, "gradient name \"%s\"\n", gradient->name); if (strcmp((const char *) gradient->name, "linearGradient") == 0) { svgtiny_parse_linear_gradient(gradient, state); } } /** * Parse a element node. * * http://www.w3.org/TR/SVG11/pservers#LinearGradients */ svgtiny_code svgtiny_parse_linear_gradient(xmlNode *linear, struct svgtiny_parse_state *state) { unsigned int i = 0; xmlNode *stop; xmlAttr *attr; xmlAttr *href = xmlHasProp(linear, (const xmlChar *) "href"); if (href && href->children->content[0] == '#') svgtiny_find_gradient((const char *) href->children->content + 1, state); for (attr = linear->properties; attr; attr = attr->next) { const char *name = (const char *) attr->name; const char *content = (const char *) attr->children->content; if (strcmp(name, "x1") == 0) state->gradient_x1 = content; else if (strcmp(name, "y1") == 0) state->gradient_y1 = content; else if (strcmp(name, "x2") == 0) state->gradient_x2 = content; else if (strcmp(name, "y2") == 0) state->gradient_y2 = content; else if (strcmp(name, "gradientUnits") == 0) state->gradient_user_space_on_use = strcmp(content, "userSpaceOnUse") == 0; else if (strcmp(name, "gradientTransform") == 0) { float a = 1, b = 0, c = 0, d = 1, e = 0, f = 0; char *s = strdup(content); if (!s) return svgtiny_OUT_OF_MEMORY; svgtiny_parse_transform(s, &a, &b, &c, &d, &e, &f); free(s); fprintf(stderr, "transform %g %g %g %g %g %g\n", a, b, c, d, e, f); state->gradient_transform.a = a; state->gradient_transform.b = b; state->gradient_transform.c = c; state->gradient_transform.d = d; state->gradient_transform.e = e; state->gradient_transform.f = f; } } for (stop = linear->children; stop; stop = stop->next) { float offset = -1; svgtiny_colour color = svgtiny_TRANSPARENT; if (stop->type != XML_ELEMENT_NODE) continue; if (strcmp((const char *) stop->name, "stop") != 0) continue; for (attr = stop->properties; attr; attr = attr->next) { const char *name = (const char *) attr->name; const char *content = (const char *) attr->children->content; if (strcmp(name, "offset") == 0) offset = svgtiny_parse_gradient_offset(content); else if (strcmp(name, "stop-color") == 0) svgtiny_parse_color(content, &color, state); else if (strcmp(name, "style") == 0) { const char *s; char *value; if ((s = strstr(content, "stop-color:"))) { s += 11; while (*s == ' ') s++; value = strndup(s, strcspn(s, "; ")); svgtiny_parse_color(value, &color, state); free(value); } } } if (offset != -1 && color != svgtiny_TRANSPARENT) { fprintf(stderr, "stop %g %x\n", offset, color); state->gradient_stop[i].offset = offset; state->gradient_stop[i].color = color; i++; } if (i == svgtiny_MAX_STOPS) break; } if (i) state->linear_gradient_stop_count = i; return svgtiny_OK; } float svgtiny_parse_gradient_offset(const char *s) { int num_length = strspn(s, "0123456789+-."); const char *unit = s + num_length; float n = atof((const char *) s); if (unit[0] == 0) ; else if (unit[0] == '%') n /= 100.0; else return -1; if (n < 0) n = 0; if (1 < n) n = 1; return n; } /** * Add a path with a linear gradient fill to the svgtiny_diagram. */ svgtiny_code svgtiny_add_path_linear_gradient(float *p, unsigned int n, struct svgtiny_parse_state *state) { struct grad_point { float x, y, r; }; float object_x0, object_y0, object_x1, object_y1; float gradient_x0, gradient_y0, gradient_x1, gradient_y1, gradient_dx, gradient_dy; float trans[6]; unsigned int steps = 10; float x0 = 0, y0 = 0, x0_trans, y0_trans, r0; /* segment start point */ float x1, y1, x1_trans, y1_trans, r1; /* segment end point */ /* segment control points (beziers only) */ float c0x = 0, c0y = 0, c1x = 0, c1y = 0; float gradient_norm_squared; struct svgtiny_list *pts; float min_r = 1000; unsigned int min_pt = 0; unsigned int j; unsigned int stop_count; unsigned int current_stop; float last_stop_r; float current_stop_r; int red0, green0, blue0, red1, green1, blue1; unsigned int t, a, b; /* determine object bounding box */ svgtiny_path_bbox(p, n, &object_x0, &object_y0, &object_x1, &object_y1); #ifdef GRADIENT_DEBUG fprintf(stderr, "object bbox: (%g %g) (%g %g)\n", object_x0, object_y0, object_x1, object_y1); #endif /* compute gradient vector */ fprintf(stderr, "x1 %s, y1 %s, x2 %s, y2 %s\n", state->gradient_x1, state->gradient_y1, state->gradient_x2, state->gradient_y2); if (!state->gradient_user_space_on_use) { gradient_x0 = object_x0 + svgtiny_parse_length(state->gradient_x1, object_x1 - object_x0, *state); gradient_y0 = object_y0 + svgtiny_parse_length(state->gradient_y1, object_y1 - object_y0, *state); gradient_x1 = object_x0 + svgtiny_parse_length(state->gradient_x2, object_x1 - object_x0, *state); gradient_y1 = object_y0 + svgtiny_parse_length(state->gradient_y2, object_y1 - object_y0, *state); } else { gradient_x0 = svgtiny_parse_length(state->gradient_x1, state->viewport_width, *state); gradient_y0 = svgtiny_parse_length(state->gradient_y1, state->viewport_height, *state); gradient_x1 = svgtiny_parse_length(state->gradient_x2, state->viewport_width, *state); gradient_y1 = svgtiny_parse_length(state->gradient_y2, state->viewport_height, *state); } gradient_dx = gradient_x1 - gradient_x0; gradient_dy = gradient_y1 - gradient_y0; #ifdef GRADIENT_DEBUG fprintf(stderr, "gradient vector: (%g %g) => (%g %g)\n", gradient_x0, gradient_y0, gradient_x1, gradient_y1); #endif /* show theoretical gradient strips for debugging */ /*unsigned int strips = 10; for (unsigned int z = 0; z != strips; z++) { float f0, fd, strip_x0, strip_y0, strip_dx, strip_dy; f0 = (float) z / (float) strips; fd = (float) 1 / (float) strips; strip_x0 = gradient_x0 + f0 * gradient_dx; strip_y0 = gradient_y0 + f0 * gradient_dy; strip_dx = fd * gradient_dx; strip_dy = fd * gradient_dy; fprintf(stderr, "strip %i vector: (%g %g) + (%g %g)\n", z, strip_x0, strip_y0, strip_dx, strip_dy); float *p = malloc(13 * sizeof p[0]); if (!p) return svgtiny_OUT_OF_MEMORY; p[0] = svgtiny_PATH_MOVE; p[1] = strip_x0 + (strip_dy * 3); p[2] = strip_y0 - (strip_dx * 3); p[3] = svgtiny_PATH_LINE; p[4] = p[1] + strip_dx; p[5] = p[2] + strip_dy; p[6] = svgtiny_PATH_LINE; p[7] = p[4] - (strip_dy * 6); p[8] = p[5] + (strip_dx * 6); p[9] = svgtiny_PATH_LINE; p[10] = p[7] - strip_dx; p[11] = p[8] - strip_dy; p[12] = svgtiny_PATH_CLOSE; svgtiny_transform_path(p, 13, state); struct svgtiny_shape *shape = svgtiny_add_shape(state); if (!shape) { free(p); return svgtiny_OUT_OF_MEMORY; } shape->path = p; shape->path_length = 13; shape->fill = svgtiny_TRANSPARENT; shape->stroke = svgtiny_RGB(0, 0xff, 0); state->diagram->shape_count++; }*/ /* invert gradient transform for applying to vertices */ svgtiny_invert_matrix(&state->gradient_transform.a, trans); fprintf(stderr, "inverse transform %g %g %g %g %g %g\n", trans[0], trans[1], trans[2], trans[3], trans[4], trans[5]); /* compute points on the path for triangle vertices */ /* r, r0, r1 are distance along gradient vector */ gradient_norm_squared = gradient_dx * gradient_dx + gradient_dy * gradient_dy; pts = svgtiny_list_create( sizeof (struct grad_point)); if (!pts) return svgtiny_OUT_OF_MEMORY; for (j = 0; j != n; ) { int segment_type = (int) p[j]; struct grad_point *point; unsigned int z; if (segment_type == svgtiny_PATH_MOVE) { x0 = p[j + 1]; y0 = p[j + 2]; j += 3; continue; } assert(segment_type == svgtiny_PATH_CLOSE || segment_type == svgtiny_PATH_LINE || segment_type == svgtiny_PATH_BEZIER); /* start point (x0, y0) */ x0_trans = trans[0]*x0 + trans[2]*y0 + trans[4]; y0_trans = trans[1]*x0 + trans[3]*y0 + trans[5]; r0 = ((x0_trans - gradient_x0) * gradient_dx + (y0_trans - gradient_y0) * gradient_dy) / gradient_norm_squared; point = svgtiny_list_push(pts); if (!point) { svgtiny_list_free(pts); return svgtiny_OUT_OF_MEMORY; } point->x = x0; point->y = y0; point->r = r0; if (r0 < min_r) { min_r = r0; min_pt = svgtiny_list_size(pts) - 1; } /* end point (x1, y1) */ if (segment_type == svgtiny_PATH_LINE) { x1 = p[j + 1]; y1 = p[j + 2]; j += 3; } else if (segment_type == svgtiny_PATH_CLOSE) { x1 = p[1]; y1 = p[2]; j++; } else /* svgtiny_PATH_BEZIER */ { c0x = p[j + 1]; c0y = p[j + 2]; c1x = p[j + 3]; c1y = p[j + 4]; x1 = p[j + 5]; y1 = p[j + 6]; j += 7; } x1_trans = trans[0]*x1 + trans[2]*y1 + trans[4]; y1_trans = trans[1]*x1 + trans[3]*y1 + trans[5]; r1 = ((x1_trans - gradient_x0) * gradient_dx + (y1_trans - gradient_y0) * gradient_dy) / gradient_norm_squared; /* determine steps from change in r */ steps = ceilf(fabsf(r1 - r0) / 0.05); if (steps == 0) steps = 1; fprintf(stderr, "r0 %g, r1 %g, steps %i\n", r0, r1, steps); /* loop through intermediate points */ for (z = 1; z != steps; z++) { float t, x, y, x_trans, y_trans, r; struct grad_point *point; t = (float) z / (float) steps; if (segment_type == svgtiny_PATH_BEZIER) { x = (1-t) * (1-t) * (1-t) * x0 + 3 * t * (1-t) * (1-t) * c0x + 3 * t * t * (1-t) * c1x + t * t * t * x1; y = (1-t) * (1-t) * (1-t) * y0 + 3 * t * (1-t) * (1-t) * c0y + 3 * t * t * (1-t) * c1y + t * t * t * y1; } else { x = (1-t) * x0 + t * x1; y = (1-t) * y0 + t * y1; } x_trans = trans[0]*x + trans[2]*y + trans[4]; y_trans = trans[1]*x + trans[3]*y + trans[5]; r = ((x_trans - gradient_x0) * gradient_dx + (y_trans - gradient_y0) * gradient_dy) / gradient_norm_squared; fprintf(stderr, "(%g %g [%g]) ", x, y, r); point = svgtiny_list_push(pts); if (!point) { svgtiny_list_free(pts); return svgtiny_OUT_OF_MEMORY; } point->x = x; point->y = y; point->r = r; if (r < min_r) { min_r = r; min_pt = svgtiny_list_size(pts) - 1; } } fprintf(stderr, "\n"); /* next segment start point is this segment end point */ x0 = x1; y0 = y1; } fprintf(stderr, "pts size %i, min_pt %i, min_r %.3f\n", svgtiny_list_size(pts), min_pt, min_r); /* render triangles */ stop_count = state->linear_gradient_stop_count; assert(2 <= stop_count); current_stop = 0; last_stop_r = 0; current_stop_r = state->gradient_stop[0].offset; red0 = red1 = svgtiny_RED(state->gradient_stop[0].color); green0 = green1 = svgtiny_GREEN(state->gradient_stop[0].color); blue0 = blue1 = svgtiny_BLUE(state->gradient_stop[0].color); t = min_pt; a = (min_pt + 1) % svgtiny_list_size(pts); b = min_pt == 0 ? svgtiny_list_size(pts) - 1 : min_pt - 1; while (a != b) { struct grad_point *point_t = svgtiny_list_get(pts, t); struct grad_point *point_a = svgtiny_list_get(pts, a); struct grad_point *point_b = svgtiny_list_get(pts, b); float mean_r = (point_t->r + point_a->r + point_b->r) / 3; float *p; struct svgtiny_shape *shape; /*fprintf(stderr, "triangle: t %i %.3f a %i %.3f b %i %.3f " "mean_r %.3f\n", t, pts[t].r, a, pts[a].r, b, pts[b].r, mean_r);*/ while (current_stop != stop_count && current_stop_r < mean_r) { current_stop++; if (current_stop == stop_count) break; red0 = red1; green0 = green1; blue0 = blue1; red1 = svgtiny_RED(state-> gradient_stop[current_stop].color); green1 = svgtiny_GREEN(state-> gradient_stop[current_stop].color); blue1 = svgtiny_BLUE(state-> gradient_stop[current_stop].color); last_stop_r = current_stop_r; current_stop_r = state-> gradient_stop[current_stop].offset; } p = malloc(10 * sizeof p[0]); if (!p) return svgtiny_OUT_OF_MEMORY; p[0] = svgtiny_PATH_MOVE; p[1] = point_t->x; p[2] = point_t->y; p[3] = svgtiny_PATH_LINE; p[4] = point_a->x; p[5] = point_a->y; p[6] = svgtiny_PATH_LINE; p[7] = point_b->x; p[8] = point_b->y; p[9] = svgtiny_PATH_CLOSE; svgtiny_transform_path(p, 10, state); shape = svgtiny_add_shape(state); if (!shape) { free(p); return svgtiny_OUT_OF_MEMORY; } shape->path = p; shape->path_length = 10; /*shape->fill = svgtiny_TRANSPARENT;*/ if (current_stop == 0) shape->fill = state->gradient_stop[0].color; else if (current_stop == stop_count) shape->fill = state-> gradient_stop[stop_count - 1].color; else { float stop_r = (mean_r - last_stop_r) / (current_stop_r - last_stop_r); shape->fill = svgtiny_RGB( (int) ((1 - stop_r) * red0 + stop_r * red1), (int) ((1 - stop_r) * green0 + stop_r * green1), (int) ((1 - stop_r) * blue0 + stop_r * blue1)); } shape->stroke = svgtiny_TRANSPARENT; #ifdef GRADIENT_DEBUG shape->stroke = svgtiny_RGB(0, 0, 0xff); #endif state->diagram->shape_count++; if (point_a->r < point_b->r) { t = a; a = (a + 1) % svgtiny_list_size(pts); } else { t = b; b = b == 0 ? svgtiny_list_size(pts) - 1 : b - 1; } } /* render gradient vector for debugging */ #ifdef GRADIENT_DEBUG { float *p = malloc(7 * sizeof p[0]); if (!p) return svgtiny_OUT_OF_MEMORY; p[0] = svgtiny_PATH_MOVE; p[1] = gradient_x0; p[2] = gradient_y0; p[3] = svgtiny_PATH_LINE; p[4] = gradient_x1; p[5] = gradient_y1; p[6] = svgtiny_PATH_CLOSE; svgtiny_transform_path(p, 7, state); struct svgtiny_shape *shape = svgtiny_add_shape(state); if (!shape) { free(p); return svgtiny_OUT_OF_MEMORY; } shape->path = p; shape->path_length = 7; shape->fill = svgtiny_TRANSPARENT; shape->stroke = svgtiny_RGB(0xff, 0, 0); state->diagram->shape_count++; } #endif /* render triangle vertices with r values for debugging */ #ifdef GRADIENT_DEBUG for (unsigned int i = 0; i != pts->size; i++) { struct grad_point *point = svgtiny_list_get(pts, i); struct svgtiny_shape *shape = svgtiny_add_shape(state); if (!shape) return svgtiny_OUT_OF_MEMORY; char *text = malloc(20); if (!text) return svgtiny_OUT_OF_MEMORY; sprintf(text, "%i=%.3f", i, point->r); shape->text = text; shape->text_x = state->ctm.a * point->x + state->ctm.c * point->y + state->ctm.e; shape->text_y = state->ctm.b * point->x + state->ctm.d * point->y + state->ctm.f; shape->fill = svgtiny_RGB(0, 0, 0); shape->stroke = svgtiny_TRANSPARENT; state->diagram->shape_count++; } #endif /* plot actual path outline */ if (state->stroke != svgtiny_TRANSPARENT) { struct svgtiny_shape *shape; svgtiny_transform_path(p, n, state); shape = svgtiny_add_shape(state); if (!shape) { free(p); return svgtiny_OUT_OF_MEMORY; } shape->path = p; shape->path_length = n; shape->fill = svgtiny_TRANSPARENT; state->diagram->shape_count++; } else { free(p); } svgtiny_list_free(pts); return svgtiny_OK; } /** * Get the bounding box of path. */ void svgtiny_path_bbox(float *p, unsigned int n, float *x0, float *y0, float *x1, float *y1) { unsigned int j; *x0 = *x1 = p[1]; *y0 = *y1 = p[2]; for (j = 0; j != n; ) { unsigned int points = 0; unsigned int k; switch ((int) p[j]) { case svgtiny_PATH_MOVE: case svgtiny_PATH_LINE: points = 1; break; case svgtiny_PATH_CLOSE: points = 0; break; case svgtiny_PATH_BEZIER: points = 3; break; default: assert(0); } j++; for (k = 0; k != points; k++) { float x = p[j], y = p[j + 1]; if (x < *x0) *x0 = x; else if (*x1 < x) *x1 = x; if (y < *y0) *y0 = y; else if (*y1 < y) *y1 = y; j += 2; } } } /** * Invert a transformation matrix. */ void svgtiny_invert_matrix(float *m, float *inv) { float determinant = m[0]*m[3] - m[1]*m[2]; inv[0] = m[3] / determinant; inv[1] = -m[1] / determinant; inv[2] = -m[2] / determinant; inv[3] = m[0] / determinant; inv[4] = (m[2]*m[5] - m[3]*m[4]) / determinant; inv[5] = (m[1]*m[4] - m[0]*m[5]) / determinant; } /** * Find an element in the document by id. */ xmlNode *svgtiny_find_element_by_id(xmlNode *node, const char *id) { xmlNode *child; xmlNode *found; for (child = node->children; child; child = child->next) { xmlAttr *attr; if (child->type != XML_ELEMENT_NODE) continue; attr = xmlHasProp(child, (const xmlChar *) "id"); if (attr && strcmp(id, (const char *) attr->children->content) == 0) return child; found = svgtiny_find_element_by_id(child, id); if (found) return found; } return 0; } netsurf-2.9/libsvgtiny-0.0.2/src/svgtiny_internal.h0000664000175000017500000000504011510173652021232 0ustar vincevince/* * This file is part of Libsvgtiny * Licensed under the MIT License, * http://opensource.org/licenses/mit-license.php * Copyright 2008 James Bursa */ #ifndef SVGTINY_INTERNAL_H #define SVGTINY_INTERNAL_H #include #ifndef UNUSED #define UNUSED(x) ((void) (x)) #endif struct svgtiny_gradient_stop { float offset; svgtiny_colour color; }; #define svgtiny_MAX_STOPS 10 #define svgtiny_LINEAR_GRADIENT 0x2000000 struct svgtiny_parse_state { struct svgtiny_diagram *diagram; xmlDoc *document; float viewport_width; float viewport_height; /* current transformation matrix */ struct { float a, b, c, d, e, f; } ctm; /*struct css_style style;*/ /* paint attributes */ svgtiny_colour fill; svgtiny_colour stroke; int stroke_width; /* gradients */ unsigned int linear_gradient_stop_count; const char *gradient_x1, *gradient_y1, *gradient_x2, *gradient_y2; struct svgtiny_gradient_stop gradient_stop[svgtiny_MAX_STOPS]; bool gradient_user_space_on_use; struct { float a, b, c, d, e, f; } gradient_transform; }; struct svgtiny_list; /* svgtiny.c */ float svgtiny_parse_length(const char *s, int viewport_size, const struct svgtiny_parse_state state); void svgtiny_parse_color(const char *s, svgtiny_colour *c, struct svgtiny_parse_state *state); void svgtiny_parse_transform(char *s, float *ma, float *mb, float *mc, float *md, float *me, float *mf); struct svgtiny_shape *svgtiny_add_shape(struct svgtiny_parse_state *state); void svgtiny_transform_path(float *p, unsigned int n, struct svgtiny_parse_state *state); #if defined(_GNU_SOURCE) #define HAVE_STRNDUP #else #undef HAVE_STRNDUP char *svgtiny_strndup(const char *s, size_t n); #define strndup svgtiny_strndup #endif /* svgtiny_gradient.c */ void svgtiny_find_gradient(const char *id, struct svgtiny_parse_state *state); svgtiny_code svgtiny_add_path_linear_gradient(float *p, unsigned int n, struct svgtiny_parse_state *state); xmlNode *svgtiny_find_element_by_id(xmlNode *node, const char *id); /* svgtiny_list.c */ struct svgtiny_list *svgtiny_list_create(size_t item_size); unsigned int svgtiny_list_size(struct svgtiny_list *list); svgtiny_code svgtiny_list_resize(struct svgtiny_list *list, unsigned int new_size); void *svgtiny_list_get(struct svgtiny_list *list, unsigned int i); void *svgtiny_list_push(struct svgtiny_list *list); void svgtiny_list_free(struct svgtiny_list *list); /* colors.gperf */ const struct svgtiny_named_color * svgtiny_color_lookup(register const char *str, register unsigned int len); #endif netsurf-2.9/libsvgtiny-0.0.2/src/Makefile0000664000175000017500000000073311541746016017132 0ustar vincevince# Sources DIR_SOURCES := svgtiny.c svgtiny_gradient.c svgtiny_list.c SOURCES := $(SOURCES) $(BUILDDIR)/src_colors.c $(BUILDDIR)/src_colors.c: src/colors.gperf $(VQ)$(ECHO) " GPERF: $<" $(Q)gperf --output-file=$@.tmp $< # Hack for GCC 4.2 compatibility (gperf 3.0.4 solves this properly) $(Q)$(SED) -e 's/#ifdef __GNUC_STDC_INLINE__/#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__/' $@.tmp >$@ $(Q)$(RM) $@.tmp include build/makefiles/Makefile.subdir netsurf-2.9/libsvgtiny-0.0.2/src/svgtiny.c0000664000175000017500000007405611510173652017346 0ustar vincevince/* * This file is part of Libsvgtiny * Licensed under the MIT License, * http://opensource.org/licenses/mit-license.php * Copyright 2008-2009 James Bursa */ #include #include #include #include #include #include #include #include #include #include "svgtiny.h" #include "svgtiny_internal.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #define KAPPA 0.5522847498 static svgtiny_code svgtiny_parse_svg(xmlNode *svg, struct svgtiny_parse_state state); static svgtiny_code svgtiny_parse_path(xmlNode *path, struct svgtiny_parse_state state); static svgtiny_code svgtiny_parse_rect(xmlNode *rect, struct svgtiny_parse_state state); static svgtiny_code svgtiny_parse_circle(xmlNode *circle, struct svgtiny_parse_state state); static svgtiny_code svgtiny_parse_ellipse(xmlNode *ellipse, struct svgtiny_parse_state state); static svgtiny_code svgtiny_parse_line(xmlNode *line, struct svgtiny_parse_state state); static svgtiny_code svgtiny_parse_poly(xmlNode *poly, struct svgtiny_parse_state state, bool polygon); static svgtiny_code svgtiny_parse_text(xmlNode *text, struct svgtiny_parse_state state); static void svgtiny_parse_position_attributes(const xmlNode *node, const struct svgtiny_parse_state state, float *x, float *y, float *width, float *height); static void svgtiny_parse_paint_attributes(const xmlNode *node, struct svgtiny_parse_state *state); static void svgtiny_parse_font_attributes(const xmlNode *node, struct svgtiny_parse_state *state); static void svgtiny_parse_transform_attributes(xmlNode *node, struct svgtiny_parse_state *state); static svgtiny_code svgtiny_add_path(float *p, unsigned int n, struct svgtiny_parse_state *state); /** * Create a new svgtiny_diagram structure. */ struct svgtiny_diagram *svgtiny_create(void) { struct svgtiny_diagram *diagram; diagram = malloc(sizeof *diagram); if (!diagram) return 0; diagram->shape = 0; diagram->shape_count = 0; diagram->error_line = 0; diagram->error_message = 0; return diagram; } /** * Parse a block of memory into a svgtiny_diagram. */ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram, const char *buffer, size_t size, const char *url, int viewport_width, int viewport_height) { xmlDoc *document; xmlNode *svg; struct svgtiny_parse_state state; float x, y, width, height; svgtiny_code code; assert(diagram); assert(buffer); assert(url); /* parse XML to tree */ document = xmlReadMemory(buffer, size, url, 0, XML_PARSE_NONET | XML_PARSE_COMPACT); if (!document) return svgtiny_LIBXML_ERROR; /*xmlDebugDumpDocument(stderr, document);*/ /* find root element */ svg = xmlDocGetRootElement(document); if (!svg) return svgtiny_NOT_SVG; if (strcmp((const char *) svg->name, "svg") != 0) return svgtiny_NOT_SVG; /* get graphic dimensions */ state.diagram = diagram; state.document = document; state.viewport_width = viewport_width; state.viewport_height = viewport_height; svgtiny_parse_position_attributes(svg, state, &x, &y, &width, &height); diagram->width = width; diagram->height = height; /* set up parsing state */ state.viewport_width = width; state.viewport_height = height; state.ctm.a = 1; /*(float) viewport_width / (float) width;*/ state.ctm.b = 0; state.ctm.c = 0; state.ctm.d = 1; /*(float) viewport_height / (float) height;*/ state.ctm.e = 0; /*x;*/ state.ctm.f = 0; /*y;*/ /*state.style = css_base_style; state.style.font_size.value.length.value = option_font_size * 0.1;*/ state.fill = 0x000000; state.stroke = svgtiny_TRANSPARENT; state.stroke_width = 1; state.linear_gradient_stop_count = 0; /* parse tree */ code = svgtiny_parse_svg(svg, state); /* free XML tree */ xmlFreeDoc(document); return code; } /** * Parse a or element node. */ svgtiny_code svgtiny_parse_svg(xmlNode *svg, struct svgtiny_parse_state state) { float x, y, width, height; xmlAttr *view_box; xmlNode *child; svgtiny_parse_position_attributes(svg, state, &x, &y, &width, &height); svgtiny_parse_paint_attributes(svg, &state); svgtiny_parse_font_attributes(svg, &state); /* parse viewBox */ view_box = xmlHasProp(svg, (const xmlChar *) "viewBox"); if (view_box) { const char *s = (const char *) view_box->children->content; float min_x, min_y, vwidth, vheight; if (sscanf(s, "%f,%f,%f,%f", &min_x, &min_y, &vwidth, &vheight) == 4 || sscanf(s, "%f %f %f %f", &min_x, &min_y, &vwidth, &vheight) == 4) { state.ctm.a = (float) state.viewport_width / vwidth; state.ctm.d = (float) state.viewport_height / vheight; state.ctm.e += -min_x * state.ctm.a; state.ctm.f += -min_y * state.ctm.d; } } svgtiny_parse_transform_attributes(svg, &state); for (child = svg->children; child; child = child->next) { svgtiny_code code = svgtiny_OK; if (child->type == XML_ELEMENT_NODE) { const char *name = (const char *) child->name; if (strcmp(name, "svg") == 0) code = svgtiny_parse_svg(child, state); else if (strcmp(name, "g") == 0) code = svgtiny_parse_svg(child, state); else if (strcmp(name, "a") == 0) code = svgtiny_parse_svg(child, state); else if (strcmp(name, "path") == 0) code = svgtiny_parse_path(child, state); else if (strcmp(name, "rect") == 0) code = svgtiny_parse_rect(child, state); else if (strcmp(name, "circle") == 0) code = svgtiny_parse_circle(child, state); else if (strcmp(name, "ellipse") == 0) code = svgtiny_parse_ellipse(child, state); else if (strcmp(name, "line") == 0) code = svgtiny_parse_line(child, state); else if (strcmp(name, "polyline") == 0) code = svgtiny_parse_poly(child, state, false); else if (strcmp(name, "polygon") == 0) code = svgtiny_parse_poly(child, state, true); else if (strcmp(name, "text") == 0) code = svgtiny_parse_text(child, state); } if (code != svgtiny_OK) return code; } return svgtiny_OK; } /** * Parse a element node. * * http://www.w3.org/TR/SVG11/paths#PathElement */ svgtiny_code svgtiny_parse_path(xmlNode *path, struct svgtiny_parse_state state) { char *s, *path_d; float *p; unsigned int i; float last_x = 0, last_y = 0; float last_cubic_x = 0, last_cubic_y = 0; float last_quad_x = 0, last_quad_y = 0; svgtiny_parse_paint_attributes(path, &state); svgtiny_parse_transform_attributes(path, &state); /* read d attribute */ s = path_d = (char *) xmlGetProp(path, (const xmlChar *) "d"); if (!s) { state.diagram->error_line = path->line; state.diagram->error_message = "path: missing d attribute"; return svgtiny_SVG_ERROR; } /* allocate space for path: it will never have more elements than d */ p = malloc(sizeof p[0] * strlen(s)); if (!p) return svgtiny_OUT_OF_MEMORY; /* parse d and build path */ for (i = 0; s[i]; i++) if (s[i] == ',') s[i] = ' '; i = 0; while (*s) { char command[2]; int plot_command; float x, y, x1, y1, x2, y2, rx, ry, rotation, large_arc, sweep; int n; /* moveto (M, m), lineto (L, l) (2 arguments) */ if (sscanf(s, " %1[MmLl] %f %f %n", command, &x, &y, &n) == 3) { /*LOG(("moveto or lineto"));*/ if (*command == 'M' || *command == 'm') plot_command = svgtiny_PATH_MOVE; else plot_command = svgtiny_PATH_LINE; do { p[i++] = plot_command; if ('a' <= *command) { x += last_x; y += last_y; } p[i++] = last_cubic_x = last_quad_x = last_x = x; p[i++] = last_cubic_y = last_quad_y = last_y = y; s += n; plot_command = svgtiny_PATH_LINE; } while (sscanf(s, "%f %f %n", &x, &y, &n) == 2); /* closepath (Z, z) (no arguments) */ } else if (sscanf(s, " %1[Zz] %n", command, &n) == 1) { /*LOG(("closepath"));*/ p[i++] = svgtiny_PATH_CLOSE; s += n; /* horizontal lineto (H, h) (1 argument) */ } else if (sscanf(s, " %1[Hh] %f %n", command, &x, &n) == 2) { /*LOG(("horizontal lineto"));*/ do { p[i++] = svgtiny_PATH_LINE; if (*command == 'h') x += last_x; p[i++] = last_cubic_x = last_quad_x = last_x = x; p[i++] = last_cubic_y = last_quad_y = last_y; s += n; } while (sscanf(s, "%f %n", &x, &n) == 1); /* vertical lineto (V, v) (1 argument) */ } else if (sscanf(s, " %1[Vv] %f %n", command, &y, &n) == 2) { /*LOG(("vertical lineto"));*/ do { p[i++] = svgtiny_PATH_LINE; if (*command == 'v') y += last_y; p[i++] = last_cubic_x = last_quad_x = last_x; p[i++] = last_cubic_y = last_quad_y = last_y = y; s += n; } while (sscanf(s, "%f %n", &x, &n) == 1); /* curveto (C, c) (6 arguments) */ } else if (sscanf(s, " %1[Cc] %f %f %f %f %f %f %n", command, &x1, &y1, &x2, &y2, &x, &y, &n) == 7) { /*LOG(("curveto"));*/ do { p[i++] = svgtiny_PATH_BEZIER; if (*command == 'c') { x1 += last_x; y1 += last_y; x2 += last_x; y2 += last_y; x += last_x; y += last_y; } p[i++] = x1; p[i++] = y1; p[i++] = last_cubic_x = x2; p[i++] = last_cubic_y = y2; p[i++] = last_quad_x = last_x = x; p[i++] = last_quad_y = last_y = y; s += n; } while (sscanf(s, "%f %f %f %f %f %f %n", &x1, &y1, &x2, &y2, &x, &y, &n) == 6); /* shorthand/smooth curveto (S, s) (4 arguments) */ } else if (sscanf(s, " %1[Ss] %f %f %f %f %n", command, &x2, &y2, &x, &y, &n) == 5) { /*LOG(("shorthand/smooth curveto"));*/ do { p[i++] = svgtiny_PATH_BEZIER; x1 = last_x + (last_x - last_cubic_x); y1 = last_y + (last_y - last_cubic_y); if (*command == 's') { x2 += last_x; y2 += last_y; x += last_x; y += last_y; } p[i++] = x1; p[i++] = y1; p[i++] = last_cubic_x = x2; p[i++] = last_cubic_y = y2; p[i++] = last_quad_x = last_x = x; p[i++] = last_quad_y = last_y = y; s += n; } while (sscanf(s, "%f %f %f %f %n", &x2, &y2, &x, &y, &n) == 4); /* quadratic Bezier curveto (Q, q) (4 arguments) */ } else if (sscanf(s, " %1[Qq] %f %f %f %f %n", command, &x1, &y1, &x, &y, &n) == 5) { /*LOG(("quadratic Bezier curveto"));*/ do { p[i++] = svgtiny_PATH_BEZIER; last_quad_x = x1; last_quad_y = y1; if (*command == 'q') { x1 += last_x; y1 += last_y; x += last_x; y += last_y; } p[i++] = 1./3 * last_x + 2./3 * x1; p[i++] = 1./3 * last_y + 2./3 * y1; p[i++] = 2./3 * x1 + 1./3 * x; p[i++] = 2./3 * y1 + 1./3 * y; p[i++] = last_cubic_x = last_x = x; p[i++] = last_cubic_y = last_y = y; s += n; } while (sscanf(s, "%f %f %f %f %n", &x1, &y1, &x, &y, &n) == 4); /* shorthand/smooth quadratic Bezier curveto (T, t) (2 arguments) */ } else if (sscanf(s, " %1[Tt] %f %f %n", command, &x, &y, &n) == 3) { /*LOG(("shorthand/smooth quadratic Bezier curveto"));*/ do { p[i++] = svgtiny_PATH_BEZIER; x1 = last_x + (last_x - last_quad_x); y1 = last_y + (last_y - last_quad_y); last_quad_x = x1; last_quad_y = y1; if (*command == 't') { x1 += last_x; y1 += last_y; x += last_x; y += last_y; } p[i++] = 1./3 * last_x + 2./3 * x1; p[i++] = 1./3 * last_y + 2./3 * y1; p[i++] = 2./3 * x1 + 1./3 * x; p[i++] = 2./3 * y1 + 1./3 * y; p[i++] = last_cubic_x = last_x = x; p[i++] = last_cubic_y = last_y = y; s += n; } while (sscanf(s, "%f %f %n", &x, &y, &n) == 2); /* elliptical arc (A, a) (7 arguments) */ } else if (sscanf(s, " %1[Aa] %f %f %f %f %f %f %f %n", command, &rx, &ry, &rotation, &large_arc, &sweep, &x, &y, &n) == 8) { do { p[i++] = svgtiny_PATH_LINE; if (*command == 'a') { x += last_x; y += last_y; } p[i++] = last_cubic_x = last_quad_x = last_x = x; p[i++] = last_cubic_y = last_quad_y = last_y = y; s += n; } while (sscanf(s, "%f %f %f %f %f %f %f %n", &rx, &ry, &rotation, &large_arc, &sweep, &x, &y, &n) == 7); } else { fprintf(stderr, "parse failed at \"%s\"\n", s); break; } } xmlFree(path_d); if (i <= 4) { /* no real segments in path */ free(p); return svgtiny_OK; } return svgtiny_add_path(p, i, &state); } /** * Parse a element node. * * http://www.w3.org/TR/SVG11/shapes#RectElement */ svgtiny_code svgtiny_parse_rect(xmlNode *rect, struct svgtiny_parse_state state) { float x, y, width, height; float *p; svgtiny_parse_position_attributes(rect, state, &x, &y, &width, &height); svgtiny_parse_paint_attributes(rect, &state); svgtiny_parse_transform_attributes(rect, &state); p = malloc(13 * sizeof p[0]); if (!p) return svgtiny_OUT_OF_MEMORY; p[0] = svgtiny_PATH_MOVE; p[1] = x; p[2] = y; p[3] = svgtiny_PATH_LINE; p[4] = x + width; p[5] = y; p[6] = svgtiny_PATH_LINE; p[7] = x + width; p[8] = y + height; p[9] = svgtiny_PATH_LINE; p[10] = x; p[11] = y + height; p[12] = svgtiny_PATH_CLOSE; return svgtiny_add_path(p, 13, &state); } /** * Parse a element node. */ svgtiny_code svgtiny_parse_circle(xmlNode *circle, struct svgtiny_parse_state state) { float x = 0, y = 0, r = -1; float *p; xmlAttr *attr; for (attr = circle->properties; attr; attr = attr->next) { const char *name = (const char *) attr->name; const char *content = (const char *) attr->children->content; if (strcmp(name, "cx") == 0) x = svgtiny_parse_length(content, state.viewport_width, state); else if (strcmp(name, "cy") == 0) y = svgtiny_parse_length(content, state.viewport_height, state); else if (strcmp(name, "r") == 0) r = svgtiny_parse_length(content, state.viewport_width, state); } svgtiny_parse_paint_attributes(circle, &state); svgtiny_parse_transform_attributes(circle, &state); if (r < 0) { state.diagram->error_line = circle->line; state.diagram->error_message = "circle: r missing or negative"; return svgtiny_SVG_ERROR; } if (r == 0) return svgtiny_OK; p = malloc(32 * sizeof p[0]); if (!p) return svgtiny_OUT_OF_MEMORY; p[0] = svgtiny_PATH_MOVE; p[1] = x + r; p[2] = y; p[3] = svgtiny_PATH_BEZIER; p[4] = x + r; p[5] = y + r * KAPPA; p[6] = x + r * KAPPA; p[7] = y + r; p[8] = x; p[9] = y + r; p[10] = svgtiny_PATH_BEZIER; p[11] = x - r * KAPPA; p[12] = y + r; p[13] = x - r; p[14] = y + r * KAPPA; p[15] = x - r; p[16] = y; p[17] = svgtiny_PATH_BEZIER; p[18] = x - r; p[19] = y - r * KAPPA; p[20] = x - r * KAPPA; p[21] = y - r; p[22] = x; p[23] = y - r; p[24] = svgtiny_PATH_BEZIER; p[25] = x + r * KAPPA; p[26] = y - r; p[27] = x + r; p[28] = y - r * KAPPA; p[29] = x + r; p[30] = y; p[31] = svgtiny_PATH_CLOSE; return svgtiny_add_path(p, 32, &state); } /** * Parse an element node. */ svgtiny_code svgtiny_parse_ellipse(xmlNode *ellipse, struct svgtiny_parse_state state) { float x = 0, y = 0, rx = -1, ry = -1; float *p; xmlAttr *attr; for (attr = ellipse->properties; attr; attr = attr->next) { const char *name = (const char *) attr->name; const char *content = (const char *) attr->children->content; if (strcmp(name, "cx") == 0) x = svgtiny_parse_length(content, state.viewport_width, state); else if (strcmp(name, "cy") == 0) y = svgtiny_parse_length(content, state.viewport_height, state); else if (strcmp(name, "rx") == 0) rx = svgtiny_parse_length(content, state.viewport_width, state); else if (strcmp(name, "ry") == 0) ry = svgtiny_parse_length(content, state.viewport_width, state); } svgtiny_parse_paint_attributes(ellipse, &state); svgtiny_parse_transform_attributes(ellipse, &state); if (rx < 0 || ry < 0) { state.diagram->error_line = ellipse->line; state.diagram->error_message = "ellipse: rx or ry missing " "or negative"; return svgtiny_SVG_ERROR; } if (rx == 0 || ry == 0) return svgtiny_OK; p = malloc(32 * sizeof p[0]); if (!p) return svgtiny_OUT_OF_MEMORY; p[0] = svgtiny_PATH_MOVE; p[1] = x + rx; p[2] = y; p[3] = svgtiny_PATH_BEZIER; p[4] = x + rx; p[5] = y + ry * KAPPA; p[6] = x + rx * KAPPA; p[7] = y + ry; p[8] = x; p[9] = y + ry; p[10] = svgtiny_PATH_BEZIER; p[11] = x - rx * KAPPA; p[12] = y + ry; p[13] = x - rx; p[14] = y + ry * KAPPA; p[15] = x - rx; p[16] = y; p[17] = svgtiny_PATH_BEZIER; p[18] = x - rx; p[19] = y - ry * KAPPA; p[20] = x - rx * KAPPA; p[21] = y - ry; p[22] = x; p[23] = y - ry; p[24] = svgtiny_PATH_BEZIER; p[25] = x + rx * KAPPA; p[26] = y - ry; p[27] = x + rx; p[28] = y - ry * KAPPA; p[29] = x + rx; p[30] = y; p[31] = svgtiny_PATH_CLOSE; return svgtiny_add_path(p, 32, &state); } /** * Parse a element node. */ svgtiny_code svgtiny_parse_line(xmlNode *line, struct svgtiny_parse_state state) { float x1 = 0, y1 = 0, x2 = 0, y2 = 0; float *p; xmlAttr *attr; for (attr = line->properties; attr; attr = attr->next) { const char *name = (const char *) attr->name; const char *content = (const char *) attr->children->content; if (strcmp(name, "x1") == 0) x1 = svgtiny_parse_length(content, state.viewport_width, state); else if (strcmp(name, "y1") == 0) y1 = svgtiny_parse_length(content, state.viewport_height, state); else if (strcmp(name, "x2") == 0) x2 = svgtiny_parse_length(content, state.viewport_width, state); else if (strcmp(name, "y2") == 0) y2 = svgtiny_parse_length(content, state.viewport_height, state); } svgtiny_parse_paint_attributes(line, &state); svgtiny_parse_transform_attributes(line, &state); p = malloc(7 * sizeof p[0]); if (!p) return svgtiny_OUT_OF_MEMORY; p[0] = svgtiny_PATH_MOVE; p[1] = x1; p[2] = y1; p[3] = svgtiny_PATH_LINE; p[4] = x2; p[5] = y2; p[6] = svgtiny_PATH_CLOSE; return svgtiny_add_path(p, 7, &state); } /** * Parse a or element node. * * http://www.w3.org/TR/SVG11/shapes#PolylineElement * http://www.w3.org/TR/SVG11/shapes#PolygonElement */ svgtiny_code svgtiny_parse_poly(xmlNode *poly, struct svgtiny_parse_state state, bool polygon) { char *s, *points; float *p; unsigned int i; svgtiny_parse_paint_attributes(poly, &state); svgtiny_parse_transform_attributes(poly, &state); /* read points attribute */ s = points = (char *) xmlGetProp(poly, (const xmlChar *) "points"); if (!s) { state.diagram->error_line = poly->line; state.diagram->error_message = "polyline/polygon: missing points attribute"; return svgtiny_SVG_ERROR; } /* allocate space for path: it will never have more elements than s */ p = malloc(sizeof p[0] * strlen(s)); if (!p) { xmlFree(points); return svgtiny_OUT_OF_MEMORY; } /* parse s and build path */ for (i = 0; s[i]; i++) if (s[i] == ',') s[i] = ' '; i = 0; while (*s) { float x, y; int n; if (sscanf(s, "%f %f %n", &x, &y, &n) == 2) { if (i == 0) p[i++] = svgtiny_PATH_MOVE; else p[i++] = svgtiny_PATH_LINE; p[i++] = x; p[i++] = y; s += n; } else { break; } } if (polygon) p[i++] = svgtiny_PATH_CLOSE; xmlFree(points); return svgtiny_add_path(p, i, &state); } /** * Parse a or element node. */ svgtiny_code svgtiny_parse_text(xmlNode *text, struct svgtiny_parse_state state) { float x, y, width, height; float px, py; xmlNode *child; svgtiny_parse_position_attributes(text, state, &x, &y, &width, &height); svgtiny_parse_font_attributes(text, &state); svgtiny_parse_transform_attributes(text, &state); px = state.ctm.a * x + state.ctm.c * y + state.ctm.e; py = state.ctm.b * x + state.ctm.d * y + state.ctm.f; /* state.ctm.e = px - state.origin_x; */ /* state.ctm.f = py - state.origin_y; */ /*struct css_style style = state.style; style.font_size.value.length.value *= state.ctm.a;*/ for (child = text->children; child; child = child->next) { svgtiny_code code = svgtiny_OK; if (child->type == XML_TEXT_NODE) { struct svgtiny_shape *shape = svgtiny_add_shape(&state); if (!shape) return svgtiny_OUT_OF_MEMORY; shape->text = strdup((const char *) child->content); shape->text_x = px; shape->text_y = py; state.diagram->shape_count++; } else if (child->type == XML_ELEMENT_NODE && strcmp((const char *) child->name, "tspan") == 0) { code = svgtiny_parse_text(child, state); } if (!code != svgtiny_OK) return code; } return svgtiny_OK; } /** * Parse x, y, width, and height attributes, if present. */ void svgtiny_parse_position_attributes(const xmlNode *node, const struct svgtiny_parse_state state, float *x, float *y, float *width, float *height) { xmlAttr *attr; *x = 0; *y = 0; *width = state.viewport_width; *height = state.viewport_height; for (attr = node->properties; attr; attr = attr->next) { const char *name = (const char *) attr->name; const char *content = (const char *) attr->children->content; if (strcmp(name, "x") == 0) *x = svgtiny_parse_length(content, state.viewport_width, state); else if (strcmp(name, "y") == 0) *y = svgtiny_parse_length(content, state.viewport_height, state); else if (strcmp(name, "width") == 0) *width = svgtiny_parse_length(content, state.viewport_width, state); else if (strcmp(name, "height") == 0) *height = svgtiny_parse_length(content, state.viewport_height, state); } } /** * Parse a length as a number of pixels. */ float svgtiny_parse_length(const char *s, int viewport_size, const struct svgtiny_parse_state state) { int num_length = strspn(s, "0123456789+-."); const char *unit = s + num_length; float n = atof((const char *) s); float font_size = 20; /*css_len2px(&state.style.font_size.value.length, 0);*/ UNUSED(state); if (unit[0] == 0) { return n; } else if (unit[0] == '%') { return n / 100.0 * viewport_size; } else if (unit[0] == 'e' && unit[1] == 'm') { return n * font_size; } else if (unit[0] == 'e' && unit[1] == 'x') { return n / 2.0 * font_size; } else if (unit[0] == 'p' && unit[1] == 'x') { return n; } else if (unit[0] == 'p' && unit[1] == 't') { return n * 1.25; } else if (unit[0] == 'p' && unit[1] == 'c') { return n * 15.0; } else if (unit[0] == 'm' && unit[1] == 'm') { return n * 3.543307; } else if (unit[0] == 'c' && unit[1] == 'm') { return n * 35.43307; } else if (unit[0] == 'i' && unit[1] == 'n') { return n * 90; } return 0; } /** * Parse paint attributes, if present. */ void svgtiny_parse_paint_attributes(const xmlNode *node, struct svgtiny_parse_state *state) { const xmlAttr *attr; for (attr = node->properties; attr; attr = attr->next) { const char *name = (const char *) attr->name; const char *content = (const char *) attr->children->content; if (strcmp(name, "fill") == 0) svgtiny_parse_color(content, &state->fill, state); else if (strcmp(name, "stroke") == 0) svgtiny_parse_color(content, &state->stroke, state); else if (strcmp(name, "stroke-width") == 0) state->stroke_width = svgtiny_parse_length(content, state->viewport_width, *state); else if (strcmp(name, "style") == 0) { const char *style = (const char *) attr->children->content; const char *s; char *value; if ((s = strstr(style, "fill:"))) { s += 5; while (*s == ' ') s++; value = strndup(s, strcspn(s, "; ")); svgtiny_parse_color(value, &state->fill, state); free(value); } if ((s = strstr(style, "stroke:"))) { s += 7; while (*s == ' ') s++; value = strndup(s, strcspn(s, "; ")); svgtiny_parse_color(value, &state->stroke, state); free(value); } if ((s = strstr(style, "stroke-width:"))) { s += 13; while (*s == ' ') s++; value = strndup(s, strcspn(s, "; ")); state->stroke_width = svgtiny_parse_length(value, state->viewport_width, *state); free(value); } } } } /** * Parse a colour. */ void svgtiny_parse_color(const char *s, svgtiny_colour *c, struct svgtiny_parse_state *state) { unsigned int r, g, b; float rf, gf, bf; size_t len = strlen(s); char *id = 0, *rparen; if (len == 4 && s[0] == '#') { if (sscanf(s + 1, "%1x%1x%1x", &r, &g, &b) == 3) *c = svgtiny_RGB(r | r << 4, g | g << 4, b | b << 4); } else if (len == 7 && s[0] == '#') { if (sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3) *c = svgtiny_RGB(r, g, b); } else if (10 <= len && s[0] == 'r' && s[1] == 'g' && s[2] == 'b' && s[3] == '(' && s[len - 1] == ')') { if (sscanf(s + 4, "%u,%u,%u", &r, &g, &b) == 3) *c = svgtiny_RGB(r, g, b); else if (sscanf(s + 4, "%f%%,%f%%,%f%%", &rf, &gf, &bf) == 3) { b = bf * 255 / 100; g = gf * 255 / 100; r = rf * 255 / 100; *c = svgtiny_RGB(r, g, b); } } else if (len == 4 && strcmp(s, "none") == 0) { *c = svgtiny_TRANSPARENT; } else if (5 < len && s[0] == 'u' && s[1] == 'r' && s[2] == 'l' && s[3] == '(') { if (s[4] == '#') { id = strdup(s + 5); if (!id) return; rparen = strchr(id, ')'); if (rparen) *rparen = 0; svgtiny_find_gradient(id, state); free(id); fprintf(stderr, "linear_gradient_stop_count %i\n", state->linear_gradient_stop_count); if (state->linear_gradient_stop_count == 0) *c = svgtiny_TRANSPARENT; else if (state->linear_gradient_stop_count == 1) *c = state->gradient_stop[0].color; else *c = svgtiny_LINEAR_GRADIENT; } } else { const struct svgtiny_named_color *named_color; named_color = svgtiny_color_lookup(s, strlen(s)); if (named_color) *c = named_color->color; } } /** * Parse font attributes, if present. */ void svgtiny_parse_font_attributes(const xmlNode *node, struct svgtiny_parse_state *state) { const xmlAttr *attr; UNUSED(state); for (attr = node->properties; attr; attr = attr->next) { if (strcmp((const char *) attr->name, "font-size") == 0) { /*if (css_parse_length( (const char *) attr->children->content, &state->style.font_size.value.length, true, true)) { state->style.font_size.size = CSS_FONT_SIZE_LENGTH; }*/ } } } /** * Parse transform attributes, if present. * * http://www.w3.org/TR/SVG11/coords#TransformAttribute */ void svgtiny_parse_transform_attributes(xmlNode *node, struct svgtiny_parse_state *state) { char *transform; /* parse transform */ transform = (char *) xmlGetProp(node, (const xmlChar *) "transform"); if (transform) { svgtiny_parse_transform(transform, &state->ctm.a, &state->ctm.b, &state->ctm.c, &state->ctm.d, &state->ctm.e, &state->ctm.f); xmlFree(transform); } } /** * Parse a transform string. */ void svgtiny_parse_transform(char *s, float *ma, float *mb, float *mc, float *md, float *me, float *mf) { float a, b, c, d, e, f; float za, zb, zc, zd, ze, zf; float angle, x, y; int n; unsigned int i; for (i = 0; s[i]; i++) if (s[i] == ',') s[i] = ' '; while (*s) { a = d = 1; b = c = 0; e = f = 0; if (sscanf(s, "matrix (%f %f %f %f %f %f) %n", &a, &b, &c, &d, &e, &f, &n) == 6) ; else if (sscanf(s, "translate (%f %f) %n", &e, &f, &n) == 2) ; else if (sscanf(s, "translate (%f) %n", &e, &n) == 1) ; else if (sscanf(s, "scale (%f %f) %n", &a, &d, &n) == 2) ; else if (sscanf(s, "scale (%f) %n", &a, &n) == 1) d = a; else if (sscanf(s, "rotate (%f %f %f) %n", &angle, &x, &y, &n) == 3) { angle = angle / 180 * M_PI; a = cos(angle); b = sin(angle); c = -sin(angle); d = cos(angle); e = -x * cos(angle) + y * sin(angle) + x; f = -x * sin(angle) - y * cos(angle) + y; } else if (sscanf(s, "rotate (%f) %n", &angle, &n) == 1) { angle = angle / 180 * M_PI; a = cos(angle); b = sin(angle); c = -sin(angle); d = cos(angle); } else if (sscanf(s, "skewX (%f) %n", &angle, &n) == 1) { angle = angle / 180 * M_PI; c = tan(angle); } else if (sscanf(s, "skewY (%f) %n", &angle, &n) == 1) { angle = angle / 180 * M_PI; b = tan(angle); } else break; za = *ma * a + *mc * b; zb = *mb * a + *md * b; zc = *ma * c + *mc * d; zd = *mb * c + *md * d; ze = *ma * e + *mc * f + *me; zf = *mb * e + *md * f + *mf; *ma = za; *mb = zb; *mc = zc; *md = zd; *me = ze; *mf = zf; s += n; } } /** * Add a path to the svgtiny_diagram. */ svgtiny_code svgtiny_add_path(float *p, unsigned int n, struct svgtiny_parse_state *state) { struct svgtiny_shape *shape; if (state->fill == svgtiny_LINEAR_GRADIENT) return svgtiny_add_path_linear_gradient(p, n, state); svgtiny_transform_path(p, n, state); shape = svgtiny_add_shape(state); if (!shape) { free(p); return svgtiny_OUT_OF_MEMORY; } shape->path = p; shape->path_length = n; state->diagram->shape_count++; return svgtiny_OK; } /** * Add a svgtiny_shape to the svgtiny_diagram. */ struct svgtiny_shape *svgtiny_add_shape(struct svgtiny_parse_state *state) { struct svgtiny_shape *shape = realloc(state->diagram->shape, (state->diagram->shape_count + 1) * sizeof (state->diagram->shape[0])); if (!shape) return 0; state->diagram->shape = shape; shape += state->diagram->shape_count; shape->path = 0; shape->path_length = 0; shape->text = 0; shape->fill = state->fill; shape->stroke = state->stroke; shape->stroke_width = lroundf((float) state->stroke_width * (state->ctm.a + state->ctm.d) / 2.0); if (0 < state->stroke_width && shape->stroke_width == 0) shape->stroke_width = 1; return shape; } /** * Apply the current transformation matrix to a path. */ void svgtiny_transform_path(float *p, unsigned int n, struct svgtiny_parse_state *state) { unsigned int j; for (j = 0; j != n; ) { unsigned int points = 0; unsigned int k; switch ((int) p[j]) { case svgtiny_PATH_MOVE: case svgtiny_PATH_LINE: points = 1; break; case svgtiny_PATH_CLOSE: points = 0; break; case svgtiny_PATH_BEZIER: points = 3; break; default: assert(0); } j++; for (k = 0; k != points; k++) { float x0 = p[j], y0 = p[j + 1]; float x = state->ctm.a * x0 + state->ctm.c * y0 + state->ctm.e; float y = state->ctm.b * x0 + state->ctm.d * y0 + state->ctm.f; p[j] = x; p[j + 1] = y; j += 2; } } } /** * Free all memory used by a diagram. */ void svgtiny_free(struct svgtiny_diagram *svg) { unsigned int i; assert(svg); for (i = 0; i != svg->shape_count; i++) { free(svg->shape[i].path); free(svg->shape[i].text); } free(svg->shape); free(svg); } #ifndef HAVE_STRNDUP char *svgtiny_strndup(const char *s, size_t n) { size_t len; char *s2; for (len = 0; len != n && s[len]; len++) continue; s2 = malloc(len + 1); if (s2 == NULL) return NULL; memcpy(s2, s, len); s2[len] = '\0'; return s2; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/README�����������������������������������������������������������������0000664�0001750�0001750�00000010743�11007214163�015553� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Libsvgtiny ========== http://www.netsurf-browser.org/projects/libsvgtiny/ Libsvgtiny is a library for parsing SVG files for display. The overall idea of the library is to take some SVG as input, and return a list of paths and texts which can be rendered easily. The library does not do the actual rendering. All supported SVG objects, for example circles, lines, and gradient filled shapes, are converted to flat-filled paths or a fragment of text, and all coordinates are converted, transformed etc. to pixels. Libsvgtiny is Licensed under the MIT License, http://opensource.org/licenses/mit-license.php Written by James Bursa . SVG support ----------- Libsvgtiny is initially aiming to implement SVG Tiny, as defined in http://www.w3.org/TR/SVGMobile/. SVG Tiny elements supported: defs, g, svg, circle, line, path, polygon, polyline, rect, text SVG Tiny elements not yet supported: desc, metadata, title, use, a, switch, ellipse, image, font, font-face, font-face-name, font-face-src, glyph, hkern, missing-glyph, animate, animateColor, animateMotion, animateTransform, mpath, set, foreignObject Additional elements supported: linearGradient, stop Text support is incomplete. The style attribute is supported. Building libsvgtiny ------------------- You will require the following tools: - a C compiler (some parts of C99 support are required) - gperf and the following libraries: - libxml2 To compile libsvgtiny, use the command make To install libsvgtiny into /usr/local, use make install To cross-compile for RISC OS, use make TARGET=riscos make install TARGET=riscos Testing libsvgtiny ------------------ The svgtiny_display script uses the library to render an SVG. It requires that ImageMagick convert is installed. Get an SVG file, for example http://www.croczilla.com/svg/samples/tiger/tiger.svg Then use svgtiny_display to parse and render it: ./svgtiny_display tiger.svg ./svgtiny_display tiger.svg 2 The optional 2nd argument is a scale. Using libsvgtiny ---------------- The interface is in the header svgtiny.h #include First create a svgtiny_diagram using svgtiny_create(): struct svgtiny_diagram *diagram; diagram = svgtiny_create(); This will return a pointer to a new diagram, or NULL if there was not enough memory. SVGs are parsed from memory using svgtiny_parse(): svgtiny_code code; code = svgtiny_parse(diagram, buffer, size, url, 1000, 1000); The arguments are the pointer returned by svgtiny_create(), a buffer containing the SVG data, the size of the SVG in bytes, the url that the SVG came from, and the target viewport width and height in pixels. The function returns svgtiny_OK if there were no problems, and diagram is updated. The diagram can then be rendered by looping through the array diagram->shape[0..diagram->shape_count]: for (unsigned int i = 0; i != diagram->shape_count; i++) { Path shapes have a non-NULL path pointer. The path is an array of floats of length path_length. The array contains segment type codes followed by 0 to 3 pairs of coordinates (depending on the segment type): - svgtiny_PATH_MOVE x y - svgtiny_PATH_CLOSE - svgtiny_PATH_LINE x y - svgtiny_PATH_BEZIER x1 y1 x2 y2 x3 y3 A path always starts with a MOVE. The fill and stroke attributes give the colors of the path, or svgtiny_TRANSPARENT if the path is not filled or stroked. Colors are in 0xRRGGBB format (except when compiled for RISC OS). The macros svgtiny_RED, svgtiny_GREEN, and svgtiny_BLUE can be used to extract the components. The width of the path is in stroke_width. Text shapes have a NULL path pointer and a non-NULL text pointer. Text is in UTF-8. The coordinates of the text are in text_x, text_y. Text colors and stroke width are as for paths. If memory runs out during parsing, svgtiny_parse() returns svgtiny_OUT_OF_MEMORY, but the diagram is still valid up to the point when memory was exhausted, and may safely be rendered. If there is an error in the SVG (for example, an element is missing an attribute required by the specification), svgtiny_SVG_ERROR is returned, but the diagram is still valid up to the point of the error. The error is recorded in diagram->error_message and the line that caused it in diagram->error_line. svgtiny_LIBXML_ERROR indicates that parsing the XML failed. The returned diagram will contain no shapes. svgtiny_NOT_SVG means that the XML did not contain a top-level element. To free memory used by a diagram, use svgtiny_free(): svgtiny_free(diagram); For an example, see svgtiny_test.c. �����������������������������netsurf-2.9/libsvgtiny-0.0.2/test/������������������������������������������������������������������0000775�0001750�0001750�00000000000�11734430273�015656� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/test/Makefile����������������������������������������������������������0000664�0001750�0001750�00000000137�11244456167�017325� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Tests DIR_TEST_ITEMS := svgtiny_test:svgtiny_test.c include build/makefiles/Makefile.subdir ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/test/svgtiny_test.c����������������������������������������������������0000664�0001750�0001750�00000007141�11244445005�020562� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of Libsvgtiny * Licensed under the MIT License, * http://opensource.org/licenses/mit-license.php * Copyright 2008 James Bursa */ #include #include #include #include #include "svgtiny.h" int main(int argc, char *argv[]) { FILE *fd; float scale = 1.0; struct stat sb; char *buffer; size_t size; size_t n; struct svgtiny_diagram *diagram; svgtiny_code code; if (argc != 2 && argc != 3) { fprintf(stderr, "Usage: %s FILE [SCALE]\n", argv[0]); return 1; } /* load file into memory buffer */ fd = fopen(argv[1], "rb"); if (!fd) { perror(argv[1]); return 1; } if (stat(argv[1], &sb)) { perror(argv[1]); return 1; } size = sb.st_size; buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %lld bytes\n", (long long) size); return 1; } n = fread(buffer, 1, size, fd); if (n != size) { perror(argv[1]); return 1; } fclose(fd); /* read scale argument */ if (argc == 3) { scale = atof(argv[2]); if (scale == 0) scale = 1.0; } /* create svgtiny object */ diagram = svgtiny_create(); if (!diagram) { fprintf(stderr, "svgtiny_create failed\n"); return 1; } /* parse */ code = svgtiny_parse(diagram, buffer, size, argv[1], 1000, 1000); if (code != svgtiny_OK) { fprintf(stderr, "svgtiny_parse failed: "); switch (code) { case svgtiny_OUT_OF_MEMORY: fprintf(stderr, "svgtiny_OUT_OF_MEMORY"); break; case svgtiny_LIBXML_ERROR: fprintf(stderr, "svgtiny_LIBXML_ERROR"); break; case svgtiny_NOT_SVG: fprintf(stderr, "svgtiny_NOT_SVG"); break; case svgtiny_SVG_ERROR: fprintf(stderr, "svgtiny_SVG_ERROR: line %i: %s", diagram->error_line, diagram->error_message); break; default: fprintf(stderr, "unknown svgtiny_code %i", code); break; } fprintf(stderr, "\n"); } free(buffer); printf("viewbox 0 0 %g %g\n", scale * diagram->width, scale * diagram->height); for (unsigned int i = 0; i != diagram->shape_count; i++) { if (diagram->shape[i].fill == svgtiny_TRANSPARENT) printf("fill none "); else printf("fill #%.6x ", diagram->shape[i].fill); if (diagram->shape[i].stroke == svgtiny_TRANSPARENT) printf("stroke none "); else printf("stroke #%.6x ", diagram->shape[i].stroke); printf("stroke-width %g ", scale * diagram->shape[i].stroke_width); if (diagram->shape[i].path) { printf("path '"); for (unsigned int j = 0; j != diagram->shape[i].path_length; ) { switch ((int) diagram->shape[i].path[j]) { case svgtiny_PATH_MOVE: printf("M %g %g ", scale * diagram->shape[i].path[j + 1], scale * diagram->shape[i].path[j + 2]); j += 3; break; case svgtiny_PATH_CLOSE: printf("Z "); j += 1; break; case svgtiny_PATH_LINE: printf("L %g %g ", scale * diagram->shape[i].path[j + 1], scale * diagram->shape[i].path[j + 2]); j += 3; break; case svgtiny_PATH_BEZIER: printf("C %g %g %g %g %g %g ", scale * diagram->shape[i].path[j + 1], scale * diagram->shape[i].path[j + 2], scale * diagram->shape[i].path[j + 3], scale * diagram->shape[i].path[j + 4], scale * diagram->shape[i].path[j + 5], scale * diagram->shape[i].path[j + 6]); j += 7; break; default: printf("error "); j += 1; } } printf("' "); } else if (diagram->shape[i].text) { printf("text %g %g '%s' ", scale * diagram->shape[i].text_x, scale * diagram->shape[i].text_y, diagram->shape[i].text); } printf("\n"); } svgtiny_free(diagram); return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/libsvgtiny.pc.in�������������������������������������������������������0000664�0001750�0001750�00000000363�11244456167�020032� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������prefix=PREFIX exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: libsvgtiny Description: SVG Tiny 1.1 rendering library Version: VERSION Requires: libxml-2.0 Libs: -L${libdir} -lsvgtiny Cflags: -I${includedir} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/Makefile���������������������������������������������������������������0000664�0001750�0001750�00000002631�11722703703�016337� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Component settings COMPONENT := svgtiny COMPONENT_VERSION := 0.0.2 # Default to a static library COMPONENT_TYPE ?= lib-static # Setup the tooling include build/makefiles/Makefile.tools TESTRUNNER := $(ECHO) # Toolchain flags WARNFLAGS := -Wall -W -Wundef -Wpointer-arith -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ -Wmissing-declarations -Wnested-externs -pedantic # BeOS/Haiku/AmigaOS standard library headers create warnings ifneq ($(TARGET),beos) ifneq ($(TARGET),AmigaOS) WARNFLAGS := $(WARNFLAGS) -Werror endif endif CFLAGS := -D_BSD_SOURCE -I$(CURDIR)/include/ \ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS) ifneq ($(GCCVER),2) CFLAGS := $(CFLAGS) -std=c99 else # __inline__ is a GCCism CFLAGS := $(CFLAGS) -Dinline="__inline__" endif # LibXML2 ifneq ($(PKGCONFIG),) CFLAGS := $(CFLAGS) \ $(shell $(PKGCONFIG) $(PKGCONFIGFLAGS) --cflags libxml-2.0) LDFLAGS := $(LDFLAGS) \ $(shell $(PKGCONFIG) $(PKGCONFIGFLAGS) --libs libxml-2.0) else ifeq ($(TARGET),beos) CFLAGS := $(CFLAGS) -I/boot/home/config/include/libxml2 endif CFLAGS := $(CFLAGS) -I$(PREFIX)/include/libxml2 LDFLAGS := $(CFLAGS) -lxml2 endif include build/makefiles/Makefile.top # Extra installation rules I := /include INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):include/svgtiny.h INSTALL_ITEMS := $(INSTALL_ITEMS) /lib/pkgconfig:lib$(COMPONENT).pc.in INSTALL_ITEMS := $(INSTALL_ITEMS) /lib:$(OUTPUT) �������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/svgtiny_display��������������������������������������������������������0000775�0001750�0001750�00000000172�11302236627�020053� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������set -e make BUILD=debug test build-Linux-Linux-debug-lib-static/test_svgtiny_test $1 $2 | convert mvg:- png:- | display - ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/build/�����������������������������������������������������������������0000775�0001750�0001750�00000000000�11734430275�016000� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/build/makefiles/�������������������������������������������������������0000775�0001750�0001750�00000000000�11734430275�017740� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/build/makefiles/Makefile.top�������������������������������������������0000664�0001750�0001750�00000042323�11537116272�022204� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Top-level Makefile fragment # # Expected inputs: # # BUILD Type of build to perform: # release - Release build # debug - Debug build # COMPONENT Name of the component (sans leading "lib" iff a library) # COMPONENT_VERSION Component version number (x.y.z) # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # TARGET Target platform identifier # # Optional inputs: # # BUILDDIR Directory to build into (defaults to # build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE)) # CC_CAN_BUILD_AND_DEP Flag whether $(CC) is capable of calculating dependency # information at the same time as compiling sources. # Set to "yes" if it can. # DESTDIR Sandboxed FS root (e.g. for packaging) # HOST Host platform identifier # REQUIRED_PKGS List of required pkg-config packages # # The client may also override all toolchain settings, including: # # ARFLAGS Archiver flags for the current compilation # CFLAGS C compiler flags for the current compilation # CXXFLAGS C++ compiler flags for the current compilation # LDFLAGS Linker flags for the current compilation # # TESTCFLAGS Any test-specific CFLAGS # TESTCXXFLAGS Any test-specific CXXFLAGS # TESTLDFLAGS Any test-specific LDFLAGS # # TESTRUNNER Test runner invocation command # The test runner takes a command line in the form # # # Targets provided: # # all Default target. Builds component using current settings # test Build and run test suite, using current settings. # coverage Determine test suite coverage (requires lcov) # profile Build with profiling support enabled (requires gprof) # docs Produce documentation (requires doxygen) # clean Clean the build # distclean Remove distribution files, too # install Install component into prefix. # uninstall Remove component from prefix. # # Variables provided: # # major-version Extracts the major version (x) from COMPONENT_VERSION # minor-version Extracts the minor version (y) from COMPONENT_VERSION # patch-version Extracts the patch version (z) from COMPONENT_VERSION # OUTPUT Path + filename of build target ############################################################################### # Sanity checks ############################################################################### # Name of component must be defined by client ifeq ($(COMPONENT),) $(error COMPONENT not defined) endif # As must the version ifeq ($(COMPONENT_VERSION),) $(error COMPONENT_VERSION not defined) endif # As must the component type ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not defined) endif # Target platform must be defined by the client ifeq ($(TARGET),) $(error TARGET not defined) endif # Build type, too ifeq ($(BUILD),) $(error BUILD not defined) endif ############################################################################## # Makefile variables ############################################################################## Q ?= @ VQ ?= @ ############################################################################## # Exported variables (also OUTPUT, further down) ############################################################################## major-version := $(word 1,$(subst ., ,$(COMPONENT_VERSION))) minor-version := $(word 2,$(subst ., ,$(COMPONENT_VERSION))) patch-version := $(word 3,$(subst ., ,$(COMPONENT_VERSION))) ############################################################################## # Build environment ############################################################################## # Build directory BUILDDIR ?= build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE) # Build tree subdirs COVERAGEDIR := $(BUILDDIR)/coverage DOCDIR := $(BUILDDIR)/docs # Determine if we want to build testcases ifeq ($(MAKECMDGOALS),test) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),profile) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),coverage) WANT_TEST := yes else WANT_TEST := no endif # List of items to delete on clean CLEAN_ITEMS := # List of items to delete on distclean DISTCLEAN_ITEMS := # List of items to build for testing TEST_ITEMS := # List of targets to run for testing TEST_TARGETS := # List of targets which are prerequisites for running tests TEST_PREREQS := # List of items to (un)install INSTALL_ITEMS := # List of targets to run before building $(OBJECT) PRE_TARGETS := # List of targets to run after building $(OBJECT) POST_TARGETS := # Source files SOURCES := # Include configuration Makefile fragment -include Makefile.config # Set the default target (before including any children) __default: all # Include Makefile fragments in subdirectories define do_include DIR := $$(dir $(1)) include $(1) endef MAKE_INCLUDES := $(wildcard */Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Calculate objects to build OBJECTS := $(addprefix $(BUILDDIR)/,$(filter %.o, \ $(subst /,_,$(subst .c,.o,$(SOURCES))) \ $(subst /,_,$(subst .cpp,.o,$(SOURCES))) \ $(subst /,_,$(subst .cmhg,.o,$(SOURCES))) \ $(subst /,_,$(subst .s,.o,$(SOURCES))))) bin_for_test = $(addprefix $(BUILDDIR)/,$(firstword $(subst :, ,$(ITEM)))) TEST_BINARIES := $(foreach ITEM,$(TEST_ITEMS),$(bin_for_test)) # Determine if we're building any C++ sources ifneq ($(filter %.cpp,$(SOURCES)),) CXX_IN_BUILD := yes else CXX_IN_BUILD := no endif # Determine the output filename ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) ifeq ($(findstring lib-shared,$(COMPONENT_TYPE)),lib-shared) SHAREDLIBNAME := lib$(COMPONENT)$(LIBEXT) SONAME := $(SHAREDLIBNAME).$(major-version) OUTPUT := $(BUILDDIR)/$(SHAREDLIBNAME).$(COMPONENT_VERSION) else OUTPUT := $(BUILDDIR)/lib$(COMPONENT)$(LIBEXT) endif else OUTPUT := $(BUILDDIR)/$(COMPONENT)$(EXEEXT) endif ############################################################################### # Build targets ############################################################################### .PHONY: all test coverage profile docs clean distclean install uninstall \ __default __precov __partial_clean __postshared ifeq ($(COMPONENT_TYPE),lib-shared) POST_TARGETS := __postshared $(POST_TARGETS) __postshared: $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SONAME) $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SHAREDLIBNAME) endif # Default target all: $(PRE_TARGETS) $(OUTPUT) $(POST_TARGETS) # Build and execute testsuite test: all $(TEST_PREREQS) $(TEST_BINARIES) $(TEST_TARGETS) $(VQ)$(ECHO) $(ECHOFLAGS) " TEST: Testing complete" # Compute coverage __precov: __partial_clean $(Q)$(LCOV) --directory . --zerocounters coverage: __precov test $(Q)$(LCOV) --directory $(BUILDDIR) --base-directory $(CURDIR) \ --capture --output-file $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(LCOV) --extract $(COVERAGEDIR)/$(COMPONENT)_tmp.info \ "$(CURDIR)/src*" -o $(COVERAGEDIR)/$(COMPONENT).info $(Q)$(RM) $(RMFLAGS) $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(GENHTML) -o $(COVERAGEDIR) --num-spaces 2 \ $(COVERAGEDIR)/$(COMPONENT).info # Build for profiling profile: __partial_clean test # Compile documentation docs: $(BUILDDIR)/stamp $(Q)$(DOXYGEN) build/Doxyfile # Clean build tree __partial_clean: -$(Q)$(RM) $(RMFLAGS) $(CLEAN_ITEMS) -$(Q)$(RM) $(RMFLAGS) gmon.out -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.d) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcda) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcno) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.o) clean: __partial_clean -$(Q)$(RM) $(RMFLAGS) -r build/docs -$(Q)$(RM) $(RMFLAGS) -r $(BUILDDIR) # Remove auto-generated non-build-tree items distclean: clean -$(Q)$(RM) $(RMFLAGS) $(DISTCLEAN_ITEMS) # The installation target, and associated canned command sequences. # For reference, the syntax of INSTALL_ITEMS is: # # :[';']* # # We also permit a trailing ';' in the file list. __comma := , __empty := __space := $(empty) $(empty) __required = $(if $(REQUIRED_PKGS),Requires: $(subst $(__space),$(__comma) ,$(strip $(REQUIRED_PKGS))),) # Install a pkg-config control file ($1) to the specified location ($2) define install_pkgconfig $(Q)$(ECHO) $(ECHOFLAGS) "sed -e... $1 >$(BUILDDIR)/$(1:.in=)" $(Q)$(SED) \ -e 's#PREFIX#$(PREFIX)#' \ -e 's#MAJOR#$(major-version)#' \ -e 's#MINOR#$(minor-version)#' \ -e 's#PATCH#$(patch-version)#' \ -e 's#VERSION#$(COMPONENT_VERSION)#' \ -e 's#REQUIRED#$(__required)#' \ $1 >$(BUILDDIR)/$(1:.in=) $(INSTALL) $(INSTALLFLAGS) -m 644 $(BUILDDIR)/$(1:.in=) \ $2/$(1:.in=) endef # TODO: Is this scheme portable? define install_shared_lib $(INSTALL) $(INSTALLFLAGS) -m 755 $1 $2/$(notdir $1) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SONAME) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SHAREDLIBNAME) endef # Install a file ($1) to the specified location ($2) define install_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(call install_pkgconfig,$1,$2), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call install_shared_lib,$1,$2), \ $(INSTALL) $(INSTALLFLAGS) -m 644 $1 $2))) endef # Install a list of files ($2) to the specified location ($1) # We create the installation location if it doesn't already exist define install_to_dest $(Q)$(MKDIR) $(MKDIRFLAGS) $(DESTDIR)$(PREFIX)$1 $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call install_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef install: all $(foreach ITEM,$(INSTALL_ITEMS), \ $(call install_to_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) # Uninstallation # TODO: Work out how to safely remove symlinks define uninstall_shared_lib $(RM) $(RMFLAGS) $2/$(notdir $1).$(COMPONENT_VERSION) endef # Uninstall a file ($1) from the specified location ($2) define uninstall_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(RM) $(RMFLAGS) $2/$(1:.pc.in=.pc), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call uninstall_shared_lib,$1,$2), \ $(RM) $(RMFLAGS) $2/$(notdir $1)))) endef # Uninstall a list of files ($2) from the specified location ($1) # TODO: Come up with a safe way of removing directories, too define uninstall_from_dest $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call uninstall_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef uninstall: $(foreach ITEM,$(INSTALL_ITEMS), \ $(call uninstall_from_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) ############################################################################### # Actual rules ############################################################################### $(BUILDDIR)/stamp: $(Q)$(MKDIR) $(MKDIRFLAGS) $(BUILDDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(COVERAGEDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(DOCDIR) $(Q)$(TOUCH) $(TOUCHFLAGS) $(BUILDDIR)/stamp $(OUTPUT): $(BUILDDIR)/stamp $(OBJECTS) ifeq ($(COMPONENT_TYPE),lib-static) $(VQ)$(ECHO) $(ECHOFLAGS) " AR: $@" $(Q)$(RM) $(RMFLAGS) $@ $(Q)$(AR) $(ARFLAGS) $@ $(OBJECTS) else $(VQ)$(ECHO) $(ECHOFLAGS) " LINK: $@" ifeq ($(CXX_IN_BUILD),yes) $(Q)$(CXX) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) else $(Q)$(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) endif endif ############################################################################### # Autogenerated, implied rules ############################################################################### DEPFILES := BUILDFILES := ifeq ($(CC_CAN_BUILD_AND_DEP),yes) # C compiler can compile and dep simultaneously define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else ifeq ($(CC_CANNOT_DEP),yes) # C compiler cannot calculate dependencies define dep_c endef define dep_cxx endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else # C compiler must calculate dependencies first, then compile (default) define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CC) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CXX) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef endif endif define build_cmhg ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " CMHG: $1" $$(Q)$$(CMHG) $$(CMHGFLAGS) $1 -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_s ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) "ASSEMBLE: $1" $$(Q)$$(CC) $$($3) $1 -c -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef BUILDCFLAGS = $(CFLAGS) $(SHAREDCFLAGS) BUILDCXXFLAGS = $(CXXFLAGS) $(SHAREDCXXFLAGS) BUILDASFLAGS = $(ASFLAGS) $(SHAREDCFLAGS) # Generate dependency rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),BUILDCXXFLAGS))) # Generate compilation rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),BUILDCXXFLAGS))) $(eval $(foreach SOURCE,$(filter %.cmhg,$(SOURCES)), \ $(call build_cmhg,$(SOURCE),$(subst /,_,$(SOURCE:.cmhg=.o))))) $(eval $(foreach SOURCE,$(filter %.s,$(SOURCES)), \ $(call build_s,$(SOURCE),$(subst /,_,$(SOURCE:.s=.o)),BUILDASFLAGS))) # Similarly for test sources ifeq ($(WANT_TEST),yes) ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) TESTLIB := $(OUTPUT) TESTLDFLAGS += -L$(BUILDDIR)/ -l$(COMPONENT) endif TESTCFLAGS := $(CFLAGS) $(TESTCFLAGS) TESTCXXFLAGS += $(CXXFLAGS) TESTLDFLAGS += $(LDFLAGS) define link_test $2: $($3) $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " LINK: $2" ifeq ($$(CXX_IN_BUILD),yes) $$(Q)$$(CXX) -o $$@ $1 $$($4) else $$(Q)$$(CC) -o $$@ $1 $$($4) endif endef srcs_for_test = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) objs_for_test = $(addprefix $(BUILDDIR)/, \ $(subst /,_,$(addsuffix .o,$(basename $(srcs_for_test))))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(call link_test,$(objs_for_test),$(bin_for_test),TESTLIB,TESTLDFLAGS))) endif # Include dependency makefiles ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) -include $(sort $(DEPFILES)) endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/build/makefiles/Makefile.clang�����������������������������������������0000664�0001750�0001750�00000002326�11545435603�022466� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Clang-specific toolchain setup # We assume that we're using a standard GCC/binutils environment, as well # as clang being mostly GCC-compatible on the command line CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### CC_CAN_BUILD_AND_DEP ?= yes ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/build/makefiles/Makefile.norcroft��������������������������������������0000664�0001750�0001750�00000002203�11545435603�023230� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Norcroft specific toolchain setup CCDEF := -D CCOPT := -Otime CCNOOPT := CCDBG := -g CCINC := -I CCLIB := -L # TODO: Norcroft CC cannot do assembler as C CCAS := CCSHR := CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g LDSHR := ARFLG := -c # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) $(error Coverage is not supported with Norcroft) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) $(error Profile is not supported with Norcroft) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -zM CXXFLAGS := $(CXXFLAGS) -zM LDFLAGS := $(LDFLAGS) -zM endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. CC_CANNOT_DEP := yes ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/build/makefiles/Makefile.gcc�������������������������������������������0000664�0001750�0001750�00000004570�11545435603�022141� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# GCC specific toolchain setup # We assume that we're using a standard GCC/binutils environment CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions for various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="__attribute__((aligned))" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) COVCFLAGS ?= -fprofile-arcs -ftest-coverage COVCXXFLAGS ?= -fprofile-arcs -ftest-coverage COVLDFLAGS ?= -lgcov CFLAGS := $(CFLAGS) $(COVCFLAGS) CXXFLAGS := $(CXXFLAGS) $(COVCXXFLAGS) LDFLAGS := $(LDFLAGS) $(COVLDFLAGS) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) PROFCFLAGS ?= -pg PROFCXXFLAGS ?= -pg PROFLDFLAGS ?= -pg CFLAGS := $(CFLAGS) $(PROFCFLAGS) CXXFLAGS := $(CXXFLAGS) $(PROFCXXFLAGS) LDFLAGS := $(LDFLAGS) $(PROFLDFLAGS) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -mmodule CXXFLAGS := $(CXXFLAGS) -mmodule LDFLAGS := $(LDFLAGS) -mmodule endif ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CC_CAN_BUILD_AND_DEP := no CC_CANNOT_DEP := yes CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. ccvsn := $(shell $(CC) -dumpversion) # ccvsn = x.y.z GCCVER := $(word 1,$(subst ., ,$(ccvsn))) # GCCVER = x # If the major version (x, above) is not 2, then assume build & dep. # This will break if using a version of GCC < 2, but that's unlikely. ifneq ($(GCCVER),2) CC_CAN_BUILD_AND_DEP ?= yes endif ����������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/build/makefiles/Makefile.pkgconfig�������������������������������������0000664�0001750�0001750�00000004265�11476474557�023373� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# General purpose pkg-config macros # Determine if a package is available # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_available ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package availability) endif ifeq ($$(shell $$(PKGCONFIG) --exists $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Retrieve the version of a package # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif $(1) := $$(shell $$(PKGCONFIG) --version $(2)) endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number define pkg_config_package_min_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number # 4: Highest accepted version number define pkg_config_package_compare_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) ifeq ($$(shell $$(PKGCONFIG) --max-version=$(4) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif else $(1) := no endif endef # Add package to compiler/linker flags # 1: Name of package to add details of # 2: CFLAGS variable to extend, or none # 3: LDFLAGS variable to extend, or none define pkg_config_package_add_flags ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifneq ($(2),) $(2) := $$($(2)) $$(shell $$(PKGCONFIG) --cflags $(1)) endif ifneq ($(3),) $(3) := $$($(3)) $$(shell $$(PKGCONFIG) --libs $(1)) endif endef �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/build/makefiles/Makefile.subdir����������������������������������������0000664�0001750�0001750�00000007417�11165262413�022673� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Child makefile fragment # # Inputs (reset on exit) # # DIR_SOURCES List of source files in this directory # DIR_TEST_ITEMS List of test items in this directory # DIR_INSTALL_ITEMS Items to install in form :; # # Toolchain is provided by top-level makefile # # Variables provided by top-level makefile # # BUILDDIR The location of the build tree root # COMPONENT The name of the component # CURDIR The location of the source tree root # EXPORTDIR The location of the export directory # WANT_TEST Whether to build testcases # # do_include Canned command sequence to include a child makefile # # Variables provided by parent makefile: # # DIR The name of the directory we're in, relative to CURDIR # # Variables we can manipulate: # # CLEAN_ITEMS The list of items to remove for "make clean" # DISTCLEAN_ITEMS The list of items to remove for "make distclean" # TEST_ITEMS The list of items to build for "make test" # TEST_TARGETS The list of target names to run for "make test" # INSTALL_ITEMS The list of items to (un)install # # SOURCES The list of sources to build for $(COMPONENT) # # Plus anything from the toolchain # Push parent directory onto the directory stack sp := $(sp).x dirstack_$(sp) := $(d) d := $(DIR) # Sources SRCS_$(d) := $(DIR_SOURCES) TEST_ITEMS_$(d) := INSTALL_ITEMS_$(d) := # Append to sources for component SOURCES := $(SOURCES) $(addprefix $(d), $(SRCS_$(d))) # Test sources ifeq ($(WANT_TEST),yes) ifneq ($(DIR_TEST_ITEMS),) # Extract the binary name from the ITEM binary = $(subst /,_,$(addprefix $(d),$(firstword $(subst :, ,$(ITEM))))) # Extract the list of sources from the ITEM sources = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) # We can't simply use the output of foreach here, # as it space separates its output, which kinda defeats the point. define append_test_src TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d))$1; endef define append_test TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d)) $1: $$(eval $$(foreach TSRC,$2, \ $$(call append_test_src,$$(addprefix $$(d),$$(TSRC))))) endef # Append test items, prepending $(d) to each source file $(eval $(foreach ITEM,$(DIR_TEST_ITEMS), \ $(call append_test,$(binary),$(sources)))) TEST_ITEMS := $(TEST_ITEMS) $(TEST_ITEMS_$(d)) TEST_TARGETS := $(TEST_TARGETS) test_$(d) # Extract the binary name from the TEST binary_name = $(firstword $(subst :, ,$(TEST))) # Target for tests in this directory test_$(d): $(d) $(addprefix $(BUILDDIR)/, \ $(foreach TEST,$(TEST_ITEMS_$(d)),$(binary_name))) $(Q)$(SHAREDLDPATH) $(TESTRUNNER) $(BUILDDIR) \ $(CURDIR)/$< $(subst /,_,$<) $(EXEEXT) endif endif # Install items ifneq ($(DIR_INSTALL_ITEMS),) # Extract the destination directory from the variable dest_dir = $(firstword $(subst :, ,$(ITEM))) # Extract the list of files to install files = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) define append_install_file INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d))$1; endef define append_install_item INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d)) $1: $$(eval $$(foreach FILE,$2, \ $$(call append_install_file,$$(addprefix $$(d),$$(FILE))))) endef # Append items to install (along with install location), prepending $(d) # to each item in the file list $(eval $(foreach ITEM,$(DIR_INSTALL_ITEMS), \ $(call append_install_item,$(dest_dir),$(files)))) INSTALL_ITEMS := $(INSTALL_ITEMS) $(INSTALL_ITEMS_$(d)) endif # Reset the inputs DIR_SOURCES := DIR_TEST_ITEMS := DIR_INSTALL_ITEMS := # Now include any children we may have MAKE_INCLUDES := $(wildcard $(d)*/Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Pop off the directory stack d := $(dirstack_$(sp)) sp := $(basename $(sp)) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libsvgtiny-0.0.2/build/makefiles/Makefile.tools�����������������������������������������0000664�0001750�0001750�00000032245�11711241331�022531� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Tools Makefile fragment # # Expected inputs: # # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # # Optional inputs: # # BUILD Type of build to perform: # release - Release build (default) # debug - Debug build # OPTCFLAGS Optional C compiler flags for $(BUILD) # OPTCXXFLAGS Optional C++ compiler flags for $(BUILD) # OPTLDFLAGS Optional linker flags for $(BUILD) # TARGET Target platform (defaults to host) # PREFIX Absolute installation path prefix # (defaults to /usr/local) # ############################################################################### # Sanity checks ############################################################################### ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not set) endif # Default build to release ifeq ($(BUILD),) BUILD := release endif ############################################################################### # Host/target platform detection ############################################################################### # Autodetect host if necessary ifeq ($(HOST),) HOST := $(shell uname -s) endif # Simple host sanitisation ifeq ($(HOST),) # Don't ask HOST := riscos else ifeq ($(HOST),RISC OS) HOST := riscos endif ifeq ($(HOST),BeOS) HOST := beos endif ifeq ($(HOST),Haiku) HOST := haiku endif ifeq ($(HOST),AmigaOS) HOST := amiga endif ifeq ($(findstring MINGW,$(HOST)),MINGW) HOST := windows endif endif ifeq ($(TARGET),) # Default target to host. Please add exceptions as required. TARGET := $(HOST) ifeq ($(HOST),haiku) # This isn't necessarily correct -- they have differences. However, in the # general case, this will work. If there are differences that are actually # important wrt the target platform (as opposed to the build host) then # we'll just have to introduce a haiku target, too. TARGET := beos endif endif # Sanitise HOST and TARGET # TODO: Ideally, we want the equivalent of s/[^A-Za-z0-9]/_/g here HOST := $(subst .,_,$(subst -,_,$(subst /,_,$(HOST)))) TARGET := $(subst .,_,$(subst -,_,$(subst /,_,$(TARGET)))) # Now setup our tooling ifeq ($(TARGET),riscos) ifeq ($(HOST),riscos) # Building on native RISC OS GCCSDK_INSTALL_ENV ?= CC__ := gcc CXX__ := g++ CMHG ?= cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= # On certain versions of RISC OS (<>4 || kernel < 8.75), # the kernel will clean up the current redirection on # OS_Exit, including closing the associated file handles. # This is problematic for UnixLib, as it's invariably using # those filehandles in a pipe between parent and child processes. # This affects us as, anywhere where we shell out and want to # capture the output of the child process may fail. # Fortunately, if we know the child process is built against # UnixLib, then we also know that it won't call OS_Exit when it # exits, instead returning directly to our exit handler (and thus # preserving the redirection). This only works, however, if the # child application is specified using its absolute path, or # found in Run$Path. In the case of Perl, it does not appear in # Run$Path, so we must invoke it using its absolute path so that # the SharedUnixLibrary successfully detects it as a child process. PERL ?= .bin.perl # This is nasty, but needed because $(CURDIR) will # contain colons, and thus confuse make mightily $(shell SetMacro Alias$$$(COMPONENT)pwd Set %0 :|$$CSD>|mUnset Alias$$$(COMPONENT)pwd) $(shell $(COMPONENT)pwd $(COMPONENT)$$Dir) CURDIR := <$(COMPONENT)$$Dir> else # Cross compiling for RISC OS ifeq ($(origin GCCSDK_INSTALL_ENV),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/env),) GCCSDK_INSTALL_ENV := /opt/netsurf/arm-unknown-riscos/env else GCCSDK_INSTALL_ENV := /home/riscos/env endif endif ifeq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/cross/bin),) GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-unknown-riscos/cross/bin else GCCSDK_INSTALL_CROSSBIN := /home/riscos/cross/bin endif endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) CMHG ?= PATH="$(GCCSDK_INSTALL_CROSSBIN):$(PATH)" $(GCCSDK_INSTALL_CROSSBIN)/cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/share/pkgconfig" pkg-config ifneq ($(COMPONENT_TYPE),riscos-module) ifeq ($(origin CC),default) ifneq ($(findstring arm-unknown-riscos-gcc,$(CC__)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif else ifneq ($(findstring arm-unknown-riscos-gcc,$(CC)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif endif else EXEEXT := ,ffa endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib CMHGFLAGS := -p -tgcc -32bit -apcs 3/32/nonreent/fpe2/noswst/nofpr/nofp # Default prefix PREFIX ?= $(GCCSDK_INSTALL_ENV) endif # BeOS-like targets ifeq ($(TARGET),beos) ifeq ($(HOST),beos) # Building on BeOS CC__ := gcc # No pkg-config PKGCONFIG ?= # Default prefix BEOS_INSTALL_ENV ?= /boot/home/config else ifeq ($(HOST),haiku) # Building on Haiku # Default prefix BEOS_INSTALL_ENV ?= /boot/common else # TODO: more sensible default BEOS_INSTALL_ENV ?= /home/jmb/haiku/env BEOS_INSTALL_CROSSBIN ?= /home/jmb/haiku/haiku/generated/cross-tools/bin CC__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*g++) AR__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*ar) PKGCONFIG := PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/share/pkgconfig" pkg-config endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -I$(BEOS_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -I$(BEOS_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(BEOS_INSTALL_ENV)/lib PREFIX ?= $(BEOS_INSTALL_ENV) endif # Windows ifeq ($(TARGET),windows) ifeq ($(HOST),windows) # Building on Windows CC__ := gcc CXX__ := g++ AR__ := ar PKGCONFIG ?= else # Cross compiling for Windows -- assumes mingw toolchain MINGW_INSTALL_ENV ?= /usr/local/mingw CC__ := i586-mingw32msvc-gcc CXX__ := i586-mingw32msvc-g++ AR__ := i586-mingw32msvc-ar PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(MINGW_INSTALL_ENV)/lib # Default prefix PREFIX ?= $(MINGW_INSTALL_ENV) endif # AmigaOS (3/4; m68k/ppc: we can treat them identically) ifeq ($(findstring amiga,$(TARGET)),amiga) ifeq ($(findstring amiga,$(HOST)),amiga) # Building on AmigaOS # Nothing to do, as we assume the default tooling works else # Cross compiling for AmigaOS ifeq ($(TARGET),amigaos3) GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-unknown-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-unknown-amigaos/cross/bin else GCCSDK_INSTALL_ENV ?= /opt/netsurf/ppc-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/ppc-amigaos/cross/bin endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib PREFIX ?= $(GCCSDK_INSTALL_ENV) endif endif # Default prefix PREFIX ?= /usr/local ############################################################################### # Tool defaults ############################################################################### CP ?= cp DOXYGEN ?= doxygen ECHO ?= echo GENHTML ?= genhtml ifeq ($(HOST),$(TARGET)) HOST_CC ?= $(CC) HOST_CXX ?= $(CXX) else HOST_CC ?= cc HOST_CXX ?= c++ endif INSTALL ?= install LCOV ?= lcov LN ?= ln MAKE ?= make MKDIR ?= mkdir MKDIRFLAGS ?= -p MV ?= mv PERL ?= perl PKGCONFIG ?= PKG_CONFIG_PATH="$(PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)" pkg-config GREP ?= grep SED ?= sed TOUCH ?= touch XSLTPROC ?= xsltproc ############################################################################### # Override defaulted tools ############################################################################### # CC ifeq ($(findstring ccc-analyzer,$(CC)),ccc-analyzer) # We're being invoked by scan-build, so export # the compiler we would have used such that # scan-build works with cross-compilation. # There's no need to do this if we would have # used the default compiler. ifdef CC__ export CCC_CC := $(CC__) endif else # Only set CC if it's not already set in the # environment and we have a value for it. # Otherwise, leave it to be defaulted. ifeq ($(origin CC),default) ifdef CC__ CC := $(CC__) endif endif endif # CXX ifeq ($(origin CXX),default) ifdef CXX__ CXX := $(CXX__) endif endif # AR ifeq ($(origin AR),default) ifdef AR__ AR := $(AR__) endif endif ############################################################################### # Auto-detect the toolchain ############################################################################### # Check for GCC first, as that's most likely # TODO: Using shell redirection like this probably hurts portability ccspecs := $(shell $(CC) -dumpspecs 2>&1) ifeq ($(findstring libgcc,$(ccspecs)),libgcc) # Looks like GCC toolchain := gcc else # Not GCC, so enquire further ccvsn := $(shell $(CC) --version 2>&1) ifeq ($(ccvsn),) # Version string is blank ifeq ($(HOST),riscos) # For some reason we never see the output of SCL apps, so might be # Norcroft. However it might also be a GCC linked against a buggy # UnixLib. # TODO: Something more useful than blindly assuming GCC. ccvsn := GCC # ccvsn := Norcroft endif endif # "Norcroft ..." ifeq ($(word 1,$(ccvsn)),Norcroft) toolchain := norcroft endif # "GCC ..." ifeq ($(word 1,$(ccvsn)),GCC) toolchain := gcc endif # "clang ..." ifeq ($(word 1,$(ccvsn)),clang) toolchain := clang endif ifeq ($(word 1,$(ccvsn)),Apple) ifeq ($(word 2,$(ccvsn)),clang) # Apple clang toolchain := clang endif endif endif ifeq ($(toolchain),) $(error Unable to detect toolchain) endif # TODO: It would be nice to avoid this hard-coded path include build/makefiles/Makefile.$(toolchain) ############################################################################### # Default assembler/compiler/linker/archiver flags ############################################################################### ifeq ($(BUILD),release) OPTCFLAGS ?= $(CCDEF)NDEBUG $(CCOPT) OPTCXXFLAGS ?= $(CXXDEF)NDEBUG $(CXXOPT) else OPTCFLAGS ?= $(CCDBG) $(CCNOOPT) $(CCDEF)DEBUG OPTCXXFLAGS ?= $(CXXDBG) $(CXXNOOPT) $(CXXDEF)DEBUG OPTLDFLAGS ?= $(LDDBG) endif ifeq ($(origin ARFLAGS),default) ARFLAGS := $(ARFLG) endif # TODO: This assumes that the C compiler can cope with assembler ASFLAGS ?= $(CCAS) CFLAGS := $(CFLAGS) $(OPTCFLAGS) $(CCDEF)BUILD_TARGET_$(TARGET) $(CCDEF)BUILD_HOST_$(HOST) CXXFLAGS := $(CXXFLAGS) $(OPTCXXFLAGS) \ $(CXXDEF)BUILD_TARGET_$(TARGET) $(CXXDEF)BUILD_HOST_$(HOST) ASFLAGS := $(ASFLAGS) $(CFLAGS) LDFLAGS := $(LDFLAGS) $(OPTLDFLAGS) ############################################################################### # lib-shared defaults ############################################################################### # Default library extension ifeq ($(COMPONENT_TYPE),lib-static) LIBEXT ?= .a else LIBEXT ?= .so endif # If we're building a shared library, modify the flags appropriately ifeq ($(COMPONENT_TYPE),lib-shared) # Default CFLAGS/LDFLAGS for shared libraries SHAREDCFLAGS ?= $(CCSHR) $(CCDEF)PIC SHAREDCXXFLAGS ?= $(CXXSHR) $(CCDEF)PIC SHAREDLDFLAGS ?= $(LDSHR) SHAREDLDPATH ?= LD_LIBRARY_PATH="$(BUILDDIR):$(LD_LIBRARY_PATH)" endif ################################################################################ # Package config macros ################################################################################ include build/makefiles/Makefile.pkgconfig �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/�������������������������������������������������������������������0000775�0001750�0001750�00000000000�11734430231�015543� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/�����������������������������������������������������������0000775�0001750�0001750�00000000000�11734430231�017166� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/�����������������������������������������������0000775�0001750�0001750�00000000000�11734430231�021543� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/parserutils.h����������������������������������0000664�0001750�0001750�00000000712�11476457062�024307� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_parserutils_h_ #define parserutils_parserutils_h_ #ifdef __cplusplus extern "C" { #endif #include #include #include #ifdef __cplusplus } #endif #endif ������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/functypes.h������������������������������������0000664�0001750�0001750�00000001074�11460664405�023746� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007-8 John-Mark Bell */ #ifndef parserutils_functypes_h_ #define parserutils_functypes_h_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include /* Type of allocation function for parserutils */ typedef void *(*parserutils_alloc)(void *ptr, size_t size, void *pw); #ifdef __cplusplus } #endif #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/utils/�����������������������������������������0000775�0001750�0001750�00000000000�11734430231�022703� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/utils/buffer.h���������������������������������0000664�0001750�0001750�00000002376�11460664405�024345� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef parserutils_utils_buffer_h_ #define parserutils_utils_buffer_h_ #ifdef __cplusplus extern "C" { #endif #include #include struct parserutils_buffer { uint8_t *data; size_t length; size_t allocated; parserutils_alloc alloc; void *pw; }; typedef struct parserutils_buffer parserutils_buffer; parserutils_error parserutils_buffer_create(parserutils_alloc alloc, void *pw, parserutils_buffer **buffer); parserutils_error parserutils_buffer_destroy(parserutils_buffer *buffer); parserutils_error parserutils_buffer_append(parserutils_buffer *buffer, const uint8_t *data, size_t len); parserutils_error parserutils_buffer_insert(parserutils_buffer *buffer, size_t offset, const uint8_t *data, size_t len); parserutils_error parserutils_buffer_discard(parserutils_buffer *buffer, size_t offset, size_t len); parserutils_error parserutils_buffer_grow(parserutils_buffer *buffer); parserutils_error parserutils_buffer_randomise(parserutils_buffer *buffer); #ifdef __cplusplus } #endif #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/utils/stack.h����������������������������������0000664�0001750�0001750�00000001721�11460664405�024172� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef parserutils_utils_stack_h_ #define parserutils_utils_stack_h_ #ifdef __cplusplus extern "C" { #endif #include #include #include struct parserutils_stack; typedef struct parserutils_stack parserutils_stack; parserutils_error parserutils_stack_create(size_t item_size, size_t chunk_size, parserutils_alloc alloc, void *pw, parserutils_stack **stack); parserutils_error parserutils_stack_destroy(parserutils_stack *stack); parserutils_error parserutils_stack_push(parserutils_stack *stack, const void *item); parserutils_error parserutils_stack_pop(parserutils_stack *stack, void *item); void *parserutils_stack_get_current(parserutils_stack *stack); #ifdef __cplusplus } #endif #endif �����������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/utils/vector.h���������������������������������0000664�0001750�0001750�00000002364�11460664405�024373� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef parserutils_utils_vector_h_ #define parserutils_utils_vector_h_ #ifdef __cplusplus extern "C" { #endif #include #include #include struct parserutils_vector; typedef struct parserutils_vector parserutils_vector; parserutils_error parserutils_vector_create(size_t item_size, size_t chunk_size, parserutils_alloc alloc, void *pw, parserutils_vector **vector); parserutils_error parserutils_vector_destroy(parserutils_vector *vector); parserutils_error parserutils_vector_append(parserutils_vector *vector, void *item); parserutils_error parserutils_vector_clear(parserutils_vector *vector); parserutils_error parserutils_vector_remove_last(parserutils_vector *vector); parserutils_error parserutils_vector_get_length(parserutils_vector *vector, size_t *length); const void *parserutils_vector_iterate(const parserutils_vector *vector, int32_t *ctx); const void *parserutils_vector_peek(const parserutils_vector *vector, int32_t ctx); #ifdef __cplusplus } #endif #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/errors.h���������������������������������������0000664�0001750�0001750�00000001672�11460664405�023246� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_errors_h_ #define parserutils_errors_h_ #ifdef __cplusplus extern "C" { #endif #include typedef enum parserutils_error { PARSERUTILS_OK = 0, PARSERUTILS_NOMEM = 1, PARSERUTILS_BADPARM = 2, PARSERUTILS_INVALID = 3, PARSERUTILS_FILENOTFOUND = 4, PARSERUTILS_NEEDDATA = 5, PARSERUTILS_BADENCODING = 6, PARSERUTILS_EOF = 7 } parserutils_error; /* Convert a parserutils error value to a string */ const char *parserutils_error_to_string(parserutils_error error); /* Convert a string to a parserutils error value */ parserutils_error parserutils_error_from_string(const char *str, size_t len); #ifdef __cplusplus } #endif #endif ����������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/input/�����������������������������������������0000775�0001750�0001750�00000000000�11734430231�022702� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/input/inputstream.h����������������������������0000664�0001750�0001750�00000012305�11460664405�025437� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_input_inputstream_h_ #define parserutils_input_inputstream_h_ #ifdef __cplusplus extern "C" { #endif #include #ifndef NDEBUG #include #endif #include #include #include #include #include #include #include /** * Type of charset detection function */ typedef parserutils_error (*parserutils_charset_detect_func)( const uint8_t *data, size_t len, uint16_t *mibenum, uint32_t *source); /** * Input stream object */ typedef struct parserutils_inputstream { parserutils_buffer *utf8; /**< Buffer containing UTF-8 data */ uint32_t cursor; /**< Byte offset of current position */ bool had_eof; /**< Whether EOF has been reached */ } parserutils_inputstream; /* Create an input stream */ parserutils_error parserutils_inputstream_create(const char *enc, uint32_t encsrc, parserutils_charset_detect_func csdetect, parserutils_alloc alloc, void *pw, parserutils_inputstream **stream); /* Destroy an input stream */ parserutils_error parserutils_inputstream_destroy( parserutils_inputstream *stream); /* Append data to an input stream */ parserutils_error parserutils_inputstream_append( parserutils_inputstream *stream, const uint8_t *data, size_t len); /* Insert data into stream at current location */ parserutils_error parserutils_inputstream_insert( parserutils_inputstream *stream, const uint8_t *data, size_t len); /* Slow form of css_inputstream_peek. */ parserutils_error parserutils_inputstream_peek_slow( parserutils_inputstream *stream, size_t offset, const uint8_t **ptr, size_t *length); /** * Look at the character in the stream that starts at * offset bytes from the cursor * * \param stream Stream to look in * \param offset Byte offset of start of character * \param ptr Pointer to location to receive pointer to character data * \param length Pointer to location to receive character length (in bytes) * \return PARSERUTILS_OK on success, * _NEEDDATA on reaching the end of available input, * _EOF on reaching the end of all input, * _BADENCODING if the input cannot be decoded, * _NOMEM on memory exhaustion, * _BADPARM if bad parameters are passed. * * Once the character pointed to by the result of this call has been advanced * past (i.e. parserutils_inputstream_advance has caused the stream cursor to * pass over the character), then no guarantee is made as to the validity of * the data pointed to. Thus, any attempt to dereference the pointer after * advancing past the data it points to is a bug. */ static inline parserutils_error parserutils_inputstream_peek( parserutils_inputstream *stream, size_t offset, const uint8_t **ptr, size_t *length) { parserutils_error error = PARSERUTILS_OK; const parserutils_buffer *utf8; const uint8_t *utf8_data; size_t len, off, utf8_len; if (stream == NULL || ptr == NULL || length == NULL) return PARSERUTILS_BADPARM; #ifndef NDEBUG #ifdef VERBOSE_INPUTSTREAM fprintf(stdout, "Peek: len: %zu cur: %u off: %zu\n", stream->utf8->length, stream->cursor, offset); #endif #ifdef RANDOMISE_INPUTSTREAM parserutils_buffer_randomise(stream->utf8); #endif #endif utf8 = stream->utf8; utf8_data = utf8->data; utf8_len = utf8->length; off = stream->cursor + offset; #define IS_ASCII(x) (((x) & 0x80) == 0) if (off < utf8_len) { if (IS_ASCII(utf8_data[off])) { /* Early exit for ASCII case */ (*length) = 1; (*ptr) = (utf8_data + off); return PARSERUTILS_OK; } else { error = parserutils_charset_utf8_char_byte_length( utf8_data + off, &len); if (error == PARSERUTILS_OK) { (*length) = len; (*ptr) = (utf8_data + off); return PARSERUTILS_OK; } else if (error != PARSERUTILS_NEEDDATA) { return error; } } } #undef IS_ASCII if (off != utf8_len && error != PARSERUTILS_NEEDDATA) abort(); return parserutils_inputstream_peek_slow(stream, offset, ptr, length); } /** * Advance the stream's current position * * \param stream The stream whose position to advance * \param bytes The number of bytes to advance */ static inline void parserutils_inputstream_advance( parserutils_inputstream *stream, size_t bytes) { if (stream == NULL) return; #if !defined(NDEBUG) && defined(VERBOSE_INPUTSTREAM) fprintf(stdout, "Advance: len: %zu cur: %u bytes: %zu\n", stream->utf8->length, stream->cursor, bytes); #endif if (bytes > stream->utf8->length - stream->cursor) abort(); if (stream->cursor == stream->utf8->length) return; stream->cursor += bytes; } /* Read the document charset */ const char *parserutils_inputstream_read_charset( parserutils_inputstream *stream, uint32_t *source); /* Change the document charset */ parserutils_error parserutils_inputstream_change_charset( parserutils_inputstream *stream, const char *enc, uint32_t source); #ifdef __cplusplus } #endif #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/charset/���������������������������������������0000775�0001750�0001750�00000000000�11734430231�023174� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/charset/utf16.h��������������������������������0000664�0001750�0001750�00000002327�11460664405�024326� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ /** \file * UTF-16 manipulation functions (interface). */ #ifndef parserutils_charset_utf16_h_ #define parserutils_charset_utf16_h_ #ifdef __cplusplus extern "C" { #endif #include #include parserutils_error parserutils_charset_utf16_to_ucs4(const uint8_t *s, size_t len, uint32_t *ucs4, size_t *clen); parserutils_error parserutils_charset_utf16_from_ucs4(uint32_t ucs4, uint8_t *s, size_t *len); parserutils_error parserutils_charset_utf16_length(const uint8_t *s, size_t max, size_t *len); parserutils_error parserutils_charset_utf16_char_byte_length(const uint8_t *s, size_t *len); parserutils_error parserutils_charset_utf16_prev(const uint8_t *s, uint32_t off, uint32_t *prevoff); parserutils_error parserutils_charset_utf16_next(const uint8_t *s, uint32_t len, uint32_t off, uint32_t *nextoff); parserutils_error parserutils_charset_utf16_next_paranoid(const uint8_t *s, uint32_t len, uint32_t off, uint32_t *nextoff); #ifdef __cplusplus } #endif #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/charset/mibenum.h������������������������������0000664�0001750�0001750�00000001533�11460664405�025013� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_charset_mibenum_h_ #define parserutils_charset_mibenum_h_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include /* Convert an encoding alias to a MIB enum value */ uint16_t parserutils_charset_mibenum_from_name(const char *alias, size_t len); /* Convert a MIB enum value into an encoding alias */ const char *parserutils_charset_mibenum_to_name(uint16_t mibenum); /* Determine if a MIB enum value represents a Unicode variant */ bool parserutils_charset_mibenum_is_unicode(uint16_t mibenum); #ifdef __cplusplus } #endif #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/charset/utf8.h���������������������������������0000664�0001750�0001750�00000002312�11460664405�024241� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ /** \file * UTF-8 manipulation functions (interface). */ #ifndef parserutils_charset_utf8_h_ #define parserutils_charset_utf8_h_ #ifdef __cplusplus extern "C" { #endif #include #include parserutils_error parserutils_charset_utf8_to_ucs4(const uint8_t *s, size_t len, uint32_t *ucs4, size_t *clen); parserutils_error parserutils_charset_utf8_from_ucs4(uint32_t ucs4, uint8_t **s, size_t *len); parserutils_error parserutils_charset_utf8_length(const uint8_t *s, size_t max, size_t *len); parserutils_error parserutils_charset_utf8_char_byte_length(const uint8_t *s, size_t *len); parserutils_error parserutils_charset_utf8_prev(const uint8_t *s, uint32_t off, uint32_t *prevoff); parserutils_error parserutils_charset_utf8_next(const uint8_t *s, uint32_t len, uint32_t off, uint32_t *nextoff); parserutils_error parserutils_charset_utf8_next_paranoid(const uint8_t *s, uint32_t len, uint32_t off, uint32_t *nextoff); #ifdef __cplusplus } #endif #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/charset/codec.h��������������������������������0000664�0001750�0001750�00000007405�11460664405�024440� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_charset_codec_h_ #define parserutils_charset_codec_h_ #ifdef __cplusplus extern "C" { #endif #include #include #include typedef struct parserutils_charset_codec parserutils_charset_codec; #define PARSERUTILS_CHARSET_CODEC_NULL (0xffffffffU) /** * Charset codec error mode * * A codec's error mode determines its behaviour in the face of: * * + characters which are unrepresentable in the destination charset (if * encoding data) or which cannot be converted to UCS-4 (if decoding data). * + invalid byte sequences (both encoding and decoding) * * The options provide a choice between the following approaches: * * + draconian, "stop processing" ("strict") * + "replace the unrepresentable character with something else" ("loose") * + "attempt to transliterate, or replace if unable" ("translit") * * The default error mode is "loose". * * * In the "loose" case, the replacement character will depend upon: * * + Whether the operation was encoding or decoding * + If encoding, what the destination charset is. * * If decoding, the replacement character will be: * * U+FFFD (REPLACEMENT CHARACTER) * * If encoding, the replacement character will be: * * U+003F (QUESTION MARK) if the destination charset is not UTF-(8|16|32) * U+FFFD (REPLACEMENT CHARACTER) otherwise. * * * In the "translit" case, the codec will attempt to transliterate into * the destination charset, if encoding. If decoding, or if transliteration * fails, this option is identical to "loose". */ typedef enum parserutils_charset_codec_errormode { /** Abort processing if unrepresentable character encountered */ PARSERUTILS_CHARSET_CODEC_ERROR_STRICT = 0, /** Replace unrepresentable characters with single alternate */ PARSERUTILS_CHARSET_CODEC_ERROR_LOOSE = 1, /** Transliterate unrepresentable characters, if possible */ PARSERUTILS_CHARSET_CODEC_ERROR_TRANSLIT = 2 } parserutils_charset_codec_errormode; /** * Charset codec option types */ typedef enum parserutils_charset_codec_opttype { /** Set codec error mode */ PARSERUTILS_CHARSET_CODEC_ERROR_MODE = 1 } parserutils_charset_codec_opttype; /** * Charset codec option parameters */ typedef union parserutils_charset_codec_optparams { /** Parameters for error mode setting */ struct { /** The desired error handling mode */ parserutils_charset_codec_errormode mode; } error_mode; } parserutils_charset_codec_optparams; /* Create a charset codec */ parserutils_error parserutils_charset_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec); /* Destroy a charset codec */ parserutils_error parserutils_charset_codec_destroy( parserutils_charset_codec *codec); /* Configure a charset codec */ parserutils_error parserutils_charset_codec_setopt( parserutils_charset_codec *codec, parserutils_charset_codec_opttype type, parserutils_charset_codec_optparams *params); /* Encode a chunk of UCS-4 data into a codec's charset */ parserutils_error parserutils_charset_codec_encode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); /* Decode a chunk of data in a codec's charset into UCS-4 */ parserutils_error parserutils_charset_codec_decode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); /* Reset a charset codec */ parserutils_error parserutils_charset_codec_reset( parserutils_charset_codec *codec); #ifdef __cplusplus } #endif #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/include/parserutils/types.h����������������������������������������0000664�0001750�0001750�00000000607�11460664405�023073� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_types_h_ #define parserutils_types_h_ #ifdef __cplusplus extern "C" { #endif #include #include #ifdef __cplusplus } #endif #endif �������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/libparserutils.pc.in�����������������������������������������������0000664�0001750�0001750�00000000373�11173431416�021546� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������prefix=PREFIX exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: libparserutils Description: Utility library for facilitating parser development Version: VERSION Libs: -L${libdir} -lparserutils Cflags: -I${includedir} ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/���������������������������������������������������������������0000775�0001750�0001750�00000000000�11734430231�016332� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/Makefile�������������������������������������������������������0000664�0001750�0001750�00000000051�11476457062�020004� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ include build/makefiles/Makefile.subdir ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/utils/���������������������������������������������������������0000775�0001750�0001750�00000000000�11734430231�017472� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/utils/buffer.c�������������������������������������������������0000664�0001750�0001750�00000011266�11114344174�021117� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #define DEFAULT_SIZE (4096) /** * Create a memory buffer * * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data * \param buffer Pointer to location to receive memory buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhausion */ parserutils_error parserutils_buffer_create(parserutils_alloc alloc, void *pw, parserutils_buffer **buffer) { parserutils_buffer *b; if (alloc == NULL || buffer == NULL) return PARSERUTILS_BADPARM; b = alloc(NULL, sizeof(parserutils_buffer), pw); if (b == NULL) return PARSERUTILS_NOMEM; b->data = alloc(NULL, DEFAULT_SIZE, pw); if (b->data == NULL) { alloc(b, 0, pw); return PARSERUTILS_NOMEM; } b->length = 0; b->allocated = DEFAULT_SIZE; b->alloc = alloc; b->pw = pw; *buffer = b; return PARSERUTILS_OK; } /** * Destroy a memory buffer * * \param buffer The buffer to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_buffer_destroy(parserutils_buffer *buffer) { if (buffer == NULL) return PARSERUTILS_BADPARM; buffer->alloc(buffer->data, 0, buffer->pw); buffer->alloc(buffer, 0, buffer->pw); return PARSERUTILS_OK; } /** * Append data to a memory buffer * * \param buffer The buffer to append to * \param data The data to append * \param len The length, in bytes, of the data to append * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_buffer_append(parserutils_buffer *buffer, const uint8_t *data, size_t len) { while (len >= buffer->allocated - buffer->length) { parserutils_error error = parserutils_buffer_grow(buffer); if (error != PARSERUTILS_OK) return error; } memcpy(buffer->data + buffer->length, data, len); buffer->length += len; return PARSERUTILS_OK; } /** * Insert data into a memory buffer * * \param buffer The buffer to insert into * \param offset The offset into the buffer to insert at * \param data The data to insert * \param len The length, in bytes, of the data to insert * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_buffer_insert(parserutils_buffer *buffer, size_t offset, const uint8_t *data, size_t len) { if (offset > buffer->length) return PARSERUTILS_BADPARM; if (offset == buffer->length) return parserutils_buffer_append(buffer, data, len); while (len >= buffer->allocated - buffer->length) { parserutils_error error = parserutils_buffer_grow(buffer); if (error != PARSERUTILS_OK) return error; } memmove(buffer->data + buffer->length + len, buffer->data + offset, buffer->length - offset); memcpy(buffer->data + offset, data, len); buffer->length += len; return PARSERUTILS_OK; } /** * Discard a section of a memory buffer * * \param buffer The buffer to discard data from * \param offset The offset into the buffer of the start of the section * \param len The number of bytes to discard * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_buffer_discard(parserutils_buffer *buffer, size_t offset, size_t len) { if (offset >= buffer->length || offset + len > buffer->length) return PARSERUTILS_BADPARM; memmove(buffer->data + offset, buffer->data + offset + len, buffer->length - len); buffer->length -= len; return PARSERUTILS_OK; } /** * Extend the amount of space allocated for a memory buffer * * \param buffer The buffer to extend * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_buffer_grow(parserutils_buffer *buffer) { uint8_t *temp = buffer->alloc(buffer->data, buffer->allocated * 2, buffer->pw); if (temp == NULL) return PARSERUTILS_NOMEM; buffer->data = temp; buffer->allocated *= 2; return PARSERUTILS_OK; } parserutils_error parserutils_buffer_randomise(parserutils_buffer *buffer) { #ifndef NDEBUG uint8_t *temp; #endif if (buffer == NULL) return PARSERUTILS_BADPARM; #ifndef NDEBUG temp = buffer->alloc(NULL, buffer->allocated, buffer->pw); if (temp == NULL) return PARSERUTILS_NOMEM; memcpy(temp, buffer->data, buffer->length); memset(buffer->data, 0xff, buffer->length); /* Leak the buffer's current data, so we don't reuse it */ /* buffer->alloc(buffer->data, 0, buffer->pw); */ buffer->data = temp; #endif return PARSERUTILS_OK; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/utils/stack.c��������������������������������������������������0000664�0001750�0001750�00000011124�11114540307�020740� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include /** * Stack object */ struct parserutils_stack { size_t item_size; /**< Size of an item in the stack */ size_t chunk_size; /**< Size of a stack chunk */ size_t items_allocated; /**< Number of slots allocated */ int32_t current_item; /**< Index of current item */ void *items; /**< Items in stack */ parserutils_alloc alloc; /**< Memory (de)allocation function */ void *pw; /**< Client-specific data */ }; /** * Create a stack * * \param item_size Length, in bytes, of an item in the stack * \param chunk_size Number of stack slots in a chunk * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data * \param stack Pointer to location to receive stack instance * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters * PARSERUTILS_NOMEM on memory exhaustion */ parserutils_error parserutils_stack_create(size_t item_size, size_t chunk_size, parserutils_alloc alloc, void *pw, parserutils_stack **stack) { parserutils_stack *s; if (item_size == 0 || chunk_size == 0 || alloc == NULL || stack == NULL) return PARSERUTILS_BADPARM; s = alloc(NULL, sizeof(parserutils_stack), pw); if (s == NULL) return PARSERUTILS_NOMEM; s->items = alloc(NULL, item_size * chunk_size, pw); if (s->items == NULL) { alloc(s, 0, pw); return PARSERUTILS_NOMEM; } s->item_size = item_size; s->chunk_size = chunk_size; s->items_allocated = chunk_size; s->current_item = -1; s->alloc = alloc; s->pw = pw; *stack = s; return PARSERUTILS_OK; } /** * Destroy a stack instance * * \param stack The stack to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_stack_destroy(parserutils_stack *stack) { if (stack == NULL) return PARSERUTILS_BADPARM; stack->alloc(stack->items, 0, stack->pw); stack->alloc(stack, 0, stack->pw); return PARSERUTILS_OK; } /** * Push an item onto the stack * * \param stack The stack to push onto * \param item The item to push * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_stack_push(parserutils_stack *stack, const void *item) { int32_t slot; if (stack == NULL || item == NULL) return PARSERUTILS_BADPARM; /* Ensure we'll get a valid slot */ if (stack->current_item < -1 || stack->current_item == INT32_MAX) return PARSERUTILS_INVALID; slot = stack->current_item + 1; if ((size_t) slot >= stack->items_allocated) { void *temp = stack->alloc(stack->items, (stack->items_allocated + stack->chunk_size) * stack->item_size, stack->pw); if (temp == NULL) return PARSERUTILS_NOMEM; stack->items = temp; stack->items_allocated += stack->chunk_size; } memcpy((uint8_t *) stack->items + (slot * stack->item_size), item, stack->item_size); stack->current_item = slot; return PARSERUTILS_OK; } /** * Pop an item off a stack * * \param stack The stack to pop from * \param item Pointer to location to receive popped item, or NULL * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_stack_pop(parserutils_stack *stack, void *item) { if (stack == NULL) return PARSERUTILS_BADPARM; if (stack->current_item < 0) return PARSERUTILS_INVALID; if (item != NULL) { memcpy(item, (uint8_t *) stack->items + (stack->current_item * stack->item_size), stack->item_size); } stack->current_item -= 1; return PARSERUTILS_OK; } /** * Retrieve a pointer to the current item on the stack * * \param stack The stack to inspect * \return Pointer to item on stack, or NULL if none */ void *parserutils_stack_get_current(parserutils_stack *stack) { if (stack == NULL || stack->current_item < 0) return NULL; return (uint8_t *) stack->items + (stack->current_item * stack->item_size); } #ifndef NDEBUG #include extern void parserutils_stack_dump(parserutils_stack *stack, const char *prefix, void (*printer)(void *item)); void parserutils_stack_dump(parserutils_stack *stack, const char *prefix, void (*printer)(void *item)) { int32_t i; if (stack == NULL || printer == NULL) return; for (i = 0; i <= stack->current_item; i++) { printf("%s %d: ", prefix != NULL ? prefix : "", i); printer((uint8_t *) stack->items + (i * stack->item_size)); printf("\n"); } } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/utils/endian.h�������������������������������������������������0000664�0001750�0001750�00000001514�11232673207�021107� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2009 John-Mark Bell */ #ifndef parserutils_endian_h_ #define parserutils_endian_h_ static inline bool endian_host_is_le(void) { static uint32_t magic = 0x10000002; return (((uint8_t *) &magic)[0] == 0x02); } static inline uint32_t endian_swap(uint32_t val) { return ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); } static inline uint32_t endian_host_to_big(uint32_t host) { if (endian_host_is_le()) return endian_swap(host); return host; } static inline uint32_t endian_big_to_host(uint32_t big) { if (endian_host_is_le()) return endian_swap(big); return big; } #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/utils/Makefile�������������������������������������������������0000664�0001750�0001750�00000000145�11171400507�021130� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Sources DIR_SOURCES := buffer.c errors.c stack.c vector.c include build/makefiles/Makefile.subdir ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/utils/vector.c�������������������������������������������������0000664�0001750�0001750�00000014235�11146002737�021150� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include /** * Vector object */ struct parserutils_vector { size_t item_size; /**< Size of an item in the vector */ size_t chunk_size; /**< Size of a vector chunk */ size_t items_allocated; /**< Number of slots allocated */ int32_t current_item; /**< Index of current item */ void *items; /**< Items in vector */ parserutils_alloc alloc; /**< Memory (de)allocation function */ void *pw; /**< Client-specific data */ }; /** * Create a vector * * \param item_size Length, in bytes, of an item in the vector * \param chunk_size Number of vector slots in a chunk * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data * \param vector Pointer to location to receive vector instance * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhaustion */ parserutils_error parserutils_vector_create(size_t item_size, size_t chunk_size, parserutils_alloc alloc, void *pw, parserutils_vector **vector) { parserutils_vector *v; if (item_size == 0 || chunk_size == 0 || alloc == NULL || vector == NULL) return PARSERUTILS_BADPARM; v = alloc(NULL, sizeof(parserutils_vector), pw); if (v == NULL) return PARSERUTILS_NOMEM; v->items = alloc(NULL, item_size * chunk_size, pw); if (v->items == NULL) { alloc(v, 0, pw); return PARSERUTILS_NOMEM; } v->item_size = item_size; v->chunk_size = chunk_size; v->items_allocated = chunk_size; v->current_item = -1; v->alloc = alloc; v->pw = pw; *vector = v; return PARSERUTILS_OK; } /** * Destroy a vector instance * * \param vector The vector to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_vector_destroy(parserutils_vector *vector) { if (vector == NULL) return PARSERUTILS_BADPARM; vector->alloc(vector->items, 0, vector->pw); vector->alloc(vector, 0, vector->pw); return PARSERUTILS_OK; } /** * Append an item to the vector * * \param vector The vector to append to * \param item The item to append * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_vector_append(parserutils_vector *vector, void *item) { int32_t slot; if (vector == NULL || item == NULL) return PARSERUTILS_BADPARM; /* Ensure we'll get a valid slot */ if (vector->current_item < -1 || vector->current_item == INT32_MAX) return PARSERUTILS_INVALID; slot = vector->current_item + 1; if ((size_t) slot >= vector->items_allocated) { void *temp = vector->alloc(vector->items, (vector->items_allocated + vector->chunk_size) * vector->item_size, vector->pw); if (temp == NULL) return PARSERUTILS_NOMEM; vector->items = temp; vector->items_allocated += vector->chunk_size; } memcpy((uint8_t *) vector->items + (slot * vector->item_size), item, vector->item_size); vector->current_item = slot; return PARSERUTILS_OK; } /** * Clear a vector * * \param vector The vector to clear * \return PARSERUTILS_OK on success, appropriate error otherwise. */ parserutils_error parserutils_vector_clear(parserutils_vector *vector) { if (vector == NULL) return PARSERUTILS_BADPARM; if (vector->current_item < 0) return PARSERUTILS_INVALID; vector->current_item = -1; return PARSERUTILS_OK; } /** * Remove the last item from a vector * * \param vector The vector to remove from * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_vector_remove_last(parserutils_vector *vector) { if (vector == NULL) return PARSERUTILS_BADPARM; if (vector->current_item < 0) return PARSERUTILS_INVALID; vector->current_item--; return PARSERUTILS_OK; } /** * Acquire the length (in items) of the vector. * * \param vector The vector to interrogate. * \param length Pointer to location to receive length information. * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_vector_get_length(parserutils_vector *vector, size_t *length) { if (vector == NULL) return PARSERUTILS_BADPARM; if (length == NULL) return PARSERUTILS_BADPARM; *length = vector->current_item + 1; return PARSERUTILS_OK; } /** * Iterate over a vector * * \param vector The vector to iterate over * \param ctx Pointer to an integer for the iterator to use as context. * \return Pointer to current item, or NULL if no more * * \note The value pointed to by \a ctx must be zero to begin the iteration. */ const void *parserutils_vector_iterate(const parserutils_vector *vector, int32_t *ctx) { void *item; if (vector == NULL || ctx == NULL || vector->current_item < 0) return NULL; if ((*ctx) > vector->current_item) return NULL; item = (uint8_t *) vector->items + ((*ctx) * vector->item_size); (*ctx)++; return item; } /** * Peek at an item in a vector * * \param vector The vector to iterate over * \param ctx Integer for the iterator to use as context. * \return Pointer to item, or NULL if no more */ const void *parserutils_vector_peek(const parserutils_vector *vector, int32_t ctx) { if (vector == NULL || vector->current_item < 0) return NULL; if (ctx > vector->current_item) return NULL; return (uint8_t *) vector->items + (ctx * vector->item_size); } #ifndef NDEBUG #include extern void parserutils_vector_dump(parserutils_vector *vector, const char *prefix, void (*printer)(void *item)); void parserutils_vector_dump(parserutils_vector *vector, const char *prefix, void (*printer)(void *item)) { int32_t i; if (vector == NULL || printer == NULL) return; for (i = 0; i <= vector->current_item; i++) { printf("%s %d: ", prefix != NULL ? prefix : "", i); printer((uint8_t *) vector->items + (i * vector->item_size)); printf("\n"); } } #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/utils/errors.c�������������������������������������������������0000664�0001750�0001750�00000004143�11130627135�021155� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include #include /** * Convert a parserutils error code to a string * * \param error The error code to convert * \return Pointer to string representation of error, or NULL if unknown. */ const char *parserutils_error_to_string(parserutils_error error) { const char *result = NULL; switch (error) { case PARSERUTILS_OK: result = "No error"; break; case PARSERUTILS_NOMEM: result = "Insufficient memory"; break; case PARSERUTILS_BADPARM: result = "Bad parameter"; break; case PARSERUTILS_INVALID: result = "Invalid input"; break; case PARSERUTILS_FILENOTFOUND: result = "File not found"; break; case PARSERUTILS_NEEDDATA: result = "Insufficient data"; break; case PARSERUTILS_BADENCODING: result = "Unsupported encoding"; break; case PARSERUTILS_EOF: result = "EOF"; break; } return result; } /** * Convert a string representation of an error name to a parserutils error code * * \param str String containing error name * \param len Length of string (bytes) * \return Error code, or PARSERUTILS_OK if unknown */ parserutils_error parserutils_error_from_string(const char *str, size_t len) { if (strncmp(str, "PARSERUTILS_OK", len) == 0) { return PARSERUTILS_OK; } else if (strncmp(str, "PARSERUTILS_NOMEM", len) == 0) { return PARSERUTILS_NOMEM; } else if (strncmp(str, "PARSERUTILS_BADPARM", len) == 0) { return PARSERUTILS_BADPARM; } else if (strncmp(str, "PARSERUTILS_INVALID", len) == 0) { return PARSERUTILS_INVALID; } else if (strncmp(str, "PARSERUTILS_FILENOTFOUND", len) == 0) { return PARSERUTILS_FILENOTFOUND; } else if (strncmp(str, "PARSERUTILS_NEEDDATA", len) == 0) { return PARSERUTILS_NEEDDATA; } else if (strncmp(str, "PARSERUTILS_BADENCODING", len) == 0) { return PARSERUTILS_BADENCODING; } else if (strncmp(str, "PARSERUTILS_EOF", len) == 0) { return PARSERUTILS_EOF; } return PARSERUTILS_OK; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/utils/utils.h��������������������������������������������������0000664�0001750�0001750�00000001271�11114653235�021007� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_utils_h_ #define parserutils_utils_h_ #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif #ifndef SLEN /* Calculate length of a string constant */ #define SLEN(s) (sizeof((s)) - 1) /* -1 for '\0' */ #endif #ifndef UNUSED #define UNUSED(x) ((x)=(x)) #endif #ifndef N_ELEMENTS #define N_ELEMENTS(s) (sizeof((s)) / sizeof((s)[0])) #endif #ifndef ALIGN #define ALIGN(val) (((val) + 3) & ~(3)) #endif #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/input/���������������������������������������������������������0000775�0001750�0001750�00000000000�11734430231�017471� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/input/filter.h�������������������������������������������������0000664�0001750�0001750�00000003027�11520016105�021122� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_input_filter_h_ #define parserutils_input_filter_h_ #include #include #include typedef struct parserutils_filter parserutils_filter; /** * Input filter option types */ typedef enum parserutils_filter_opttype { PARSERUTILS_FILTER_SET_ENCODING = 0 } parserutils_filter_opttype; /** * Input filter option parameters */ typedef union parserutils_filter_optparams { /** Parameters for encoding setting */ struct { /** Encoding name */ const char *name; } encoding; } parserutils_filter_optparams; /* Create an input filter */ parserutils_error parserutils__filter_create(const char *int_enc, parserutils_alloc alloc, void *pw, parserutils_filter **filter); /* Destroy an input filter */ parserutils_error parserutils__filter_destroy(parserutils_filter *input); /* Configure an input filter */ parserutils_error parserutils__filter_setopt(parserutils_filter *input, parserutils_filter_opttype type, parserutils_filter_optparams *params); /* Process a chunk of data */ parserutils_error parserutils__filter_process_chunk(parserutils_filter *input, const uint8_t **data, size_t *len, uint8_t **output, size_t *outlen); /* Reset an input filter's state */ parserutils_error parserutils__filter_reset(parserutils_filter *input); #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/input/inputstream.c��������������������������������������������0000664�0001750�0001750�00000043166�11611233654�022226� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include #include #include #include #include #include #include "input/filter.h" #include "utils/utils.h" /** * Private input stream definition */ typedef struct parserutils_inputstream_private { parserutils_inputstream public; /**< Public part. Must be first */ parserutils_buffer *raw; /**< Buffer containing raw data */ bool done_first_chunk; /**< Whether the first chunk has * been processed */ uint16_t mibenum; /**< MIB enum for charset, or 0 */ uint32_t encsrc; /**< Charset source */ parserutils_filter *input; /**< Charset conversion filter */ parserutils_charset_detect_func csdetect; /**< Charset detection func.*/ parserutils_alloc alloc; /**< Memory (de)allocation function */ void *pw; /**< Client private data */ } parserutils_inputstream_private; static inline parserutils_error parserutils_inputstream_refill_buffer( parserutils_inputstream_private *stream); static inline parserutils_error parserutils_inputstream_strip_bom( uint16_t *mibenum, parserutils_buffer *buffer); /** * Create an input stream * * \param enc Document charset, or NULL to autodetect * \param encsrc Value for encoding source, if specified, or 0 * \param csdetect Charset detection function, or NULL * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data (may be NULL) * \param stream Pointer to location to receive stream instance * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhaustion, * PARSERUTILS_BADENCODING on unsupported encoding * * The value 0 is defined as being the lowest priority encoding source * (i.e. the default fallback encoding). Beyond this, no further * interpretation is made upon the encoding source. */ parserutils_error parserutils_inputstream_create(const char *enc, uint32_t encsrc, parserutils_charset_detect_func csdetect, parserutils_alloc alloc, void *pw, parserutils_inputstream **stream) { parserutils_inputstream_private *s; parserutils_error error; if (alloc == NULL || stream == NULL) return PARSERUTILS_BADPARM; s = alloc(NULL, sizeof(parserutils_inputstream_private), pw); if (s == NULL) return PARSERUTILS_NOMEM; error = parserutils_buffer_create(alloc, pw, &s->raw); if (error != PARSERUTILS_OK) { alloc(s, 0, pw); return error; } error = parserutils_buffer_create(alloc, pw, &s->public.utf8); if (error != PARSERUTILS_OK) { parserutils_buffer_destroy(s->raw); alloc(s, 0, pw); return error; } s->public.cursor = 0; s->public.had_eof = false; s->done_first_chunk = false; error = parserutils__filter_create("UTF-8", alloc, pw, &s->input); if (error != PARSERUTILS_OK) { parserutils_buffer_destroy(s->public.utf8); parserutils_buffer_destroy(s->raw); alloc(s, 0, pw); return error; } if (enc != NULL) { parserutils_filter_optparams params; s->mibenum = parserutils_charset_mibenum_from_name(enc, strlen(enc)); if (s->mibenum == 0) return PARSERUTILS_BADENCODING; params.encoding.name = enc; error = parserutils__filter_setopt(s->input, PARSERUTILS_FILTER_SET_ENCODING, ¶ms); if (error != PARSERUTILS_OK) { parserutils__filter_destroy(s->input); parserutils_buffer_destroy(s->public.utf8); parserutils_buffer_destroy(s->raw); alloc(s, 0, pw); return error; } s->encsrc = encsrc; } else { s->mibenum = 0; s->encsrc = 0; } s->csdetect = csdetect; s->alloc = alloc; s->pw = pw; *stream = (parserutils_inputstream *) s; return PARSERUTILS_OK; } /** * Destroy an input stream * * \param stream Input stream to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_inputstream_destroy( parserutils_inputstream *stream) { parserutils_inputstream_private *s = (parserutils_inputstream_private *) stream; if (stream == NULL) return PARSERUTILS_BADPARM; parserutils__filter_destroy(s->input); parserutils_buffer_destroy(s->public.utf8); parserutils_buffer_destroy(s->raw); s->alloc(s, 0, s->pw); return PARSERUTILS_OK; } /** * Append data to an input stream * * \param stream Input stream to append data to * \param data Data to append (in document charset), or NULL to flag EOF * \param len Length, in bytes, of data * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_inputstream_append( parserutils_inputstream *stream, const uint8_t *data, size_t len) { parserutils_inputstream_private *s = (parserutils_inputstream_private *) stream; if (stream == NULL) return PARSERUTILS_BADPARM; if (data == NULL) { s->public.had_eof = true; return PARSERUTILS_OK; } return parserutils_buffer_append(s->raw, data, len); } /** * Insert data into stream at current location * * \param stream Input stream to insert into * \param data Data to insert (UTF-8 encoded) * \param len Length, in bytes, of data * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_inputstream_insert( parserutils_inputstream *stream, const uint8_t *data, size_t len) { parserutils_inputstream_private *s = (parserutils_inputstream_private *) stream; if (stream == NULL || data == NULL) return PARSERUTILS_BADPARM; return parserutils_buffer_insert(s->public.utf8, s->public.cursor, data, len); } #define IS_ASCII(x) (((x) & 0x80) == 0) /** * Look at the character in the stream that starts at * offset bytes from the cursor (slow version) * * \param stream Stream to look in * \param offset Byte offset of start of character * \param ptr Pointer to location to receive pointer to character data * \param length Pointer to location to receive character length (in bytes) * \return PARSERUTILS_OK on success, * _NEEDDATA on reaching the end of available input, * _EOF on reaching the end of all input, * _BADENCODING if the input cannot be decoded, * _NOMEM on memory exhaustion, * _BADPARM if bad parameters are passed. * * Once the character pointed to by the result of this call has been advanced * past (i.e. parserutils_inputstream_advance has caused the stream cursor to * pass over the character), then no guarantee is made as to the validity of * the data pointed to. Thus, any attempt to dereference the pointer after * advancing past the data it points to is a bug. */ parserutils_error parserutils_inputstream_peek_slow( parserutils_inputstream *stream, size_t offset, const uint8_t **ptr, size_t *length) { parserutils_inputstream_private *s = (parserutils_inputstream_private *) stream; parserutils_error error = PARSERUTILS_OK; size_t len; if (stream == NULL || ptr == NULL || length == NULL) return PARSERUTILS_BADPARM; /* There's insufficient data in the buffer, so read some more */ if (s->raw->length == 0) { /* No more data to be had */ return s->public.had_eof ? PARSERUTILS_EOF : PARSERUTILS_NEEDDATA; } /* Refill utf8 buffer from raw buffer */ error = parserutils_inputstream_refill_buffer(s); if (error != PARSERUTILS_OK) return error; /* Refill may have succeeded, but not actually produced any new data */ if (s->public.cursor + offset == s->public.utf8->length) return PARSERUTILS_NEEDDATA; /* Now try the read */ if (IS_ASCII(s->public.utf8->data[s->public.cursor + offset])) { len = 1; } else { error = parserutils_charset_utf8_char_byte_length( s->public.utf8->data + s->public.cursor + offset, &len); if (error != PARSERUTILS_OK && error != PARSERUTILS_NEEDDATA) return error; if (error == PARSERUTILS_NEEDDATA) { return s->public.had_eof ? PARSERUTILS_EOF : PARSERUTILS_NEEDDATA; } } (*length) = len; (*ptr) = (s->public.utf8->data + s->public.cursor + offset); return PARSERUTILS_OK; } #undef IS_ASCII /** * Read the source charset of the input stream * * \param stream Input stream to query * \param source Pointer to location to receive charset source identifier * \return Pointer to charset name (constant; do not free) */ const char *parserutils_inputstream_read_charset( parserutils_inputstream *stream, uint32_t *source) { parserutils_inputstream_private *s = (parserutils_inputstream_private *) stream; if (stream == NULL || source == NULL) return NULL; *source = s->encsrc; if (s->encsrc == 0) return "UTF-8"; return parserutils_charset_mibenum_to_name(s->mibenum); } /** * Change the source charset of the input stream * * \param stream Input stream to modify * \param enc Charset name * \param source Charset source identifier * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on invalid parameters, * PARSERUTILS_INVALID if called after data has been read from stream, * PARSERUTILS_BADENCODING if the encoding is unsupported, * PARSERUTILS_NOMEM on memory exhaustion. */ parserutils_error parserutils_inputstream_change_charset( parserutils_inputstream *stream, const char *enc, uint32_t source) { parserutils_inputstream_private *s = (parserutils_inputstream_private *) stream; parserutils_filter_optparams params; uint16_t temp; parserutils_error error; if (stream == NULL || enc == NULL) return PARSERUTILS_BADPARM; if (s->done_first_chunk) return PARSERUTILS_INVALID; temp = parserutils_charset_mibenum_from_name(enc, strlen(enc)); if (temp == 0) return PARSERUTILS_BADENCODING; /* Ensure filter is using the correct encoding */ params.encoding.name = enc; error = parserutils__filter_setopt(s->input, PARSERUTILS_FILTER_SET_ENCODING, ¶ms); if (error != PARSERUTILS_OK) return error; /* Finally, replace the current settings */ s->mibenum = temp; s->encsrc = source; return PARSERUTILS_OK; } /****************************************************************************** ******************************************************************************/ /** * Refill the UTF-8 buffer from the raw buffer * * \param stream The inputstream to operate on * \return PARSERUTILS_OK on success */ parserutils_error parserutils_inputstream_refill_buffer( parserutils_inputstream_private *stream) { const uint8_t *raw; uint8_t *utf8; size_t raw_length, utf8_space; parserutils_error error; /* If this is the first chunk of data, we must detect the charset and * strip the BOM, if one exists */ if (stream->done_first_chunk == false) { parserutils_filter_optparams params; /* If there is a charset detection routine, give it an * opportunity to override any charset specified when the * inputstream was created */ if (stream->csdetect != NULL) { error = stream->csdetect(stream->raw->data, stream->raw->length, &stream->mibenum, &stream->encsrc); if (error != PARSERUTILS_OK) { if (error != PARSERUTILS_NEEDDATA || stream->public.had_eof == false) return error; /* We don't have enough data to detect the * input encoding, but we're not going to get * any more as we've been notified of EOF. * Therefore, leave the encoding alone * so that any charset specified when the * inputstream was created will be preserved. * If there was no charset specified, then * we'll default to UTF-8, below */ error = PARSERUTILS_OK; } } /* Default to UTF-8 if there is still no encoding information * We'll do this if there was no encoding specified up-front * and: * 1) there was no charset detection routine * or 2) there was insufficient data for the charset * detection routine to detect an encoding */ if (stream->mibenum == 0) { stream->mibenum = parserutils_charset_mibenum_from_name("UTF-8", SLEN("UTF-8")); stream->encsrc = 0; } if (stream->mibenum == 0) abort(); /* Strip any BOM, and update encoding as appropriate */ error = parserutils_inputstream_strip_bom(&stream->mibenum, stream->raw); if (error != PARSERUTILS_OK) return error; /* Ensure filter is using the correct encoding */ params.encoding.name = parserutils_charset_mibenum_to_name(stream->mibenum); error = parserutils__filter_setopt(stream->input, PARSERUTILS_FILTER_SET_ENCODING, ¶ms); if (error != PARSERUTILS_OK) return error; stream->done_first_chunk = true; } /* Work out how to perform the buffer fill */ if (stream->public.cursor == stream->public.utf8->length) { /* Cursor's at the end, so simply reuse the entire buffer */ utf8 = stream->public.utf8->data; utf8_space = stream->public.utf8->allocated; } else { /* Cursor's not at the end, so shift data after cursor to the * bottom of the buffer. If the buffer's still over half full, * extend it. */ memmove(stream->public.utf8->data, stream->public.utf8->data + stream->public.cursor, stream->public.utf8->length - stream->public.cursor); stream->public.utf8->length -= stream->public.cursor; if (stream->public.utf8->length > stream->public.utf8->allocated / 2) { error = parserutils_buffer_grow(stream->public.utf8); if (error != PARSERUTILS_OK) return error; } utf8 = stream->public.utf8->data + stream->public.utf8->length; utf8_space = stream->public.utf8->allocated - stream->public.utf8->length; } raw = stream->raw->data; raw_length = stream->raw->length; /* Try to fill utf8 buffer from the raw data */ error = parserutils__filter_process_chunk(stream->input, &raw, &raw_length, &utf8, &utf8_space); /* _NOMEM implies that there's more input to read than available space * in the utf8 buffer. That's fine, so we'll ignore that error. */ if (error != PARSERUTILS_OK && error != PARSERUTILS_NOMEM) return error; /* Remove the raw data we've processed from the raw buffer */ error = parserutils_buffer_discard(stream->raw, 0, stream->raw->length - raw_length); if (error != PARSERUTILS_OK) return error; /* Fix up the utf8 buffer information */ stream->public.utf8->length = stream->public.utf8->allocated - utf8_space; /* Finally, fix up the cursor */ stream->public.cursor = 0; return PARSERUTILS_OK; } /** * Strip a BOM from a buffer in the given encoding * * \param mibenum Pointer to the character set of the buffer, updated on exit * \param buffer The buffer to process */ parserutils_error parserutils_inputstream_strip_bom(uint16_t *mibenum, parserutils_buffer *buffer) { static uint16_t utf8; static uint16_t utf16; static uint16_t utf16be; static uint16_t utf16le; static uint16_t utf32; static uint16_t utf32be; static uint16_t utf32le; if (utf8 == 0) { utf8 = parserutils_charset_mibenum_from_name("UTF-8", SLEN("UTF-8")); utf16 = parserutils_charset_mibenum_from_name("UTF-16", SLEN("UTF-16")); utf16be = parserutils_charset_mibenum_from_name("UTF-16BE", SLEN("UTF-16BE")); utf16le = parserutils_charset_mibenum_from_name("UTF-16LE", SLEN("UTF-16LE")); utf32 = parserutils_charset_mibenum_from_name("UTF-32", SLEN("UTF-32")); utf32be = parserutils_charset_mibenum_from_name("UTF-32BE", SLEN("UTF-32BE")); utf32le = parserutils_charset_mibenum_from_name("UTF-32LE", SLEN("UTF-32LE")); } #define UTF32_BOM_LEN (4) #define UTF16_BOM_LEN (2) #define UTF8_BOM_LEN (3) if (*mibenum == utf8) { if (buffer->length >= UTF8_BOM_LEN && buffer->data[0] == 0xEF && buffer->data[1] == 0xBB && buffer->data[2] == 0xBF) { return parserutils_buffer_discard( buffer, 0, UTF8_BOM_LEN); } } else if (*mibenum == utf16be) { if (buffer->length >= UTF16_BOM_LEN && buffer->data[0] == 0xFE && buffer->data[1] == 0xFF) { return parserutils_buffer_discard( buffer, 0, UTF16_BOM_LEN); } } else if (*mibenum == utf16le) { if (buffer->length >= UTF16_BOM_LEN && buffer->data[0] == 0xFF && buffer->data[1] == 0xFE) { return parserutils_buffer_discard( buffer, 0, UTF16_BOM_LEN); } } else if (*mibenum == utf16) { *mibenum = utf16be; if (buffer->length >= UTF16_BOM_LEN) { if (buffer->data[0] == 0xFE && buffer->data[1] == 0xFF) { return parserutils_buffer_discard( buffer, 0, UTF16_BOM_LEN); } else if (buffer->data[0] == 0xFF && buffer->data[1] == 0xFE) { *mibenum = utf16le; return parserutils_buffer_discard( buffer, 0, UTF16_BOM_LEN); } } } else if (*mibenum == utf32be) { if (buffer->length >= UTF32_BOM_LEN && buffer->data[0] == 0x00 && buffer->data[1] == 0x00 && buffer->data[2] == 0xFE && buffer->data[3] == 0xFF) { return parserutils_buffer_discard( buffer, 0, UTF32_BOM_LEN); } } else if (*mibenum == utf32le) { if (buffer->length >= UTF32_BOM_LEN && buffer->data[0] == 0xFF && buffer->data[1] == 0xFE && buffer->data[2] == 0x00 && buffer->data[3] == 0x00) { return parserutils_buffer_discard( buffer, 0, UTF32_BOM_LEN); } } else if (*mibenum == utf32) { *mibenum = utf32be; if (buffer->length >= UTF32_BOM_LEN) { if (buffer->data[0] == 0x00 && buffer->data[1] == 0x00 && buffer->data[2] == 0xFE && buffer->data[3] == 0xFF) { return parserutils_buffer_discard( buffer, 0, UTF32_BOM_LEN); } else if (buffer->data[0] == 0xFF && buffer->data[1] == 0xFE && buffer->data[2] == 0x00 && buffer->data[3] == 0x00) { *mibenum = utf32le; return parserutils_buffer_discard( buffer, 0, UTF32_BOM_LEN); } } } #undef UTF8_BOM_LEN #undef UTF16_BOM_LEN #undef UTF32_BOM_LEN return PARSERUTILS_OK; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/input/Makefile�������������������������������������������������0000664�0001750�0001750�00000000131�11162216376�021133� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Sources DIR_SOURCES := filter.c inputstream.c include build/makefiles/Makefile.subdir ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/input/filter.c�������������������������������������������������0000664�0001750�0001750�00000023500�11554115215�021124� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include #include #include #include #ifndef WITHOUT_ICONV_FILTER #include #endif #include #include #include "input/filter.h" #include "utils/utils.h" /** Input filter */ struct parserutils_filter { #ifndef WITHOUT_ICONV_FILTER iconv_t cd; /**< Iconv conversion descriptor */ uint16_t int_enc; /**< The internal encoding */ #else parserutils_charset_codec *read_codec; /**< Read codec */ parserutils_charset_codec *write_codec; /**< Write codec */ uint32_t pivot_buf[64]; /**< Conversion pivot buffer */ bool leftover; /**< Data remains from last call */ uint8_t *pivot_left; /**< Remaining pivot to write */ size_t pivot_len; /**< Length of pivot remaining */ #endif struct { uint16_t encoding; /**< Input encoding */ } settings; /**< Filter settings */ parserutils_alloc alloc; /**< Memory (de)allocation function */ void *pw; /**< Client private data */ }; static parserutils_error filter_set_defaults(parserutils_filter *input); static parserutils_error filter_set_encoding(parserutils_filter *input, const char *enc); /** * Create an input filter * * \param int_enc Desired encoding of document * \param alloc Function used to (de)allocate data * \param pw Pointer to client-specific private data (may be NULL) * \param filter Pointer to location to receive filter instance * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhausion, * PARSERUTILS_BADENCODING if the encoding is unsupported */ parserutils_error parserutils__filter_create(const char *int_enc, parserutils_alloc alloc, void *pw, parserutils_filter **filter) { parserutils_filter *f; parserutils_error error; if (int_enc == NULL || alloc == NULL || filter == NULL) return PARSERUTILS_BADPARM; f = alloc(NULL, sizeof(parserutils_filter), pw); if (f == NULL) return PARSERUTILS_NOMEM; #ifndef WITHOUT_ICONV_FILTER f->cd = (iconv_t) -1; f->int_enc = parserutils_charset_mibenum_from_name( int_enc, strlen(int_enc)); if (f->int_enc == 0) { alloc(f, 0, pw); return PARSERUTILS_BADENCODING; } #else f->leftover = false; f->pivot_left = NULL; f->pivot_len = 0; #endif f->alloc = alloc; f->pw = pw; error = filter_set_defaults(f); if (error != PARSERUTILS_OK) { f->alloc(f, 0, pw); return error; } #ifdef WITHOUT_ICONV_FILTER error = parserutils_charset_codec_create(int_enc, alloc, pw, &f->write_codec); if (error != PARSERUTILS_OK) { if (f->read_codec != NULL) { parserutils_charset_codec_destroy(f->read_codec); f->read_codec = NULL; } f->alloc(f, 0, pw); return error; } #endif *filter = f; return PARSERUTILS_OK; } /** * Destroy an input filter * * \param input Pointer to filter instance * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils__filter_destroy(parserutils_filter *input) { if (input == NULL) return PARSERUTILS_BADPARM; #ifndef WITHOUT_ICONV_FILTER if (input->cd != (iconv_t) -1) { iconv_close(input->cd); input->cd = (iconv_t) -1; } #else if (input->read_codec != NULL) { parserutils_charset_codec_destroy(input->read_codec); input->read_codec = NULL; } if (input->write_codec != NULL) { parserutils_charset_codec_destroy(input->write_codec); input->write_codec = NULL; } #endif input->alloc(input, 0, input->pw); return PARSERUTILS_OK; } /** * Configure an input filter * * \param input Pointer to filter instance * \param type Input option type to configure * \param params Option-specific parameters * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils__filter_setopt(parserutils_filter *input, parserutils_filter_opttype type, parserutils_filter_optparams *params) { parserutils_error error = PARSERUTILS_OK; if (input == NULL || params == NULL) return PARSERUTILS_BADPARM; switch (type) { case PARSERUTILS_FILTER_SET_ENCODING: error = filter_set_encoding(input, params->encoding.name); break; } return error; } /** * Process a chunk of data * * \param input Pointer to filter instance * \param data Pointer to pointer to input buffer * \param len Pointer to length of input buffer * \param output Pointer to pointer to output buffer * \param outlen Pointer to length of output buffer * \return PARSERUTILS_OK on success, appropriate error otherwise * * Call this with an input buffer length of 0 to flush any buffers. */ parserutils_error parserutils__filter_process_chunk(parserutils_filter *input, const uint8_t **data, size_t *len, uint8_t **output, size_t *outlen) { if (input == NULL || data == NULL || *data == NULL || len == NULL || output == NULL || *output == NULL || outlen == NULL) return PARSERUTILS_BADPARM; #ifndef WITHOUT_ICONV_FILTER if (iconv(input->cd, (void *) data, len, (char **) output, outlen) == (size_t) -1) { switch (errno) { case E2BIG: return PARSERUTILS_NOMEM; case EILSEQ: if (*outlen < 3) return PARSERUTILS_NOMEM; (*output)[0] = 0xef; (*output)[1] = 0xbf; (*output)[2] = 0xbd; *output += 3; *outlen -= 3; (*data)++; (*len)--; while (*len > 0) { size_t ret; ret = iconv(input->cd, (void *) data, len, (char **) output, outlen); if (ret != (size_t) -1 || errno != EILSEQ) break; if (*outlen < 3) return PARSERUTILS_NOMEM; (*output)[0] = 0xef; (*output)[1] = 0xbf; (*output)[2] = 0xbd; *output += 3; *outlen -= 3; (*data)++; (*len)--; } return errno == E2BIG ? PARSERUTILS_NOMEM : PARSERUTILS_OK; } } return PARSERUTILS_OK; #else if (input->leftover) { parserutils_error write_error; /* Some data left to be written from last call */ /* Attempt to flush the remaining data. */ write_error = parserutils_charset_codec_encode( input->write_codec, (const uint8_t **) &input->pivot_left, &input->pivot_len, output, outlen); if (write_error != PARSERUTILS_OK) return write_error; /* And clear leftover */ input->pivot_left = NULL; input->pivot_len = 0; input->leftover = false; } while (*len > 0) { parserutils_error read_error, write_error; size_t pivot_len = sizeof(input->pivot_buf); uint8_t *pivot = (uint8_t *) input->pivot_buf; read_error = parserutils_charset_codec_decode(input->read_codec, data, len, (uint8_t **) &pivot, &pivot_len); pivot = (uint8_t *) input->pivot_buf; pivot_len = sizeof(input->pivot_buf) - pivot_len; if (pivot_len > 0) { write_error = parserutils_charset_codec_encode( input->write_codec, (const uint8_t **) &pivot, &pivot_len, output, outlen); if (write_error != PARSERUTILS_OK) { input->leftover = true; input->pivot_left = pivot; input->pivot_len = pivot_len; return write_error; } } if (read_error != PARSERUTILS_OK && read_error != PARSERUTILS_NOMEM) return read_error; } return PARSERUTILS_OK; #endif } /** * Reset an input filter's state * * \param input The input filter to reset * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils__filter_reset(parserutils_filter *input) { parserutils_error error = PARSERUTILS_OK; if (input == NULL) return PARSERUTILS_BADPARM; #ifndef WITHOUT_ICONV_FILTER iconv(input->cd, NULL, 0, NULL, 0); #else /* Clear pivot buffer leftovers */ input->pivot_left = NULL; input->pivot_len = 0; input->leftover = false; /* Reset read codec */ error = parserutils_charset_codec_reset(input->read_codec); if (error != PARSERUTILS_OK) return error; /* Reset write codec */ error = parserutils_charset_codec_reset(input->write_codec); if (error != PARSERUTILS_OK) return error; #endif return error; } /** * Set an input filter's default settings * * \param input Input filter to configure * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error filter_set_defaults(parserutils_filter *input) { parserutils_error error; if (input == NULL) return PARSERUTILS_BADPARM; #ifdef WITHOUT_ICONV_FILTER input->read_codec = NULL; input->write_codec = NULL; #endif input->settings.encoding = 0; error = filter_set_encoding(input, "UTF-8"); if (error != PARSERUTILS_OK) return error; return PARSERUTILS_OK; } /** * Set an input filter's encoding * * \param input Input filter to configure * \param enc Encoding name * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error filter_set_encoding(parserutils_filter *input, const char *enc) { parserutils_error error = PARSERUTILS_OK; uint16_t mibenum; if (input == NULL || enc == NULL) return PARSERUTILS_BADPARM; mibenum = parserutils_charset_mibenum_from_name(enc, strlen(enc)); if (mibenum == 0) return PARSERUTILS_BADENCODING; /* Exit early if we're already using this encoding */ if (input->settings.encoding == mibenum) return PARSERUTILS_OK; #ifndef WITHOUT_ICONV_FILTER if (input->cd != (iconv_t) -1) { iconv_close(input->cd); input->cd = (iconv_t) -1; } input->cd = iconv_open( parserutils_charset_mibenum_to_name(input->int_enc), parserutils_charset_mibenum_to_name(mibenum)); if (input->cd == (iconv_t) -1) { return (errno == EINVAL) ? PARSERUTILS_BADENCODING : PARSERUTILS_NOMEM; } #else if (input->read_codec != NULL) { parserutils_charset_codec_destroy(input->read_codec); input->read_codec = NULL; } error = parserutils_charset_codec_create(enc, input->alloc, input->pw, &input->read_codec); if (error != PARSERUTILS_OK) return error; #endif input->settings.encoding = mibenum; return error; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/�������������������������������������������������������0000775�0001750�0001750�00000000000�11734430231�017763� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codec.c������������������������������������������������0000664�0001750�0001750�00000013031�11520016105�021173� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include #include "charset/aliases.h" #include "charset/codecs/codec_impl.h" extern parserutils_charset_handler charset_ascii_codec_handler; extern parserutils_charset_handler charset_8859_codec_handler; extern parserutils_charset_handler charset_ext8_codec_handler; extern parserutils_charset_handler charset_utf8_codec_handler; extern parserutils_charset_handler charset_utf16_codec_handler; static parserutils_charset_handler *handler_table[] = { &charset_utf8_codec_handler, &charset_utf16_codec_handler, &charset_8859_codec_handler, &charset_ext8_codec_handler, &charset_ascii_codec_handler, NULL, }; /** * Create a charset codec * * \param charset Target charset * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data (may be NULL) * \param codec Pointer to location to receive codec instance * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhaustion, * PARSERUTILS_BADENCODING on unsupported charset */ parserutils_error parserutils_charset_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec) { parserutils_charset_codec *c; parserutils_charset_handler **handler; const parserutils_charset_aliases_canon * canon; parserutils_error error; if (charset == NULL || alloc == NULL || codec == NULL) return PARSERUTILS_BADPARM; /* Canonicalise parserutils_charset name. */ canon = parserutils__charset_alias_canonicalise(charset, strlen(charset)); if (canon == NULL) return PARSERUTILS_BADENCODING; /* Search for handler class */ for (handler = handler_table; *handler != NULL; handler++) { if ((*handler)->handles_charset(canon->name)) break; } /* None found */ if ((*handler) == NULL) return PARSERUTILS_BADENCODING; /* Instantiate class */ error = (*handler)->create(canon->name, alloc, pw, &c); if (error != PARSERUTILS_OK) return error; /* and initialise it */ c->mibenum = canon->mib_enum; c->errormode = PARSERUTILS_CHARSET_CODEC_ERROR_LOOSE; c->alloc = alloc; c->alloc_pw = pw; *codec = c; return PARSERUTILS_OK; } /** * Destroy a charset codec * * \param codec The codec to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_codec_destroy( parserutils_charset_codec *codec) { if (codec == NULL) return PARSERUTILS_BADPARM; codec->handler.destroy(codec); codec->alloc(codec, 0, codec->alloc_pw); return PARSERUTILS_OK; } /** * Configure a charset codec * * \param codec The codec to configure * \param type The codec option type to configure * \param params Option-specific parameters * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_codec_setopt( parserutils_charset_codec *codec, parserutils_charset_codec_opttype type, parserutils_charset_codec_optparams *params) { if (codec == NULL || params == NULL) return PARSERUTILS_BADPARM; switch (type) { case PARSERUTILS_CHARSET_CODEC_ERROR_MODE: codec->errormode = params->error_mode.mode; break; } return PARSERUTILS_OK; } /** * Encode a chunk of UCS-4 data into a codec's charset * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, appropriate error otherwise. * * source, sourcelen, dest and destlen will be updated appropriately on exit */ parserutils_error parserutils_charset_codec_encode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { if (codec == NULL || source == NULL || *source == NULL || sourcelen == NULL || dest == NULL || *dest == NULL || destlen == NULL) return PARSERUTILS_BADPARM; return codec->handler.encode(codec, source, sourcelen, dest, destlen); } /** * Decode a chunk of data in a codec's charset into UCS-4 * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, appropriate error otherwise. * * source, sourcelen, dest and destlen will be updated appropriately on exit * * Call this with a source length of 0 to flush any buffers. */ parserutils_error parserutils_charset_codec_decode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { if (codec == NULL || source == NULL || *source == NULL || sourcelen == NULL || dest == NULL || *dest == NULL || destlen == NULL) return PARSERUTILS_BADPARM; return codec->handler.decode(codec, source, sourcelen, dest, destlen); } /** * Clear a charset codec's encoding state * * \param codec The codec to reset * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_codec_reset( parserutils_charset_codec *codec) { if (codec == NULL) return PARSERUTILS_BADPARM; return codec->handler.reset(codec); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/encodings/���������������������������������������������0000775�0001750�0001750�00000000000�11734430231�021734� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/encodings/utf16.c��������������������������������������0000664�0001750�0001750�00000014174�11031522713�023051� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ /** \file * UTF-16 manipulation functions (implementation). */ #include #include #include #include /** * Convert a UTF-16 sequence into a single UCS-4 character * * \param s The sequence to process * \param len Length of sequence in bytes * \param ucs4 Pointer to location to receive UCS-4 character (host endian) * \param clen Pointer to location to receive byte length of UTF-16 sequence * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf16_to_ucs4(const uint8_t *s, size_t len, uint32_t *ucs4, size_t *clen) { const uint16_t *ss = (const uint16_t *) (const void *) s; if (s == NULL || ucs4 == NULL || clen == NULL) return PARSERUTILS_BADPARM; if (len < 2) return PARSERUTILS_NEEDDATA; if (*ss < 0xD800 || *ss > 0xDFFF) { *ucs4 = *ss; *clen = 2; } else if (0xD800 <= *ss && *ss <= 0xDBFF) { /* High-surrogate code unit. */ if (len < 4) return PARSERUTILS_NEEDDATA; if (0xDC00 <= ss[1] && ss[1] <= 0xDFFF) { /* We have a valid surrogate pair. */ *ucs4 = (((ss[0] & 0x3FF) << 10) | (ss[1] & 0x3FF)) + (1<<16); *clen = 4; } else { return PARSERUTILS_INVALID; } } else { /* Low-surrogate code unit. */ return PARSERUTILS_INVALID; } return PARSERUTILS_OK; } /** * Convert a single UCS-4 character into a UTF-16 sequence * * \param ucs4 The character to process (0 <= c <= 0x7FFFFFFF) (host endian) * \param s Pointer to 4 byte long output buffer * \param len Pointer to location to receive length of multibyte sequence * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf16_from_ucs4(uint32_t ucs4, uint8_t *s, size_t *len) { uint16_t *ss = (uint16_t *) (void *) s; uint32_t l = 0; if (s == NULL || len == NULL) return PARSERUTILS_BADPARM; else if (ucs4 < 0x10000) { *ss = (uint16_t) ucs4; l = 2; } else if (ucs4 < 0x110000) { ss[0] = 0xD800 | (((ucs4 >> 16) & 0x1f) - 1) | (ucs4 >> 10); ss[1] = 0xDC00 | (ucs4 & 0x3ff); l = 4; } else { return PARSERUTILS_INVALID; } *len = l; return PARSERUTILS_OK; } /** * Calculate the length (in characters) of a bounded UTF-16 string * * \param s The string * \param max Maximum length * \param len Pointer to location to receive length of string * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf16_length(const uint8_t *s, size_t max, size_t *len) { const uint16_t *ss = (const uint16_t *) (const void *) s; const uint16_t *end = (const uint16_t *) (const void *) (s + max); int l = 0; if (s == NULL || len == NULL) return PARSERUTILS_BADPARM; while (ss < end) { if (*ss < 0xD800 || 0xDFFF < *ss) ss++; else ss += 2; l++; } *len = l; return PARSERUTILS_OK; } /** * Calculate the length (in bytes) of a UTF-16 character * * \param s Pointer to start of character * \param len Pointer to location to receive length * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf16_char_byte_length(const uint8_t *s, size_t *len) { const uint16_t *ss = (const uint16_t *) (const void *) s; if (s == NULL || len == NULL) return PARSERUTILS_BADPARM; if (*ss < 0xD800 || 0xDFFF < *ss) *len = 2; else *len = 4; return PARSERUTILS_OK; } /** * Find previous legal UTF-16 char in string * * \param s The string * \param off Offset in the string to start at * \param prevoff Pointer to location to receive offset of first byte of * previous legal character * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf16_prev(const uint8_t *s, uint32_t off, uint32_t *prevoff) { const uint16_t *ss = (const uint16_t *) (const void *) s; if (s == NULL || prevoff == NULL) return PARSERUTILS_BADPARM; if (off < 2) *prevoff = 0; else if (ss[-1] < 0xDC00 || ss[-1] > 0xDFFF) *prevoff = off - 2; else *prevoff = (off < 4) ? 0 : off - 4; return PARSERUTILS_OK; } /** * Find next legal UTF-16 char in string * * \param s The string (assumed valid) * \param len Maximum offset in string * \param off Offset in the string to start at * \param nextoff Pointer to location to receive offset of first byte of * next legal character * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf16_next(const uint8_t *s, uint32_t len, uint32_t off, uint32_t *nextoff) { const uint16_t *ss = (const uint16_t *) (const void *) s; if (s == NULL || off >= len || nextoff == NULL) return PARSERUTILS_BADPARM; if (len - off < 4) *nextoff = len; else if (ss[1] < 0xD800 || ss[1] > 0xDBFF) *nextoff = off + 2; else *nextoff = (len - off < 6) ? len : off + 4; return PARSERUTILS_OK; } /** * Find next legal UTF-16 char in string * * \param s The string (assumed to be of dubious validity) * \param len Maximum offset in string * \param off Offset in the string to start at * \param nextoff Pointer to location to receive offset of first byte of * next legal character * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf16_next_paranoid(const uint8_t *s, uint32_t len, uint32_t off, uint32_t *nextoff) { const uint16_t *ss = (const uint16_t *) (const void *) s; if (s == NULL || off >= len || nextoff == NULL) return PARSERUTILS_BADPARM; while (1) { if (len - off < 4) { return PARSERUTILS_NEEDDATA; } else if (ss[1] < 0xD800 || ss[1] > 0xDFFF) { *nextoff = off + 2; break; } else if (ss[1] >= 0xD800 && ss[1] <= 0xDBFF) { if (len - off < 6) return PARSERUTILS_NEEDDATA; if (ss[2] >= 0xDC00 && ss[2] <= 0xDFFF) { *nextoff = off + 4; break; } else { ss++; off += 2; } } } return PARSERUTILS_OK; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/encodings/utf8.c���������������������������������������0000664�0001750�0001750�00000012200�11031444302�022753� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ /** \file * UTF-8 manipulation functions (implementation). */ #include #include #include #include #include "charset/encodings/utf8impl.h" /** Number of continuation bytes for a given start byte */ const uint8_t numContinuations[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, }; /** * Convert a UTF-8 multibyte sequence into a single UCS-4 character * * Encoding of UCS values outside the UTF-16 plane has been removed from * RFC3629. This function conforms to RFC2279, however. * * \param s The sequence to process * \param len Length of sequence * \param ucs4 Pointer to location to receive UCS-4 character (host endian) * \param clen Pointer to location to receive byte length of UTF-8 sequence * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf8_to_ucs4(const uint8_t *s, size_t len, uint32_t *ucs4, size_t *clen) { parserutils_error error; UTF8_TO_UCS4(s, len, ucs4, clen, error); return error; } /** * Convert a single UCS-4 character into a UTF-8 multibyte sequence * * Encoding of UCS values outside the UTF-16 plane has been removed from * RFC3629. This function conforms to RFC2279, however. * * \param ucs4 The character to process (0 <= c <= 0x7FFFFFFF) (host endian) * \param s Pointer to pointer to output buffer, updated on exit * \param len Pointer to length, in bytes, of output buffer, updated on exit * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf8_from_ucs4(uint32_t ucs4, uint8_t **s, size_t *len) { parserutils_error error; UTF8_FROM_UCS4(ucs4, s, len, error); return error; } /** * Calculate the length (in characters) of a bounded UTF-8 string * * \param s The string * \param max Maximum length * \param len Pointer to location to receive length of string * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf8_length(const uint8_t *s, size_t max, size_t *len) { parserutils_error error; UTF8_LENGTH(s, max, len, error); return error; } /** * Calculate the length (in bytes) of a UTF-8 character * * \param s Pointer to start of character * \param len Pointer to location to receive length * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf8_char_byte_length(const uint8_t *s, size_t *len) { parserutils_error error; UTF8_CHAR_BYTE_LENGTH(s, len, error); return error; } /** * Find previous legal UTF-8 char in string * * \param s The string * \param off Offset in the string to start at * \param prevoff Pointer to location to receive offset of first byte of * previous legal character * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf8_prev(const uint8_t *s, uint32_t off, uint32_t *prevoff) { parserutils_error error; UTF8_PREV(s, off, prevoff, error); return error; } /** * Find next legal UTF-8 char in string * * \param s The string (assumed valid) * \param len Maximum offset in string * \param off Offset in the string to start at * \param nextoff Pointer to location to receive offset of first byte of * next legal character * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf8_next(const uint8_t *s, uint32_t len, uint32_t off, uint32_t *nextoff) { parserutils_error error; UTF8_NEXT(s, len, off, nextoff, error); return error; } /** * Find next legal UTF-8 char in string * * \param s The string (assumed to be of dubious validity) * \param len Maximum offset in string * \param off Offset in the string to start at * \param nextoff Pointer to location to receive offset of first byte of * next legal character * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error parserutils_charset_utf8_next_paranoid(const uint8_t *s, uint32_t len, uint32_t off, uint32_t *nextoff) { parserutils_error error; UTF8_NEXT_PARANOID(s, len, off, nextoff, error); return error; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/encodings/Makefile�������������������������������������0000664�0001750�0001750�00000000121�11162216376�023375� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Sources DIR_SOURCES := utf8.c utf16.c include build/makefiles/Makefile.subdir �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/encodings/utf8impl.h�����������������������������������0000664�0001750�0001750�00000021321�11114356560�023660� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_charset_encodings_utf8impl_h_ #define parserutils_charset_encodings_utf8impl_h_ /** \file * UTF-8 manipulation macros (implementation). */ #include #include #include /** Number of continuation bytes for a given start byte */ extern const uint8_t numContinuations[256]; /** * Convert a UTF-8 multibyte sequence into a single UCS-4 character * * Encoding of UCS values outside the UTF-16 plane has been removed from * RFC3629. This macro conforms to RFC2279, however. * * \param s The sequence to process * \param len Length of sequence * \param ucs4 Pointer to location to receive UCS-4 character (host endian) * \param clen Pointer to location to receive byte length of UTF-8 sequence * \param error Location to receive error code */ #define UTF8_TO_UCS4(s, len, ucs4, clen, error) \ do { \ uint32_t c, min; \ uint8_t n; \ uint8_t i; \ \ error = PARSERUTILS_OK; \ \ if (s == NULL || ucs4 == NULL || clen == NULL) { \ error = PARSERUTILS_BADPARM; \ break; \ } \ \ if (len == 0) { \ error = PARSERUTILS_NEEDDATA; \ break; \ } \ \ c = s[0]; \ \ if (c < 0x80) { \ n = 1; \ min = 0; \ } else if ((c & 0xE0) == 0xC0) { \ c &= 0x1F; \ n = 2; \ min = 0x80; \ } else if ((c & 0xF0) == 0xE0) { \ c &= 0x0F; \ n = 3; \ min = 0x800; \ } else if ((c & 0xF8) == 0xF0) { \ c &= 0x07; \ n = 4; \ min = 0x10000; \ } else if ((c & 0xFC) == 0xF8) { \ c &= 0x03; \ n = 5; \ min = 0x200000; \ } else if ((c & 0xFE) == 0xFC) { \ c &= 0x01; \ n = 6; \ min = 0x4000000; \ } else { \ error = PARSERUTILS_INVALID; \ break; \ } \ \ if (len < n) { \ error = PARSERUTILS_NEEDDATA; \ break; \ } \ \ for (i = 1; i < n; i++) { \ uint32_t t = s[i]; \ \ if ((t & 0xC0) != 0x80) { \ error = PARSERUTILS_INVALID; \ break; \ } \ \ c <<= 6; \ c |= t & 0x3F; \ } \ \ if (error == PARSERUTILS_OK) { \ /* Detect overlong sequences, surrogates and fffe/ffff */ \ if (c < min || (c >= 0xD800 && c <= 0xDFFF) || \ c == 0xFFFE || c == 0xFFFF) { \ error = PARSERUTILS_INVALID; \ break; \ } \ \ *ucs4 = c; \ *clen = n; \ } \ } while(0) /** * Convert a single UCS-4 character into a UTF-8 multibyte sequence * * Encoding of UCS values outside the UTF-16 plane has been removed from * RFC3629. This macro conforms to RFC2279, however. * * \param ucs4 The character to process (0 <= c <= 0x7FFFFFFF) (host endian) * \param s Pointer to pointer to output buffer, updated on exit * \param len Pointer to length, in bytes, of output buffer, updated on exit * \param error Location to receive error code */ #define UTF8_FROM_UCS4(ucs4, s, len, error) \ do { \ uint8_t *buf; \ uint8_t l = 0; \ \ error = PARSERUTILS_OK; \ \ if (s == NULL || *s == NULL || len == NULL) { \ error = PARSERUTILS_BADPARM; \ break; \ } \ \ if (ucs4 < 0x80) { \ l = 1; \ } else if (ucs4 < 0x800) { \ l = 2; \ } else if (ucs4 < 0x10000) { \ l = 3; \ } else if (ucs4 < 0x200000) { \ l = 4; \ } else if (ucs4 < 0x4000000) { \ l = 5; \ } else if (ucs4 <= 0x7FFFFFFF) { \ l = 6; \ } else { \ error = PARSERUTILS_INVALID; \ break; \ } \ \ if (l > *len) { \ error = PARSERUTILS_NOMEM; \ break; \ } \ \ buf = *s; \ \ if (l == 1) { \ buf[0] = (uint8_t) ucs4; \ } else { \ uint8_t i; \ for (i = l; i > 1; i--) { \ buf[i - 1] = 0x80 | (ucs4 & 0x3F); \ ucs4 >>= 6; \ } \ buf[0] = ~((1 << (8 - l)) - 1) | ucs4; \ } \ \ *s += l; \ *len -= l; \ } while(0) /** * Calculate the length (in characters) of a bounded UTF-8 string * * \param s The string * \param max Maximum length * \param len Pointer to location to receive length of string * \param error Location to receive error code */ #define UTF8_LENGTH(s, max, len, error) \ do { \ const uint8_t *end = s + max; \ int l = 0; \ \ error = PARSERUTILS_OK; \ \ if (s == NULL || len == NULL) { \ error = PARSERUTILS_BADPARM; \ break; \ } \ \ while (s < end) { \ uint32_t c = s[0]; \ \ if ((c & 0x80) == 0x00) \ s += 1; \ else if ((c & 0xE0) == 0xC0) \ s += 2; \ else if ((c & 0xF0) == 0xE0) \ s += 3; \ else if ((c & 0xF8) == 0xF0) \ s += 4; \ else if ((c & 0xFC) == 0xF8) \ s += 5; \ else if ((c & 0xFE) == 0xFC) \ s += 6; \ else { \ error = PARSERUTILS_INVALID; \ break; \ } \ \ l++; \ } \ \ if (error == PARSERUTILS_OK) \ *len = l; \ } while(0) /** * Calculate the length (in bytes) of a UTF-8 character * * \param s Pointer to start of character * \param len Pointer to location to receive length * \param error Location to receive error code */ #define UTF8_CHAR_BYTE_LENGTH(s, len, error) \ do { \ if (s == NULL || len == NULL) { \ error = PARSERUTILS_BADPARM; \ break; \ } \ \ *len = numContinuations[s[0]] + 1 /* Start byte */; \ \ error = PARSERUTILS_OK; \ } while(0) /** * Find previous legal UTF-8 char in string * * \param s The string * \param off Offset in the string to start at * \param prevoff Pointer to location to receive offset of first byte of * previous legal character * \param error Location to receive error code */ #define UTF8_PREV(s, off, prevoff, error) \ do { \ if (s == NULL || prevoff == NULL) { \ error = PARSERUTILS_BADPARM; \ break; \ } \ \ while (off != 0 && (s[--off] & 0xC0) == 0x80) \ /* do nothing */; \ \ *prevoff = off; \ \ error = PARSERUTILS_OK; \ } while(0) /** * Find next legal UTF-8 char in string * * \param s The string (assumed valid) * \param len Maximum offset in string * \param off Offset in the string to start at * \param nextoff Pointer to location to receive offset of first byte of * next legal character * \param error Location to receive error code */ #define UTF8_NEXT(s, len, off, nextoff, error) \ do { \ if (s == NULL || off >= len || nextoff == NULL) { \ error = PARSERUTILS_BADPARM; \ break; \ } \ \ /* Skip current start byte (if present - may be mid-sequence) */\ if (s[off] < 0x80 || (s[off] & 0xC0) == 0xC0) \ off++; \ \ while (off < len && (s[off] & 0xC0) == 0x80) \ off++; \ \ *nextoff = off; \ \ error = PARSERUTILS_OK; \ } while(0) /** * Skip to start of next sequence in UTF-8 input * * \param s The string (assumed to be of dubious validity) * \param len Maximum offset in string * \param off Offset in the string to start at * \param nextoff Pointer to location to receive offset of first byte of * next legal character * \param error Location to receive error code */ #define UTF8_NEXT_PARANOID(s, len, off, nextoff, error) \ do { \ uint8_t c; \ \ error = PARSERUTILS_OK; \ \ if (s == NULL || off >= len || nextoff == NULL) { \ error = PARSERUTILS_BADPARM; \ break; \ } \ \ c = s[off]; \ \ /* If we're mid-sequence, simply advance to next byte */ \ if (!(c < 0x80 || (c & 0xC0) == 0xC0)) { \ off++; \ } else { \ uint32_t nCont = numContinuations[c]; \ uint32_t nToSkip; \ \ if (off + nCont + 1 >= len) { \ error = PARSERUTILS_NEEDDATA; \ break; \ } \ \ /* Verify continuation bytes */ \ for (nToSkip = 1; nToSkip <= nCont; nToSkip++) { \ if ((s[off + nToSkip] & 0xC0) != 0x80) \ break; \ } \ \ /* Skip over the valid bytes */ \ off += nToSkip; \ } \ \ *nextoff = off; \ } while(0) #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/aliases.h����������������������������������������������0000664�0001750�0001750�00000001326�11520016105�021550� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_charset_aliases_h_ #define parserutils_charset_aliases_h_ #include #include typedef struct parserutils_charset_aliases_canon { /* Do not change the ordering here without changing make-aliases.pl */ uint16_t mib_enum; uint16_t name_len; const char *name; } parserutils_charset_aliases_canon; /* Canonicalise an alias name */ parserutils_charset_aliases_canon *parserutils__charset_alias_canonicalise( const char *alias, size_t len); #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/Makefile�����������������������������������������������0000664�0001750�0001750�00000000532�11477251567�021444� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Sources DIR_SOURCES := aliases.c codec.c $(DIR)aliases.c: $(DIR)aliases.inc $(DIR)aliases.inc: build/make-aliases.pl build/Aliases $(VQ)$(ECHO) " ALIAS: $@" $(Q)$(PERL) build/make-aliases.pl ifeq ($(findstring clean,$(MAKECMDGOALS)),clean) CLEAN_ITEMS := $(CLEAN_ITEMS) $(DIR)aliases.inc endif include build/makefiles/Makefile.subdir ����������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/aliases.c����������������������������������������������0000664�0001750�0001750�00000007440�11520016105�021546� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include #include #include #include #include #include #include #include "charset/aliases.h" #include "utils/utils.h" /* Bring in the aliases tables */ #include "aliases.inc" typedef struct { size_t slen; const char *s; } lengthed_string; #define IS_PUNCT_OR_SPACE(x) \ (!(((x) >= 'A' && (x) <= 'Z') || \ ((x) >= 'a' && (x) <= 'z') || \ ((x) >= '0' && (x) <= '9'))) static int parserutils_charset_alias_match(const void *a, const void *b) { lengthed_string *s = (lengthed_string *)a; parserutils_charset_aliases_alias *alias = (parserutils_charset_aliases_alias*)b; size_t key_left = s->slen; size_t alias_left = alias->name_len; const char *s_alias = alias->name; const char *s_key = s->s; int cmpret; while ((key_left > 0) && (alias_left > 0)) { while ((key_left > 0) && IS_PUNCT_OR_SPACE(*s_key)) { key_left--; s_key++; } if (key_left == 0) break; cmpret = tolower(*s_key) - *s_alias; if (cmpret != 0) { return cmpret; } key_left--; s_key++; alias_left--; s_alias++; } while ((key_left > 0) && IS_PUNCT_OR_SPACE(*s_key)) { key_left--; s_key++; } return key_left - alias_left; } /** * Retrieve the canonical form of an alias name * * \param alias The alias name * \param len The length of the alias name * \return Pointer to canonical form or NULL if not found */ parserutils_charset_aliases_canon *parserutils__charset_alias_canonicalise( const char *alias, size_t len) { parserutils_charset_aliases_alias *c; lengthed_string s; s.slen = len; s.s = alias; c = (parserutils_charset_aliases_alias*)bsearch(&s, &charset_aliases[0], charset_aliases_count, sizeof(parserutils_charset_aliases_alias), parserutils_charset_alias_match); if (c == NULL) return NULL; return c->canon; } /** * Retrieve the MIB enum value assigned to an encoding name * * \param alias The alias to lookup * \param len The length of the alias string * \return The MIB enum value, or 0 if not found */ uint16_t parserutils_charset_mibenum_from_name(const char *alias, size_t len) { parserutils_charset_aliases_canon *c; if (alias == NULL) return 0; c = parserutils__charset_alias_canonicalise(alias, len); if (c == NULL) return 0; return c->mib_enum; } /** * Retrieve the canonical name of an encoding from the MIB enum * * \param mibenum The MIB enum value * \return Pointer to canonical name, or NULL if not found */ const char *parserutils_charset_mibenum_to_name(uint16_t mibenum) { int i; parserutils_charset_aliases_canon *c; for (i = 0; i < charset_aliases_canon_count; ++i) { c = &canonical_charset_names[i]; if (c->mib_enum == mibenum) return c->name; } return NULL; } /** * Detect if a parserutils_charset is Unicode * * \param mibenum The MIB enum to consider * \return true if a Unicode variant, false otherwise */ bool parserutils_charset_mibenum_is_unicode(uint16_t mibenum) { return MIBENUM_IS_UNICODE(mibenum); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/������������������������������������������������0000775�0001750�0001750�00000000000�11734430231�021223� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/codec_utf16.c�����������������������������������0000664�0001750�0001750�00000037255�11223172060�023501� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include #include #include #include #include "charset/codecs/codec_impl.h" #include "utils/endian.h" #include "utils/utils.h" /** * UTF-16 charset codec */ typedef struct charset_utf16_codec { parserutils_charset_codec base; /**< Base class */ #define INVAL_BUFSIZE (32) uint8_t inval_buf[INVAL_BUFSIZE]; /**< Buffer for fixing up * incomplete input * sequences */ size_t inval_len; /*< Byte length of inval_buf **/ #define READ_BUFSIZE (8) uint32_t read_buf[READ_BUFSIZE]; /**< Buffer for partial * output sequences (decode) * (host-endian) */ size_t read_len; /**< Character length of read_buf */ #define WRITE_BUFSIZE (8) uint32_t write_buf[WRITE_BUFSIZE]; /**< Buffer for partial * output sequences (encode) * (host-endian) */ size_t write_len; /**< Character length of write_buf */ } charset_utf16_codec; static bool charset_utf16_codec_handles_charset(const char *charset); static parserutils_error charset_utf16_codec_create( const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec); static parserutils_error charset_utf16_codec_destroy( parserutils_charset_codec *codec); static parserutils_error charset_utf16_codec_encode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_utf16_codec_decode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_utf16_codec_reset( parserutils_charset_codec *codec); static inline parserutils_error charset_utf16_codec_read_char( charset_utf16_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static inline parserutils_error charset_utf16_codec_output_decoded_char( charset_utf16_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen); /** * Determine whether this codec handles a specific charset * * \param charset Charset to test * \return true if handleable, false otherwise */ bool charset_utf16_codec_handles_charset(const char *charset) { return parserutils_charset_mibenum_from_name(charset, strlen(charset)) == parserutils_charset_mibenum_from_name("UTF-16", SLEN("UTF-16")); } /** * Create a UTF-16 codec * * \param charset The charset to read from / write to * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data (may be NULL) * \param codec Pointer to location to receive codec * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhausion */ parserutils_error charset_utf16_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec) { charset_utf16_codec *c; UNUSED(charset); c = alloc(NULL, sizeof(charset_utf16_codec), pw); if (c == NULL) return PARSERUTILS_NOMEM; c->inval_buf[0] = '\0'; c->inval_len = 0; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; /* Finally, populate vtable */ c->base.handler.destroy = charset_utf16_codec_destroy; c->base.handler.encode = charset_utf16_codec_encode; c->base.handler.decode = charset_utf16_codec_decode; c->base.handler.reset = charset_utf16_codec_reset; *codec = (parserutils_charset_codec *) c; return PARSERUTILS_OK; } /** * Destroy a UTF-16 codec * * \param codec The codec to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_utf16_codec_destroy (parserutils_charset_codec *codec) { UNUSED(codec); return PARSERUTILS_OK; } /** * Encode a chunk of UCS-4 (big endian) data into UTF-16 * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read. Any remaining output for the character will be buffered by the * codec for writing on the next call. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_utf16_codec_encode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_utf16_codec *c = (charset_utf16_codec *) codec; uint32_t ucs4; uint32_t *towrite; size_t towritelen; parserutils_error error; /* Process any outstanding characters from the previous call */ if (c->write_len > 0) { uint32_t *pwrite = c->write_buf; uint8_t buf[4]; size_t len; while (c->write_len > 0) { error = parserutils_charset_utf16_from_ucs4( pwrite[0], buf, &len); if (error != PARSERUTILS_OK) abort(); if (*destlen < len) { /* Insufficient output buffer space */ for (len = 0; len < c->write_len; len++) c->write_buf[len] = pwrite[len]; return PARSERUTILS_NOMEM; } memcpy(*dest, buf, len); *dest += len; *destlen -= len; pwrite++; c->write_len--; } } /* Now process the characters for this call */ while (*sourcelen > 0) { ucs4 = endian_big_to_host(*((uint32_t *) (void *) *source)); towrite = &ucs4; towritelen = 1; /* Output current characters */ while (towritelen > 0) { uint8_t buf[4]; size_t len; error = parserutils_charset_utf16_from_ucs4( towrite[0], buf, &len); if (error != PARSERUTILS_OK) abort(); if (*destlen < len) { /* Insufficient output space */ if (towritelen >= WRITE_BUFSIZE) abort(); c->write_len = towritelen; /* Copy pending chars to save area, for * processing next call. */ for (len = 0; len < towritelen; len++) c->write_buf[len] = towrite[len]; /* Claim character we've just buffered, * so it's not reprocessed */ *source += 4; *sourcelen -= 4; return PARSERUTILS_NOMEM; } memcpy(*dest, buf, len); *dest += len; *destlen -= len; towrite++; towritelen--; } *source += 4; *sourcelen -= 4; } return PARSERUTILS_OK; } /** * Decode a chunk of UTF-16 data into UCS-4 (big endian) * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * If STRICT error handling is configured and an illegal sequence is split * over two calls, then _INVALID will be returned from the second call, * but ::source will point mid-way through the invalid sequence (i.e. it * will be unmodified over the second call). In addition, the internal * incomplete-sequence buffer will be emptied, such that subsequent calls * will progress, rather than re-evaluating the same invalid sequence. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. * * Call this with a source length of 0 to flush the output buffer. */ parserutils_error charset_utf16_codec_decode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_utf16_codec *c = (charset_utf16_codec *) codec; parserutils_error error; if (c->read_len > 0) { /* Output left over from last decode */ uint32_t *pread = c->read_buf; while (c->read_len > 0 && *destlen >= c->read_len * 4) { *((uint32_t *) (void *) *dest) = endian_host_to_big(pread[0]); *dest += 4; *destlen -= 4; pread++; c->read_len--; } if (*destlen < c->read_len * 4) { /* Ran out of output buffer */ size_t i; /* Shuffle remaining output down */ for (i = 0; i < c->read_len; i++) c->read_buf[i] = pread[i]; return PARSERUTILS_NOMEM; } } if (c->inval_len > 0) { /* The last decode ended in an incomplete sequence. * Fill up inval_buf with data from the start of the * new chunk and process it. */ uint8_t *in = c->inval_buf; size_t ol = c->inval_len; size_t l = min(INVAL_BUFSIZE - ol - 1, *sourcelen); size_t orig_l = l; memcpy(c->inval_buf + ol, *source, l); l += c->inval_len; error = charset_utf16_codec_read_char(c, (const uint8_t **) &in, &l, dest, destlen); if (error != PARSERUTILS_OK && error != PARSERUTILS_NOMEM) { return error; } /* And now, fix up source pointers */ *source += max((signed) (orig_l - l), 0); *sourcelen -= max((signed) (orig_l - l), 0); /* Failed to resolve an incomplete character and * ran out of buffer space. No recovery strategy * possible, so explode everywhere. */ if ((orig_l + ol) - l == 0) abort(); /* Report memory exhaustion case from above */ if (error != PARSERUTILS_OK) return error; } /* Finally, the "normal" case; process all outstanding characters */ while (*sourcelen > 0) { error = charset_utf16_codec_read_char(c, source, sourcelen, dest, destlen); if (error != PARSERUTILS_OK) { return error; } } return PARSERUTILS_OK; } /** * Clear a UTF-16 codec's encoding state * * \param codec The codec to reset * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_utf16_codec_reset(parserutils_charset_codec *codec) { charset_utf16_codec *c = (charset_utf16_codec *) codec; c->inval_buf[0] = '\0'; c->inval_len = 0; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; return PARSERUTILS_OK; } /** * Read a character from the UTF-16 to UCS-4 (big endian) * * \param c The codec * \param source Pointer to pointer to source buffer (updated on exit) * \param sourcelen Pointer to length of source buffer (updated on exit) * \param dest Pointer to pointer to output buffer (updated on exit) * \param destlen Pointer to length of output buffer (updated on exit) * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_utf16_codec_read_char(charset_utf16_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { uint32_t ucs4; size_t sucs4; parserutils_error error; /* Convert a single character */ error = parserutils_charset_utf16_to_ucs4(*source, *sourcelen, &ucs4, &sucs4); if (error == PARSERUTILS_OK) { /* Read a character */ error = charset_utf16_codec_output_decoded_char(c, ucs4, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += sucs4; *sourcelen -= sucs4; } /* Clear inval buffer */ c->inval_buf[0] = '\0'; c->inval_len = 0; return error; } else if (error == PARSERUTILS_NEEDDATA) { /* Incomplete input sequence */ if (*sourcelen > INVAL_BUFSIZE) abort(); memmove(c->inval_buf, *source, *sourcelen); c->inval_buf[*sourcelen] = '\0'; c->inval_len = *sourcelen; *source += *sourcelen; *sourcelen = 0; return PARSERUTILS_OK; } else if (error == PARSERUTILS_INVALID) { /* Illegal input sequence */ uint32_t nextchar; /* Clear inval buffer */ c->inval_buf[0] = '\0'; c->inval_len = 0; /* Strict errormode; simply flag invalid character */ if (c->base.errormode == PARSERUTILS_CHARSET_CODEC_ERROR_STRICT) { return PARSERUTILS_INVALID; } /* Find next valid UTF-16 sequence. * We're processing client-provided data, so let's * be paranoid about its validity. */ error = parserutils_charset_utf16_next_paranoid( *source, *sourcelen, 0, &nextchar); if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_NEEDDATA) { /* Need more data to be sure */ if (*sourcelen > INVAL_BUFSIZE) abort(); memmove(c->inval_buf, *source, *sourcelen); c->inval_buf[*sourcelen] = '\0'; c->inval_len = *sourcelen; *source += *sourcelen; *sourcelen = 0; nextchar = 0; } else { return error; } } /* output U+FFFD and continue processing. */ error = charset_utf16_codec_output_decoded_char(c, 0xFFFD, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += nextchar; *sourcelen -= nextchar; } return error; } return PARSERUTILS_OK; } /** * Output a UCS-4 character (big endian) * * \param c Codec to use * \param ucs4 UCS-4 character (host endian) * \param dest Pointer to pointer to output buffer * \param destlen Pointer to output buffer length * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, */ parserutils_error charset_utf16_codec_output_decoded_char(charset_utf16_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen) { if (*destlen < 4) { /* Run out of output buffer */ c->read_len = 1; c->read_buf[0] = ucs4; return PARSERUTILS_NOMEM; } *((uint32_t *) (void *) *dest) = endian_host_to_big(ucs4); *dest += 4; *destlen -= 4; return PARSERUTILS_OK; } const parserutils_charset_handler charset_utf16_codec_handler = { charset_utf16_codec_handles_charset, charset_utf16_codec_create }; ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/codec_impl.h������������������������������������0000664�0001750�0001750�00000002740�11105415756�023504� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #ifndef parserutils_charset_codecs_codecimpl_h_ #define parserutils_charset_codecs_codecimpl_h_ #include #include #include /** * Core charset codec definition; implementations extend this */ struct parserutils_charset_codec { uint16_t mibenum; /**< MIB enum for charset */ parserutils_charset_codec_errormode errormode; /**< error mode */ parserutils_alloc alloc; /**< allocation function */ void *alloc_pw; /**< private word */ struct { parserutils_error (*destroy)(parserutils_charset_codec *codec); parserutils_error (*encode)(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); parserutils_error (*decode)(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); parserutils_error (*reset)(parserutils_charset_codec *codec); } handler; /**< Vtable for handler code */ }; /** * Codec factory component definition */ typedef struct parserutils_charset_handler { bool (*handles_charset)(const char *charset); parserutils_error (*create)(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec); } parserutils_charset_handler; #endif ��������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/8859_tables.h�����������������������������������0000664�0001750�0001750�00000031003�11060004620�023327� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef parserutils_charset_codecs_8859tables_h_ #define parserutils_charset_codecs_8859tables_h_ /* Mapping tables for ISO-8859-n -> UCS4. * Undefined characters are mapped to U+FFFF, * which is a guaranteed non-character */ static uint32_t t1[96] = { 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, }; static uint32_t t2[96] = { 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9, }; static uint32_t t3[96] = { 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0xFFFF, 0x0124, 0x00A7, 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0xFFFF, 0x017B, 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0xFFFF, 0x017C, 0x00C0, 0x00C1, 0x00C2, 0xFFFF, 0x00C4, 0x010A, 0x0108, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0xFFFF, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0xFFFF, 0x00E4, 0x010B, 0x0109, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0xFFFF, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9, }; static uint32_t t4[96] = { 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF, 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B, 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A, 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF, 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B, 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9, }; static uint32_t t5[96] = { 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F, }; static uint32_t t6[96] = { 0x00A0, 0xFFFF, 0xFFFF, 0xFFFF, 0x00A4, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x060C, 0x00AD, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x061B, 0xFFFF, 0xFFFF, 0xFFFF, 0x061F, 0xFFFF, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x0651, 0x0652, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, }; static uint32_t t7[96] = { 0x00A0, 0x2018, 0x2019, 0x00A3, 0x20AC, 0x20AF, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x037A, 0x00AB, 0x00AC, 0x00AD, 0xFFFF, 0x2015, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7, 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0xFFFF, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFF, }; static uint32_t t8[96] = { 0x00A0, 0xFFFF, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2017, 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0xFFFF, 0xFFFF, 0x200E, 0x200F, 0xFFFF, }; static uint32_t t9[96] = { 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF, }; static uint32_t t10[96] = { 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A, 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B, 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138, }; static uint32_t t11[96] = { 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0E3F, 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, }; static uint32_t t13[96] = { 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7, 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7, 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019, }; static uint32_t t14[96] = { 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7, 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178, 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56, 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF, }; static uint32_t t15[96] = { 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7, 0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, }; static uint32_t t16[96] = { 0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B, 0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7, 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C, 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A, 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B, 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF, }; #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/codec_ascii.c�����������������������������������0000664�0001750�0001750�00000036545�11223172060�023625� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include #include #include "charset/codecs/codec_impl.h" #include "utils/endian.h" #include "utils/utils.h" /** * US-ASCII charset codec */ typedef struct charset_ascii_codec { parserutils_charset_codec base; /**< Base class */ #define READ_BUFSIZE (8) uint32_t read_buf[READ_BUFSIZE]; /**< Buffer for partial * output sequences (decode) * (host-endian) */ size_t read_len; /**< Character length of read_buf */ #define WRITE_BUFSIZE (8) uint32_t write_buf[WRITE_BUFSIZE]; /**< Buffer for partial * output sequences (encode) * (host-endian) */ size_t write_len; /**< Character length of write_buf */ } charset_ascii_codec; static bool charset_ascii_codec_handles_charset(const char *charset); static parserutils_error charset_ascii_codec_create( const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec); static parserutils_error charset_ascii_codec_destroy( parserutils_charset_codec *codec); static parserutils_error charset_ascii_codec_encode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_ascii_codec_decode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_ascii_codec_reset( parserutils_charset_codec *codec); static inline parserutils_error charset_ascii_codec_read_char( charset_ascii_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static inline parserutils_error charset_ascii_codec_output_decoded_char( charset_ascii_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen); static inline parserutils_error charset_ascii_from_ucs4(charset_ascii_codec *c, uint32_t ucs4, uint8_t **s, size_t *len); static inline parserutils_error charset_ascii_to_ucs4(charset_ascii_codec *c, const uint8_t *s, size_t len, uint32_t *ucs4); /** * Determine whether this codec handles a specific charset * * \param charset Charset to test * \return true if handleable, false otherwise */ bool charset_ascii_codec_handles_charset(const char *charset) { static uint16_t ascii; uint16_t match = parserutils_charset_mibenum_from_name(charset, strlen(charset)); if (ascii == 0) { ascii = parserutils_charset_mibenum_from_name( "US-ASCII", SLEN("US-ASCII")); } if (ascii != 0 && ascii == match) return true; return false; } /** * Create a US-ASCII codec * * \param charset The charset to read from / write to * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data (may be NULL) * \param codec Pointer to location to receive codec * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhausion */ parserutils_error charset_ascii_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec) { charset_ascii_codec *c; UNUSED(charset); c = alloc(NULL, sizeof(charset_ascii_codec), pw); if (c == NULL) return PARSERUTILS_NOMEM; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; /* Finally, populate vtable */ c->base.handler.destroy = charset_ascii_codec_destroy; c->base.handler.encode = charset_ascii_codec_encode; c->base.handler.decode = charset_ascii_codec_decode; c->base.handler.reset = charset_ascii_codec_reset; *codec = (parserutils_charset_codec *) c; return PARSERUTILS_OK; } /** * Destroy a US-ASCII codec * * \param codec The codec to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_ascii_codec_destroy (parserutils_charset_codec *codec) { UNUSED(codec); return PARSERUTILS_OK; } /** * Encode a chunk of UCS-4 (big endian) data into US-ASCII * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read. Any remaining output for the character will be buffered by the * codec for writing on the next call. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_ascii_codec_encode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_ascii_codec *c = (charset_ascii_codec *) codec; uint32_t ucs4; uint32_t *towrite; size_t towritelen; parserutils_error error; /* Process any outstanding characters from the previous call */ if (c->write_len > 0) { uint32_t *pwrite = c->write_buf; while (c->write_len > 0) { error = charset_ascii_from_ucs4(c, pwrite[0], dest, destlen); if (error != PARSERUTILS_OK) { uint32_t len; assert(error == PARSERUTILS_NOMEM); for (len = 0; len < c->write_len; len++) { c->write_buf[len] = pwrite[len]; } return error; } pwrite++; c->write_len--; } } /* Now process the characters for this call */ while (*sourcelen > 0) { ucs4 = endian_big_to_host(*((uint32_t *) (void *) *source)); towrite = &ucs4; towritelen = 1; /* Output current characters */ while (towritelen > 0) { error = charset_ascii_from_ucs4(c, towrite[0], dest, destlen); if (error != PARSERUTILS_OK) { uint32_t len; if (error != PARSERUTILS_NOMEM) { return error; } /* Insufficient output space */ if (towritelen >= WRITE_BUFSIZE) abort(); c->write_len = towritelen; /* Copy pending chars to save area, for * processing next call. */ for (len = 0; len < towritelen; len++) c->write_buf[len] = towrite[len]; /* Claim character we've just buffered, * so it's not reprocessed */ *source += 4; *sourcelen -= 4; return PARSERUTILS_NOMEM; } towrite++; towritelen--; } *source += 4; *sourcelen -= 4; } return PARSERUTILS_OK; } /** * Decode a chunk of US-ASCII data into UCS-4 (big endian) * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * If STRICT error handling is configured and an illegal sequence is split * over two calls, then _INVALID will be returned from the second call, * but ::source will point mid-way through the invalid sequence (i.e. it * will be unmodified over the second call). In addition, the internal * incomplete-sequence buffer will be emptied, such that subsequent calls * will progress, rather than re-evaluating the same invalid sequence. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. * * Call this with a source length of 0 to flush the output buffer. */ parserutils_error charset_ascii_codec_decode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_ascii_codec *c = (charset_ascii_codec *) codec; parserutils_error error; if (c->read_len > 0) { /* Output left over from last decode */ uint32_t *pread = c->read_buf; while (c->read_len > 0 && *destlen >= c->read_len * 4) { *((uint32_t *) (void *) *dest) = endian_host_to_big(pread[0]); *dest += 4; *destlen -= 4; pread++; c->read_len--; } if (*destlen < c->read_len * 4) { /* Ran out of output buffer */ size_t i; /* Shuffle remaining output down */ for (i = 0; i < c->read_len; i++) c->read_buf[i] = pread[i]; return PARSERUTILS_NOMEM; } } /* Finally, the "normal" case; process all outstanding characters */ while (*sourcelen > 0) { error = charset_ascii_codec_read_char(c, source, sourcelen, dest, destlen); if (error != PARSERUTILS_OK) { return error; } } return PARSERUTILS_OK; } /** * Clear a US-ASCII codec's encoding state * * \param codec The codec to reset * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_ascii_codec_reset(parserutils_charset_codec *codec) { charset_ascii_codec *c = (charset_ascii_codec *) codec; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; return PARSERUTILS_OK; } /** * Read a character from US-ASCII to UCS-4 (big endian) * * \param c The codec * \param source Pointer to pointer to source buffer (updated on exit) * \param sourcelen Pointer to length of source buffer (updated on exit) * \param dest Pointer to pointer to output buffer (updated on exit) * \param destlen Pointer to length of output buffer (updated on exit) * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_ascii_codec_read_char(charset_ascii_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { uint32_t ucs4; parserutils_error error; /* Convert a single character */ error = charset_ascii_to_ucs4(c, *source, *sourcelen, &ucs4); if (error == PARSERUTILS_OK) { /* Read a character */ error = charset_ascii_codec_output_decoded_char(c, ucs4, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += 1; *sourcelen -= 1; } return error; } else if (error == PARSERUTILS_NEEDDATA) { /* Can only happen if sourcelen == 0 */ return error; } else if (error == PARSERUTILS_INVALID) { /* Illegal input sequence */ /* Strict errormode; simply flag invalid character */ if (c->base.errormode == PARSERUTILS_CHARSET_CODEC_ERROR_STRICT) { return PARSERUTILS_INVALID; } /* output U+FFFD and continue processing. */ error = charset_ascii_codec_output_decoded_char(c, 0xFFFD, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += 1; *sourcelen -= 1; } return error; } return PARSERUTILS_OK; } /** * Output a UCS-4 character (big endian) * * \param c Codec to use * \param ucs4 UCS-4 character (host endian) * \param dest Pointer to pointer to output buffer * \param destlen Pointer to output buffer length * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, */ parserutils_error charset_ascii_codec_output_decoded_char( charset_ascii_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen) { if (*destlen < 4) { /* Run out of output buffer */ c->read_len = 1; c->read_buf[0] = ucs4; return PARSERUTILS_NOMEM; } *((uint32_t *) (void *) *dest) = endian_host_to_big(ucs4); *dest += 4; *destlen -= 4; return PARSERUTILS_OK; } /** * Convert a UCS4 (host endian) character to US-ASCII * * \param c The codec instance * \param ucs4 The UCS4 character to convert * \param s Pointer to pointer to destination buffer * \param len Pointer to destination buffer length * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if there's insufficient space in the output buffer, * PARSERUTILS_INVALID if the character cannot be represented * * _INVALID will only be returned if the codec's conversion mode is STRICT. * Otherwise, '?' will be output. * * On successful conversion, *s and *len will be updated. */ parserutils_error charset_ascii_from_ucs4(charset_ascii_codec *c, uint32_t ucs4, uint8_t **s, size_t *len) { uint8_t out = 0; if (*len < 1) return PARSERUTILS_NOMEM; if (ucs4 < 0x80) { /* ASCII */ out = ucs4; } else { if (c->base.errormode == PARSERUTILS_CHARSET_CODEC_ERROR_STRICT) return PARSERUTILS_INVALID; else out = '?'; } *(*s) = out; (*s)++; (*len)--; return PARSERUTILS_OK; } /** * Convert a US-ASCII character to UCS4 (host endian) * * \param c The codec instance * \param s Pointer to source buffer * \param len Source buffer length * \param ucs4 Pointer to destination buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NEEDDATA if there's insufficient input data * PARSERUTILS_INVALID if the character cannot be represented */ parserutils_error charset_ascii_to_ucs4(charset_ascii_codec *c, const uint8_t *s, size_t len, uint32_t *ucs4) { uint32_t out; UNUSED(c); if (len < 1) return PARSERUTILS_NEEDDATA; if (*s < 0x80) { out = *s; } else { return PARSERUTILS_INVALID; } *ucs4 = out; return PARSERUTILS_OK; } const parserutils_charset_handler charset_ascii_codec_handler = { charset_ascii_codec_handles_charset, charset_ascii_codec_create }; �����������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/codec_8859.c������������������������������������0000664�0001750�0001750�00000041653�11223172060�023146� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include #include #include "charset/codecs/codec_impl.h" #include "utils/endian.h" #include "utils/utils.h" #include "charset/codecs/8859_tables.h" static struct { uint16_t mib; const char *name; size_t len; uint32_t *table; } known_charsets[] = { { 0, "ISO-8859-1", SLEN("ISO-8859-1"), t1 }, { 0, "ISO-8859-2", SLEN("ISO-8859-2"), t2 }, { 0, "ISO-8859-3", SLEN("ISO-8859-3"), t3 }, { 0, "ISO-8859-4", SLEN("ISO-8859-4"), t4 }, { 0, "ISO-8859-5", SLEN("ISO-8859-5"), t5 }, { 0, "ISO-8859-6", SLEN("ISO-8859-6"), t6 }, { 0, "ISO-8859-7", SLEN("ISO-8859-7"), t7 }, { 0, "ISO-8859-8", SLEN("ISO-8859-8"), t8 }, { 0, "ISO-8859-9", SLEN("ISO-8859-9"), t9 }, { 0, "ISO-8859-10", SLEN("ISO-8859-10"), t10 }, { 0, "ISO-8859-11", SLEN("ISO-8859-11"), t11 }, { 0, "ISO-8859-13", SLEN("ISO-8859-13"), t13 }, { 0, "ISO-8859-14", SLEN("ISO-8859-14"), t14 }, { 0, "ISO-8859-15", SLEN("ISO-8859-15"), t15 }, { 0, "ISO-8859-16", SLEN("ISO-8859-16"), t16 } }; /** * ISO-8859-n charset codec */ typedef struct charset_8859_codec { parserutils_charset_codec base; /**< Base class */ uint32_t *table; /**< Mapping table for 0xA0-0xFF */ #define READ_BUFSIZE (8) uint32_t read_buf[READ_BUFSIZE]; /**< Buffer for partial * output sequences (decode) * (host-endian) */ size_t read_len; /**< Character length of read_buf */ #define WRITE_BUFSIZE (8) uint32_t write_buf[WRITE_BUFSIZE]; /**< Buffer for partial * output sequences (encode) * (host-endian) */ size_t write_len; /**< Character length of write_buf */ } charset_8859_codec; static bool charset_8859_codec_handles_charset(const char *charset); static parserutils_error charset_8859_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec); static parserutils_error charset_8859_codec_destroy( parserutils_charset_codec *codec); static parserutils_error charset_8859_codec_encode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_8859_codec_decode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_8859_codec_reset( parserutils_charset_codec *codec); static inline parserutils_error charset_8859_codec_read_char( charset_8859_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static inline parserutils_error charset_8859_codec_output_decoded_char( charset_8859_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen); static inline parserutils_error charset_8859_from_ucs4(charset_8859_codec *c, uint32_t ucs4, uint8_t **s, size_t *len); static inline parserutils_error charset_8859_to_ucs4(charset_8859_codec *c, const uint8_t *s, size_t len, uint32_t *ucs4); /** * Determine whether this codec handles a specific charset * * \param charset Charset to test * \return true if handleable, false otherwise */ bool charset_8859_codec_handles_charset(const char *charset) { uint32_t i; uint16_t match = parserutils_charset_mibenum_from_name(charset, strlen(charset)); if (known_charsets[0].mib == 0) { for (i = 0; i < N_ELEMENTS(known_charsets); i++) { known_charsets[i].mib = parserutils_charset_mibenum_from_name( known_charsets[i].name, known_charsets[i].len); } } for (i = 0; i < N_ELEMENTS(known_charsets); i++) { if (known_charsets[i].mib == match) return true; } return false; } /** * Create an ISO-8859-n codec * * \param charset The charset to read from / write to * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data (may be NULL) * \param codec Pointer to location to receive codec * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhausion */ parserutils_error charset_8859_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec) { uint32_t i; charset_8859_codec *c; uint16_t match = parserutils_charset_mibenum_from_name( charset, strlen(charset)); uint32_t *table = NULL; for (i = 0; i < N_ELEMENTS(known_charsets); i++) { if (known_charsets[i].mib == match) { table = known_charsets[i].table; break; } } assert(table != NULL); c = alloc(NULL, sizeof(charset_8859_codec), pw); if (c == NULL) return PARSERUTILS_NOMEM; c->table = table; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; /* Finally, populate vtable */ c->base.handler.destroy = charset_8859_codec_destroy; c->base.handler.encode = charset_8859_codec_encode; c->base.handler.decode = charset_8859_codec_decode; c->base.handler.reset = charset_8859_codec_reset; *codec = (parserutils_charset_codec *) c; return PARSERUTILS_OK; } /** * Destroy an ISO-8859-n codec * * \param codec The codec to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_8859_codec_destroy (parserutils_charset_codec *codec) { UNUSED(codec); return PARSERUTILS_OK; } /** * Encode a chunk of UCS-4 (big endian) data into ISO-8859-n * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read. Any remaining output for the character will be buffered by the * codec for writing on the next call. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_8859_codec_encode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_8859_codec *c = (charset_8859_codec *) codec; uint32_t ucs4; uint32_t *towrite; size_t towritelen; parserutils_error error; /* Process any outstanding characters from the previous call */ if (c->write_len > 0) { uint32_t *pwrite = c->write_buf; while (c->write_len > 0) { error = charset_8859_from_ucs4(c, pwrite[0], dest, destlen); if (error != PARSERUTILS_OK) { uint32_t len; assert(error == PARSERUTILS_NOMEM); for (len = 0; len < c->write_len; len++) { c->write_buf[len] = pwrite[len]; } return error; } pwrite++; c->write_len--; } } /* Now process the characters for this call */ while (*sourcelen > 0) { ucs4 = endian_big_to_host(*((uint32_t *) (void *) *source)); towrite = &ucs4; towritelen = 1; /* Output current characters */ while (towritelen > 0) { error = charset_8859_from_ucs4(c, towrite[0], dest, destlen); if (error != PARSERUTILS_OK) { uint32_t len; if (error != PARSERUTILS_NOMEM) { return error; } /* Insufficient output space */ if (towritelen >= WRITE_BUFSIZE) abort(); c->write_len = towritelen; /* Copy pending chars to save area, for * processing next call. */ for (len = 0; len < towritelen; len++) c->write_buf[len] = towrite[len]; /* Claim character we've just buffered, * so it's not reprocessed */ *source += 4; *sourcelen -= 4; return PARSERUTILS_NOMEM; } towrite++; towritelen--; } *source += 4; *sourcelen -= 4; } return PARSERUTILS_OK; } /** * Decode a chunk of ISO-8859-n data into UCS-4 (big endian) * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * If STRICT error handling is configured and an illegal sequence is split * over two calls, then _INVALID will be returned from the second call, * but ::source will point mid-way through the invalid sequence (i.e. it * will be unmodified over the second call). In addition, the internal * incomplete-sequence buffer will be emptied, such that subsequent calls * will progress, rather than re-evaluating the same invalid sequence. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. * * Call this with a source length of 0 to flush the output buffer. */ parserutils_error charset_8859_codec_decode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_8859_codec *c = (charset_8859_codec *) codec; parserutils_error error; if (c->read_len > 0) { /* Output left over from last decode */ uint32_t *pread = c->read_buf; while (c->read_len > 0 && *destlen >= c->read_len * 4) { *((uint32_t *) (void *) *dest) = endian_host_to_big(pread[0]); *dest += 4; *destlen -= 4; pread++; c->read_len--; } if (*destlen < c->read_len * 4) { /* Ran out of output buffer */ size_t i; /* Shuffle remaining output down */ for (i = 0; i < c->read_len; i++) c->read_buf[i] = pread[i]; return PARSERUTILS_NOMEM; } } /* Finally, the "normal" case; process all outstanding characters */ while (*sourcelen > 0) { error = charset_8859_codec_read_char(c, source, sourcelen, dest, destlen); if (error != PARSERUTILS_OK) { return error; } } return PARSERUTILS_OK; } /** * Clear an ISO-8859-n codec's encoding state * * \param codec The codec to reset * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_8859_codec_reset(parserutils_charset_codec *codec) { charset_8859_codec *c = (charset_8859_codec *) codec; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; return PARSERUTILS_OK; } /** * Read a character from the ISO-8859-n to UCS-4 (big endian) * * \param c The codec * \param source Pointer to pointer to source buffer (updated on exit) * \param sourcelen Pointer to length of source buffer (updated on exit) * \param dest Pointer to pointer to output buffer (updated on exit) * \param destlen Pointer to length of output buffer (updated on exit) * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_8859_codec_read_char(charset_8859_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { uint32_t ucs4; parserutils_error error; /* Convert a single character */ error = charset_8859_to_ucs4(c, *source, *sourcelen, &ucs4); if (error == PARSERUTILS_OK) { /* Read a character */ error = charset_8859_codec_output_decoded_char(c, ucs4, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += 1; *sourcelen -= 1; } return error; } else if (error == PARSERUTILS_NEEDDATA) { /* Can only happen if sourcelen == 0 */ return error; } else if (error == PARSERUTILS_INVALID) { /* Illegal input sequence */ /* Strict errormode; simply flag invalid character */ if (c->base.errormode == PARSERUTILS_CHARSET_CODEC_ERROR_STRICT) { return PARSERUTILS_INVALID; } /* output U+FFFD and continue processing. */ error = charset_8859_codec_output_decoded_char(c, 0xFFFD, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += 1; *sourcelen -= 1; } return error; } return PARSERUTILS_OK; } /** * Output a UCS-4 character (big endian) * * \param c Codec to use * \param ucs4 UCS-4 character (host endian) * \param dest Pointer to pointer to output buffer * \param destlen Pointer to output buffer length * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, */ parserutils_error charset_8859_codec_output_decoded_char(charset_8859_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen) { if (*destlen < 4) { /* Run out of output buffer */ c->read_len = 1; c->read_buf[0] = ucs4; return PARSERUTILS_NOMEM; } *((uint32_t *) (void *) *dest) = endian_host_to_big(ucs4); *dest += 4; *destlen -= 4; return PARSERUTILS_OK; } /** * Convert a UCS4 (host endian) character to ISO-8859-n * * \param c The codec instance * \param ucs4 The UCS4 character to convert * \param s Pointer to pointer to destination buffer * \param len Pointer to destination buffer length * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if there's insufficient space in the output buffer, * PARSERUTILS_INVALID if the character cannot be represented * * _INVALID will only be returned if the codec's conversion mode is STRICT. * Otherwise, '?' will be output. * * On successful conversion, *s and *len will be updated. */ parserutils_error charset_8859_from_ucs4(charset_8859_codec *c, uint32_t ucs4, uint8_t **s, size_t *len) { uint8_t out = 0; if (*len < 1) return PARSERUTILS_NOMEM; if (ucs4 < 0x80) { /* ASCII */ out = ucs4; } else { uint32_t i; for (i = 0; i < 96; i++) { if (ucs4 == c->table[i]) break; } if (i == 96) { if (c->base.errormode == PARSERUTILS_CHARSET_CODEC_ERROR_STRICT) return PARSERUTILS_INVALID; else out = '?'; } else { out = 0xA0 + i; } } *(*s) = out; (*s)++; (*len)--; return PARSERUTILS_OK; } /** * Convert an ISO-8859-n character to UCS4 (host endian) * * \param c The codec instance * \param s Pointer to source buffer * \param len Source buffer length * \param ucs4 Pointer to destination buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NEEDDATA if there's insufficient input data * PARSERUTILS_INVALID if the character cannot be represented */ parserutils_error charset_8859_to_ucs4(charset_8859_codec *c, const uint8_t *s, size_t len, uint32_t *ucs4) { uint32_t out; if (len < 1) return PARSERUTILS_NEEDDATA; if (*s < 0x80) { out = *s; } else if (*s >= 0xA0) { if (c->table[*s - 0xA0] == 0xFFFF) return PARSERUTILS_INVALID; out = c->table[*s - 0xA0]; } else { return PARSERUTILS_INVALID; } *ucs4 = out; return PARSERUTILS_OK; } const parserutils_charset_handler charset_8859_codec_handler = { charset_8859_codec_handles_charset, charset_8859_codec_create }; �������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/Makefile����������������������������������������0000664�0001750�0001750�00000000210�11162216376�022663� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Sources DIR_SOURCES := codec_ascii.c codec_8859.c codec_ext8.c \ codec_utf8.c codec_utf16.c include build/makefiles/Makefile.subdir ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/ext8_tables.h�����������������������������������0000664�0001750�0001750�00000024042�11060012226�023610� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #ifndef parserutils_charset_codecs_ext8tables_h_ #define parserutils_charset_codecs_ext8tables_h_ /* Mapping tables for extended 8bit -> UCS4. * Undefined characters are mapped to U+FFFF, * which is a guaranteed non-character */ static uint32_t w1250[128] = { 0x20AC, 0xFFFF, 0x201A, 0xFFFF, 0x201E, 0x2026, 0x2020, 0x2021, 0xFFFF, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, 0xFFFF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0xFFFF, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9, }; static uint32_t w1251[128] = { 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0xFFFF, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, }; static uint32_t w1252[128] = { 0x20AC, 0xFFFF, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFF, 0x017D, 0xFFFF, 0xFFFF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFF, 0x017E, 0x0178, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, }; static uint32_t w1253[128] = { 0x20AC, 0xFFFF, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0xFFFF, 0x2030, 0xFFFF, 0x2039, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0xFFFF, 0x2122, 0xFFFF, 0x203A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0xFFFF, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0xFFFF, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0xFFFF, }; static uint32_t w1254[128] = { 0x20AC, 0xFFFF, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0xFFFF, 0xFFFF, 0x0178, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF, }; static uint32_t w1255[128] = { 0x20AC, 0xFFFF, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0xFFFF, 0x2039, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0xFFFF, 0x203A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AA, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0xFFFF, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0xFFFF, 0xFFFF, 0x200E, 0x200F, 0xFFFF, }; static uint32_t w1256[128] = { 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0641, 0x0642, 0x0643, 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2, }; static uint32_t w1257[128] = { 0x20AC, 0xFFFF, 0x201A, 0xFFFF, 0x201E, 0x2026, 0x2020, 0x2021, 0xFFFF, 0x2030, 0xFFFF, 0x2039, 0xFFFF, 0x00A8, 0x02C7, 0x00B8, 0xFFFF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0xFFFF, 0x2122, 0xFFFF, 0x203A, 0xFFFF, 0x00AF, 0x02DB, 0xFFFF, 0x00A0, 0xFFFF, 0x00A2, 0x00A3, 0x00A4, 0xFFFF, 0x00A6, 0x00A7, 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9, }; static uint32_t w1258[128] = { 0x20AC, 0xFFFF, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6, 0x2030, 0xFFFF, 0x2039, 0x0152, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC, 0x2122, 0xFFFF, 0x203A, 0x0153, 0xFFFF, 0xFFFF, 0x0178, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF, }; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/codec_ext8.c������������������������������������0000664�0001750�0001750�00000041244�11223172060�023415� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2008 John-Mark Bell */ #include #include #include #include #include "charset/codecs/codec_impl.h" #include "utils/endian.h" #include "utils/utils.h" #include "charset/codecs/ext8_tables.h" static struct { uint16_t mib; const char *name; size_t len; uint32_t *table; } known_charsets[] = { { 0, "Windows-1250", SLEN("Windows-1250"), w1250 }, { 0, "Windows-1251", SLEN("Windows-1251"), w1251 }, { 0, "Windows-1252", SLEN("Windows-1252"), w1252 }, { 0, "Windows-1253", SLEN("Windows-1253"), w1253 }, { 0, "Windows-1254", SLEN("Windows-1254"), w1254 }, { 0, "Windows-1255", SLEN("Windows-1255"), w1255 }, { 0, "Windows-1256", SLEN("Windows-1256"), w1256 }, { 0, "Windows-1257", SLEN("Windows-1257"), w1257 }, { 0, "Windows-1258", SLEN("Windows-1258"), w1258 }, }; /** * Windows charset codec */ typedef struct charset_ext8_codec { parserutils_charset_codec base; /**< Base class */ uint32_t *table; /**< Mapping table for 0x80-0xFF */ #define READ_BUFSIZE (8) uint32_t read_buf[READ_BUFSIZE]; /**< Buffer for partial * output sequences (decode) * (host-endian) */ size_t read_len; /**< Character length of read_buf */ #define WRITE_BUFSIZE (8) uint32_t write_buf[WRITE_BUFSIZE]; /**< Buffer for partial * output sequences (encode) * (host-endian) */ size_t write_len; /**< Character length of write_buf */ } charset_ext8_codec; static bool charset_ext8_codec_handles_charset(const char *charset); static parserutils_error charset_ext8_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec); static parserutils_error charset_ext8_codec_destroy( parserutils_charset_codec *codec); static parserutils_error charset_ext8_codec_encode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_ext8_codec_decode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_ext8_codec_reset( parserutils_charset_codec *codec); static inline parserutils_error charset_ext8_codec_read_char( charset_ext8_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static inline parserutils_error charset_ext8_codec_output_decoded_char( charset_ext8_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen); static inline parserutils_error charset_ext8_from_ucs4(charset_ext8_codec *c, uint32_t ucs4, uint8_t **s, size_t *len); static inline parserutils_error charset_ext8_to_ucs4(charset_ext8_codec *c, const uint8_t *s, size_t len, uint32_t *ucs4); /** * Determine whether this codec handles a specific charset * * \param charset Charset to test * \return true if handleable, false otherwise */ bool charset_ext8_codec_handles_charset(const char *charset) { uint32_t i; uint16_t match = parserutils_charset_mibenum_from_name(charset, strlen(charset)); if (known_charsets[0].mib == 0) { for (i = 0; i < N_ELEMENTS(known_charsets); i++) { known_charsets[i].mib = parserutils_charset_mibenum_from_name( known_charsets[i].name, known_charsets[i].len); } } for (i = 0; i < N_ELEMENTS(known_charsets); i++) { if (known_charsets[i].mib == match) return true; } return false; } /** * Create an extended 8bit codec * * \param charset The charset to read from / write to * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data (may be NULL) * \param codec Pointer to location to receive codec * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhausion */ parserutils_error charset_ext8_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec) { uint32_t i; charset_ext8_codec *c; uint16_t match = parserutils_charset_mibenum_from_name( charset, strlen(charset)); uint32_t *table = NULL; for (i = 0; i < N_ELEMENTS(known_charsets); i++) { if (known_charsets[i].mib == match) { table = known_charsets[i].table; break; } } assert(table != NULL); c = alloc(NULL, sizeof(charset_ext8_codec), pw); if (c == NULL) return PARSERUTILS_NOMEM; c->table = table; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; /* Finally, populate vtable */ c->base.handler.destroy = charset_ext8_codec_destroy; c->base.handler.encode = charset_ext8_codec_encode; c->base.handler.decode = charset_ext8_codec_decode; c->base.handler.reset = charset_ext8_codec_reset; *codec = (parserutils_charset_codec *) c; return PARSERUTILS_OK; } /** * Destroy an extended 8bit codec * * \param codec The codec to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_ext8_codec_destroy (parserutils_charset_codec *codec) { UNUSED(codec); return PARSERUTILS_OK; } /** * Encode a chunk of UCS-4 (big endian) data into extended 8bit * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read. Any remaining output for the character will be buffered by the * codec for writing on the next call. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_ext8_codec_encode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_ext8_codec *c = (charset_ext8_codec *) codec; uint32_t ucs4; uint32_t *towrite; size_t towritelen; parserutils_error error; /* Process any outstanding characters from the previous call */ if (c->write_len > 0) { uint32_t *pwrite = c->write_buf; while (c->write_len > 0) { error = charset_ext8_from_ucs4(c, pwrite[0], dest, destlen); if (error != PARSERUTILS_OK) { uint32_t len; assert(error == PARSERUTILS_NOMEM); for (len = 0; len < c->write_len; len++) { c->write_buf[len] = pwrite[len]; } return error; } pwrite++; c->write_len--; } } /* Now process the characters for this call */ while (*sourcelen > 0) { ucs4 = endian_big_to_host(*((uint32_t *) (void *) *source)); towrite = &ucs4; towritelen = 1; /* Output current characters */ while (towritelen > 0) { error = charset_ext8_from_ucs4(c, towrite[0], dest, destlen); if (error != PARSERUTILS_OK) { uint32_t len; if (error != PARSERUTILS_NOMEM) { return error; } /* Insufficient output space */ if (towritelen >= WRITE_BUFSIZE) abort(); c->write_len = towritelen; /* Copy pending chars to save area, for * processing next call. */ for (len = 0; len < towritelen; len++) c->write_buf[len] = towrite[len]; /* Claim character we've just buffered, * so it's not reprocessed */ *source += 4; *sourcelen -= 4; return PARSERUTILS_NOMEM; } towrite++; towritelen--; } *source += 4; *sourcelen -= 4; } return PARSERUTILS_OK; } /** * Decode a chunk of extended 8bit data into UCS-4 (big endian) * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * If STRICT error handling is configured and an illegal sequence is split * over two calls, then _INVALID will be returned from the second call, * but ::source will point mid-way through the invalid sequence (i.e. it * will be unmodified over the second call). In addition, the internal * incomplete-sequence buffer will be emptied, such that subsequent calls * will progress, rather than re-evaluating the same invalid sequence. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. * * Call this with a source length of 0 to flush the output buffer. */ parserutils_error charset_ext8_codec_decode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_ext8_codec *c = (charset_ext8_codec *) codec; parserutils_error error; if (c->read_len > 0) { /* Output left over from last decode */ uint32_t *pread = c->read_buf; while (c->read_len > 0 && *destlen >= c->read_len * 4) { *((uint32_t *) (void *) *dest) = endian_host_to_big(pread[0]); *dest += 4; *destlen -= 4; pread++; c->read_len--; } if (*destlen < c->read_len * 4) { /* Ran out of output buffer */ size_t i; /* Shuffle remaining output down */ for (i = 0; i < c->read_len; i++) c->read_buf[i] = pread[i]; return PARSERUTILS_NOMEM; } } /* Finally, the "normal" case; process all outstanding characters */ while (*sourcelen > 0) { error = charset_ext8_codec_read_char(c, source, sourcelen, dest, destlen); if (error != PARSERUTILS_OK) { return error; } } return PARSERUTILS_OK; } /** * Clear an extended 8bit codec's encoding state * * \param codec The codec to reset * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_ext8_codec_reset(parserutils_charset_codec *codec) { charset_ext8_codec *c = (charset_ext8_codec *) codec; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; return PARSERUTILS_OK; } /** * Read a character from the extended 8bit to UCS-4 (big endian) * * \param c The codec * \param source Pointer to pointer to source buffer (updated on exit) * \param sourcelen Pointer to length of source buffer (updated on exit) * \param dest Pointer to pointer to output buffer (updated on exit) * \param destlen Pointer to length of output buffer (updated on exit) * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_ext8_codec_read_char(charset_ext8_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { uint32_t ucs4; parserutils_error error; /* Convert a single character */ error = charset_ext8_to_ucs4(c, *source, *sourcelen, &ucs4); if (error == PARSERUTILS_OK) { /* Read a character */ error = charset_ext8_codec_output_decoded_char(c, ucs4, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += 1; *sourcelen -= 1; } return error; } else if (error == PARSERUTILS_NEEDDATA) { /* Can only happen if sourcelen == 0 */ return error; } else if (error == PARSERUTILS_INVALID) { /* Illegal input sequence */ /* Strict errormode; simply flag invalid character */ if (c->base.errormode == PARSERUTILS_CHARSET_CODEC_ERROR_STRICT) { return PARSERUTILS_INVALID; } /* output U+FFFD and continue processing. */ error = charset_ext8_codec_output_decoded_char(c, 0xFFFD, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += 1; *sourcelen -= 1; } return error; } return PARSERUTILS_OK; } /** * Output a UCS-4 character (big endian) * * \param c Codec to use * \param ucs4 UCS-4 character (host endian) * \param dest Pointer to pointer to output buffer * \param destlen Pointer to output buffer length * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, */ parserutils_error charset_ext8_codec_output_decoded_char(charset_ext8_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen) { if (*destlen < 4) { /* Run out of output buffer */ c->read_len = 1; c->read_buf[0] = ucs4; return PARSERUTILS_NOMEM; } *((uint32_t *) (void *) *dest) = endian_host_to_big(ucs4); *dest += 4; *destlen -= 4; return PARSERUTILS_OK; } /** * Convert a UCS4 (host endian) character to extended 8bit * * \param c The codec instance * \param ucs4 The UCS4 character to convert * \param s Pointer to pointer to destination buffer * \param len Pointer to destination buffer length * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if there's insufficient space in the output buffer, * PARSERUTILS_INVALID if the character cannot be represented * * _INVALID will only be returned if the codec's conversion mode is STRICT. * Otherwise, '?' will be output. * * On successful conversion, *s and *len will be updated. */ parserutils_error charset_ext8_from_ucs4(charset_ext8_codec *c, uint32_t ucs4, uint8_t **s, size_t *len) { uint8_t out = 0; if (*len < 1) return PARSERUTILS_NOMEM; if (ucs4 < 0x80) { /* ASCII */ out = ucs4; } else { uint32_t i; for (i = 0; i < 128; i++) { if (ucs4 == c->table[i]) break; } if (i == 128) { if (c->base.errormode == PARSERUTILS_CHARSET_CODEC_ERROR_STRICT) return PARSERUTILS_INVALID; else out = '?'; } else { out = 0x80 + i; } } *(*s) = out; (*s)++; (*len)--; return PARSERUTILS_OK; } /** * Convert an extended 8bit character to UCS4 (host endian) * * \param c The codec instance * \param s Pointer to source buffer * \param len Source buffer length * \param ucs4 Pointer to destination buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NEEDDATA if there's insufficient input data * PARSERUTILS_INVALID if the character cannot be represented */ parserutils_error charset_ext8_to_ucs4(charset_ext8_codec *c, const uint8_t *s, size_t len, uint32_t *ucs4) { uint32_t out; if (len < 1) return PARSERUTILS_NEEDDATA; if (*s < 0x80) { out = *s; } else { if (c->table[*s - 0x80] == 0xFFFF) return PARSERUTILS_INVALID; out = c->table[*s - 0x80]; } *ucs4 = out; return PARSERUTILS_OK; } const parserutils_charset_handler charset_ext8_codec_handler = { charset_ext8_codec_handles_charset, charset_ext8_codec_create }; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/src/charset/codecs/codec_utf8.c������������������������������������0000664�0001750�0001750�00000037316�11223172060�023420� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2007 John-Mark Bell */ #include #include #include #include "charset/codecs/codec_impl.h" #include "charset/encodings/utf8impl.h" #include "utils/endian.h" #include "utils/utils.h" /** * UTF-8 charset codec */ typedef struct charset_utf8_codec { parserutils_charset_codec base; /**< Base class */ #define INVAL_BUFSIZE (32) uint8_t inval_buf[INVAL_BUFSIZE]; /**< Buffer for fixing up * incomplete input * sequences */ size_t inval_len; /*< Byte length of inval_buf **/ #define READ_BUFSIZE (8) uint32_t read_buf[READ_BUFSIZE]; /**< Buffer for partial * output sequences (decode) * (host-endian) */ size_t read_len; /**< Character length of read_buf */ #define WRITE_BUFSIZE (8) uint32_t write_buf[WRITE_BUFSIZE]; /**< Buffer for partial * output sequences (encode) * (host-endian) */ size_t write_len; /**< Character length of write_buf */ } charset_utf8_codec; static bool charset_utf8_codec_handles_charset(const char *charset); static parserutils_error charset_utf8_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec); static parserutils_error charset_utf8_codec_destroy( parserutils_charset_codec *codec); static parserutils_error charset_utf8_codec_encode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_utf8_codec_decode( parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static parserutils_error charset_utf8_codec_reset( parserutils_charset_codec *codec); static inline parserutils_error charset_utf8_codec_read_char( charset_utf8_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen); static inline parserutils_error charset_utf8_codec_output_decoded_char( charset_utf8_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen); /** * Determine whether this codec handles a specific charset * * \param charset Charset to test * \return true if handleable, false otherwise */ bool charset_utf8_codec_handles_charset(const char *charset) { return parserutils_charset_mibenum_from_name(charset, strlen(charset)) == parserutils_charset_mibenum_from_name("UTF-8", SLEN("UTF-8")); } /** * Create a UTF-8 codec * * \param charset The charset to read from / write to * \param alloc Memory (de)allocation function * \param pw Pointer to client-specific private data (may be NULL) * \param codec Pointer to location to receive codec * \return PARSERUTILS_OK on success, * PARSERUTILS_BADPARM on bad parameters, * PARSERUTILS_NOMEM on memory exhausion */ parserutils_error charset_utf8_codec_create(const char *charset, parserutils_alloc alloc, void *pw, parserutils_charset_codec **codec) { charset_utf8_codec *c; UNUSED(charset); c = alloc(NULL, sizeof(charset_utf8_codec), pw); if (c == NULL) return PARSERUTILS_NOMEM; c->inval_buf[0] = '\0'; c->inval_len = 0; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; /* Finally, populate vtable */ c->base.handler.destroy = charset_utf8_codec_destroy; c->base.handler.encode = charset_utf8_codec_encode; c->base.handler.decode = charset_utf8_codec_decode; c->base.handler.reset = charset_utf8_codec_reset; *codec = (parserutils_charset_codec *) c; return PARSERUTILS_OK; } /** * Destroy a UTF-8 codec * * \param codec The codec to destroy * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_utf8_codec_destroy (parserutils_charset_codec *codec) { UNUSED(codec); return PARSERUTILS_OK; } /** * Encode a chunk of UCS-4 (big endian) data into UTF-8 * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read. Any remaining output for the character will be buffered by the * codec for writing on the next call. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_utf8_codec_encode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_utf8_codec *c = (charset_utf8_codec *) codec; uint32_t ucs4; uint32_t *towrite; size_t towritelen; parserutils_error error; /* Process any outstanding characters from the previous call */ if (c->write_len > 0) { uint32_t *pwrite = c->write_buf; while (c->write_len > 0) { UTF8_FROM_UCS4(pwrite[0], dest, destlen, error); if (error != PARSERUTILS_OK) { uint32_t len; if (error != PARSERUTILS_NOMEM) abort(); /* Insufficient output buffer space */ for (len = 0; len < c->write_len; len++) { c->write_buf[len] = pwrite[len]; } return PARSERUTILS_NOMEM; } pwrite++; c->write_len--; } } /* Now process the characters for this call */ while (*sourcelen > 0) { ucs4 = endian_big_to_host(*((uint32_t *) (void *) *source)); towrite = &ucs4; towritelen = 1; /* Output current characters */ while (towritelen > 0) { UTF8_FROM_UCS4(towrite[0], dest, destlen, error); if (error != PARSERUTILS_OK) { uint32_t len; if (error != PARSERUTILS_NOMEM) abort(); /* Insufficient output space */ if (towritelen >= WRITE_BUFSIZE) abort(); c->write_len = towritelen; /* Copy pending chars to save area, for * processing next call. */ for (len = 0; len < towritelen; len++) c->write_buf[len] = towrite[len]; /* Claim character we've just buffered, * so it's not reprocessed */ *source += 4; *sourcelen -= 4; return PARSERUTILS_NOMEM; } towrite++; towritelen--; } *source += 4; *sourcelen -= 4; } return PARSERUTILS_OK; } /** * Decode a chunk of UTF-8 data into UCS-4 (big endian) * * \param codec The codec to use * \param source Pointer to pointer to source data * \param sourcelen Pointer to length (in bytes) of source data * \param dest Pointer to pointer to output buffer * \param destlen Pointer to length (in bytes) of output buffer * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * Note that, if failure occurs whilst attempting to write any output * buffered by the last call, then ::source and ::sourcelen will remain * unchanged (as nothing more has been read). * * If STRICT error handling is configured and an illegal sequence is split * over two calls, then _INVALID will be returned from the second call, * but ::source will point mid-way through the invalid sequence (i.e. it * will be unmodified over the second call). In addition, the internal * incomplete-sequence buffer will be emptied, such that subsequent calls * will progress, rather than re-evaluating the same invalid sequence. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. * * Call this with a source length of 0 to flush the output buffer. */ parserutils_error charset_utf8_codec_decode(parserutils_charset_codec *codec, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { charset_utf8_codec *c = (charset_utf8_codec *) codec; parserutils_error error; if (c->read_len > 0) { /* Output left over from last decode */ uint32_t *pread = c->read_buf; while (c->read_len > 0 && *destlen >= c->read_len * 4) { *((uint32_t *) (void *) *dest) = endian_host_to_big(pread[0]); *dest += 4; *destlen -= 4; pread++; c->read_len--; } if (*destlen < c->read_len * 4) { /* Ran out of output buffer */ size_t i; /* Shuffle remaining output down */ for (i = 0; i < c->read_len; i++) c->read_buf[i] = pread[i]; return PARSERUTILS_NOMEM; } } if (c->inval_len > 0) { /* The last decode ended in an incomplete sequence. * Fill up inval_buf with data from the start of the * new chunk and process it. */ uint8_t *in = c->inval_buf; size_t ol = c->inval_len; size_t l = min(INVAL_BUFSIZE - ol - 1, *sourcelen); size_t orig_l = l; memcpy(c->inval_buf + ol, *source, l); l += c->inval_len; error = charset_utf8_codec_read_char(c, (const uint8_t **) &in, &l, dest, destlen); if (error != PARSERUTILS_OK && error != PARSERUTILS_NOMEM) { return error; } /* And now, fix up source pointers */ *source += max((signed) (orig_l - l), 0); *sourcelen -= max((signed) (orig_l - l), 0); /* Failed to resolve an incomplete character and * ran out of buffer space. No recovery strategy * possible, so explode everywhere. */ if ((orig_l + ol) - l == 0) abort(); /* Report memory exhaustion case from above */ if (error != PARSERUTILS_OK) return error; } /* Finally, the "normal" case; process all outstanding characters */ while (*sourcelen > 0) { error = charset_utf8_codec_read_char(c, source, sourcelen, dest, destlen); if (error != PARSERUTILS_OK) { return error; } } return PARSERUTILS_OK; } /** * Clear a UTF-8 codec's encoding state * * \param codec The codec to reset * \return PARSERUTILS_OK on success, appropriate error otherwise */ parserutils_error charset_utf8_codec_reset(parserutils_charset_codec *codec) { charset_utf8_codec *c = (charset_utf8_codec *) codec; c->inval_buf[0] = '\0'; c->inval_len = 0; c->read_buf[0] = 0; c->read_len = 0; c->write_buf[0] = 0; c->write_len = 0; return PARSERUTILS_OK; } /** * Read a character from the UTF-8 to UCS-4 (big endian) * * \param c The codec * \param source Pointer to pointer to source buffer (updated on exit) * \param sourcelen Pointer to length of source buffer (updated on exit) * \param dest Pointer to pointer to output buffer (updated on exit) * \param destlen Pointer to length of output buffer (updated on exit) * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, * PARSERUTILS_INVALID if a character cannot be represented and the * codec's error handling mode is set to STRICT, * * On exit, ::source will point immediately _after_ the last input character * read, if the result is _OK or _NOMEM. Any remaining output for the * character will be buffered by the codec for writing on the next call. * * In the case of the result being _INVALID, ::source will point _at_ the * last input character read; nothing will be written or buffered for the * failed character. It is up to the client to fix the cause of the failure * and retry the decoding process. * * ::sourcelen will be reduced appropriately on exit. * * ::dest will point immediately _after_ the last character written. * * ::destlen will be reduced appropriately on exit. */ parserutils_error charset_utf8_codec_read_char(charset_utf8_codec *c, const uint8_t **source, size_t *sourcelen, uint8_t **dest, size_t *destlen) { uint32_t ucs4; size_t sucs4; parserutils_error error; /* Convert a single character */ { const uint8_t *src = *source; size_t srclen = *sourcelen; uint32_t *uptr = &ucs4; size_t *usptr = &sucs4; UTF8_TO_UCS4(src, srclen, uptr, usptr, error); } if (error == PARSERUTILS_OK) { /* Read a character */ error = charset_utf8_codec_output_decoded_char(c, ucs4, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += sucs4; *sourcelen -= sucs4; } /* Clear inval buffer */ c->inval_buf[0] = '\0'; c->inval_len = 0; return error; } else if (error == PARSERUTILS_NEEDDATA) { /* Incomplete input sequence */ if (*sourcelen > INVAL_BUFSIZE) abort(); memmove(c->inval_buf, *source, *sourcelen); c->inval_buf[*sourcelen] = '\0'; c->inval_len = *sourcelen; *source += *sourcelen; *sourcelen = 0; return PARSERUTILS_OK; } else if (error == PARSERUTILS_INVALID) { /* Illegal input sequence */ uint32_t nextchar; /* Strict errormode; simply flag invalid character */ if (c->base.errormode == PARSERUTILS_CHARSET_CODEC_ERROR_STRICT) { /* Clear inval buffer */ c->inval_buf[0] = '\0'; c->inval_len = 0; return PARSERUTILS_INVALID; } /* Find next valid UTF-8 sequence. * We're processing client-provided data, so let's * be paranoid about its validity. */ { const uint8_t *src = *source; size_t srclen = *sourcelen; uint32_t off = 0; uint32_t *ncptr = &nextchar; UTF8_NEXT_PARANOID(src, srclen, off, ncptr, error); } if (error != PARSERUTILS_OK) { if (error == PARSERUTILS_NEEDDATA) { /* Need more data to be sure */ if (*sourcelen > INVAL_BUFSIZE) abort(); memmove(c->inval_buf, *source, *sourcelen); c->inval_buf[*sourcelen] = '\0'; c->inval_len = *sourcelen; *source += *sourcelen; *sourcelen = 0; nextchar = 0; } else { return error; } } /* Clear inval buffer */ c->inval_buf[0] = '\0'; c->inval_len = 0; /* output U+FFFD and continue processing. */ error = charset_utf8_codec_output_decoded_char(c, 0xFFFD, dest, destlen); if (error == PARSERUTILS_OK || error == PARSERUTILS_NOMEM) { /* output succeeded; update source pointers */ *source += nextchar; *sourcelen -= nextchar; } return error; } return PARSERUTILS_OK; } /** * Output a UCS-4 character (big endian) * * \param c Codec to use * \param ucs4 UCS-4 character (host endian) * \param dest Pointer to pointer to output buffer * \param destlen Pointer to output buffer length * \return PARSERUTILS_OK on success, * PARSERUTILS_NOMEM if output buffer is too small, */ parserutils_error charset_utf8_codec_output_decoded_char(charset_utf8_codec *c, uint32_t ucs4, uint8_t **dest, size_t *destlen) { if (*destlen < 4) { /* Run out of output buffer */ c->read_len = 1; c->read_buf[0] = ucs4; return PARSERUTILS_NOMEM; } *((uint32_t *) (void *) *dest) = endian_host_to_big(ucs4); *dest += 4; *destlen -= 4; return PARSERUTILS_OK; } const parserutils_charset_handler charset_utf8_codec_handler = { charset_utf8_codec_handles_charset, charset_utf8_codec_create }; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/README�������������������������������������������������������������0000664�0001750�0001750�00000005335�11554115215�016433� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������LibParserUtils -- a utility library for parser building ======================================================= Overview -------- LibParserUtils provides various pieces of functionality that are useful when writing parsers. These are: + A number of character set convertors + Mapping of character set names to/from MIB enum values + UTF-8 and UTF-16 (host endian) support functions + Various simple data structures (resizeable buffer, stack, vector) + A UTF-8 input stream Requirements ------------ LibParserUtils requires the following tools: + A C99 capable C compiler + GNU make or compatible + Perl (for the testcases) + Pkg-config (for the testcases) + doxygen (for the API documentation) For enhanced charset support, LibParserUtils requires an iconv() implementation. If you don't have an implementation of iconv(), this requirement may be disabled: see the "Disabling iconv() support" section, below. Compilation ----------- The exact type of build may be configured by passing parameters to make. Common usage is described below. For a static library: $ make For a shared library: $ make COMPONENT_TYPE=lib-shared For a static library with debug enabled: $ make BUILD=debug To cross-compile a static library: $ make TARGET= Verification ------------ The library's functionality may be verified, thus: $ make test If you wish to see test coverage statistics, run: $ make coverage Then open build/coverage/index.html in a web browser. In both cases, ensure that the same parameters to make are passed as when building the library. (Un)installation ---------------- To install the library: $ make install Ensure that the same parameters to make are passed as when building the library. To specify the installation prefix: $ make install PREFIX=/path/to/prefix To specify a staging directory for packaging: $ make install DESTDIR=/path/to/directory Items will be installed to $(DESTDIR)$(PREFIX)/ To uninstall: $ make uninstall API documentation ----------------- Use doxygen to auto-generate API documentation, thus: $ make docs Then open build/docs/html/index.html in a web browser. The test driver code in test/ may also provide some useful pointers. Disabling iconv() support ------------------------- Without iconv() support enabled, libparserutils only supports the following character sets: + UTF-16 (platform-native endian) + UTF-8 + ISO-8859-n + Windows-125n + US-ASCII To disable iconv() support in libparserutils, do the following: $ echo "CFLAGS += -DWITHOUT_ICONV_FILTER" \ >build/Makefile.config.override Then build libparserutils as normal. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/docs/��������������������������������������������������������������0000775�0001750�0001750�00000000000�11734430231�016473� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/docs/Todo����������������������������������������������������������0000664�0001750�0001750�00000000124�11060201556�017316� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Todo list --------- + Charset conversion should use Unicode Normalisation Form C. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/��������������������������������������������������������������0000775�0001750�0001750�00000000000�11734430231�016522� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/cscodec-ext8.c������������������������������������������������0000664�0001750�0001750�00000013741�11476512761�021201� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include #include #include "utils/utils.h" #include "testutils.h" typedef struct line_ctx { parserutils_charset_codec *codec; size_t buflen; size_t bufused; uint8_t *buf; size_t explen; size_t expused; uint8_t *exp; bool hadenc; bool indata; bool inexp; parserutils_error exp_ret; enum { ENCODE, DECODE, BOTH } dir; } line_ctx; static bool handle_line(const char *data, size_t datalen, void *pw); static void run_test(line_ctx *ctx); static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_charset_codec *codec; line_ctx ctx; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } assert(parserutils_charset_codec_create("NATS-SEFI-ADD", myrealloc, NULL, &codec) == PARSERUTILS_BADENCODING); ctx.buflen = parse_filesize(argv[1]); if (ctx.buflen == 0) return 1; ctx.buf = malloc(2 * ctx.buflen); if (ctx.buf == NULL) { printf("Failed allocating %u bytes\n", (unsigned int) ctx.buflen); return 1; } ctx.exp = ctx.buf + ctx.buflen; ctx.explen = ctx.buflen; ctx.buf[0] = '\0'; ctx.exp[0] = '\0'; ctx.bufused = 0; ctx.expused = 0; ctx.hadenc = false; ctx.indata = false; ctx.inexp = false; ctx.exp_ret = PARSERUTILS_OK; assert(parse_testfile(argv[1], handle_line, &ctx) == true); /* and run final test */ if (ctx.bufused > 0 && ctx.buf[ctx.bufused - 1] == '\n') ctx.bufused -= 1; if (ctx.expused > 0 && ctx.exp[ctx.expused - 1] == '\n') ctx.expused -= 1; run_test(&ctx); free(ctx.buf); parserutils_charset_codec_destroy(ctx.codec); printf("PASS\n"); return 0; } bool handle_line(const char *data, size_t datalen, void *pw) { line_ctx *ctx = (line_ctx *) pw; if (data[0] == '#') { if (ctx->inexp) { /* This marks end of testcase, so run it */ if (ctx->buf[ctx->bufused - 1] == '\n') ctx->bufused -= 1; if (ctx->exp[ctx->expused - 1] == '\n') ctx->expused -= 1; run_test(ctx); ctx->buf[0] = '\0'; ctx->exp[0] = '\0'; ctx->bufused = 0; ctx->expused = 0; ctx->exp_ret = PARSERUTILS_OK; } if (strncasecmp(data+1, "data", 4) == 0) { parserutils_charset_codec_optparams params; const char *ptr = data + 6; ctx->indata = true; ctx->inexp = false; if (strncasecmp(ptr, "decode", 6) == 0) ctx->dir = DECODE; else if (strncasecmp(ptr, "encode", 6) == 0) ctx->dir = ENCODE; else ctx->dir = BOTH; ptr += 7; if (strncasecmp(ptr, "LOOSE", 5) == 0) { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_LOOSE; ptr += 6; } else if (strncasecmp(ptr, "STRICT", 6) == 0) { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_STRICT; ptr += 7; } else { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_TRANSLIT; ptr += 9; } assert(parserutils_charset_codec_setopt(ctx->codec, PARSERUTILS_CHARSET_CODEC_ERROR_MODE, (parserutils_charset_codec_optparams *) ¶ms) == PARSERUTILS_OK); } else if (strncasecmp(data+1, "expected", 8) == 0) { ctx->indata = false; ctx->inexp = true; ctx->exp_ret = parserutils_error_from_string(data + 10, datalen - 10 - 1 /* \n */); } else if (strncasecmp(data+1, "reset", 5) == 0) { ctx->indata = false; ctx->inexp = false; parserutils_charset_codec_reset(ctx->codec); } else if (strncasecmp(data+1, "enc", 3) == 0) { const char *enc = data + 5; const char *end; char *enc_name; for (end = enc; !isspace(*end); end++) ; enc_name = alloca(end - enc + 1); memcpy(enc_name, enc, end - enc); enc_name[end - enc] = 0; assert(parserutils_charset_codec_create(enc_name, myrealloc, NULL, &ctx->codec) == PARSERUTILS_OK); ctx->hadenc = true; } } else { if (ctx->indata) { memcpy(ctx->buf + ctx->bufused, data, datalen); ctx->bufused += datalen; } if (ctx->inexp) { memcpy(ctx->exp + ctx->expused, data, datalen); ctx->expused += datalen; } } return true; } void run_test(line_ctx *ctx) { static int testnum; size_t destlen = ctx->bufused * 4; uint8_t *dest = alloca(destlen); uint8_t *pdest = dest; const uint8_t *psrc = ctx->buf; size_t srclen = ctx->bufused; size_t i; if (ctx->dir == DECODE) { assert(parserutils_charset_codec_decode(ctx->codec, &psrc, &srclen, &pdest, &destlen) == ctx->exp_ret); } else if (ctx->dir == ENCODE) { assert(parserutils_charset_codec_encode(ctx->codec, &psrc, &srclen, &pdest, &destlen) == ctx->exp_ret); } else { size_t templen = ctx->bufused * 4; uint8_t *temp = alloca(templen); uint8_t *ptemp = temp; const uint8_t *ptemp2; size_t templen2; assert(parserutils_charset_codec_decode(ctx->codec, &psrc, &srclen, &ptemp, &templen) == ctx->exp_ret); /* \todo currently there is no way to specify the number of consumed & produced data in case of a deliberate bad input data set. */ if (ctx->exp_ret == PARSERUTILS_OK) { assert(temp + (ctx->bufused * 4 - templen) == ptemp); } ptemp2 = temp; templen2 = ctx->bufused * 4 - templen; assert(parserutils_charset_codec_encode(ctx->codec, &ptemp2, &templen2, &pdest, &destlen) == ctx->exp_ret); if (ctx->exp_ret == PARSERUTILS_OK) { assert(templen2 == 0); assert(temp + (ctx->bufused * 4 - templen) == ptemp2); } } if (ctx->exp_ret == PARSERUTILS_OK) { assert(srclen == 0); assert(ctx->buf + ctx->bufused == psrc); assert(dest + (ctx->bufused * 4 - destlen) == pdest); assert(ctx->bufused * 4 - destlen == ctx->expused); } printf("%d: Read '", ++testnum); for (i = 0; i < ctx->expused; i++) { printf("%c%c ", "0123456789abcdef"[(dest[i] >> 4) & 0xf], "0123456789abcdef"[dest[i] & 0xf]); } printf("' Expected '"); for (i = 0; i < ctx->expused; i++) { printf("%c%c ", "0123456789abcdef"[(ctx->exp[i] >> 4) & 0xf], "0123456789abcdef"[ctx->exp[i] & 0xf]); } printf("'\n"); assert(pdest == dest + ctx->expused); assert(memcmp(dest, ctx->exp, ctx->expused) == 0); } �������������������������������netsurf-2.9/libparserutils-0.1.1/test/regression/���������������������������������������������������0000775�0001750�0001750�00000000000�11734430230�020701� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/regression/filter-badenc-segv.c�������������������������������0000664�0001750�0001750�00000001654�11554115215�024517� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include #include "input/filter.h" #include "testutils.h" static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_filter *input; parserutils_filter_optparams params; parserutils_error expected; #ifndef WITHOUT_ICONV_FILTER expected = PARSERUTILS_OK; #else expected = PARSERUTILS_BADENCODING; #endif UNUSED(argc); UNUSED(argv); assert(parserutils__filter_create("UTF-8", myrealloc, NULL, &input) == PARSERUTILS_OK); params.encoding.name = "GBK"; assert(parserutils__filter_setopt(input, PARSERUTILS_FILTER_SET_ENCODING, ¶ms) == expected); params.encoding.name = "GBK"; assert(parserutils__filter_setopt(input, PARSERUTILS_FILTER_SET_ENCODING, ¶ms) == expected); parserutils__filter_destroy(input); printf("PASS\n"); return 0; } ������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/regression/data/����������������������������������������������0000775�0001750�0001750�00000000000�11734430230�021612� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/regression/Makefile�������������������������������������������0000664�0001750�0001750�00000000312�11476457062�022354� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Tests DIR_TEST_ITEMS := filter-segv:filter-segv.c \ stream-nomem:stream-nomem.c filter-badenc-segv:filter-badenc-segv.c CFLAGS := $(CFLAGS) -I$(CURDIR)/test include build/makefiles/Makefile.subdir ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/regression/filter-segv.c��������������������������������������0000664�0001750�0001750�00000000751�11520016105�023271� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include #include "input/filter.h" #include "testutils.h" static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_filter *input; UNUSED(argc); UNUSED(argv); assert(parserutils__filter_create("UTF-8", myrealloc, NULL, &input) == PARSERUTILS_OK); parserutils__filter_destroy(input); printf("PASS\n"); return 0; } �����������������������netsurf-2.9/libparserutils-0.1.1/test/regression/stream-nomem.c�������������������������������������0000664�0001750�0001750�00000004212�11476512761�023465� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include #include #include "utils/utils.h" #include "testutils.h" static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_inputstream *stream; /* This is specially calculated so that the inputstream is forced to * reallocate (it assumes that the inputstream's buffer chunk size * is 4k) */ #define BUFFER_SIZE (4096 + 4) uint8_t input_buffer[BUFFER_SIZE]; // uint8_t *buffer; // size_t buflen; const uint8_t *c; size_t clen; UNUSED(argc); UNUSED(argv); /* Populate the buffer with something sane */ memset(input_buffer, 'a', BUFFER_SIZE); /* Now, set up our test data */ input_buffer[BUFFER_SIZE - 1] = '5'; input_buffer[BUFFER_SIZE - 2] = '4'; input_buffer[BUFFER_SIZE - 3] = '\xbd'; input_buffer[BUFFER_SIZE - 4] = '\xbf'; /* This byte will occupy the 4095th byte in the buffer and * thus cause the entirety of U+FFFD to be buffered until after * the buffer has been enlarged */ input_buffer[BUFFER_SIZE - 5] = '\xef'; input_buffer[BUFFER_SIZE - 6] = '3'; input_buffer[BUFFER_SIZE - 7] = '2'; input_buffer[BUFFER_SIZE - 8] = '1'; assert(parserutils_inputstream_create("UTF-8", 0, NULL, myrealloc, NULL, &stream) == PARSERUTILS_OK); assert(parserutils_inputstream_append(stream, input_buffer, BUFFER_SIZE) == PARSERUTILS_OK); assert(parserutils_inputstream_append(stream, NULL, 0) == PARSERUTILS_OK); while (parserutils_inputstream_peek(stream, 0, &c, &clen) != PARSERUTILS_EOF) parserutils_inputstream_advance(stream, clen); /* assert(css_inputstream_claim_buffer(stream, &buffer, &buflen) == CSS_OK); assert(buflen == BUFFER_SIZE); printf("Buffer: '%.*s'\n", 8, buffer + (BUFFER_SIZE - 8)); assert( buffer[BUFFER_SIZE - 6] == '3' && buffer[BUFFER_SIZE - 5] == (uint8_t) '\xef' && buffer[BUFFER_SIZE - 4] == (uint8_t) '\xbf' && buffer[BUFFER_SIZE - 3] == (uint8_t) '\xbd' && buffer[BUFFER_SIZE - 2] == '4'); free(buffer); */ parserutils_inputstream_destroy(stream); printf("PASS\n"); return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/regression/INDEX����������������������������������������������0000664�0001750�0001750�00000000312�11476457062�021506� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Index for testcases # # Test Description DataDir filter-segv Segfault in input filtering stream-nomem Inputstream buffer expansion filter-badenc-segv Segfault on resetting bad encoding in filter ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/inputstream.c�������������������������������������������������0000664�0001750�0001750�00000003657�11476512761�021270� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include #include #include #include "utils/utils.h" #include "testutils.h" #ifdef __riscos const char * const __dynamic_da_name = "InputStream"; int __dynamic_da_max_size = 128*1024*1024; #endif static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_inputstream *stream; FILE *fp; size_t len, origlen; #define CHUNK_SIZE (4096) uint8_t buf[CHUNK_SIZE]; const uint8_t *c; size_t clen; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } assert(parserutils_inputstream_create("UTF-8", 1, NULL, myrealloc, NULL, &stream) == PARSERUTILS_OK); fp = fopen(argv[1], "rb"); if (fp == NULL) { printf("Failed opening %s\n", argv[1]); return 1; } fseek(fp, 0, SEEK_END); origlen = len = ftell(fp); fseek(fp, 0, SEEK_SET); while (len >= CHUNK_SIZE) { size_t read = fread(buf, 1, CHUNK_SIZE, fp); assert(read == CHUNK_SIZE); assert(parserutils_inputstream_append(stream, buf, CHUNK_SIZE) == PARSERUTILS_OK); len -= CHUNK_SIZE; while (parserutils_inputstream_peek(stream, 0, &c, &clen) != PARSERUTILS_NEEDDATA) { parserutils_inputstream_advance(stream, clen); } } if (len > 0) { size_t read = fread(buf, 1, len, fp); assert(read == len); assert(parserutils_inputstream_append(stream, buf, len) == PARSERUTILS_OK); len = 0; } fclose(fp); assert(parserutils_inputstream_insert(stream, (const uint8_t *) "hello!!!", SLEN("hello!!!")) == PARSERUTILS_OK); assert(parserutils_inputstream_append(stream, NULL, 0) == PARSERUTILS_OK); while (parserutils_inputstream_peek(stream, 0, &c, &clen) != PARSERUTILS_EOF) { parserutils_inputstream_advance(stream, clen); } parserutils_inputstream_destroy(stream); printf("PASS\n"); return 0; } ���������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/README��������������������������������������������������������0000664�0001750�0001750�00000004523�11006370446�017411� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Libcharset testcases ==================== Testcases for Libcharset are self-contained binaries which test various parts of the charset library. These may make use of external data files to drive the testing. Testcase command lines ---------------------- Testcase command lines are in a unified format, thus: [ ] The aliases file parameter will always be specified (as it is required for the library to work at all). The data file parameter is optional and may be provided on a test-by-test basis. Testcase output --------------- Testcases may output anything at all to stdout. The final line of the output must begin with either PASS or FAIL (case sensitive), indicating the success status of the test. Test Index ---------- In the test sources directory, is a file, named INDEX, which provides an index of all available test binaries. Any new test applications should be added to this index as they are created. The test index file format is as follows: file = *line line = ( entry / comment / blank ) LF entry = testname 1*HTAB description [ 1*HTAB datadir ] comment = "#" *non-newline blank = 0 testname = 1*non-reserved description = 1*non-reserved datadir = 1*non-reserved non-newline = VCHAR / WSP non-reserved = VCHAR / SP Each entry contains a mandatory binary name and description followed by an optional data directory specifier. The data directory specifier is used to state the name of the directory containing data files for the test name. This directory will be searched for within the "data" directory in the source tree. If a data directory is specified, the test binary will be invoked for each data file listed within the data directory INDEX, passing the filename as the second parameter (, above). Data Index ---------- Each test data directory contains a file, named INDEX, which provides an index of all available test data files. The data index file format is as follows: file = *line line = ( entry / comment / blank ) LF entry = dataname 1*HTAB description comment = "#" *non-newline blank = 0 dataname = 1*non-reserved description = 1*non-reserved non-newline = VCHAR / WSP non-reserved = VCHAR / SP Each entry contains a mandatory data file name and description. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/cscodec-utf8.c������������������������������������������������0000664�0001750�0001750�00000013167�11476512761�021201� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include #include "utils/utils.h" #include "testutils.h" typedef struct line_ctx { parserutils_charset_codec *codec; size_t buflen; size_t bufused; uint8_t *buf; size_t explen; size_t expused; uint8_t *exp; bool indata; bool inexp; parserutils_error exp_ret; enum { ENCODE, DECODE, BOTH } dir; } line_ctx; static bool handle_line(const char *data, size_t datalen, void *pw); static void run_test(line_ctx *ctx); static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_charset_codec *codec; line_ctx ctx; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } assert(parserutils_charset_codec_create("NATS-SEFI-ADD", myrealloc, NULL, &codec) == PARSERUTILS_BADENCODING); assert(parserutils_charset_codec_create("UTF-8", myrealloc, NULL, &ctx.codec) == PARSERUTILS_OK); ctx.buflen = parse_filesize(argv[1]); if (ctx.buflen == 0) return 1; ctx.buf = malloc(2 * ctx.buflen); if (ctx.buf == NULL) { printf("Failed allocating %u bytes\n", (unsigned int) ctx.buflen); return 1; } ctx.exp = ctx.buf + ctx.buflen; ctx.explen = ctx.buflen; ctx.buf[0] = '\0'; ctx.exp[0] = '\0'; ctx.bufused = 0; ctx.expused = 0; ctx.indata = false; ctx.inexp = false; ctx.exp_ret = PARSERUTILS_OK; assert(parse_testfile(argv[1], handle_line, &ctx) == true); /* and run final test */ if (ctx.bufused > 0 && ctx.buf[ctx.bufused - 1] == '\n') ctx.bufused -= 1; if (ctx.expused > 0 && ctx.exp[ctx.expused - 1] == '\n') ctx.expused -= 1; run_test(&ctx); free(ctx.buf); parserutils_charset_codec_destroy(ctx.codec); printf("PASS\n"); return 0; } bool handle_line(const char *data, size_t datalen, void *pw) { line_ctx *ctx = (line_ctx *) pw; if (data[0] == '#') { if (ctx->inexp) { /* This marks end of testcase, so run it */ if (ctx->buf[ctx->bufused - 1] == '\n') ctx->bufused -= 1; if (ctx->exp[ctx->expused - 1] == '\n') ctx->expused -= 1; run_test(ctx); ctx->buf[0] = '\0'; ctx->exp[0] = '\0'; ctx->bufused = 0; ctx->expused = 0; ctx->exp_ret = PARSERUTILS_OK; } if (strncasecmp(data+1, "data", 4) == 0) { parserutils_charset_codec_optparams params; const char *ptr = data + 6; ctx->indata = true; ctx->inexp = false; if (strncasecmp(ptr, "decode", 6) == 0) ctx->dir = DECODE; else if (strncasecmp(ptr, "encode", 6) == 0) ctx->dir = ENCODE; else ctx->dir = BOTH; ptr += 7; if (strncasecmp(ptr, "LOOSE", 5) == 0) { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_LOOSE; ptr += 6; } else if (strncasecmp(ptr, "STRICT", 6) == 0) { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_STRICT; ptr += 7; } else { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_TRANSLIT; ptr += 9; } assert(parserutils_charset_codec_setopt(ctx->codec, PARSERUTILS_CHARSET_CODEC_ERROR_MODE, (parserutils_charset_codec_optparams *) ¶ms) == PARSERUTILS_OK); } else if (strncasecmp(data+1, "expected", 8) == 0) { ctx->indata = false; ctx->inexp = true; ctx->exp_ret = parserutils_error_from_string(data + 10, datalen - 10 - 1 /* \n */); } else if (strncasecmp(data+1, "reset", 5) == 0) { ctx->indata = false; ctx->inexp = false; parserutils_charset_codec_reset(ctx->codec); } } else { if (ctx->indata) { memcpy(ctx->buf + ctx->bufused, data, datalen); ctx->bufused += datalen; } if (ctx->inexp) { memcpy(ctx->exp + ctx->expused, data, datalen); ctx->expused += datalen; } } return true; } void run_test(line_ctx *ctx) { static int testnum; size_t destlen = ctx->bufused * 4; uint8_t *dest = alloca(destlen); uint8_t *pdest = dest; const uint8_t *psrc = ctx->buf; size_t srclen = ctx->bufused; size_t i; if (ctx->dir == DECODE) { assert(parserutils_charset_codec_decode(ctx->codec, &psrc, &srclen, &pdest, &destlen) == ctx->exp_ret); } else if (ctx->dir == ENCODE) { assert(parserutils_charset_codec_encode(ctx->codec, &psrc, &srclen, &pdest, &destlen) == ctx->exp_ret); } else { size_t templen = ctx->bufused * 4; uint8_t *temp = alloca(templen); uint8_t *ptemp = temp; const uint8_t *ptemp2; size_t templen2; assert(parserutils_charset_codec_decode(ctx->codec, &psrc, &srclen, &ptemp, &templen) == ctx->exp_ret); /* \todo currently there is no way to specify the number of consumed & produced data in case of a deliberate bad input data set. */ if (ctx->exp_ret == PARSERUTILS_OK) { assert(temp + (ctx->bufused * 4 - templen) == ptemp); } ptemp2 = temp; templen2 = ctx->bufused * 4 - templen; assert(parserutils_charset_codec_encode(ctx->codec, &ptemp2, &templen2, &pdest, &destlen) == ctx->exp_ret); if (ctx->exp_ret == PARSERUTILS_OK) { assert(templen2 == 0); assert(temp + (ctx->bufused * 4 - templen) == ptemp2); } } if (ctx->exp_ret == PARSERUTILS_OK) { assert(srclen == 0); assert(ctx->buf + ctx->bufused == psrc); assert(dest + (ctx->bufused * 4 - destlen) == pdest); assert(ctx->bufused * 4 - destlen == ctx->expused); } printf("%d: Read '", ++testnum); for (i = 0; i < ctx->expused; i++) { printf("%c%c ", "0123456789abcdef"[(dest[i] >> 4) & 0xf], "0123456789abcdef"[dest[i] & 0xf]); } printf("' Expected '"); for (i = 0; i < ctx->expused; i++) { printf("%c%c ", "0123456789abcdef"[(ctx->exp[i] >> 4) & 0xf], "0123456789abcdef"[ctx->exp[i] & 0xf]); } printf("'\n"); assert(pdest == dest + ctx->expused); assert(memcmp(dest, ctx->exp, ctx->expused) == 0); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/���������������������������������������������������������0000775�0001750�0001750�00000000000�11734430230�017432� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-utf8/��������������������������������������������0000775�0001750�0001750�00000000000�11734430230�021721� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-utf8/simple.dat����������������������������������0000664�0001750�0001750�00000002125�11006370446�023710� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#data decode LOOSE he llo!! #expected CHARSET_OK ���h���e������l���l���o���!���! #reset #data decode STRICT he llo!! #expected CHARSET_OK ���h���e������l���l���o���!���! #reset #data decode TRANSLIT he llo!! #expected CHARSET_OK ���h���e������l���l���o���!���! #reset #data decode LOOSE he llo!! #expected CHARSET_OK ���h���e������l���l���o���!���! #reset #data decode STRICT he llo!! #expected CHARSET_OK ���h���e������l���l���o���!���! #reset #data decode TRANSLIT he llo!! #expected CHARSET_OK ���h���e������l���l���o���!���! #reset #data encode LOOSE ���h���e������l���l���o���!���! #expected CHARSET_OK he llo!! #reset #data encode STRICT ���h���e������l���l���o���!���! #expected CHARSET_OK he llo!! #reset #data encode TRANSLIT ���h���e������l���l���o���!���! #expected CHARSET_OK he llo!! #reset #data encode LOOSE ���h���e������l���l���o���!���! #expected CHARSET_OK he llo!! #reset #data encode STRICT ���h���e������l���l���o���!���! #expected CHARSET_OK he llo!! #reset #data encode TRANSLIT ���h���e������l���l���o���!���! #expected CHARSET_OK he llo!! #reset �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-utf8/UTF-8-test.txt������������������������������0000664�0001750�0001750�00000120065�11006370446�024252� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#data recode LOOSE UTF-8 decoder capability and stress test ---------------------------------------- Markus Kuhn - 2003-02-19 This test file can help you examine, how your UTF-8 decoder handles various types of correct, malformed, or otherwise interesting UTF-8 sequences. This file is not meant to be a conformance test. It does not prescribes any particular outcome and therefore there is no way to "pass" or "fail" this test file, even though the texts suggests a preferable decoder behaviour at some places. The aim is instead to help you think about and test the behaviour of your UTF-8 on a systematic collection of unusual inputs. Experience so far suggests that most first-time authors of UTF-8 decoders find at least one serious problem in their decoder by using this file. The test lines below cover boundary conditions, malformed UTF-8 sequences as well as correctly encoded UTF-8 sequences of Unicode code points that should never occur in a correct UTF-8 file. According to ISO 10646-1:2000, sections D.7 and 2.3c, a device receiving UTF-8 shall interpret a "malformed sequence in the same way that it interprets a character that is outside the adopted subset" and "characters that are not within the adopted subset shall be indicated to the user" by a receiving device. A quite commonly used approach in UTF-8 decoders is to replace any malformed UTF-8 sequence by a replacement character (U+FFFD), which looks a bit like an inverted question mark, or a similar symbol. It might be a good idea to visually distinguish a malformed UTF-8 sequence from a correctly encoded Unicode character that is just not available in the current font but otherwise fully legal, even though ISO 10646-1 doesn't mandate this. In any case, just ignoring malformed sequences or unavailable characters does not conform to ISO 10646, will make debugging more difficult, and can lead to user confusion. Please check, whether a malformed UTF-8 sequence is (1) represented at all, (2) represented by exactly one single replacement character (or equivalent signal), and (3) the following quotation mark after an illegal UTF-8 sequence is correctly displayed, i.e. proper resynchronization takes place immageately after any malformed sequence. This file says "THE END" in the last line, so if you don't see that, your decoder crashed somehow before, which should always be cause for concern. All lines in this file are exactly 79 characters long (plus the line feed). In addition, all lines end with "|", except for the two test lines 2.1.1 and 2.2.1, which contain non-printable ASCII controls U+0000 and U+007F. If you display this file with a fixed-width font, these "|" characters should all line up in column 79 (right margin). This allows you to test quickly, whether your UTF-8 decoder finds the correct number of characters in every line, that is whether each malformed sequences is replaced by a single replacement character. Note that as an alternative to the notion of malformed sequence used here, it is also a perfectly acceptable (and in some situations even preferable) solution to represent each individual byte of a malformed sequence by a replacement character. If you follow this strategy in your decoder, then please ignore the "|" column. Here come the tests: | | 1 Some correct UTF-8 text | | You should see the Greek word 'kosme': "κόσμε" | | 2 Boundary condition test cases | | 2.1 First possible sequence of a certain length | | 2.1.1 1 byte (U-00000000): "�" 2.1.2 2 bytes (U-00000080): "€" | 2.1.3 3 bytes (U-00000800): "ࠀ" | 2.1.4 4 bytes (U-00010000): "𐀀" | 2.1.5 5 bytes (U-00200000): "" | 2.1.6 6 bytes (U-04000000): "" | | 2.2 Last possible sequence of a certain length | | 2.2.1 1 byte (U-0000007F): "" 2.2.2 2 bytes (U-000007FF): "߿" | 2.2.3 3 bytes (U-0000FFFF): "￿" | 2.2.4 4 bytes (U-001FFFFF): "" | 2.2.5 5 bytes (U-03FFFFFF): "" | 2.2.6 6 bytes (U-7FFFFFFF): "" | | 2.3 Other boundary conditions | | 2.3.1 U-0000D7FF = ed 9f bf = "퟿" | 2.3.2 U-0000E000 = ee 80 80 = "" | 2.3.3 U-0000FFFD = ef bf bd = "�" | 2.3.4 U-0010FFFF = f4 8f bf bf = "􏿿" | 2.3.5 U-00110000 = f4 90 80 80 = "" | | 3 Malformed sequences | | 3.1 Unexpected continuation bytes | | Each unexpected continuation byte should be separately signalled as a | malformed sequence of its own. | | 3.1.1 First continuation byte 0x80: "" | 3.1.2 Last continuation byte 0xbf: "" | | 3.1.3 2 continuation bytes: "" | 3.1.4 3 continuation bytes: "" | 3.1.5 4 continuation bytes: "" | 3.1.6 5 continuation bytes: "" | 3.1.7 6 continuation bytes: "" | 3.1.8 7 continuation bytes: "" | | 3.1.9 Sequence of all 64 possible continuation bytes (0x80-0xbf): | | " | | | " | | 3.2 Lonely start characters | | 3.2.1 All 32 first bytes of 2-byte sequences (0xc0-0xdf), | each followed by a space character: | | " | " | | 3.2.2 All 16 first bytes of 3-byte sequences (0xe0-0xef), | each followed by a space character: | | " " | | 3.2.3 All 8 first bytes of 4-byte sequences (0xf0-0xf7), | each followed by a space character: | | " " | | 3.2.4 All 4 first bytes of 5-byte sequences (0xf8-0xfb), | each followed by a space character: | | " " | | 3.2.5 All 2 first bytes of 6-byte sequences (0xfc-0xfd), | each followed by a space character: | | " " | | 3.3 Sequences with last continuation byte missing | | All bytes of an incomplete sequence should be signalled as a single | malformed sequence, i.e., you should see only a single replacement | character in each of the next 10 tests. (Characters as in section 2) | | 3.3.1 2-byte sequence with last byte missing (U+0000): "" | 3.3.2 3-byte sequence with last byte missing (U+0000): "" | 3.3.3 4-byte sequence with last byte missing (U+0000): "" | 3.3.4 5-byte sequence with last byte missing (U+0000): "" | 3.3.5 6-byte sequence with last byte missing (U+0000): "" | 3.3.6 2-byte sequence with last byte missing (U-000007FF): "" | 3.3.7 3-byte sequence with last byte missing (U-0000FFFF): "" | 3.3.8 4-byte sequence with last byte missing (U-001FFFFF): "" | 3.3.9 5-byte sequence with last byte missing (U-03FFFFFF): "" | 3.3.10 6-byte sequence with last byte missing (U-7FFFFFFF): "" | | 3.4 Concatenation of incomplete sequences | | All the 10 sequences of 3.3 concatenated, you should see 10 malformed | sequences being signalled: | | "" | | 3.5 Impossible bytes | | The following two bytes cannot appear in a correct UTF-8 string | | 3.5.1 fe = "" | 3.5.2 ff = "" | 3.5.3 fe fe ff ff = "" | | 4 Overlong sequences | | The following sequences are not malformed according to the letter of | the Unicode 2.0 standard. However, they are longer then necessary and | a correct UTF-8 encoder is not allowed to produce them. A "safe UTF-8 | decoder" should reject them just like malformed sequences for two | reasons: (1) It helps to debug applications if overlong sequences are | not treated as valid representations of characters, because this helps | to spot problems more quickly. (2) Overlong sequences provide | alternative representations of characters, that could maliciously be | used to bypass filters that check only for ASCII characters. For | instance, a 2-byte encoded line feed (LF) would not be caught by a | line counter that counts only 0x0a bytes, but it would still be | processed as a line feed by an unsafe UTF-8 decoder later in the | pipeline. From a security point of view, ASCII compatibility of UTF-8 | sequences means also, that ASCII characters are *only* allowed to be | represented by ASCII bytes in the range 0x00-0x7f. To ensure this | aspect of ASCII compatibility, use only "safe UTF-8 decoders" that | reject overlong UTF-8 sequences for which a shorter encoding exists. | | 4.1 Examples of an overlong ASCII character | | With a safe UTF-8 decoder, all of the following five overlong | representations of the ASCII character slash ("/") should be rejected | like a malformed UTF-8 sequence, for instance by substituting it with | a replacement character. If you see a slash below, you do not have a | safe UTF-8 decoder! | | 4.1.1 U+002F = c0 af = "" | 4.1.2 U+002F = e0 80 af = "" | 4.1.3 U+002F = f0 80 80 af = "" | 4.1.4 U+002F = f8 80 80 80 af = "" | 4.1.5 U+002F = fc 80 80 80 80 af = "" | | 4.2 Maximum overlong sequences | | Below you see the highest Unicode value that is still resulting in an | overlong sequence if represented with the given number of bytes. This | is a boundary test for safe UTF-8 decoders. All five characters should | be rejected like malformed UTF-8 sequences. | | 4.2.1 U-0000007F = c1 bf = "" | 4.2.2 U-000007FF = e0 9f bf = "" | 4.2.3 U-0000FFFF = f0 8f bf bf = "" | 4.2.4 U-001FFFFF = f8 87 bf bf bf = "" | 4.2.5 U-03FFFFFF = fc 83 bf bf bf bf = "" | | 4.3 Overlong representation of the NUL character | | The following five sequences should also be rejected like malformed | UTF-8 sequences and should not be treated like the ASCII NUL | character. | | 4.3.1 U+0000 = c0 80 = "" | 4.3.2 U+0000 = e0 80 80 = "" | 4.3.3 U+0000 = f0 80 80 80 = "" | 4.3.4 U+0000 = f8 80 80 80 80 = "" | 4.3.5 U+0000 = fc 80 80 80 80 80 = "" | | 5 Illegal code positions | | The following UTF-8 sequences should be rejected like malformed | sequences, because they never represent valid ISO 10646 characters and | a UTF-8 decoder that accepts them might introduce security problems | comparable to overlong UTF-8 sequences. | | 5.1 Single UTF-16 surrogates | | 5.1.1 U+D800 = ed a0 80 = "" | 5.1.2 U+DB7F = ed ad bf = "" | 5.1.3 U+DB80 = ed ae 80 = "" | 5.1.4 U+DBFF = ed af bf = "" | 5.1.5 U+DC00 = ed b0 80 = "" | 5.1.6 U+DF80 = ed be 80 = "" | 5.1.7 U+DFFF = ed bf bf = "" | | 5.2 Paired UTF-16 surrogates | | 5.2.1 U+D800 U+DC00 = ed a0 80 ed b0 80 = "" | 5.2.2 U+D800 U+DFFF = ed a0 80 ed bf bf = "" | 5.2.3 U+DB7F U+DC00 = ed ad bf ed b0 80 = "" | 5.2.4 U+DB7F U+DFFF = ed ad bf ed bf bf = "" | 5.2.5 U+DB80 U+DC00 = ed ae 80 ed b0 80 = "" | 5.2.6 U+DB80 U+DFFF = ed ae 80 ed bf bf = "" | 5.2.7 U+DBFF U+DC00 = ed af bf ed b0 80 = "" | 5.2.8 U+DBFF U+DFFF = ed af bf ed bf bf = "" | | 5.3 Other illegal code positions | | 5.3.1 U+FFFE = ef bf be = "￾" | 5.3.2 U+FFFF = ef bf bf = "￿" | | THE END | #expected CHARSET_OK UTF-8 decoder capability and stress test ---------------------------------------- Markus Kuhn - 2003-02-19 This test file can help you examine, how your UTF-8 decoder handles various types of correct, malformed, or otherwise interesting UTF-8 sequences. This file is not meant to be a conformance test. It does not prescribes any particular outcome and therefore there is no way to "pass" or "fail" this test file, even though the texts suggests a preferable decoder behaviour at some places. The aim is instead to help you think about and test the behaviour of your UTF-8 on a systematic collection of unusual inputs. Experience so far suggests that most first-time authors of UTF-8 decoders find at least one serious problem in their decoder by using this file. The test lines below cover boundary conditions, malformed UTF-8 sequences as well as correctly encoded UTF-8 sequences of Unicode code points that should never occur in a correct UTF-8 file. According to ISO 10646-1:2000, sections D.7 and 2.3c, a device receiving UTF-8 shall interpret a "malformed sequence in the same way that it interprets a character that is outside the adopted subset" and "characters that are not within the adopted subset shall be indicated to the user" by a receiving device. A quite commonly used approach in UTF-8 decoders is to replace any malformed UTF-8 sequence by a replacement character (U+FFFD), which looks a bit like an inverted question mark, or a similar symbol. It might be a good idea to visually distinguish a malformed UTF-8 sequence from a correctly encoded Unicode character that is just not available in the current font but otherwise fully legal, even though ISO 10646-1 doesn't mandate this. In any case, just ignoring malformed sequences or unavailable characters does not conform to ISO 10646, will make debugging more difficult, and can lead to user confusion. Please check, whether a malformed UTF-8 sequence is (1) represented at all, (2) represented by exactly one single replacement character (or equivalent signal), and (3) the following quotation mark after an illegal UTF-8 sequence is correctly displayed, i.e. proper resynchronization takes place immageately after any malformed sequence. This file says "THE END" in the last line, so if you don't see that, your decoder crashed somehow before, which should always be cause for concern. All lines in this file are exactly 79 characters long (plus the line feed). In addition, all lines end with "|", except for the two test lines 2.1.1 and 2.2.1, which contain non-printable ASCII controls U+0000 and U+007F. If you display this file with a fixed-width font, these "|" characters should all line up in column 79 (right margin). This allows you to test quickly, whether your UTF-8 decoder finds the correct number of characters in every line, that is whether each malformed sequences is replaced by a single replacement character. Note that as an alternative to the notion of malformed sequence used here, it is also a perfectly acceptable (and in some situations even preferable) solution to represent each individual byte of a malformed sequence by a replacement character. If you follow this strategy in your decoder, then please ignore the "|" column. Here come the tests: | | 1 Some correct UTF-8 text | | You should see the Greek word 'kosme': "κόσμε" | | 2 Boundary condition test cases | | 2.1 First possible sequence of a certain length | | 2.1.1 1 byte (U-00000000): "�" 2.1.2 2 bytes (U-00000080): "€" | 2.1.3 3 bytes (U-00000800): "ࠀ" | 2.1.4 4 bytes (U-00010000): "𐀀" | 2.1.5 5 bytes (U-00200000): "" | 2.1.6 6 bytes (U-04000000): "" | | 2.2 Last possible sequence of a certain length | | 2.2.1 1 byte (U-0000007F): "" 2.2.2 2 bytes (U-000007FF): "߿" | 2.2.3 3 bytes (U-0000FFFF): "�" | 2.2.4 4 bytes (U-001FFFFF): "" | 2.2.5 5 bytes (U-03FFFFFF): "" | 2.2.6 6 bytes (U-7FFFFFFF): "" | | 2.3 Other boundary conditions | | 2.3.1 U-0000D7FF = ed 9f bf = "퟿" | 2.3.2 U-0000E000 = ee 80 80 = "" | 2.3.3 U-0000FFFD = ef bf bd = "�" | 2.3.4 U-0010FFFF = f4 8f bf bf = "􏿿" | 2.3.5 U-00110000 = f4 90 80 80 = "" | | 3 Malformed sequences | | 3.1 Unexpected continuation bytes | | Each unexpected continuation byte should be separately signalled as a | malformed sequence of its own. | | 3.1.1 First continuation byte 0x80: "�" | 3.1.2 Last continuation byte 0xbf: "�" | | 3.1.3 2 continuation bytes: "��" | 3.1.4 3 continuation bytes: "���" | 3.1.5 4 continuation bytes: "����" | 3.1.6 5 continuation bytes: "�����" | 3.1.7 6 continuation bytes: "������" | 3.1.8 7 continuation bytes: "�������" | | 3.1.9 Sequence of all 64 possible continuation bytes (0x80-0xbf): | | "���������������� | ���������������� | ���������������� | ����������������" | | 3.2 Lonely start characters | | 3.2.1 All 32 first bytes of 2-byte sequences (0xc0-0xdf), | each followed by a space character: | | "� � � � � � � � � � � � � � � � | � � � � � � � � � � � � � � � � " | | 3.2.2 All 16 first bytes of 3-byte sequences (0xe0-0xef), | each followed by a space character: | | "� � � � � � � � � � � � � � � � " | | 3.2.3 All 8 first bytes of 4-byte sequences (0xf0-0xf7), | each followed by a space character: | | "� � � � � � � � " | | 3.2.4 All 4 first bytes of 5-byte sequences (0xf8-0xfb), | each followed by a space character: | | "� � � � " | | 3.2.5 All 2 first bytes of 6-byte sequences (0xfc-0xfd), | each followed by a space character: | | "� � " | | 3.3 Sequences with last continuation byte missing | | All bytes of an incomplete sequence should be signalled as a single | malformed sequence, i.e., you should see only a single replacement | character in each of the next 10 tests. (Characters as in section 2) | | 3.3.1 2-byte sequence with last byte missing (U+0000): "�" | 3.3.2 3-byte sequence with last byte missing (U+0000): "�" | 3.3.3 4-byte sequence with last byte missing (U+0000): "�" | 3.3.4 5-byte sequence with last byte missing (U+0000): "�" | 3.3.5 6-byte sequence with last byte missing (U+0000): "�" | 3.3.6 2-byte sequence with last byte missing (U-000007FF): "�" | 3.3.7 3-byte sequence with last byte missing (U-0000FFFF): "�" | 3.3.8 4-byte sequence with last byte missing (U-001FFFFF): "�" | 3.3.9 5-byte sequence with last byte missing (U-03FFFFFF): "�" | 3.3.10 6-byte sequence with last byte missing (U-7FFFFFFF): "�" | | 3.4 Concatenation of incomplete sequences | | All the 10 sequences of 3.3 concatenated, you should see 10 malformed | sequences being signalled: | | "����������" | | 3.5 Impossible bytes | | The following two bytes cannot appear in a correct UTF-8 string | | 3.5.1 fe = "�" | 3.5.2 ff = "�" | 3.5.3 fe fe ff ff = "����" | | 4 Overlong sequences | | The following sequences are not malformed according to the letter of | the Unicode 2.0 standard. However, they are longer then necessary and | a correct UTF-8 encoder is not allowed to produce them. A "safe UTF-8 | decoder" should reject them just like malformed sequences for two | reasons: (1) It helps to debug applications if overlong sequences are | not treated as valid representations of characters, because this helps | to spot problems more quickly. (2) Overlong sequences provide | alternative representations of characters, that could maliciously be | used to bypass filters that check only for ASCII characters. For | instance, a 2-byte encoded line feed (LF) would not be caught by a | line counter that counts only 0x0a bytes, but it would still be | processed as a line feed by an unsafe UTF-8 decoder later in the | pipeline. From a security point of view, ASCII compatibility of UTF-8 | sequences means also, that ASCII characters are *only* allowed to be | represented by ASCII bytes in the range 0x00-0x7f. To ensure this | aspect of ASCII compatibility, use only "safe UTF-8 decoders" that | reject overlong UTF-8 sequences for which a shorter encoding exists. | | 4.1 Examples of an overlong ASCII character | | With a safe UTF-8 decoder, all of the following five overlong | representations of the ASCII character slash ("/") should be rejected | like a malformed UTF-8 sequence, for instance by substituting it with | a replacement character. If you see a slash below, you do not have a | safe UTF-8 decoder! | | 4.1.1 U+002F = c0 af = "�" | 4.1.2 U+002F = e0 80 af = "�" | 4.1.3 U+002F = f0 80 80 af = "�" | 4.1.4 U+002F = f8 80 80 80 af = "�" | 4.1.5 U+002F = fc 80 80 80 80 af = "�" | | 4.2 Maximum overlong sequences | | Below you see the highest Unicode value that is still resulting in an | overlong sequence if represented with the given number of bytes. This | is a boundary test for safe UTF-8 decoders. All five characters should | be rejected like malformed UTF-8 sequences. | | 4.2.1 U-0000007F = c1 bf = "�" | 4.2.2 U-000007FF = e0 9f bf = "�" | 4.2.3 U-0000FFFF = f0 8f bf bf = "�" | 4.2.4 U-001FFFFF = f8 87 bf bf bf = "�" | 4.2.5 U-03FFFFFF = fc 83 bf bf bf bf = "�" | | 4.3 Overlong representation of the NUL character | | The following five sequences should also be rejected like malformed | UTF-8 sequences and should not be treated like the ASCII NUL | character. | | 4.3.1 U+0000 = c0 80 = "�" | 4.3.2 U+0000 = e0 80 80 = "�" | 4.3.3 U+0000 = f0 80 80 80 = "�" | 4.3.4 U+0000 = f8 80 80 80 80 = "�" | 4.3.5 U+0000 = fc 80 80 80 80 80 = "�" | | 5 Illegal code positions | | The following UTF-8 sequences should be rejected like malformed | sequences, because they never represent valid ISO 10646 characters and | a UTF-8 decoder that accepts them might introduce security problems | comparable to overlong UTF-8 sequences. | | 5.1 Single UTF-16 surrogates | | 5.1.1 U+D800 = ed a0 80 = "�" | 5.1.2 U+DB7F = ed ad bf = "�" | 5.1.3 U+DB80 = ed ae 80 = "�" | 5.1.4 U+DBFF = ed af bf = "�" | 5.1.5 U+DC00 = ed b0 80 = "�" | 5.1.6 U+DF80 = ed be 80 = "�" | 5.1.7 U+DFFF = ed bf bf = "�" | | 5.2 Paired UTF-16 surrogates | | 5.2.1 U+D800 U+DC00 = ed a0 80 ed b0 80 = "��" | 5.2.2 U+D800 U+DFFF = ed a0 80 ed bf bf = "��" | 5.2.3 U+DB7F U+DC00 = ed ad bf ed b0 80 = "��" | 5.2.4 U+DB7F U+DFFF = ed ad bf ed bf bf = "��" | 5.2.5 U+DB80 U+DC00 = ed ae 80 ed b0 80 = "��" | 5.2.6 U+DB80 U+DFFF = ed ae 80 ed bf bf = "��" | 5.2.7 U+DBFF U+DC00 = ed af bf ed b0 80 = "��" | 5.2.8 U+DBFF U+DFFF = ed af bf ed bf bf = "��" | | 5.3 Other illegal code positions | | 5.3.1 U+FFFE = ef bf be = "�" | 5.3.2 U+FFFF = ef bf bf = "�" | | THE END | #reset ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-utf8/INDEX���������������������������������������0000664�0001750�0001750�00000000256�11006370446�022522� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Index file for charset codec tests # # Test Description simple.dat Simple tests, designed to validate testdriver UTF-8-test.txt Markus Kuhn's UTF-8 decoding test file ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/��������������������������������������������0000775�0001750�0001750�00000000000�11734430231�021451� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/16.dat��������������������������������������0000664�0001750�0001750�00000004453�11060207421�022372� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-16 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~���������A�� �� ��`�����a����������y�����z��{�������� ��B��}�� ��������~�� �������R��S��x��|��������������������������������������������������C�����������P�����Z��p���������������������������������������������������������������������D�����������Q�����[��q������������������� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~���������A�� �� ��`�����a����������y�����z��{�������� ��B��}�� ��������~�� �������R��S��x��|��������������������������������������������������C�����������P�����Z��p���������������������������������������������������������������������D�����������Q�����[��q������������������� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/15.dat��������������������������������������0000664�0001750�0001750�00000004453�11060207421�022371� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-15 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�������������� �����`�����a�����������������������������������}�����������~�����������R��S��x��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�������������� �����`�����a�����������������������������������}�����������~�����������R��S��x��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/5.dat���������������������������������������0000664�0001750�0001750�00000004452�11060207421�022307� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-5 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~��������������������� �� �� �� ����������������������������������������� ��!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6��7��8��9��:��;��<��=��>��?��@��A��B��C��D��E��F��G��H��I��J��K��L��M��N��O��!��Q��R��S��T��U��V��W��X��Y��Z��[��\�����^��_ #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~��������������������� �� �� �� ����������������������������������������� ��!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6��7��8��9��:��;��<��=��>��?��@��A��B��C��D��E��F��G��H��I��J��K��L��M��N��O��!��Q��R��S��T��U��V��W��X��Y��Z��[��\�����^��_ #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/2.dat���������������������������������������0000664�0001750�0001750�00000004452�11060207421�022304� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-2 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~���������A�����=��Z��������`��^��d��y�����}��{���������B�����>��[�������a��_��e��z����~��|��T�������������9������� ����������������������C��G��������P��������X��n�����p��������b�����U�������������:������� ����������������������D��H��������Q��������Y��o�����q��������c�� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~���������A�����=��Z��������`��^��d��y�����}��{���������B�����>��[�������a��_��e��z����~��|��T�������������9������� ����������������������C��G��������P��������X��n�����p��������b�����U�������������:������� ����������������������D��H��������Q��������Y��o�����q��������c�� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/3.dat���������������������������������������0000664�0001750�0001750�00000004332�11060207421�022302� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-3 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�����&����������$��������0��^����4�����{�����'��������������%��������1��_����5��|�������������� ������������������������������������������� ����������������������l��\����������������� �� �����������������������������������������!����������������������m��]�� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�����&����������$��������0��^����4�����{�����'��������������%��������1��_����5��|�������������� ������������������������������������������� ����������������������l��\����������������� �� �����������������������������������������!����������������������m��]�� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/8.dat���������������������������������������0000664�0001750�0001750�00000003702�11060207421�022307� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-8 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�������������������������������������������������������������������������������������������� �������������������������������������������������������� ��  #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�������������������������������������������������������������������������������������������� �������������������������������������������������������� ��  #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ��������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/9.dat���������������������������������������0000664�0001750�0001750�00000004452�11060207421�022313� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-9 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0��^�������������������������������������������������������������������������������������������1��_��� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0��^�������������������������������������������������������������������������������������������1��_��� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/7.dat���������������������������������������0000664�0001750�0001750�00000004414�11060207421�022307� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-7 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~����� �� ����� �� ��������������z����������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~����� �� ����� �� ��������������z����������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/13.dat��������������������������������������0000664�0001750�0001750�00000004453�11060207421�022367� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-13 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~����� ����������� ��������������V����������������������������� �����������������W�������������������.����������������� �����y����"��6��*��;��`��C��E�����L�����������r��A��Z��j�����{��}�������/���������������� �����z����#��7��+��<��a��D��F�����M�����������s��B��[��k�����|��~��  #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~����� ����������� ��������������V����������������������������� �����������������W�������������������.����������������� �����y����"��6��*��;��`��C��E�����L�����������r��A��Z��j�����{��}�������/���������������� �����z����#��7��+��<��a��D��F�����M�����������s��B��[��k�����|��~��  #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/6.dat���������������������������������������0000664�0001750�0001750�00000003550�11060207421�022306� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-6 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�������� ���������!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6��7��8��9��:��@��A��B��C��D��E��F��G��H��I��J��K��L��M��N��O��P��Q��R #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�������� ���������!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6��7��8��9��:��@��A��B��C��D��E��F��G��H��I��J��K��L��M��N��O��P��Q��R #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ��������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/INDEX���������������������������������������0000664�0001750�0001750�00000000546�11060207421�022243� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Index file for charset codec tests # # Test Description 1.dat ISO-8859-1 2.dat ISO-8859-2 3.dat ISO-8859-3 4.dat ISO-8859-4 5.dat ISO-8859-5 6.dat ISO-8859-6 7.dat ISO-8859-7 8.dat ISO-8859-8 9.dat ISO-8859-9 10.dat ISO-8859-10 11.dat ISO-8859-11 13.dat ISO-8859-13 14.dat ISO-8859-14 15.dat ISO-8859-15 16.dat ISO-8859-16 ����������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/4.dat���������������������������������������0000664�0001750�0001750�00000004452�11060207421�022306� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-4 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�������8��V�����(��;��������`����"��f�����}������������W�����)��<�������a����#��g��J��~��K�����������������������.�� ������������������*����E��L��6�����������������r�����������h��j�������������������������/�� ������������������+����F��M��7�����������������s�����������i��k�� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�������8��V�����(��;��������`����"��f�����}������������W�����)��<�������a����#��g��J��~��K�����������������������.�� ������������������*����E��L��6�����������������r�����������h��j�������������������������/�� ������������������+����F��M��7�����������������s�����������i��k�� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/10.dat��������������������������������������0000664�0001750�0001750�00000004453�11060207421�022364� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-10 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~���������"��*��(��6�����;����`��f��}�����j��J���������#��+��)��7�����<����a��g��~�� ��k��K�����������������������.�� ������������������������E��L��������������h�����r����������������������������������������/�� ������������������������F��M��������������i�����s�����������������8 #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~���������"��*��(��6�����;����`��f��}�����j��J���������#��+��)��7�����<����a��g��~�� ��k��K�����������������������.�� ������������������������E��L��������������h�����r����������������������������������������/�� ������������������������F��M��������������i�����s�����������������8 #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/14.dat��������������������������������������0000664�0001750�0001750�00000004453�11060207421�022370� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-14 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~������������ �� �� ������������ ����������x������ ��!��@��A�����V����W����`��������a��������������������������������������������������t��������������������j��������������������v�����������������������������������������������������u��������������������k��������������������w��� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~������������ �� �� ������������ ����������x������ ��!��@��A�����V����W����`��������a��������������������������������������������������t��������������������j��������������������v�����������������������������������������������������u��������������������k��������������������w��� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/1.dat���������������������������������������0000664�0001750�0001750�00000004452�11060207421�022303� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-1 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-8859/11.dat��������������������������������������0000664�0001750�0001750�00000004333�11060207421�022362� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc ISO-8859-11 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~��������������������� �� �� �� �� �������������������������������������� ��!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6��7��8��9��:��?��@��A��B��C��D��E��F��G��H��I��J��K��L��M��N��O��P��Q��R��S��T��U��V��W��X��Y��Z��[ #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~��������������������� �� �� �� �� �������������������������������������� ��!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6��7��8��9��:��?��@��A��B��C��D��E��F��G��H��I��J��K��L��M��N��O��P��Q��R��S��T��U��V��W��X��Y��Z��[ #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-utf16/�������������������������������������������0000775�0001750�0001750�00000000000�11734430230�022000� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-utf16/simple.dat���������������������������������0000664�0001750�0001750�00000001076�11031522713�023765� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# *** Simple test: #data decode STRICT @䅂 #expected PARSERUTILS_OK @䅂 #reset # *** Surrogate test: #data decode STRICT �� #expected PARSERUTILS_OK 𐌂 #reset # *** Lonely high surrogate: # This is a bit strange that end status is ok. #data decode STRICT � #expected PARSERUTILS_OK #reset # With an extra code point, the status is different. #data decode STRICT �䅂 #expected PARSERUTILS_INVALID #reset # *** Wrong low surrogate start: #data decode STRICT � #expected PARSERUTILS_INVALID #reset ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-utf16/INDEX��������������������������������������0000664�0001750�0001750�00000000177�11031522713�022575� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Index file for UTF-16 charset codec tests # # Test Description simple.dat Simple tests, designed to validate testdriver �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/input/���������������������������������������������������0000775�0001750�0001750�00000000000�11734430230�020571� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/input/UTF-8-test.txt�������������������������������������0000664�0001750�0001750�00000047556�11006370446�023137� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������UTF-8 decoder capability and stress test ---------------------------------------- Markus Kuhn - 2003-02-19 This test file can help you examine, how your UTF-8 decoder handles various types of correct, malformed, or otherwise interesting UTF-8 sequences. This file is not meant to be a conformance test. It does not prescribes any particular outcome and therefore there is no way to "pass" or "fail" this test file, even though the texts suggests a preferable decoder behaviour at some places. The aim is instead to help you think about and test the behaviour of your UTF-8 on a systematic collection of unusual inputs. Experience so far suggests that most first-time authors of UTF-8 decoders find at least one serious problem in their decoder by using this file. The test lines below cover boundary conditions, malformed UTF-8 sequences as well as correctly encoded UTF-8 sequences of Unicode code points that should never occur in a correct UTF-8 file. According to ISO 10646-1:2000, sections D.7 and 2.3c, a device receiving UTF-8 shall interpret a "malformed sequence in the same way that it interprets a character that is outside the adopted subset" and "characters that are not within the adopted subset shall be indicated to the user" by a receiving device. A quite commonly used approach in UTF-8 decoders is to replace any malformed UTF-8 sequence by a replacement character (U+FFFD), which looks a bit like an inverted question mark, or a similar symbol. It might be a good idea to visually distinguish a malformed UTF-8 sequence from a correctly encoded Unicode character that is just not available in the current font but otherwise fully legal, even though ISO 10646-1 doesn't mandate this. In any case, just ignoring malformed sequences or unavailable characters does not conform to ISO 10646, will make debugging more difficult, and can lead to user confusion. Please check, whether a malformed UTF-8 sequence is (1) represented at all, (2) represented by exactly one single replacement character (or equivalent signal), and (3) the following quotation mark after an illegal UTF-8 sequence is correctly displayed, i.e. proper resynchronization takes place immageately after any malformed sequence. This file says "THE END" in the last line, so if you don't see that, your decoder crashed somehow before, which should always be cause for concern. All lines in this file are exactly 79 characters long (plus the line feed). In addition, all lines end with "|", except for the two test lines 2.1.1 and 2.2.1, which contain non-printable ASCII controls U+0000 and U+007F. If you display this file with a fixed-width font, these "|" characters should all line up in column 79 (right margin). This allows you to test quickly, whether your UTF-8 decoder finds the correct number of characters in every line, that is whether each malformed sequences is replaced by a single replacement character. Note that as an alternative to the notion of malformed sequence used here, it is also a perfectly acceptable (and in some situations even preferable) solution to represent each individual byte of a malformed sequence by a replacement character. If you follow this strategy in your decoder, then please ignore the "|" column. Here come the tests: | | 1 Some correct UTF-8 text | | You should see the Greek word 'kosme': "κόσμε" | | 2 Boundary condition test cases | | 2.1 First possible sequence of a certain length | | 2.1.1 1 byte (U-00000000): "�" 2.1.2 2 bytes (U-00000080): "€" | 2.1.3 3 bytes (U-00000800): "ࠀ" | 2.1.4 4 bytes (U-00010000): "𐀀" | 2.1.5 5 bytes (U-00200000): "" | 2.1.6 6 bytes (U-04000000): "" | | 2.2 Last possible sequence of a certain length | | 2.2.1 1 byte (U-0000007F): "" 2.2.2 2 bytes (U-000007FF): "߿" | 2.2.3 3 bytes (U-0000FFFF): "￿" | 2.2.4 4 bytes (U-001FFFFF): "" | 2.2.5 5 bytes (U-03FFFFFF): "" | 2.2.6 6 bytes (U-7FFFFFFF): "" | | 2.3 Other boundary conditions | | 2.3.1 U-0000D7FF = ed 9f bf = "퟿" | 2.3.2 U-0000E000 = ee 80 80 = "" | 2.3.3 U-0000FFFD = ef bf bd = "�" | 2.3.4 U-0010FFFF = f4 8f bf bf = "􏿿" | 2.3.5 U-00110000 = f4 90 80 80 = "" | | 3 Malformed sequences | | 3.1 Unexpected continuation bytes | | Each unexpected continuation byte should be separately signalled as a | malformed sequence of its own. | | 3.1.1 First continuation byte 0x80: "" | 3.1.2 Last continuation byte 0xbf: "" | | 3.1.3 2 continuation bytes: "" | 3.1.4 3 continuation bytes: "" | 3.1.5 4 continuation bytes: "" | 3.1.6 5 continuation bytes: "" | 3.1.7 6 continuation bytes: "" | 3.1.8 7 continuation bytes: "" | | 3.1.9 Sequence of all 64 possible continuation bytes (0x80-0xbf): | | " | | | " | | 3.2 Lonely start characters | | 3.2.1 All 32 first bytes of 2-byte sequences (0xc0-0xdf), | each followed by a space character: | | " | " | | 3.2.2 All 16 first bytes of 3-byte sequences (0xe0-0xef), | each followed by a space character: | | " " | | 3.2.3 All 8 first bytes of 4-byte sequences (0xf0-0xf7), | each followed by a space character: | | " " | | 3.2.4 All 4 first bytes of 5-byte sequences (0xf8-0xfb), | each followed by a space character: | | " " | | 3.2.5 All 2 first bytes of 6-byte sequences (0xfc-0xfd), | each followed by a space character: | | " " | | 3.3 Sequences with last continuation byte missing | | All bytes of an incomplete sequence should be signalled as a single | malformed sequence, i.e., you should see only a single replacement | character in each of the next 10 tests. (Characters as in section 2) | | 3.3.1 2-byte sequence with last byte missing (U+0000): "" | 3.3.2 3-byte sequence with last byte missing (U+0000): "" | 3.3.3 4-byte sequence with last byte missing (U+0000): "" | 3.3.4 5-byte sequence with last byte missing (U+0000): "" | 3.3.5 6-byte sequence with last byte missing (U+0000): "" | 3.3.6 2-byte sequence with last byte missing (U-000007FF): "" | 3.3.7 3-byte sequence with last byte missing (U-0000FFFF): "" | 3.3.8 4-byte sequence with last byte missing (U-001FFFFF): "" | 3.3.9 5-byte sequence with last byte missing (U-03FFFFFF): "" | 3.3.10 6-byte sequence with last byte missing (U-7FFFFFFF): "" | | 3.4 Concatenation of incomplete sequences | | All the 10 sequences of 3.3 concatenated, you should see 10 malformed | sequences being signalled: | | "" | | 3.5 Impossible bytes | | The following two bytes cannot appear in a correct UTF-8 string | | 3.5.1 fe = "" | 3.5.2 ff = "" | 3.5.3 fe fe ff ff = "" | | 4 Overlong sequences | | The following sequences are not malformed according to the letter of | the Unicode 2.0 standard. However, they are longer then necessary and | a correct UTF-8 encoder is not allowed to produce them. A "safe UTF-8 | decoder" should reject them just like malformed sequences for two | reasons: (1) It helps to debug applications if overlong sequences are | not treated as valid representations of characters, because this helps | to spot problems more quickly. (2) Overlong sequences provide | alternative representations of characters, that could maliciously be | used to bypass filters that check only for ASCII characters. For | instance, a 2-byte encoded line feed (LF) would not be caught by a | line counter that counts only 0x0a bytes, but it would still be | processed as a line feed by an unsafe UTF-8 decoder later in the | pipeline. From a security point of view, ASCII compatibility of UTF-8 | sequences means also, that ASCII characters are *only* allowed to be | represented by ASCII bytes in the range 0x00-0x7f. To ensure this | aspect of ASCII compatibility, use only "safe UTF-8 decoders" that | reject overlong UTF-8 sequences for which a shorter encoding exists. | | 4.1 Examples of an overlong ASCII character | | With a safe UTF-8 decoder, all of the following five overlong | representations of the ASCII character slash ("/") should be rejected | like a malformed UTF-8 sequence, for instance by substituting it with | a replacement character. If you see a slash below, you do not have a | safe UTF-8 decoder! | | 4.1.1 U+002F = c0 af = "" | 4.1.2 U+002F = e0 80 af = "" | 4.1.3 U+002F = f0 80 80 af = "" | 4.1.4 U+002F = f8 80 80 80 af = "" | 4.1.5 U+002F = fc 80 80 80 80 af = "" | | 4.2 Maximum overlong sequences | | Below you see the highest Unicode value that is still resulting in an | overlong sequence if represented with the given number of bytes. This | is a boundary test for safe UTF-8 decoders. All five characters should | be rejected like malformed UTF-8 sequences. | | 4.2.1 U-0000007F = c1 bf = "" | 4.2.2 U-000007FF = e0 9f bf = "" | 4.2.3 U-0000FFFF = f0 8f bf bf = "" | 4.2.4 U-001FFFFF = f8 87 bf bf bf = "" | 4.2.5 U-03FFFFFF = fc 83 bf bf bf bf = "" | | 4.3 Overlong representation of the NUL character | | The following five sequences should also be rejected like malformed | UTF-8 sequences and should not be treated like the ASCII NUL | character. | | 4.3.1 U+0000 = c0 80 = "" | 4.3.2 U+0000 = e0 80 80 = "" | 4.3.3 U+0000 = f0 80 80 80 = "" | 4.3.4 U+0000 = f8 80 80 80 80 = "" | 4.3.5 U+0000 = fc 80 80 80 80 80 = "" | | 5 Illegal code positions | | The following UTF-8 sequences should be rejected like malformed | sequences, because they never represent valid ISO 10646 characters and | a UTF-8 decoder that accepts them might introduce security problems | comparable to overlong UTF-8 sequences. | | 5.1 Single UTF-16 surrogates | | 5.1.1 U+D800 = ed a0 80 = "" | 5.1.2 U+DB7F = ed ad bf = "" | 5.1.3 U+DB80 = ed ae 80 = "" | 5.1.4 U+DBFF = ed af bf = "" | 5.1.5 U+DC00 = ed b0 80 = "" | 5.1.6 U+DF80 = ed be 80 = "" | 5.1.7 U+DFFF = ed bf bf = "" | | 5.2 Paired UTF-16 surrogates | | 5.2.1 U+D800 U+DC00 = ed a0 80 ed b0 80 = "" | 5.2.2 U+D800 U+DFFF = ed a0 80 ed bf bf = "" | 5.2.3 U+DB7F U+DC00 = ed ad bf ed b0 80 = "" | 5.2.4 U+DB7F U+DFFF = ed ad bf ed bf bf = "" | 5.2.5 U+DB80 U+DC00 = ed ae 80 ed b0 80 = "" | 5.2.6 U+DB80 U+DFFF = ed ae 80 ed bf bf = "" | 5.2.7 U+DBFF U+DC00 = ed af bf ed b0 80 = "" | 5.2.8 U+DBFF U+DFFF = ed af bf ed bf bf = "" | | 5.3 Other illegal code positions | | 5.3.1 U+FFFE = ef bf be = "￾" | 5.3.2 U+FFFF = ef bf bf = "￿" | | THE END | ��������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/input/INDEX����������������������������������������������0000664�0001750�0001750�00000000162�11006370446�021366� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Index file for inputstream tests # # Test Description UTF-8-test.txt Markus Kuhn's UTF-8 decoding test file ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/��������������������������������������������0000775�0001750�0001750�00000000000�11734430230�021723� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/cp1258.dat����������������������������������0000664�0001750�0001750�00000005022�11060176361�023342� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc Windows-1258 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !���� 0�� 9��R�� �� �� �� �� "�� �� ����!"�� :��S��x������������������������������������������������������������������������������������������������������������������������������������������������������ �����������������������������������������������������������������������������������������#��������������������������������� ��� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !���� 0�� 9��R�� �� �� �� �� "�� �� ����!"�� :��S��x������������������������������������������������������������������������������������������������������������������������������������������������������ �����������������������������������������������������������������������������������������#��������������������������������� ��� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/cp1255.dat����������������������������������0000664�0001750�0001750�00000004606�11060176361�023346� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc Windows-1255 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !���� 0�� 9�� �� �� �� �� "�� �� ����!"�� :�������������� ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ��  #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !���� 0�� 9�� �� �� �� �� "�� �� ����!"�� :�������������� ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ��  #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ��������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/cp1250.dat����������������������������������0000664�0001750�0001750�00000005072�11060176361�023337� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc Windows-1250 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� �� �� &�� �� !�� 0��`�� 9��Z��d��}��y�� �� �� �� �� "�� �� ��!"��a�� :��[��e��~��z���������A�������������������^��������������{����������B�������������������_�����=����>��|��T�������������9������� ����������������������C��G��������P��������X��n�����p��������b�����U�������������:������� ����������������������D��H��������Q��������Y��o�����q��������c�� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� �� �� &�� �� !�� 0��`�� 9��Z��d��}��y�� �� �� �� �� "�� �� ��!"��a�� :��[��e��~��z���������A�������������������^��������������{����������B�������������������_�����=����>��|��T�������������9������� ����������������������C��G��������P��������X��n�����p��������b�����U�������������:������� ����������������������D��H��������Q��������Y��o�����q��������c�� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/cp1256.dat����������������������������������0000664�0001750�0001750�00000005154�11060176361�023346� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc Windows-1256 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� ��~�� ���� �� &�� �� !���� 0��y�� 9��R���������� �� �� �� �� "�� �� ����!"���� :��S�� �� ������� �������������������������������������������������������������������������������������������!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6�����7��8��9��:��@��A��B��C�����D�����E��F��G��H�����������������I��J��������K��L��M��N�����O��P�����Q�����R�������� �� �� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� ��~�� ���� �� &�� �� !���� 0��y�� 9��R���������� �� �� �� �� "�� �� ����!"���� :��S�� �� ������� �������������������������������������������������������������������������������������������!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6�����7��8��9��:��@��A��B��C�����D�����E��F��G��H�����������������I��J��������K��L��M��N�����O��P�����Q�����R�������� �� �� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/cp1253.dat����������������������������������0000664�0001750�0001750�00000004702�11060176361�023341� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc Windows-1253 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !�� 0�� 9�� �� �� �� �� "�� �� ��!"�� :������������������������������������������ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !�� 0�� 9�� �� �� �� �� "�� �� ��!"�� :������������������������������������������ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ��������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/cp1257.dat����������������������������������0000664�0001750�0001750�00000004764�11060176361�023355� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc Windows-1257 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� �� �� &�� �� !�� 0�� 9���������� �� �� �� �� "�� �� ��!"�� :�������������������������������V�����������������������������������������������W�������������������.����������������� �����y����"��6��*��;��`��C��E�����L�����������r��A��Z��j�����{��}�������/���������������� �����z����#��7��+��<��a��D��F�����M�����������s��B��[��k�����|��~�� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� �� �� &�� �� !�� 0�� 9���������� �� �� �� �� "�� �� ��!"�� :�������������������������������V�����������������������������������������������W�������������������.����������������� �����y����"��6��*��;��`��C��E�����L�����������r��A��Z��j�����{��}�������/���������������� �����z����#��7��+��<��a��D��F�����M�����������s��B��[��k�����|��~�� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/cp1251.dat����������������������������������0000664�0001750�0001750�00000005142�11060176361�023336� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc Windows-1251 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~������ ��S�� �� &�� �� !�� �� 0�� �� 9�� �� �� ����R�� �� �� �� �� "�� �� ��!"��Y�� :��Z��\��[��_�������^��������������������������������������������V�������������Q��!��T�����X����U��W���������������������������������� ��!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6��7��8��9��:��;��<��=��>��?��@��A��B��C��D��E��F��G��H��I��J��K��L��M��N��O #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~������ ��S�� �� &�� �� !�� �� 0�� �� 9�� �� �� ����R�� �� �� �� �� "�� �� ��!"��Y�� :��Z��\��[��_�������^��������������������������������������������V�������������Q��!��T�����X����U��W���������������������������������� ��!��"��#��$��%��&��'��(��)��*��+��,��-��.��/��0��1��2��3��4��5��6��7��8��9��:��;��<��=��>��?��@��A��B��C��D��E��F��G��H��I��J��K��L��M��N��O #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/INDEX���������������������������������������0000664�0001750�0001750�00000000436�11060176361�022524� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Index file for charset codec tests # # Test Description cp1250.dat Windows-1250 cp1251.dat Windows-1251 cp1252.dat Windows-1252 cp1253.dat Windows-1253 cp1254.dat Windows-1254 cp1255.dat Windows-1255 cp1256.dat Windows-1256 cp1257.dat Windows-1257 cp1258.dat Windows-1258 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/cp1254.dat����������������������������������0000664�0001750�0001750�00000005046�11060176361�023344� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc Windows-1254 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !���� 0��`�� 9��R�� �� �� �� �� "�� �� ����!"��a�� :��S��x����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0��^�������������������������������������������������������������������������������������������1��_��� #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !���� 0��`�� 9��R�� �� �� �� �� "�� �� ����!"��a�� :��S��x����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0��^�������������������������������������������������������������������������������������������1��_��� #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/data/cscodec-ext8/cp1252.dat����������������������������������0000664�0001750�0001750�00000005072�11060164426�023340� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#enc Windows-1252 #data decode LOOSE �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #expected CHARSET_OK ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !���� 0��`�� 9��R��}�� �� �� �� �� "�� �� ����!"��a�� :��S��~��x������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #reset #data encode LOOSE ������������������������������� ��� ��� ��� ��� ��������������������������������������������������������� ���!���"���#���$���%���&���'���(���)���*���+���,���-���.���/���0���1���2���3���4���5���6���7���8���9���:���;���<���=���>���?���@���A���B���C���D���E���F���G���H���I���J���K���L���M���N���O���P���Q���R���S���T���U���V���W���X���Y���Z���[���\���]���^���_���`���a���b���c���d���e���f���g���h���i���j���k���l���m���n���o���p���q���r���s���t���u���v���w���x���y���z���{���|���}���~�� �� ���� �� &�� �� !���� 0��`�� 9��R��}�� �� �� �� �� "�� �� ����!"��a�� :��S��~��x������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #expected CHARSET_OK �  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ #reset ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/Makefile������������������������������������������������������0000664�0001750�0001750�00000000372�11476457062�020202� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Tests DIR_TEST_ITEMS := aliases:aliases.c cscodec-8859:cscodec-8859.c \ cscodec-ext8:cscodec-ext8.c cscodec-utf8:cscodec-utf8.c \ cscodec-utf16:cscodec-utf16.c filter:filter.c \ inputstream:inputstream.c include build/makefiles/Makefile.subdir ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/filter.c������������������������������������������������������0000664�0001750�0001750�00000022202�11520016105�020142� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include #include #include #include "utils/utils.h" #include "input/filter.h" #include "testutils.h" static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_filter_optparams params; parserutils_filter *input; uint8_t inbuf[64], outbuf[64]; size_t inlen, outlen; const uint8_t *in = inbuf; uint8_t *out = outbuf; UNUSED(argc); UNUSED(argv); /* Create input filter */ assert(parserutils__filter_create("UTF-8", myrealloc, NULL, &input) == PARSERUTILS_OK); /* Convert filter to UTF-8 encoding */ params.encoding.name = "UTF-8"; assert(parserutils__filter_setopt(input, PARSERUTILS_FILTER_SET_ENCODING, (parserutils_filter_optparams *) ¶ms) == PARSERUTILS_OK); /* Simple case - valid input & output buffer large enough */ in = inbuf; out = outbuf; strcpy((char *) inbuf, "hell\xc2\xa0o!"); inlen = strlen((const char *) inbuf); outbuf[0] = '\0'; outlen = 64; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); assert(parserutils__filter_reset(input) == PARSERUTILS_OK); assert(memcmp(outbuf, "hell\xc2\xa0o!", SLEN("hell\xc2\xa0o!")) == 0); /* Too small an output buffer; no encoding edge cases */ in = inbuf; out = outbuf; strcpy((char *) inbuf, "hello!"); inlen = strlen((const char *) inbuf); outbuf[0] = '\0'; outlen = 5; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_NOMEM); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); outlen = 64 - 5 + outlen; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); assert(parserutils__filter_reset(input) == PARSERUTILS_OK); assert(memcmp(outbuf, "hello!", SLEN("hello!")) == 0); /* Illegal input sequence; output buffer large enough */ in = inbuf; out = outbuf; strcpy((char *) inbuf, "hell\x96o!"); inlen = strlen((const char *) inbuf); outbuf[0] = '\0'; outlen = 64; /* Input does loose decoding, converting to U+FFFD if illegal * input is encountered */ assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); assert(parserutils__filter_reset(input) == PARSERUTILS_OK); assert(memcmp(outbuf, "hell\xef\xbf\xbdo!", SLEN("hell\xef\xbf\xbdo!")) == 0); /* Input ends mid-sequence */ in = inbuf; out = outbuf; strcpy((char *) inbuf, "hell\xc2\xa0o!"); inlen = strlen((const char *) inbuf) - 3; outbuf[0] = '\0'; outlen = 64; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); inlen += 3; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); assert(parserutils__filter_reset(input) == PARSERUTILS_OK); assert(memcmp(outbuf, "hell\xc2\xa0o!", SLEN("hell\xc2\xa0o!")) == 0); /* Input ends mid-sequence, but second attempt has too small a * buffer, but large enough to write out the incomplete character. */ in = inbuf; out = outbuf; strcpy((char *) inbuf, "hell\xc2\xa0o!"); inlen = strlen((const char *) inbuf) - 3; outbuf[0] = '\0'; outlen = 64; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); inlen += 3; outlen = 3; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_NOMEM); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); outlen = 64 - 7; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); assert(parserutils__filter_reset(input) == PARSERUTILS_OK); assert(memcmp(outbuf, "hell\xc2\xa0o!", SLEN("hell\xc2\xa0o!")) == 0); /* Input ends mid-sequence, but second attempt has too small a * buffer, not large enough to write out the incomplete character. */ in = inbuf; out = outbuf; strcpy((char *) inbuf, "hell\xc2\xa0o!"); inlen = strlen((const char *) inbuf) - 3; outbuf[0] = '\0'; outlen = 64; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); inlen += 3; outlen = 1; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_NOMEM); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); outlen = 60; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); assert(parserutils__filter_reset(input) == PARSERUTILS_OK); assert(memcmp(outbuf, "hell\xc2\xa0o!", SLEN("hell\xc2\xa0o!")) == 0); /* Input ends mid-sequence, but second attempt contains * invalid character */ in = inbuf; out = outbuf; strcpy((char *) inbuf, "hell\xc2\xc2o!"); inlen = strlen((const char *) inbuf) - 3; outbuf[0] = '\0'; outlen = 64; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); inlen += 3; /* Input does loose decoding, converting to U+FFFD if illegal * input is encountered */ assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); assert(parserutils__filter_reset(input) == PARSERUTILS_OK); assert(memcmp(outbuf, "hell\xef\xbf\xbd\xef\xbf\xbdo!", SLEN("hell\xef\xbf\xbd\xef\xbf\xbdo!")) == 0); /* Input ends mid-sequence, but second attempt contains another * incomplete character */ in = inbuf; out = outbuf; strcpy((char *) inbuf, "hell\xc2\xa0\xc2\xa1o!"); inlen = strlen((const char *) inbuf) - 5; outbuf[0] = '\0'; outlen = 64; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); inlen += 2; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); inlen += 3; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); assert(parserutils__filter_reset(input) == PARSERUTILS_OK); assert(memcmp(outbuf, "hell\xc2\xa0\xc2\xa1o!", SLEN("hell\xc2\xa0\xc2\xa1o!")) == 0); /* Input ends mid-sequence, but second attempt contains insufficient * data to complete the incomplete character */ in = inbuf; out = outbuf; strcpy((char *) inbuf, "hell\xe2\x80\xa2o!"); inlen = strlen((const char *) inbuf) - 4; outbuf[0] = '\0'; outlen = 64; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); inlen += 1; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); inlen += 3; assert(parserutils__filter_process_chunk(input, &in, &inlen, &out, &outlen) == PARSERUTILS_OK); printf("'%.*s' %d '%.*s' %d\n", (int) inlen, in, (int) inlen, (int) (out - ((uint8_t *) outbuf)), outbuf, (int) outlen); assert(parserutils__filter_reset(input) == PARSERUTILS_OK); assert(memcmp(outbuf, "hell\xe2\x80\xa2o!", SLEN("hell\xe2\x80\xa2o!")) == 0); /* Clean up */ parserutils__filter_destroy(input); printf("PASS\n"); return 0; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/aliases.c�����������������������������������������������������0000664�0001750�0001750�00000002472�11520016105�020305� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include "charset/aliases.h" #include "testutils.h" int main (int argc, char **argv) { parserutils_charset_aliases_canon *c; UNUSED(argc); UNUSED(argv); c = parserutils__charset_alias_canonicalise("moose", 5); if (c) { printf("FAIL - found invalid encoding 'moose'\n"); return 1; } c = parserutils__charset_alias_canonicalise("csinvariant", 11); if (c) { printf("%s %d\n", c->name, c->mib_enum); } else { printf("FAIL - failed finding encoding 'csinvariant'\n"); return 1; } c = parserutils__charset_alias_canonicalise("csinvariant\"", 12); if (c) { printf("%s %d\n", c->name, c->mib_enum); } else { printf("FAIL - failed finding encoding 'csinvariant'\n"); return 1; } c = parserutils__charset_alias_canonicalise("nats-sefi-add", 13); if (c) { printf("%s %d\n", c->name, c->mib_enum); } else { printf("FAIL - failed finding encoding 'nats-sefi-add'\n"); return 1; } printf("%d\n", parserutils_charset_mibenum_from_name(c->name, strlen(c->name))); printf("%s\n", parserutils_charset_mibenum_to_name(c->mib_enum)); c = parserutils__charset_alias_canonicalise("u.t.f.8", 7); if (c) { printf("%s %d\n", c->name, c->mib_enum); } else { printf("FAIL - failed finding encoding 'u.t.f.8'\n"); return 1; } printf("PASS\n"); return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/cscodec-8859.c������������������������������������������������0000664�0001750�0001750�00000013741�11476512761�020726� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include #include #include "utils/utils.h" #include "testutils.h" typedef struct line_ctx { parserutils_charset_codec *codec; size_t buflen; size_t bufused; uint8_t *buf; size_t explen; size_t expused; uint8_t *exp; bool hadenc; bool indata; bool inexp; parserutils_error exp_ret; enum { ENCODE, DECODE, BOTH } dir; } line_ctx; static bool handle_line(const char *data, size_t datalen, void *pw); static void run_test(line_ctx *ctx); static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_charset_codec *codec; line_ctx ctx; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } assert(parserutils_charset_codec_create("NATS-SEFI-ADD", myrealloc, NULL, &codec) == PARSERUTILS_BADENCODING); ctx.buflen = parse_filesize(argv[1]); if (ctx.buflen == 0) return 1; ctx.buf = malloc(2 * ctx.buflen); if (ctx.buf == NULL) { printf("Failed allocating %u bytes\n", (unsigned int) ctx.buflen); return 1; } ctx.exp = ctx.buf + ctx.buflen; ctx.explen = ctx.buflen; ctx.buf[0] = '\0'; ctx.exp[0] = '\0'; ctx.bufused = 0; ctx.expused = 0; ctx.hadenc = false; ctx.indata = false; ctx.inexp = false; ctx.exp_ret = PARSERUTILS_OK; assert(parse_testfile(argv[1], handle_line, &ctx) == true); /* and run final test */ if (ctx.bufused > 0 && ctx.buf[ctx.bufused - 1] == '\n') ctx.bufused -= 1; if (ctx.expused > 0 && ctx.exp[ctx.expused - 1] == '\n') ctx.expused -= 1; run_test(&ctx); free(ctx.buf); parserutils_charset_codec_destroy(ctx.codec); printf("PASS\n"); return 0; } bool handle_line(const char *data, size_t datalen, void *pw) { line_ctx *ctx = (line_ctx *) pw; if (data[0] == '#') { if (ctx->inexp) { /* This marks end of testcase, so run it */ if (ctx->buf[ctx->bufused - 1] == '\n') ctx->bufused -= 1; if (ctx->exp[ctx->expused - 1] == '\n') ctx->expused -= 1; run_test(ctx); ctx->buf[0] = '\0'; ctx->exp[0] = '\0'; ctx->bufused = 0; ctx->expused = 0; ctx->exp_ret = PARSERUTILS_OK; } if (strncasecmp(data+1, "data", 4) == 0) { parserutils_charset_codec_optparams params; const char *ptr = data + 6; ctx->indata = true; ctx->inexp = false; if (strncasecmp(ptr, "decode", 6) == 0) ctx->dir = DECODE; else if (strncasecmp(ptr, "encode", 6) == 0) ctx->dir = ENCODE; else ctx->dir = BOTH; ptr += 7; if (strncasecmp(ptr, "LOOSE", 5) == 0) { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_LOOSE; ptr += 6; } else if (strncasecmp(ptr, "STRICT", 6) == 0) { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_STRICT; ptr += 7; } else { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_TRANSLIT; ptr += 9; } assert(parserutils_charset_codec_setopt(ctx->codec, PARSERUTILS_CHARSET_CODEC_ERROR_MODE, (parserutils_charset_codec_optparams *) ¶ms) == PARSERUTILS_OK); } else if (strncasecmp(data+1, "expected", 8) == 0) { ctx->indata = false; ctx->inexp = true; ctx->exp_ret = parserutils_error_from_string(data + 10, datalen - 10 - 1 /* \n */); } else if (strncasecmp(data+1, "reset", 5) == 0) { ctx->indata = false; ctx->inexp = false; parserutils_charset_codec_reset(ctx->codec); } else if (strncasecmp(data+1, "enc", 3) == 0) { const char *enc = data + 5; const char *end; char *enc_name; for (end = enc; !isspace(*end); end++) ; enc_name = alloca(end - enc + 1); memcpy(enc_name, enc, end - enc); enc_name[end - enc] = 0; assert(parserutils_charset_codec_create(enc_name, myrealloc, NULL, &ctx->codec) == PARSERUTILS_OK); ctx->hadenc = true; } } else { if (ctx->indata) { memcpy(ctx->buf + ctx->bufused, data, datalen); ctx->bufused += datalen; } if (ctx->inexp) { memcpy(ctx->exp + ctx->expused, data, datalen); ctx->expused += datalen; } } return true; } void run_test(line_ctx *ctx) { static int testnum; size_t destlen = ctx->bufused * 4; uint8_t *dest = alloca(destlen); uint8_t *pdest = dest; const uint8_t *psrc = ctx->buf; size_t srclen = ctx->bufused; size_t i; if (ctx->dir == DECODE) { assert(parserutils_charset_codec_decode(ctx->codec, &psrc, &srclen, &pdest, &destlen) == ctx->exp_ret); } else if (ctx->dir == ENCODE) { assert(parserutils_charset_codec_encode(ctx->codec, &psrc, &srclen, &pdest, &destlen) == ctx->exp_ret); } else { size_t templen = ctx->bufused * 4; uint8_t *temp = alloca(templen); uint8_t *ptemp = temp; const uint8_t *ptemp2; size_t templen2; assert(parserutils_charset_codec_decode(ctx->codec, &psrc, &srclen, &ptemp, &templen) == ctx->exp_ret); /* \todo currently there is no way to specify the number of consumed & produced data in case of a deliberate bad input data set. */ if (ctx->exp_ret == PARSERUTILS_OK) { assert(temp + (ctx->bufused * 4 - templen) == ptemp); } ptemp2 = temp; templen2 = ctx->bufused * 4 - templen; assert(parserutils_charset_codec_encode(ctx->codec, &ptemp2, &templen2, &pdest, &destlen) == ctx->exp_ret); if (ctx->exp_ret == PARSERUTILS_OK) { assert(templen2 == 0); assert(temp + (ctx->bufused * 4 - templen) == ptemp2); } } if (ctx->exp_ret == PARSERUTILS_OK) { assert(srclen == 0); assert(ctx->buf + ctx->bufused == psrc); assert(dest + (ctx->bufused * 4 - destlen) == pdest); assert(ctx->bufused * 4 - destlen == ctx->expused); } printf("%d: Read '", ++testnum); for (i = 0; i < ctx->expused; i++) { printf("%c%c ", "0123456789abcdef"[(dest[i] >> 4) & 0xf], "0123456789abcdef"[dest[i] & 0xf]); } printf("' Expected '"); for (i = 0; i < ctx->expused; i++) { printf("%c%c ", "0123456789abcdef"[(ctx->exp[i] >> 4) & 0xf], "0123456789abcdef"[ctx->exp[i] & 0xf]); } printf("'\n"); assert(pdest == dest + ctx->expused); assert(memcmp(dest, ctx->exp, ctx->expused) == 0); } �������������������������������netsurf-2.9/libparserutils-0.1.1/test/INDEX���������������������������������������������������������0000664�0001750�0001750�00000000602�11476457062�017330� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Index for testcases # # Test Description DataDir aliases Encoding alias handling cscodec-utf8 UTF-8 charset codec implementation cscodec-utf8 cscodec-utf16 UTF-16 charset codec implementation cscodec-utf16 cscodec-ext8 Extended 8bit charset codec cscodec-ext8 cscodec-8859 ISO-8859-n codec cscodec-8859 filter Input stream filtering inputstream Inputstream handling input ������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/cscodec-utf16.c�����������������������������������������������0000664�0001750�0001750�00000017425�11476512761�021261� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include #include #include /* These two are for htonl / ntohl */ #include #include #include #include "utils/utils.h" #include "testutils.h" typedef struct line_ctx { parserutils_charset_codec *codec; size_t buflen; size_t bufused; uint8_t *buf; size_t explen; size_t expused; uint8_t *exp; bool indata; bool inexp; parserutils_error exp_ret; enum { ENCODE, DECODE, BOTH } dir; } line_ctx; static bool handle_line(const char *data, size_t datalen, void *pw); static void run_test(line_ctx *ctx); static void *myrealloc(void *ptr, size_t len, void *pw) { UNUSED(pw); return realloc(ptr, len); } int main(int argc, char **argv) { parserutils_charset_codec *codec; line_ctx ctx; if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } assert(parserutils_charset_codec_create("NATS-SEFI-ADD", myrealloc, NULL, &codec) == PARSERUTILS_BADENCODING); assert(parserutils_charset_codec_create("UTF-16", myrealloc, NULL, &ctx.codec) == PARSERUTILS_OK); ctx.buflen = parse_filesize(argv[1]); if (ctx.buflen == 0) return 1; ctx.buf = malloc(ctx.buflen); if (ctx.buf == NULL) { printf("Failed allocating %u bytes\n", (int) ctx.buflen); return 1; } ctx.exp = malloc(ctx.buflen); if (ctx.exp == NULL) { printf("Failed allocating %u bytes\n", (int) ctx.buflen); free(ctx.buf); return 1; } ctx.explen = ctx.buflen; ctx.buf[0] = '\0'; ctx.exp[0] = '\0'; ctx.bufused = 0; ctx.expused = 0; ctx.indata = false; ctx.inexp = false; ctx.exp_ret = PARSERUTILS_OK; assert(parse_testfile(argv[1], handle_line, &ctx) == true); /* and run final test */ if (ctx.bufused > 0 && ctx.buf[ctx.bufused - 1] == '\n') ctx.bufused -= 1; if (ctx.expused > 0 && ctx.exp[ctx.expused - 1] == '\n') ctx.expused -= 1; run_test(&ctx); free(ctx.buf); parserutils_charset_codec_destroy(ctx.codec); printf("PASS\n"); return 0; } /** * Converts hex character ('0' ... '9' or 'a' ... 'f' or 'A' ... 'F') to * digit value. * \param hex Valid hex character * \return Corresponding digit value. */ static inline int hex2digit(char hex) { return (hex <= '9') ? hex - '0' : (hex | 0x20) - 'a' + 10; } bool handle_line(const char *data, size_t datalen, void *pw) { line_ctx *ctx = (line_ctx *) pw; if (data[0] == '#') { if (ctx->inexp) { /* This marks end of testcase, so run it */ if (ctx->buf[ctx->bufused - 1] == '\n') ctx->bufused -= 1; if (ctx->exp[ctx->expused - 1] == '\n') ctx->expused -= 1; run_test(ctx); ctx->buf[0] = '\0'; ctx->exp[0] = '\0'; ctx->bufused = 0; ctx->expused = 0; ctx->exp_ret = PARSERUTILS_OK; } if (strncasecmp(data+1, "data", 4) == 0) { parserutils_charset_codec_optparams params; const char *ptr = data + 6; ctx->indata = true; ctx->inexp = false; if (strncasecmp(ptr, "decode", 6) == 0) ctx->dir = DECODE; else if (strncasecmp(ptr, "encode", 6) == 0) ctx->dir = ENCODE; else ctx->dir = BOTH; ptr += 7; if (strncasecmp(ptr, "LOOSE", 5) == 0) { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_LOOSE; ptr += 6; } else if (strncasecmp(ptr, "STRICT", 6) == 0) { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_STRICT; ptr += 7; } else { params.error_mode.mode = PARSERUTILS_CHARSET_CODEC_ERROR_TRANSLIT; ptr += 9; } assert(parserutils_charset_codec_setopt(ctx->codec, PARSERUTILS_CHARSET_CODEC_ERROR_MODE, (parserutils_charset_codec_optparams *) ¶ms) == PARSERUTILS_OK); } else if (strncasecmp(data+1, "expected", 8) == 0) { ctx->indata = false; ctx->inexp = true; ctx->exp_ret = parserutils_error_from_string(data + 10, datalen - 10 - 1 /* \n */); } else if (strncasecmp(data+1, "reset", 5) == 0) { ctx->indata = false; ctx->inexp = false; parserutils_charset_codec_reset(ctx->codec); } } else { if (ctx->indata) { /* Process "&#xNNNN" as 16-bit code units. */ while (datalen) { uint16_t nCodePoint; if (data[0] == '\n') { ctx->buf[ctx->bufused++] = *data++; --datalen; continue; } assert(datalen >= sizeof ("&#xNNNN")-1 \ && data[0] == '&' && data[1] == '#' \ && data[2] == 'x' && isxdigit(data[3]) \ && isxdigit(data[4]) && isxdigit(data[5]) \ && isxdigit(data[6])); /* UTF-16 code is always host endian (different than UCS-32 !). */ nCodePoint = (hex2digit(data[3]) << 12) | (hex2digit(data[4]) << 8) | (hex2digit(data[5]) << 4) | hex2digit(data[6]); *((uint16_t *) (void *) (ctx->buf + ctx->bufused)) = nCodePoint; ctx->bufused += 2; data += sizeof ("&#xNNNN")-1; datalen -= sizeof ("&#xNNNN")-1; } } if (ctx->inexp) { /* Process "&#xXXXXYYYY as 32-bit code units. */ while (datalen) { uint32_t nCodePoint; if (data[0] == '\n') { ctx->exp[ctx->expused++] = *data++; --datalen; continue; } assert(datalen >= sizeof ("&#xXXXXYYYY")-1 \ && data[0] == '&' && data[1] == '#' \ && data[2] == 'x' && isxdigit(data[3]) \ && isxdigit(data[4]) && isxdigit(data[5]) \ && isxdigit(data[6]) && isxdigit(data[7]) \ && isxdigit(data[8]) && isxdigit(data[9]) \ && isxdigit(data[10])); /* UCS-4 code is always big endian, so convert host endian to big endian. */ nCodePoint = htonl((hex2digit(data[3]) << 28) | (hex2digit(data[4]) << 24) | (hex2digit(data[5]) << 20) | (hex2digit(data[6]) << 16) | (hex2digit(data[7]) << 12) | (hex2digit(data[8]) << 8) | (hex2digit(data[9]) << 4) | hex2digit(data[10])); *((uint32_t *) (void *) (ctx->exp + ctx->expused)) = nCodePoint; ctx->expused += 4; data += sizeof ("&#xXXXXYYYY")-1; datalen -= sizeof ("&#xXXXXYYYY")-1; } } } return true; } void run_test(line_ctx *ctx) { static int testnum; size_t destlen = ctx->bufused * 4; uint8_t *dest = alloca(destlen); uint8_t *pdest = dest; const uint8_t *psrc = ctx->buf; size_t srclen = ctx->bufused; size_t i; if (ctx->dir == DECODE) { assert(parserutils_charset_codec_decode(ctx->codec, &psrc, &srclen, &pdest, &destlen) == ctx->exp_ret); } else if (ctx->dir == ENCODE) { assert(parserutils_charset_codec_encode(ctx->codec, &psrc, &srclen, &pdest, &destlen) == ctx->exp_ret); } else { size_t templen = ctx->bufused * 4; uint8_t *temp = alloca(templen); uint8_t *ptemp = temp; const uint8_t *ptemp2; size_t templen2; assert(parserutils_charset_codec_decode(ctx->codec, &psrc, &srclen, &ptemp, &templen) == ctx->exp_ret); /* \todo currently there is no way to specify the number of consumed & produced data in case of a deliberate bad input data set. */ if (ctx->exp_ret == PARSERUTILS_OK) { assert(temp + (ctx->bufused * 4 - templen) == ptemp); } ptemp2 = temp; templen2 = ctx->bufused * 4 - templen; assert(parserutils_charset_codec_encode(ctx->codec, &ptemp2, &templen2, &pdest, &destlen) == ctx->exp_ret); if (ctx->exp_ret == PARSERUTILS_OK) { assert(templen2 == 0); assert(temp + (ctx->bufused * 4 - templen) == ptemp2); } } if (ctx->exp_ret == PARSERUTILS_OK) { assert(srclen == 0); assert(ctx->buf + ctx->bufused == psrc); assert(dest + (ctx->bufused * 4 - destlen) == pdest); assert(ctx->bufused * 4 - destlen == ctx->expused); } printf("%d: Read '", ++testnum); for (i = 0; i < ctx->expused; i++) { printf("%c%c ", "0123456789abcdef"[(dest[i] >> 4) & 0xf], "0123456789abcdef"[dest[i] & 0xf]); } printf("' Expected '"); for (i = 0; i < ctx->expused; i++) { printf("%c%c ", "0123456789abcdef"[(ctx->exp[i] >> 4) & 0xf], "0123456789abcdef"[ctx->exp[i] & 0xf]); } printf("'\n"); assert(pdest == dest + ctx->expused); assert(memcmp(dest, ctx->exp, ctx->expused) == 0); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/test/testutils.h���������������������������������������������������0000664�0001750�0001750�00000004615�11060156504�020741� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef test_testutils_h_ #define test_testutils_h_ #include #include #include #ifndef UNUSED #define UNUSED(x) ((x) = (x)) #endif /* Redefine assert, so we can simply use the standard assert mechanism * within testcases and exit with the right output for the testrunner * to do the right thing. */ void __assert2(const char *expr, const char *function, const char *file, int line); void __assert2(const char *expr, const char *function, const char *file, int line) { UNUSED(function); UNUSED(file); printf("FAIL - %s at line %d\n", expr, line); exit(EXIT_FAILURE); } #define assert(expr) \ ((void) ((expr) || (__assert2 (#expr, __func__, __FILE__, __LINE__), 0))) typedef bool (*line_func)(const char *data, size_t datalen, void *pw); static size_t parse_strlen(const char *str, size_t limit); bool parse_testfile(const char *filename, line_func callback, void *pw); size_t parse_filesize(const char *filename); /** * Testcase datafile parser driver * * \param filename Name of file to parse * \param callback Pointer to function to handle each line of input data * \param pw Pointer to client-specific private data * \return true on success, false otherwise. */ bool parse_testfile(const char *filename, line_func callback, void *pw) { FILE *fp; char buf[300]; fp = fopen(filename, "rb"); if (fp == NULL) { printf("Failed opening %s\n", filename); return false; } while (fgets(buf, sizeof buf, fp)) { if (buf[0] == '\n') continue; if (!callback(buf, parse_strlen(buf, sizeof buf - 1), pw)) { fclose(fp); return false; } } fclose(fp); return true; } /** * Utility string length measurer; assumes strings are '\n' terminated * * \param str String to measure length of * \param limit Upper bound on string length * \return String length */ size_t parse_strlen(const char *str, size_t limit) { size_t len = 0; if (str == NULL) return 0; while (len < limit - 1 && *str != '\n') { len++; str++; } len++; return len; } /** * Read the size of a file * * \param filename Name of file to read size of * \return File size (in bytes), or 0 on error */ size_t parse_filesize(const char *filename) { FILE *fp; size_t len = 0; fp = fopen(filename, "rb"); if (fp == NULL) { printf("Failed opening %s\n", filename); return 0; } fseek(fp, 0, SEEK_END); len = ftell(fp); fclose(fp); return len; } #endif �������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/Makefile�����������������������������������������������������������0000664�0001750�0001750�00000003027�11635457532�017222� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Component settings COMPONENT := parserutils COMPONENT_VERSION := 0.1.1 # Default to a static library COMPONENT_TYPE ?= lib-static # Setup the tooling include build/makefiles/Makefile.tools TESTRUNNER := $(PERL) build/testtools/testrunner.pl # Toolchain flags WARNFLAGS := -Wall -W -Wundef -Wpointer-arith -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ -Wmissing-declarations -Wnested-externs -pedantic # BeOS/Haiku standard library headers create warnings. ifneq ($(TARGET),beos) WARNFLAGS := $(WARNFLAGS) -Werror endif CFLAGS := -D_BSD_SOURCE -I$(CURDIR)/include/ \ -I$(CURDIR)/src $(WARNFLAGS) $(CFLAGS) ifneq ($(GCCVER),2) CFLAGS := $(CFLAGS) -std=c99 else # __inline__ is a GCCism CFLAGS := $(CFLAGS) -Dinline="__inline__" endif include build/makefiles/Makefile.top # Extra installation rules Is := include/parserutils I := /include/parserutils INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/errors.h;$(Is)/functypes.h;$(Is)/parserutils.h;$(Is)/types.h Is := include/parserutils/charset I := /include/parserutils/charset INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/codec.h;$(Is)/mibenum.h;$(Is)/utf16.h;$(Is)/utf8.h Is := include/parserutils/input I := /include/parserutils/input INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/inputstream.h Is := include/parserutils/utils I := /include/parserutils/utils INSTALL_ITEMS := $(INSTALL_ITEMS) $(I):$(Is)/buffer.h;$(Is)/stack.h;$(Is)/vector.h INSTALL_ITEMS := $(INSTALL_ITEMS) /lib/pkgconfig:lib$(COMPONENT).pc.in INSTALL_ITEMS := $(INSTALL_ITEMS) /lib:$(OUTPUT) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/COPYING������������������������������������������������������������0000664�0001750�0001750�00000002047�11006370446�016604� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Copyright (C) 2007-8 J-M Bell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/�������������������������������������������������������������0000775�0001750�0001750�00000000000�11734430235�016646� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/makefiles/���������������������������������������������������0000775�0001750�0001750�00000000000�11734430233�020604� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/makefiles/Makefile.top���������������������������������������0000664�0001750�0001750�00000042323�11537116272�023056� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Top-level Makefile fragment # # Expected inputs: # # BUILD Type of build to perform: # release - Release build # debug - Debug build # COMPONENT Name of the component (sans leading "lib" iff a library) # COMPONENT_VERSION Component version number (x.y.z) # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # TARGET Target platform identifier # # Optional inputs: # # BUILDDIR Directory to build into (defaults to # build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE)) # CC_CAN_BUILD_AND_DEP Flag whether $(CC) is capable of calculating dependency # information at the same time as compiling sources. # Set to "yes" if it can. # DESTDIR Sandboxed FS root (e.g. for packaging) # HOST Host platform identifier # REQUIRED_PKGS List of required pkg-config packages # # The client may also override all toolchain settings, including: # # ARFLAGS Archiver flags for the current compilation # CFLAGS C compiler flags for the current compilation # CXXFLAGS C++ compiler flags for the current compilation # LDFLAGS Linker flags for the current compilation # # TESTCFLAGS Any test-specific CFLAGS # TESTCXXFLAGS Any test-specific CXXFLAGS # TESTLDFLAGS Any test-specific LDFLAGS # # TESTRUNNER Test runner invocation command # The test runner takes a command line in the form # # # Targets provided: # # all Default target. Builds component using current settings # test Build and run test suite, using current settings. # coverage Determine test suite coverage (requires lcov) # profile Build with profiling support enabled (requires gprof) # docs Produce documentation (requires doxygen) # clean Clean the build # distclean Remove distribution files, too # install Install component into prefix. # uninstall Remove component from prefix. # # Variables provided: # # major-version Extracts the major version (x) from COMPONENT_VERSION # minor-version Extracts the minor version (y) from COMPONENT_VERSION # patch-version Extracts the patch version (z) from COMPONENT_VERSION # OUTPUT Path + filename of build target ############################################################################### # Sanity checks ############################################################################### # Name of component must be defined by client ifeq ($(COMPONENT),) $(error COMPONENT not defined) endif # As must the version ifeq ($(COMPONENT_VERSION),) $(error COMPONENT_VERSION not defined) endif # As must the component type ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not defined) endif # Target platform must be defined by the client ifeq ($(TARGET),) $(error TARGET not defined) endif # Build type, too ifeq ($(BUILD),) $(error BUILD not defined) endif ############################################################################## # Makefile variables ############################################################################## Q ?= @ VQ ?= @ ############################################################################## # Exported variables (also OUTPUT, further down) ############################################################################## major-version := $(word 1,$(subst ., ,$(COMPONENT_VERSION))) minor-version := $(word 2,$(subst ., ,$(COMPONENT_VERSION))) patch-version := $(word 3,$(subst ., ,$(COMPONENT_VERSION))) ############################################################################## # Build environment ############################################################################## # Build directory BUILDDIR ?= build-$(HOST)-$(TARGET)-$(BUILD)-$(COMPONENT_TYPE) # Build tree subdirs COVERAGEDIR := $(BUILDDIR)/coverage DOCDIR := $(BUILDDIR)/docs # Determine if we want to build testcases ifeq ($(MAKECMDGOALS),test) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),profile) WANT_TEST := yes else ifeq ($(MAKECMDGOALS),coverage) WANT_TEST := yes else WANT_TEST := no endif # List of items to delete on clean CLEAN_ITEMS := # List of items to delete on distclean DISTCLEAN_ITEMS := # List of items to build for testing TEST_ITEMS := # List of targets to run for testing TEST_TARGETS := # List of targets which are prerequisites for running tests TEST_PREREQS := # List of items to (un)install INSTALL_ITEMS := # List of targets to run before building $(OBJECT) PRE_TARGETS := # List of targets to run after building $(OBJECT) POST_TARGETS := # Source files SOURCES := # Include configuration Makefile fragment -include Makefile.config # Set the default target (before including any children) __default: all # Include Makefile fragments in subdirectories define do_include DIR := $$(dir $(1)) include $(1) endef MAKE_INCLUDES := $(wildcard */Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Calculate objects to build OBJECTS := $(addprefix $(BUILDDIR)/,$(filter %.o, \ $(subst /,_,$(subst .c,.o,$(SOURCES))) \ $(subst /,_,$(subst .cpp,.o,$(SOURCES))) \ $(subst /,_,$(subst .cmhg,.o,$(SOURCES))) \ $(subst /,_,$(subst .s,.o,$(SOURCES))))) bin_for_test = $(addprefix $(BUILDDIR)/,$(firstword $(subst :, ,$(ITEM)))) TEST_BINARIES := $(foreach ITEM,$(TEST_ITEMS),$(bin_for_test)) # Determine if we're building any C++ sources ifneq ($(filter %.cpp,$(SOURCES)),) CXX_IN_BUILD := yes else CXX_IN_BUILD := no endif # Determine the output filename ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) ifeq ($(findstring lib-shared,$(COMPONENT_TYPE)),lib-shared) SHAREDLIBNAME := lib$(COMPONENT)$(LIBEXT) SONAME := $(SHAREDLIBNAME).$(major-version) OUTPUT := $(BUILDDIR)/$(SHAREDLIBNAME).$(COMPONENT_VERSION) else OUTPUT := $(BUILDDIR)/lib$(COMPONENT)$(LIBEXT) endif else OUTPUT := $(BUILDDIR)/$(COMPONENT)$(EXEEXT) endif ############################################################################### # Build targets ############################################################################### .PHONY: all test coverage profile docs clean distclean install uninstall \ __default __precov __partial_clean __postshared ifeq ($(COMPONENT_TYPE),lib-shared) POST_TARGETS := __postshared $(POST_TARGETS) __postshared: $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SONAME) $(Q)$(LN) $(LNFLAGS) -f -s $(notdir $(OUTPUT)) $(BUILDDIR)/$(SHAREDLIBNAME) endif # Default target all: $(PRE_TARGETS) $(OUTPUT) $(POST_TARGETS) # Build and execute testsuite test: all $(TEST_PREREQS) $(TEST_BINARIES) $(TEST_TARGETS) $(VQ)$(ECHO) $(ECHOFLAGS) " TEST: Testing complete" # Compute coverage __precov: __partial_clean $(Q)$(LCOV) --directory . --zerocounters coverage: __precov test $(Q)$(LCOV) --directory $(BUILDDIR) --base-directory $(CURDIR) \ --capture --output-file $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(LCOV) --extract $(COVERAGEDIR)/$(COMPONENT)_tmp.info \ "$(CURDIR)/src*" -o $(COVERAGEDIR)/$(COMPONENT).info $(Q)$(RM) $(RMFLAGS) $(COVERAGEDIR)/$(COMPONENT)_tmp.info $(Q)$(GENHTML) -o $(COVERAGEDIR) --num-spaces 2 \ $(COVERAGEDIR)/$(COMPONENT).info # Build for profiling profile: __partial_clean test # Compile documentation docs: $(BUILDDIR)/stamp $(Q)$(DOXYGEN) build/Doxyfile # Clean build tree __partial_clean: -$(Q)$(RM) $(RMFLAGS) $(CLEAN_ITEMS) -$(Q)$(RM) $(RMFLAGS) gmon.out -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.d) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcda) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.gcno) -$(Q)$(RM) $(RMFLAGS) $(wildcard $(BUILDDIR)/*.o) clean: __partial_clean -$(Q)$(RM) $(RMFLAGS) -r build/docs -$(Q)$(RM) $(RMFLAGS) -r $(BUILDDIR) # Remove auto-generated non-build-tree items distclean: clean -$(Q)$(RM) $(RMFLAGS) $(DISTCLEAN_ITEMS) # The installation target, and associated canned command sequences. # For reference, the syntax of INSTALL_ITEMS is: # # :[';']* # # We also permit a trailing ';' in the file list. __comma := , __empty := __space := $(empty) $(empty) __required = $(if $(REQUIRED_PKGS),Requires: $(subst $(__space),$(__comma) ,$(strip $(REQUIRED_PKGS))),) # Install a pkg-config control file ($1) to the specified location ($2) define install_pkgconfig $(Q)$(ECHO) $(ECHOFLAGS) "sed -e... $1 >$(BUILDDIR)/$(1:.in=)" $(Q)$(SED) \ -e 's#PREFIX#$(PREFIX)#' \ -e 's#MAJOR#$(major-version)#' \ -e 's#MINOR#$(minor-version)#' \ -e 's#PATCH#$(patch-version)#' \ -e 's#VERSION#$(COMPONENT_VERSION)#' \ -e 's#REQUIRED#$(__required)#' \ $1 >$(BUILDDIR)/$(1:.in=) $(INSTALL) $(INSTALLFLAGS) -m 644 $(BUILDDIR)/$(1:.in=) \ $2/$(1:.in=) endef # TODO: Is this scheme portable? define install_shared_lib $(INSTALL) $(INSTALLFLAGS) -m 755 $1 $2/$(notdir $1) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SONAME) $(LN) $(LNFLAGS) -f -s $(notdir $1) $2/$(SHAREDLIBNAME) endef # Install a file ($1) to the specified location ($2) define install_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(call install_pkgconfig,$1,$2), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call install_shared_lib,$1,$2), \ $(INSTALL) $(INSTALLFLAGS) -m 644 $1 $2))) endef # Install a list of files ($2) to the specified location ($1) # We create the installation location if it doesn't already exist define install_to_dest $(Q)$(MKDIR) $(MKDIRFLAGS) $(DESTDIR)$(PREFIX)$1 $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call install_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef install: all $(foreach ITEM,$(INSTALL_ITEMS), \ $(call install_to_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) # Uninstallation # TODO: Work out how to safely remove symlinks define uninstall_shared_lib $(RM) $(RMFLAGS) $2/$(notdir $1).$(COMPONENT_VERSION) endef # Uninstall a file ($1) from the specified location ($2) define uninstall_file $(if $1, \ $(if $(findstring .pc.in,$1), \ $(RM) $(RMFLAGS) $2/$(1:.pc.in=.pc), \ $(if $(and $(filter lib-shared,$(COMPONENT_TYPE)), \ $(filter $(OUTPUT),$1)), \ $(call uninstall_shared_lib,$1,$2), \ $(RM) $(RMFLAGS) $2/$(notdir $1)))) endef # Uninstall a list of files ($2) from the specified location ($1) # TODO: Come up with a safe way of removing directories, too define uninstall_from_dest $(foreach FILE,$(strip $(subst ;, ,$2)), \ $(call uninstall_file,$(FILE),$(DESTDIR)$(PREFIX)$1)) endef uninstall: $(foreach ITEM,$(INSTALL_ITEMS), \ $(call uninstall_from_dest,$(firstword $(subst :, ,$(ITEM))), \ $(lastword $(subst :, ,$(ITEM))))) ############################################################################### # Actual rules ############################################################################### $(BUILDDIR)/stamp: $(Q)$(MKDIR) $(MKDIRFLAGS) $(BUILDDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(COVERAGEDIR) $(Q)$(MKDIR) $(MKDIRFLAGS) $(DOCDIR) $(Q)$(TOUCH) $(TOUCHFLAGS) $(BUILDDIR)/stamp $(OUTPUT): $(BUILDDIR)/stamp $(OBJECTS) ifeq ($(COMPONENT_TYPE),lib-static) $(VQ)$(ECHO) $(ECHOFLAGS) " AR: $@" $(Q)$(RM) $(RMFLAGS) $@ $(Q)$(AR) $(ARFLAGS) $@ $(OBJECTS) else $(VQ)$(ECHO) $(ECHOFLAGS) " LINK: $@" ifeq ($(CXX_IN_BUILD),yes) $(Q)$(CXX) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) else $(Q)$(CC) -o $@ $(OBJECTS) $(LDFLAGS) $(SHAREDLDFLAGS) endif endif ############################################################################### # Autogenerated, implied rules ############################################################################### DEPFILES := BUILDFILES := ifeq ($(CC_CAN_BUILD_AND_DEP),yes) # C compiler can compile and dep simultaneously define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) -MMD -MP $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else ifeq ($(CC_CANNOT_DEP),yes) # C compiler cannot calculate dependencies define dep_c endef define dep_cxx endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef else # C compiler must calculate dependencies first, then compile (default) define dep_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CC) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define dep_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(DEPFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " DEP: $1" $$(Q)$$(RM) $$(RMFLAGS) $($@) $$(Q)$$(CXX) $$($3) -MM $1 > $$@.tmp $$(Q)$$(SED) $$(SEDFLAGS) 's,^.*:,$$@ $$(@:.d=.o):,' < $$@.tmp > $$@ $$(Q)$$(RM) $$@.tmp DEPFILES += $$(BUILDDIR)/$2 endif endef define build_c ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CC) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_cxx ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " COMPILE: $1" $$(Q)$$(CXX) $$($3) -o $$@ -c $1 BUILDFILES += $$(BUILDDIR)/$2 endif endef endif endif define build_cmhg ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " CMHG: $1" $$(Q)$$(CMHG) $$(CMHGFLAGS) $1 -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef define build_s ifeq ($$(findstring $$(BUILDDIR)/$2,$$(BUILDFILES)),) $$(BUILDDIR)/$2: $$(BUILDDIR)/stamp $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) "ASSEMBLE: $1" $$(Q)$$(CC) $$($3) $1 -c -o $$@ BUILDFILES += $$(BUILDDIR)/$2 endif endef BUILDCFLAGS = $(CFLAGS) $(SHAREDCFLAGS) BUILDCXXFLAGS = $(CXXFLAGS) $(SHAREDCXXFLAGS) BUILDASFLAGS = $(ASFLAGS) $(SHAREDCFLAGS) # Generate dependency rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),BUILDCXXFLAGS))) # Generate compilation rules $(eval $(foreach SOURCE,$(filter %.c,$(SOURCES)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),BUILDCFLAGS))) $(eval $(foreach SOURCE,$(filter %.cpp,$(SOURCES)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),BUILDCXXFLAGS))) $(eval $(foreach SOURCE,$(filter %.cmhg,$(SOURCES)), \ $(call build_cmhg,$(SOURCE),$(subst /,_,$(SOURCE:.cmhg=.o))))) $(eval $(foreach SOURCE,$(filter %.s,$(SOURCES)), \ $(call build_s,$(SOURCE),$(subst /,_,$(SOURCE:.s=.o)),BUILDASFLAGS))) # Similarly for test sources ifeq ($(WANT_TEST),yes) ifeq ($(findstring lib,$(COMPONENT_TYPE)),lib) TESTLIB := $(OUTPUT) TESTLDFLAGS += -L$(BUILDDIR)/ -l$(COMPONENT) endif TESTCFLAGS := $(CFLAGS) $(TESTCFLAGS) TESTCXXFLAGS += $(CXXFLAGS) TESTLDFLAGS += $(LDFLAGS) define link_test $2: $($3) $1 $$(VQ)$$(ECHO) $$(ECHOFLAGS) " LINK: $2" ifeq ($$(CXX_IN_BUILD),yes) $$(Q)$$(CXX) -o $$@ $1 $$($4) else $$(Q)$$(CC) -o $$@ $1 $$($4) endif endef srcs_for_test = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) objs_for_test = $(addprefix $(BUILDDIR)/, \ $(subst /,_,$(addsuffix .o,$(basename $(srcs_for_test))))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call dep_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.d)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call dep_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.d)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.c,$(srcs_for_test)), \ $(call build_c,$(SOURCE),$(subst /,_,$(SOURCE:.c=.o)),TESTCFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(foreach SOURCE,$(filter %.cpp,$(srcs_for_test)), \ $(call build_cxx,$(SOURCE),$(subst /,_,$(SOURCE:.cpp=.o)),TESTCXXFLAGS)))) $(eval $(foreach ITEM,$(TEST_ITEMS), \ $(call link_test,$(objs_for_test),$(bin_for_test),TESTLIB,TESTLDFLAGS))) endif # Include dependency makefiles ifneq ($(findstring clean,$(MAKECMDGOALS)),clean) -include $(sort $(DEPFILES)) endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/makefiles/Makefile.clang�������������������������������������0000664�0001750�0001750�00000002326�11545435603�023340� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Clang-specific toolchain setup # We assume that we're using a standard GCC/binutils environment, as well # as clang being mostly GCC-compatible on the command line CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### CC_CAN_BUILD_AND_DEP ?= yes ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/makefiles/Makefile.norcroft����������������������������������0000664�0001750�0001750�00000002203�11545435603�024102� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Norcroft specific toolchain setup CCDEF := -D CCOPT := -Otime CCNOOPT := CCDBG := -g CCINC := -I CCLIB := -L # TODO: Norcroft CC cannot do assembler as C CCAS := CCSHR := CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g LDSHR := ARFLG := -c # Definitions of various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) $(error Coverage is not supported with Norcroft) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) $(error Profile is not supported with Norcroft) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -zM CXXFLAGS := $(CXXFLAGS) -zM LDFLAGS := $(LDFLAGS) -zM endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. CC_CANNOT_DEP := yes ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/makefiles/Makefile.gcc���������������������������������������0000664�0001750�0001750�00000004570�11545435603�023013� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# GCC specific toolchain setup # We assume that we're using a standard GCC/binutils environment CCDEF := -D CCOPT := -O2 CCNOOPT := -O0 CCDBG := -g CCINC := -I CCLIB := -L CCAS := -xassembler-with-cpp CCSHR := -fPIC CXXDEF := -D CXXOPT := -O2 CXXNOOPT := -O0 CXXDBG := -g CXXINC := -I CXXLIB := -L CXXSHR := -fPIC LDDBG := -g # Reevaluation is required here LDSHR = -shared -Wl,-soname,$(SONAME) ARFLG := cru # Definitions for various attributes CFLAGS := $(CFLAGS) -D_ALIGNED="__attribute__((aligned))" # Extensions for coverage target ifeq ($(MAKECMDGOALS),coverage) COVCFLAGS ?= -fprofile-arcs -ftest-coverage COVCXXFLAGS ?= -fprofile-arcs -ftest-coverage COVLDFLAGS ?= -lgcov CFLAGS := $(CFLAGS) $(COVCFLAGS) CXXFLAGS := $(CXXFLAGS) $(COVCXXFLAGS) LDFLAGS := $(LDFLAGS) $(COVLDFLAGS) endif # Extensions for profile target ifeq ($(MAKECMDGOALS),profile) PROFCFLAGS ?= -pg PROFCXXFLAGS ?= -pg PROFLDFLAGS ?= -pg CFLAGS := $(CFLAGS) $(PROFCFLAGS) CXXFLAGS := $(CXXFLAGS) $(PROFCXXFLAGS) LDFLAGS := $(LDFLAGS) $(PROFLDFLAGS) endif # RISC OS module extensions ifeq ($(COMPONENT_TYPE),riscos-module) ifneq ($(TARGET),riscos) $(error Attempting to build a RISC OS module for a non-RISC OS target) endif CFLAGS := $(CFLAGS) -mmodule CXXFLAGS := $(CXXFLAGS) -mmodule LDFLAGS := $(LDFLAGS) -mmodule endif ############################################################################### # Mac OS X Universal Binaries ############################################################################### ifeq ($(TARGET),Darwin) ifneq ($(UNIVERSAL),) UNIVERSAL_FLAGS := $(foreach arch,$(UNIVERSAL),-arch $(arch) ) CC_CAN_BUILD_AND_DEP := no CC_CANNOT_DEP := yes CFLAGS := $(CFLAGS) $(UNIVERSAL_FLAGS) LDFLAGS := $(LDFLAGS) $(UNIVERSAL_FLAGS) CXXFLAGS := $(CXXFLAGS) $(UNIVERSAL_FLAGS) ARFLAGS := $(ARFLAGS) -s endif endif ############################################################################### # Other settings ############################################################################### # Determine if the compiler supports simultaneous build & dep. ccvsn := $(shell $(CC) -dumpversion) # ccvsn = x.y.z GCCVER := $(word 1,$(subst ., ,$(ccvsn))) # GCCVER = x # If the major version (x, above) is not 2, then assume build & dep. # This will break if using a version of GCC < 2, but that's unlikely. ifneq ($(GCCVER),2) CC_CAN_BUILD_AND_DEP ?= yes endif ����������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/makefiles/Makefile.pkgconfig���������������������������������0000664�0001750�0001750�00000004265�11476474557�024245� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# General purpose pkg-config macros # Determine if a package is available # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_available ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package availability) endif ifeq ($$(shell $$(PKGCONFIG) --exists $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Retrieve the version of a package # 1: Name of variable to assign result into # 2: Name of package to search for define pkg_config_package_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif $(1) := $$(shell $$(PKGCONFIG) --version $(2)) endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number define pkg_config_package_min_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif endef # Test the presence of a minimum version of a package # 1: Name of variable to assign result into # 2: Name of package to search for # 3: Lowest accepted version number # 4: Highest accepted version number define pkg_config_package_compare_version ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifeq ($$(shell $$(PKGCONFIG) --atleast-version=$(3) $(2) && echo yes),yes) ifeq ($$(shell $$(PKGCONFIG) --max-version=$(4) $(2) && echo yes),yes) $(1) := yes else $(1) := no endif else $(1) := no endif endef # Add package to compiler/linker flags # 1: Name of package to add details of # 2: CFLAGS variable to extend, or none # 3: LDFLAGS variable to extend, or none define pkg_config_package_add_flags ifeq ($$(PKGCONFIG),) $$(error pkg-config is required to auto-detect package version) endif ifneq ($(2),) $(2) := $$($(2)) $$(shell $$(PKGCONFIG) --cflags $(1)) endif ifneq ($(3),) $(3) := $$($(3)) $$(shell $$(PKGCONFIG) --libs $(1)) endif endef �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/makefiles/Makefile.subdir������������������������������������0000664�0001750�0001750�00000007417�11165262413�023545� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Child makefile fragment # # Inputs (reset on exit) # # DIR_SOURCES List of source files in this directory # DIR_TEST_ITEMS List of test items in this directory # DIR_INSTALL_ITEMS Items to install in form :; # # Toolchain is provided by top-level makefile # # Variables provided by top-level makefile # # BUILDDIR The location of the build tree root # COMPONENT The name of the component # CURDIR The location of the source tree root # EXPORTDIR The location of the export directory # WANT_TEST Whether to build testcases # # do_include Canned command sequence to include a child makefile # # Variables provided by parent makefile: # # DIR The name of the directory we're in, relative to CURDIR # # Variables we can manipulate: # # CLEAN_ITEMS The list of items to remove for "make clean" # DISTCLEAN_ITEMS The list of items to remove for "make distclean" # TEST_ITEMS The list of items to build for "make test" # TEST_TARGETS The list of target names to run for "make test" # INSTALL_ITEMS The list of items to (un)install # # SOURCES The list of sources to build for $(COMPONENT) # # Plus anything from the toolchain # Push parent directory onto the directory stack sp := $(sp).x dirstack_$(sp) := $(d) d := $(DIR) # Sources SRCS_$(d) := $(DIR_SOURCES) TEST_ITEMS_$(d) := INSTALL_ITEMS_$(d) := # Append to sources for component SOURCES := $(SOURCES) $(addprefix $(d), $(SRCS_$(d))) # Test sources ifeq ($(WANT_TEST),yes) ifneq ($(DIR_TEST_ITEMS),) # Extract the binary name from the ITEM binary = $(subst /,_,$(addprefix $(d),$(firstword $(subst :, ,$(ITEM))))) # Extract the list of sources from the ITEM sources = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) # We can't simply use the output of foreach here, # as it space separates its output, which kinda defeats the point. define append_test_src TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d))$1; endef define append_test TEST_ITEMS_$(d) := $$(TEST_ITEMS_$(d)) $1: $$(eval $$(foreach TSRC,$2, \ $$(call append_test_src,$$(addprefix $$(d),$$(TSRC))))) endef # Append test items, prepending $(d) to each source file $(eval $(foreach ITEM,$(DIR_TEST_ITEMS), \ $(call append_test,$(binary),$(sources)))) TEST_ITEMS := $(TEST_ITEMS) $(TEST_ITEMS_$(d)) TEST_TARGETS := $(TEST_TARGETS) test_$(d) # Extract the binary name from the TEST binary_name = $(firstword $(subst :, ,$(TEST))) # Target for tests in this directory test_$(d): $(d) $(addprefix $(BUILDDIR)/, \ $(foreach TEST,$(TEST_ITEMS_$(d)),$(binary_name))) $(Q)$(SHAREDLDPATH) $(TESTRUNNER) $(BUILDDIR) \ $(CURDIR)/$< $(subst /,_,$<) $(EXEEXT) endif endif # Install items ifneq ($(DIR_INSTALL_ITEMS),) # Extract the destination directory from the variable dest_dir = $(firstword $(subst :, ,$(ITEM))) # Extract the list of files to install files = $(subst ;, ,$(lastword $(subst :, ,$(ITEM)))) define append_install_file INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d))$1; endef define append_install_item INSTALL_ITEMS_$(d) := $$(INSTALL_ITEMS_$(d)) $1: $$(eval $$(foreach FILE,$2, \ $$(call append_install_file,$$(addprefix $$(d),$$(FILE))))) endef # Append items to install (along with install location), prepending $(d) # to each item in the file list $(eval $(foreach ITEM,$(DIR_INSTALL_ITEMS), \ $(call append_install_item,$(dest_dir),$(files)))) INSTALL_ITEMS := $(INSTALL_ITEMS) $(INSTALL_ITEMS_$(d)) endif # Reset the inputs DIR_SOURCES := DIR_TEST_ITEMS := DIR_INSTALL_ITEMS := # Now include any children we may have MAKE_INCLUDES := $(wildcard $(d)*/Makefile) $(eval $(foreach INC, $(MAKE_INCLUDES), $(call do_include,$(INC)))) # Pop off the directory stack d := $(dirstack_$(sp)) sp := $(basename $(sp)) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/makefiles/Makefile.tools�������������������������������������0000664�0001750�0001750�00000032245�11537136047�023420� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Tools Makefile fragment # # Expected inputs: # # COMPONENT_TYPE Type of component: # binary - Executable binary # lib-static - Static library # lib-shared - Shared library # riscos-module - RISC OS module # # Optional inputs: # # BUILD Type of build to perform: # release - Release build (default) # debug - Debug build # OPTCFLAGS Optional C compiler flags for $(BUILD) # OPTCXXFLAGS Optional C++ compiler flags for $(BUILD) # OPTLDFLAGS Optional linker flags for $(BUILD) # TARGET Target platform (defaults to host) # PREFIX Absolute installation path prefix # (defaults to /usr/local) # ############################################################################### # Sanity checks ############################################################################### ifeq ($(COMPONENT_TYPE),) $(error COMPONENT_TYPE not set) endif # Default build to release ifeq ($(BUILD),) BUILD := release endif ############################################################################### # Host/target platform detection ############################################################################### # Autodetect host if necessary ifeq ($(HOST),) HOST := $(shell uname -s) endif # Simple host sanitisation ifeq ($(HOST),) # Don't ask HOST := riscos else ifeq ($(HOST),RISC OS) HOST := riscos endif ifeq ($(HOST),BeOS) HOST := beos endif ifeq ($(HOST),Haiku) HOST := haiku endif ifeq ($(HOST),AmigaOS) HOST := amiga endif ifeq ($(findstring MINGW,$(HOST)),MINGW) HOST := windows endif endif ifeq ($(TARGET),) # Default target to host. Please add exceptions as required. TARGET := $(HOST) ifeq ($(HOST),haiku) # This isn't necessarily correct -- they have differences. However, in the # general case, this will work. If there are differences that are actually # important wrt the target platform (as opposed to the build host) then # we'll just have to introduce a haiku target, too. TARGET := beos endif endif # Sanitise HOST and TARGET # TODO: Ideally, we want the equivalent of s/[^A-Za-z0-9]/_/g here HOST := $(subst .,_,$(subst -,_,$(subst /,_,$(HOST)))) TARGET := $(subst .,_,$(subst -,_,$(subst /,_,$(TARGET)))) # Now setup our tooling ifeq ($(TARGET),riscos) ifeq ($(HOST),riscos) # Building on native RISC OS GCCSDK_INSTALL_ENV ?= CC__ := gcc CXX__ := g++ CMHG ?= cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= # On certain versions of RISC OS (<>4 || kernel < 8.75), # the kernel will clean up the current redirection on # OS_Exit, including closing the associated file handles. # This is problematic for UnixLib, as it's invariably using # those filehandles in a pipe between parent and child processes. # This affects us as, anywhere where we shell out and want to # capture the output of the child process may fail. # Fortunately, if we know the child process is built against # UnixLib, then we also know that it won't call OS_Exit when it # exits, instead returning directly to our exit handler (and thus # preserving the redirection). This only works, however, if the # child application is specified using its absolute path, or # found in Run$Path. In the case of Perl, it does not appear in # Run$Path, so we must invoke it using its absolute path so that # the SharedUnixLibrary successfully detects it as a child process. PERL ?= .bin.perl # This is nasty, but needed because $(CURDIR) will # contain colons, and thus confuse make mightily $(shell SetMacro Alias$$$(COMPONENT)pwd Set %0 :|$$CSD>|mUnset Alias$$$(COMPONENT)pwd) $(shell $(COMPONENT)pwd $(COMPONENT)$$Dir) CURDIR := <$(COMPONENT)$$Dir> else # Cross compiling for RISC OS ifeq ($(origin GCCSDK_INSTALL_ENV),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/env),) GCCSDK_INSTALL_ENV := /opt/netsurf/arm-unknown-riscos/env else GCCSDK_INSTALL_ENV := /home/riscos/env endif endif ifeq ($(origin GCCSDK_INSTALL_CROSSBIN),undefined) ifneq ($(realpath /opt/netsurf/arm-unknown-riscos/cross/bin),) GCCSDK_INSTALL_CROSSBIN := /opt/netsurf/arm-unknown-riscos/cross/bin else GCCSDK_INSTALL_CROSSBIN := /home/riscos/cross/bin endif endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) CMHG ?= PATH="$(GCCSDK_INSTALL_CROSSBIN):$(PATH)" $(GCCSDK_INSTALL_CROSSBIN)/cmunge GENHTML ?= echo LCOV ?= echo PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/lib/pkgconfig:$(GCCSDK_INSTALL_ENV)/share/pkgconfig" pkg-config ifneq ($(COMPONENT_TYPE),riscos-module) ifeq ($(origin CC),default) ifneq ($(findstring arm-unknown-riscos-gcc,$(CC__)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif else ifneq ($(findstring arm-unknown-riscos-gcc,$(CC)),) EXEEXT := ,e1f else EXEEXT := ,ff8 endif endif else EXEEXT := ,ffa endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib CMHGFLAGS := -p -tgcc -32bit -apcs 3/32/nonreent/fpe2/noswst/nofpr/nofp # Default prefix PREFIX ?= $(GCCSDK_INSTALL_ENV) endif # BeOS-like targets ifeq ($(TARGET),beos) ifeq ($(HOST),beos) # Building on BeOS CC__ := gcc # No pkg-config PKGCONFIG ?= # Default prefix BEOS_INSTALL_ENV ?= /boot/home/config else ifeq ($(HOST),haiku) # Building on Haiku # Default prefix BEOS_INSTALL_ENV ?= /boot/common else # TODO: more sensible default BEOS_INSTALL_ENV ?= /home/jmb/haiku/env BEOS_INSTALL_CROSSBIN ?= /home/jmb/haiku/haiku/generated/cross-tools/bin CC__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*g++) AR__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*ar) PKGCONFIG := PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/share/pkgconfig" pkg-config endif endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -I$(BEOS_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -I$(BEOS_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(BEOS_INSTALL_ENV)/lib PREFIX ?= $(BEOS_INSTALL_ENV) endif # Windows ifeq ($(TARGET),windows) ifeq ($(HOST),windows) # Building on Windows CC__ := gcc CXX__ := g++ AR__ := ar PKGCONFIG ?= else # Cross compiling for Windows -- assumes mingw toolchain MINGW_INSTALL_ENV ?= /usr/local/mingw CC__ := i586-mingw32msvc-gcc CXX__ := i586-mingw32msvc-g++ AR__ := i586-mingw32msvc-ar PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config endif # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(MINGW_INSTALL_ENV)/lib # Default prefix PREFIX ?= $(MINGW_INSTALL_ENV) endif # AmigaOS (3/4; m68k/ppc: we can treat them identically) ifeq ($(findstring amiga,$(TARGET)),amiga) ifeq ($(findstring amiga,$(HOST)),amiga) # Building on AmigaOS # Nothing to do, as we assume the default tooling works else # Cross compiling for AmigaOS ifeq ($(TARGET),amigaos3) GCCSDK_INSTALL_ENV ?= /opt/netsurf/m68k-unknown-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/m68k-unknown-amigaos/cross/bin else GCCSDK_INSTALL_ENV ?= /opt/netsurf/ppc-amigaos/env GCCSDK_INSTALL_CROSSBIN ?= /opt/netsurf/ppc-amigaos/cross/bin endif AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar) CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc) CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++) PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(PREFIX)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/lib/pkgconfig:$(MINGW_INSTALL_ENV)/share/pkgconfig" pkg-config # TODO: this assumes GCC CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(GCCSDK_INSTALL_ENV)/include LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib PREFIX ?= $(GCCSDK_INSTALL_ENV) endif endif # Default prefix PREFIX ?= /usr/local ############################################################################### # Tool defaults ############################################################################### CP ?= cp DOXYGEN ?= doxygen ECHO ?= echo GENHTML ?= genhtml ifeq ($(HOST),$(TARGET)) HOST_CC ?= $(CC) HOST_CXX ?= $(CXX) else HOST_CC ?= cc HOST_CXX ?= c++ endif INSTALL ?= install LCOV ?= lcov LN ?= ln MAKE ?= make MKDIR ?= mkdir MKDIRFLAGS ?= -p MV ?= mv PERL ?= perl PKGCONFIG ?= PKG_CONFIG_PATH="$(PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)" pkg-config GREP ?= grep SED ?= sed TOUCH ?= touch XSLTPROC ?= xsltproc ############################################################################### # Override defaulted tools ############################################################################### # CC ifeq ($(findstring ccc-analyzer,$(CC)),ccc-analyzer) # We're being invoked by scan-build, so export # the compiler we would have used such that # scan-build works with cross-compilation. # There's no need to do this if we would have # used the default compiler. ifdef CC__ export CCC_CC := $(CC__) endif else # Only set CC if it's not already set in the # environment and we have a value for it. # Otherwise, leave it to be defaulted. ifeq ($(origin CC),default) ifdef CC__ CC := $(CC__) endif endif endif # CXX ifeq ($(origin CXX),default) ifdef CXX__ CXX := $(CXX__) endif endif # AR ifeq ($(origin AR),default) ifdef AR__ AR := $(AR__) endif endif ############################################################################### # Auto-detect the toolchain ############################################################################### # Check for GCC first, as that's most likely # TODO: Using shell redirection like this probably hurts portability ccspecs := $(shell $(CC) -dumpspecs 2>&1) ifeq ($(findstring libgcc,$(ccspecs)),libgcc) # Looks like GCC toolchain := gcc else # Not GCC, so enquire further ccvsn := $(shell $(CC) --version 2>&1) ifeq ($(ccvsn),) # Version string is blank ifeq ($(HOST),riscos) # For some reason we never see the output of SCL apps, so might be # Norcroft. However it might also be a GCC linked against a buggy # UnixLib. # TODO: Something more useful than blindly assuming GCC. ccvsn := GCC # ccvsn := Norcroft endif endif # "Norcroft ..." ifeq ($(word 1,$(ccvsn)),Norcroft) toolchain := norcroft endif # "GCC ..." ifeq ($(word 1,$(ccvsn)),GCC) toolchain := gcc endif # "clang ..." ifeq ($(word 1,$(ccvsn)),clang) toolchain := clang endif ifeq ($(word 1,$(ccvsn)),Apple) ifeq ($(word 2,$(ccvsn)),clang) # Apple clang toolchain := clang endif endif endif ifeq ($(toolchain),) $(error Unable to detect toolchain) endif # TODO: It would be nice to avoid this hard-coded path include build/makefiles/Makefile.$(toolchain) ############################################################################### # Default assembler/compiler/linker/archiver flags ############################################################################### ifeq ($(BUILD),release) OPTCFLAGS ?= $(CCDEF)NDEBUG $(CCOPT) OPTCXXFLAGS ?= $(CXXDEF)NDEBUG $(CXXOPT) else OPTCFLAGS ?= $(CCDBG) $(CCNOOPT) $(CCDEF)DEBUG OPTCXXFLAGS ?= $(CXXDBG) $(CXXNOOPT) $(CXXDEF)DEBUG OPTLDFLAGS ?= $(LDDBG) endif ifeq ($(origin ARFLAGS),default) ARFLAGS := $(ARFLG) endif # TODO: This assumes that the C compiler can cope with assembler ASFLAGS ?= $(CCAS) CFLAGS := $(CFLAGS) $(OPTCFLAGS) $(CCDEF)BUILD_TARGET_$(TARGET) $(CCDEF)BUILD_HOST_$(HOST) CXXFLAGS := $(CXXFLAGS) $(OPTCXXFLAGS) \ $(CXXDEF)BUILD_TARGET_$(TARGET) $(CXXDEF)BUILD_HOST_$(HOST) ASFLAGS := $(ASFLAGS) $(CFLAGS) LDFLAGS := $(LDFLAGS) $(OPTLDFLAGS) ############################################################################### # lib-shared defaults ############################################################################### # Default library extension ifeq ($(COMPONENT_TYPE),lib-static) LIBEXT ?= .a else LIBEXT ?= .so endif # If we're building a shared library, modify the flags appropriately ifeq ($(COMPONENT_TYPE),lib-shared) # Default CFLAGS/LDFLAGS for shared libraries SHAREDCFLAGS ?= $(CCSHR) $(CCDEF)PIC SHAREDCXXFLAGS ?= $(CXXSHR) $(CCDEF)PIC SHAREDLDFLAGS ?= $(LDSHR) SHAREDLDPATH ?= LD_LIBRARY_PATH="$(BUILDDIR):$(LD_LIBRARY_PATH)" endif ################################################################################ # Package config macros ################################################################################ include build/makefiles/Makefile.pkgconfig �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/make-aliases.pl����������������������������������������������0000664�0001750�0001750�00000006045�11476457062�021556� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/perl -w # This file is part of LibParserUtils. # Licensed under the MIT License, # http://www.opensource.org/licenses/mit-license.php # Copyright 2010 Daniel Silverstone # John-Mark Bell use strict; use constant ALIAS_FILE => 'build/Aliases'; use constant ALIAS_INC => 'src/charset/aliases.inc'; use constant UNICODE_CHARSETS => [ qr'^ISO-10646-UCS-[24]$', qr'^UTF-16', qr'^UTF-8$', qr'^UTF-32' ]; open(INFILE, "<", ALIAS_FILE) || die "Unable to open " . ALIAS_FILE; my %charsets; while (my $line = ) { last unless (defined $line); next if ($line =~ /^#/); chomp $line; next if ($line eq ''); my @elements = split /\s+/, $line; my $canon = shift @elements; my $mibenum = shift @elements; $charsets{$canon} = [$mibenum, \@elements]; } close(INFILE); my $unicodeexp = ""; my $output = <<'EOH'; /* * This file is part of LibParserUtils. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2010 The NetSurf Project. * * Note: This file is automatically generated by make-aliases.pl * * Do not edit file file, changes will be overwritten during build. */ static parserutils_charset_aliases_canon canonical_charset_names[] = { EOH my %aliases; my $canonnr = 0; foreach my $canon (sort keys %charsets) { my ($mibenum, $elements) = @{$charsets{$canon}}; # Ordering must match struct in src/charset/aliases.h $output .= "\t{ " . $mibenum . ", " . length($canon) . ', "' . $canon . '" },' . "\n"; my $isunicode = 0; foreach my $unirexp (@{UNICODE_CHARSETS()}) { $isunicode = 1 if ($canon =~ $unirexp); } if ($isunicode == 1) { $unicodeexp .= "((x) == $mibenum) || "; } $canon =~ y/A-Z/a-z/; $canon =~ s/[^a-z0-9]//g; $aliases{$canon} = $canonnr; foreach my $alias (@$elements) { $alias =~ y/A-Z/a-z/; $alias =~ s/[^a-z0-9]//g; $aliases{$alias} = $canonnr; } $canonnr += 1; } $output .= "};\n\nstatic const uint16_t charset_aliases_canon_count = ${canonnr};\n\n"; $output .= <<'EOT'; typedef struct { uint16_t name_len; const char *name; parserutils_charset_aliases_canon *canon; } parserutils_charset_aliases_alias; static parserutils_charset_aliases_alias charset_aliases[] = { EOT my $aliascount = 0; foreach my $alias (sort keys %aliases) { my $canonnr = $aliases{$alias}; $output .= "\t{ " . length($alias) . ', "' . $alias . '", &canonical_charset_names[' . $canonnr . "] },\n"; $aliascount += 1; } $output .= "};\n\n"; # Drop the final " || " chop $unicodeexp; chop $unicodeexp; chop $unicodeexp; chop $unicodeexp; $output .= <<"EOS"; static const uint16_t charset_aliases_count = ${aliascount}; #define MIBENUM_IS_UNICODE(x) ($unicodeexp) EOS if (open(EXISTING, "<", ALIAS_INC)) { local $/ = undef(); my $now = ; undef($output) if ($output eq $now); close(EXISTING); } if (defined($output)) { open(OUTF, ">", ALIAS_INC); print OUTF $output; close(OUTF); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/testtools/���������������������������������������������������0000775�0001750�0001750�00000000000�11734430235�020706� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/testtools/testrunner.pl��������������������������������������0000664�0001750�0001750�00000012751�11476511774�023475� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/perl # # Testcase runner for libhubbub # # Usage: testrunner [] # # Operates upon INDEX files described in the README. # Locates and executes testcases, feeding data files to programs # as appropriate. # Logs testcase output to file. # Aborts test sequence on detection of error. # use warnings; use strict; use File::Spec; use IO::Select; use IPC::Open3; use Symbol; if (@ARGV < 3) { print "Usage: testrunner.pl []\n"; exit; } # Get directories my $builddir = shift @ARGV; my $directory = shift @ARGV; my $prefix = shift @ARGV; # Get EXE extension (if any) my $exeext = ""; $exeext = shift @ARGV if (@ARGV > 0); # Open log file and /dev/null open(LOG, ">$builddir/testlog") or die "Failed opening test log"; open(NULL, "+<", File::Spec->devnull) or die "Failed opening /dev/null"; # Open testcase index open(TINDEX, "<$directory/INDEX") or die "Failed opening test INDEX"; # Parse testcase index, looking for testcases while (my $line = ) { next if ($line =~ /^(#.*)?$/); # Found one; decompose (my $test, my $desc, my $data) = split /\t+/, $line; # Strip whitespace $test =~ s/^\s+|\s+$//g; $desc =~ s/^\s+|\s+$//g; $data =~ s/^\s+|\s+$//g if ($data); # Append prefix & EXE extension to binary name $test = $prefix . $test . $exeext; print "Test: $desc\n"; if ($data) { # Testcase has external data files # Open datafile index open(DINDEX, "<$directory/data/$data/INDEX") or die "Failed opening $directory/data/$data/INDEX"; # Parse datafile index, looking for datafiles while (my $dentry = ) { next if ($dentry =~ /^(#.*)?$/); # Found one; decompose (my $dtest, my $ddesc) = split /\t+/, $dentry; # Strip whitespace $dtest =~ s/^\s+|\s+$//g; $ddesc =~ s/^\s+|\s+$//g; print LOG "Running $builddir/$test " . "$directory/data/$data/$dtest\n"; # Make message fit on an 80 column terminal my $msg = " ==> $test [$data/$dtest]"; $msg = $msg . "." x (80 - length($msg) - 8); print $msg; # Run testcase run_test("$builddir/$test", "$directory/data/$data/$dtest"); } close(DINDEX); } else { # Testcase has no external data files print LOG "Running $builddir/$test\n"; # Make message fit on an 80 column terminal my $msg = " ==> $test"; $msg = $msg . "." x (80 - length($msg) - 8); print $msg; # Run testcase run_test("$builddir/$test"); } print "\n"; } # Clean up close(TINDEX); close(NULL); close(LOG); sub run_test { my @errors; # Handles for communicating with the child my ($out, $err); $err = gensym(); # Apparently, this is required my $pid; # Invoke child eval { $pid = open3("&new(); $selector->add($out, $err); my $last = "FAIL"; my $outcont = 0; my $errcont = 0; # Marshal testcase output to log file while (my @ready = $selector->can_read) { foreach my $fh (@ready) { my $input; # Read up to 4096 bytes from handle my $len = sysread($fh, $input, 4096); if (!defined $len) { die "Error reading from child: $!\n"; } elsif ($len == 0) { # EOF, so remove handle $selector->remove($fh); next; } else { # Split into lines my @lines = split('\n', $input); # Grab the last character of the input my $lastchar = substr($input, -1, 1); if ($fh == $out) { # Child's stdout foreach my $l (@lines) { # Last line of previous read # was incomplete, and this is # the first line of this read # Simply contatenate. if ($outcont == 1 && $l eq $lines[0]) { print LOG "$l\n"; $last .= $l; # Last char of this read was # not '\n', so don't terminate # line in log. } elsif ($lastchar ne '\n' && $l eq $lines[-1]) { print LOG " $l"; $last = $l; # Normal behaviour, just print # the line to the log. } else { print LOG " $l\n"; $last = $l; } } # Flag whether last line was incomplete # for next time. if ($lastchar ne '\n') { $outcont = 1; } else { $outcont = 0; } } elsif ($fh == $err) { # Child's stderr if ($errcont == 1) { # Continuation required, # concatenate first line of # this read with last of # previous, then append the # rest from this read. $errors[-1] .= $lines[0]; push(@errors, @lines[1 .. -1]); } else { # Normal behaviour, just append push(@errors, @lines); } # Flag need for continuation if ($lastchar ne '\n') { $errcont = 1; } else { $errcont = 0; } } else { die "Unexpected file handle\n"; } } } } # Last line of child's output may not be terminated, so ensure it # is in the log, for readability. print LOG "\n"; # Reap child waitpid($pid, 0); # Catch non-zero exit status and turn it into failure if ($? != 0) { my $status = $? & 127; if ($status != 0) { print LOG " FAIL: Exit status $status\n"; } $last = "FAIL"; } # Only interested in first 4 characters of last line $last = substr($last, 0, 4); # Convert all non-pass to fail if ($last ne "PASS") { $last = "FAIL"; } print "$last\n"; # Bail, noisily, on failure if ($last eq "FAIL") { # Write any stderr output to the log foreach my $error (@errors) { print LOG " $error\n"; } print "\n\nFailure detected: consult log file\n\n\n"; exit(1); } } �����������������������netsurf-2.9/libparserutils-0.1.1/build/Doxyfile�����������������������������������������������������0000664�0001750�0001750�00000143722�11131520454�020357� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Doxyfile 1.4.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = Libparserutils # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = build/docs # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = include src # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py FILE_PATTERNS = *.c *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */.svn/* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that a graph may be further truncated if the graph's # image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH # and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), # the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO ����������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/conv.pl������������������������������������������������������0000775�0001750�0001750�00000001530�11060012135�020135� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/perl use warnings; use strict; # Convert Unicode mapping tables to C structures # Input files may be found at http://unicode.org/Public/MAPPINGS # # Usage: conv.pl die "Usage: conv.pl \n" if (scalar(@ARGV) != 1); my @table; open MAP, "<$ARGV[0]" or die "Failed opening $ARGV[0]: $!\n"; while () { next if (/^#/); my @parts = split(/\s+/); # Ignore ASCII part next if (hex($parts[0]) < 0x80); # Convert undefined entries to U+FFFF if ($parts[1] =~ /^#/) { push(@table, "0xFFFF"); } else { push(@table, $parts[1]); } } close MAP; # You'll have to go through and fix up the structure name print "static uint32_t ${ARGV[0]}[128] = {\n\t"; my $count = 0; foreach my $item (@table) { print "$item, "; $count++; if ($count % 8 == 0 && $count != 128) { print "\n\t"; } } print "\n};\n\n"; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/build/Aliases������������������������������������������������������0000664�0001750�0001750�00000030666�11476506046�020174� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# > Unicode:Files.Aliases # Mapping of character set encoding names to their canonical form # # Lines starting with a '#' are comments, blank lines are ignored. # # Based on http://www.iana.org/assignments/character-sets and # http://www.iana.org/assignments/ianacharset-mib # # Canonical Form MIBenum Aliases... # US-ASCII 3 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII ISO646-US ANSI_X3.4-1968 us IBM367 cp367 csASCII ISO-10646-UTF-1 27 csISO10646UTF1 ISO_646.basic:1983 28 ref csISO646basic1983 INVARIANT 29 csINVARIANT ISO_646.irv:1983 30 iso-ir-2 irv csISO2IntlRefVersion BS_4730 20 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom NATS-SEFI 31 iso-ir-8-1 csNATSSEFI NATS-SEFI-ADD 32 iso-ir-8-2 csNATSSEFIADD NATS-DANO 33 iso-ir-9-1 csNATSDANO NATS-DANO-ADD 34 iso-ir-9-2 csNATSDANOADD SEN_850200_B 35 iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish SEN_850200_C 21 iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames KS_C_5601-1987 36 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 ISO-2022-KR 37 csISO2022KR EUC-KR 38 csEUCKR EUCKR ISO-2022-JP 39 csISO2022JP ISO-2022-JP-2 40 csISO2022JP2 ISO-2022-CN 104 ISO-2022-CN-EXT 105 JIS_C6220-1969-jp 41 JIS_C6220-1969 iso-ir-13 katakana x0201-7 csISO13JISC6220jp JIS_C6220-1969-ro 42 iso-ir-14 jp ISO646-JP csISO14JISC6220ro IT 22 iso-ir-15 ISO646-IT csISO15Italian PT 43 iso-ir-16 ISO646-PT csISO16Portuguese ES 23 iso-ir-17 ISO646-ES csISO17Spanish greek7-old 44 iso-ir-18 csISO18Greek7Old latin-greek 45 iso-ir-19 csISO19LatinGreek DIN_66003 24 iso-ir-21 de ISO646-DE csISO21German NF_Z_62-010_(1973) 46 iso-ir-25 ISO646-FR1 csISO25French Latin-greek-1 47 iso-ir-27 csISO27LatinGreek1 ISO_5427 48 iso-ir-37 csISO5427Cyrillic JIS_C6226-1978 49 iso-ir-42 csISO42JISC62261978 BS_viewdata 50 iso-ir-47 csISO47BSViewdata INIS 51 iso-ir-49 csISO49INIS INIS-8 52 iso-ir-50 csISO50INIS8 INIS-cyrillic 53 iso-ir-51 csISO51INISCyrillic ISO_5427:1981 54 iso-ir-54 ISO5427Cyrillic1981 ISO_5428:1980 55 iso-ir-55 csISO5428Greek GB_1988-80 56 iso-ir-57 cn ISO646-CN csISO57GB1988 GB_2312-80 57 iso-ir-58 chinese csISO58GB231280 NS_4551-1 25 iso-ir-60 ISO646-NO no csISO60DanishNorwegian csISO60Norwegian1 NS_4551-2 58 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 NF_Z_62-010 26 iso-ir-69 ISO646-FR fr csISO69French videotex-suppl 59 iso-ir-70 csISO70VideotexSupp1 PT2 60 iso-ir-84 ISO646-PT2 csISO84Portuguese2 ES2 61 iso-ir-85 ISO646-ES2 csISO85Spanish2 MSZ_7795.3 62 iso-ir-86 ISO646-HU hu csISO86Hungarian JIS_C6226-1983 63 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 greek7 64 iso-ir-88 csISO88Greek7 ASMO_449 65 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 iso-ir-90 66 csISO90 JIS_C6229-1984-a 67 iso-ir-91 jp-ocr-a csISO91JISC62291984a JIS_C6229-1984-b 68 iso-ir-92 ISO646-JP-OCR-B jp-ocr-b csISO92JISC62991984b JIS_C6229-1984-b-add 69 iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd JIS_C6229-1984-hand 70 iso-ir-94 jp-ocr-hand csISO94JIS62291984hand JIS_C6229-1984-hand-add 71 iso-ir-95 jp-ocr-hand-add csISO95JIS62291984handadd JIS_C6229-1984-kana 72 iso-ir-96 csISO96JISC62291984kana ISO_2033-1983 73 iso-ir-98 e13b csISO2033 ANSI_X3.110-1983 74 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS ISO-8859-1 4 iso-ir-100 ISO_8859-1 ISO_8859-1:1987 latin1 l1 IBM819 CP819 csISOLatin1 8859_1 ISO8859-1 ISO-8859-2 5 iso-ir-101 ISO_8859-2 ISO_8859-2:1987 latin2 l2 csISOLatin2 8859_2 ISO8859-2 T.61-7bit 75 iso-ir-102 csISO102T617bit T.61-8bit 76 T.61 iso-ir-103 csISO103T618bit ISO-8859-3 6 iso-ir-109 ISO_8859-3 ISO_8859-3:1988 latin3 l3 csISOLatin3 8859_3 ISO8859-3 ISO-8859-4 7 iso-ir-110 ISO_8859-4 ISO_8859-4:1988 latin4 l4 csISOLatin4 8859_4 ISO8859-4 ECMA-cyrillic 77 iso-ir-111 KOI8-E csISO111ECMACyrillic CSA_Z243.4-1985-1 78 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 CSA_Z243.4-1985-2 79 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 CSA_Z243.4-1985-gr 80 iso-ir-123 csISO123CSAZ24341985gr ISO-8859-6 9 iso-ir-127 ISO_8859-6 ISO_8859-6:1987 ECMA-114 ASMO-708 arabic csISOLatinArabic ISO-8859-6-E 81 csISO88596E ISO_8859-6-E ISO-8859-6-I 82 csISO88596I ISO_8859-6-I ISO-8859-7 10 iso-ir-126 ISO_8859-7 ISO_8859-7:1987 ELOT_928 ECMA-118 greek greek8 csISOLatinGreek 8859_7 ISO8859-7 T.101-G2 83 iso-ir-128 csISO128T101G2 ISO-8859-8 11 iso-ir-138 ISO_8859-8 ISO_8859-8:1988 hebrew csISOLatinHebrew 8859_8 ISO8859-8 ISO-8859-8-E 84 csISO88598E ISO_8859-8-E ISO-8859-8-I 85 csISO88598I ISO_8859-8-I CSN_369103 86 iso-ir-139 csISO139CSN369103 JUS_I.B1.002 87 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 ISO_6937-2-add 14 iso-ir-142 csISOTextComm IEC_P27-1 88 iso-ir-143 csISO143IECP271 ISO-8859-5 8 iso-ir-144 ISO_8859-5 ISO_8859-5:1988 cyrillic csISOLatinCyrillic 8859_5 ISO8859-5 JUS_I.B1.003-serb 89 iso-ir-146 serbian csISO146Serbian JUS_I.B1.003-mac 90 macedonian iso-ir-147 csISO147Macedonian ISO-8859-9 12 iso-ir-148 ISO_8859-9 ISO_8859-9:1989 latin5 l5 csISOLatin5 8859_9 ISO8859-9 greek-ccitt 91 iso-ir-150 csISO150 csISO150GreekCCITT NC_NC00-10:81 92 cuba iso-ir-151 ISO646-CU csISO151Cuba ISO_6937-2-25 93 iso-ir-152 csISO6937Add GOST_19768-74 94 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 ISO_8859-supp 95 iso-ir-154 latin1-2-5 csISO8859Supp ISO_10367-box 96 iso-ir-155 csISO10367Box ISO-8859-10 13 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 8859_10 ISO8859-10 latin-lap 97 lap iso-ir-158 csISO158Lap JIS_X0212-1990 98 x0212 iso-ir-159 csISO159JISX02121990 DS_2089 99 DS2089 ISO646-DK dk csISO646Danish us-dk 100 csUSDK dk-us 101 csDKUS JIS_X0201 15 X0201 csHalfWidthKatakana KSC5636 102 ISO646-KR csKSC5636 ISO-10646-UCS-2 1000 csUnicode UCS-2 UCS2 ISO-10646-UCS-4 1001 csUCS4 UCS-4 UCS4 DEC-MCS 2008 dec csDECMCS hp-roman8 2004 roman8 r8 csHPRoman8 macintosh 2027 mac csMacintosh MACROMAN MAC-ROMAN X-MAC-ROMAN IBM037 2028 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl csIBM037 IBM038 2029 EBCDIC-INT cp038 csIBM038 IBM273 2030 CP273 csIBM273 IBM274 2031 EBCDIC-BE CP274 csIBM274 IBM275 2032 EBCDIC-BR cp275 csIBM275 IBM277 2033 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 IBM278 2034 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 IBM280 2035 CP280 ebcdic-cp-it csIBM280 IBM281 2036 EBCDIC-JP-E cp281 csIBM281 IBM284 2037 CP284 ebcdic-cp-es csIBM284 IBM285 2038 CP285 ebcdic-cp-gb csIBM285 IBM290 2039 cp290 EBCDIC-JP-kana csIBM290 IBM297 2040 cp297 ebcdic-cp-fr csIBM297 IBM420 2041 cp420 ebcdic-cp-ar1 csIBM420 IBM423 2042 cp423 ebcdic-cp-gr csIBM423 IBM424 2043 cp424 ebcdic-cp-he csIBM424 IBM437 2011 cp437 437 csPC8CodePage437 IBM500 2044 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 IBM775 2087 cp775 csPC775Baltic IBM850 2009 cp850 850 csPC850Multilingual IBM851 2045 cp851 851 csIBM851 IBM852 2010 cp852 852 csPCp852 IBM855 2046 cp855 855 csIBM855 IBM857 2047 cp857 857 csIBM857 IBM860 2048 cp860 860 csIBM860 IBM861 2049 cp861 861 cp-is csIBM861 IBM862 2013 cp862 862 csPC862LatinHebrew IBM863 2050 cp863 863 csIBM863 IBM864 2051 cp864 csIBM864 IBM865 2052 cp865 865 csIBM865 IBM866 2086 cp866 866 csIBM866 IBM868 2053 CP868 cp-ar csIBM868 IBM869 2054 cp869 869 cp-gr csIBM869 IBM870 2055 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 IBM871 2056 CP871 ebcdic-cp-is csIBM871 IBM880 2057 cp880 EBCDIC-Cyrillic csIBM880 IBM891 2058 cp891 csIBM891 IBM903 2059 cp903 csIBM903 IBM904 2060 cp904 904 csIBBM904 IBM905 2061 CP905 ebcdic-cp-tr csIBM905 IBM918 2062 CP918 ebcdic-cp-ar2 csIBM918 IBM1026 2063 CP1026 csIBM1026 EBCDIC-AT-DE 2064 csIBMEBCDICATDE EBCDIC-AT-DE-A 2065 csEBCDICATDEA EBCDIC-CA-FR 2066 csEBCDICCAFR EBCDIC-DK-NO 2067 csEBCDICDKNO EBCDIC-DK-NO-A 2068 csEBCDICDKNOA EBCDIC-FI-SE 2069 csEBCDICFISE EBCDIC-FI-SE-A 2070 csEBCDICFISEA EBCDIC-FR 2071 csEBCDICFR EBCDIC-IT 2072 csEBCDICIT EBCDIC-PT 2073 csEBCDICPT EBCDIC-ES 2074 csEBCDICES EBCDIC-ES-A 2075 csEBCDICESA EBCDIC-ES-S 2076 csEBCDICESS EBCDIC-UK 2077 csEBCDICUK EBCDIC-US 2078 csEBCDICUS UNKNOWN-8BIT 2079 csUnknown8BiT MNEMONIC 2080 csMnemonic MNEM 2081 csMnem VISCII 2082 csVISCII VIQR 2083 csVIQR KOI8-R 2084 csKOI8R KOI8-U 2088 IBM00858 2089 CCSID00858 CP00858 PC-Multilingual-850+euro IBM00924 2090 CCSID00924 CP00924 ebcdic-Latin9--euro IBM01140 2091 CCSID01140 CP01140 ebcdic-us-37+euro IBM01141 2092 CCSID01141 CP01141 ebcdic-de-273+euro IBM01142 2093 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro IBM01143 2094 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro IBM01144 2095 CCSID01144 CP01144 ebcdic-it-280+euro IBM01145 2096 CCSID01145 CP01145 ebcdic-es-284+euro IBM01146 2097 CCSID01146 CP01146 ebcdic-gb-285+euro IBM01147 2098 CCSID01147 CP01147 ebcdic-fr-297+euro IBM01148 2099 CCSID01148 CP01148 ebcdic-international-500+euro IBM01149 2100 CCSID01149 CP01149 ebcdic-is-871+euro Big5-HKSCS 2101 IBM1047 2102 IBM-1047 PTCP154 2103 csPTCP154 PT154 CP154 Cyrillic-Asian Amiga-1251 2104 Ami1251 Amiga1251 Ami-1251 KOI7-switched 2105 UNICODE-1-1 1010 csUnicode11 SCSU 1011 UTF-7 1012 UTF-16BE 1013 UTF-16LE 1014 UTF-16 1015 CESU-8 1016 csCESU-8 UTF-32 1017 UTF-32BE 1018 UTF-32LE 1019 BOCU-1 1020 csBOCU-1 UNICODE-1-1-UTF-7 103 csUnicode11UTF7 UTF-8 106 UNICODE-1-1-UTF-8 UNICODE-2-0-UTF-8 utf8 ISO-8859-13 109 8859_13 ISO8859-13 ISO-8859-14 110 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic l8 8859_14 ISO8859-14 ISO-8859-15 111 ISO_8859-15 Latin-9 8859_15 ISO8859-15 ISO-8859-16 112 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 GBK 113 CP936 MS936 windows-936 GB18030 114 OSD_EBCDIC_DF04_15 115 OSD_EBCDIC_DF03_IRV 116 OSD_EBCDIC_DF04_1 117 JIS_Encoding 16 csJISEncoding Shift_JIS 17 MS_Kanji csShiftJIS X-SJIS Shift-JIS EUC-JP 18 csEUCPkdFmtJapanese Extended_UNIX_Code_Packed_Format_for_Japanese EUCJP Extended_UNIX_Code_Fixed_Width_for_Japanese 19 csEUCFixWidJapanese ISO-10646-UCS-Basic 1002 csUnicodeASCII ISO-10646-Unicode-Latin1 1003 csUnicodeLatin1 ISO-10646 ISO-Unicode-IBM-1261 1005 csUnicodeIBM1261 ISO-Unicode-IBM-1268 1006 csUnicodeIBM1268 ISO-Unicode-IBM-1276 1007 csUnicodeIBM1276 ISO-Unicode-IBM-1264 1008 csUnicodeIBM1264 ISO-Unicode-IBM-1265 1009 csUnicodeIBM1265 ISO-8859-1-Windows-3.0-Latin-1 2000 csWindows30Latin1 ISO-8859-1-Windows-3.1-Latin-1 2001 csWindows31Latin1 ISO-8859-2-Windows-Latin-2 2002 csWindows31Latin2 ISO-8859-9-Windows-Latin-5 2003 csWindows31Latin5 Adobe-Standard-Encoding 2005 csAdobeStandardEncoding Ventura-US 2006 csVenturaUS Ventura-International 2007 csVenturaInternational PC8-Danish-Norwegian 2012 csPC8DanishNorwegian PC8-Turkish 2014 csPC8Turkish IBM-Symbols 2015 csIBMSymbols IBM-Thai 2016 csIBMThai HP-Legal 2017 csHPLegal HP-Pi-font 2018 csHPPiFont HP-Math8 2019 csHPMath8 Adobe-Symbol-Encoding 2020 csHPPSMath HP-DeskTop 2021 csHPDesktop Ventura-Math 2022 csVenturaMath Microsoft-Publishing 2023 csMicrosoftPublishing Windows-31J 2024 csWindows31J GB2312 2025 csGB2312 EUC-CN EUCCN CN-GB Big5 2026 csBig5 BIG-FIVE BIG-5 CN-BIG5 BIG_FIVE x-x-big5 windows-1250 2250 CP1250 MS-EE windows-1251 2251 CP1251 MS-CYRL windows-1252 2252 CP1252 MS-ANSI windows-1253 2253 CP1253 MS-GREEK windows-1254 2254 CP1254 MS-TURK windows-1255 2255 windows-1256 2256 CP1256 MS-ARAB windows-1257 2257 CP1257 WINBALTRIM windows-1258 2258 TIS-620 2259 HZ-GB-2312 2085 # Additional encodings not defined by IANA # Arbitrary allocations #CP737 3001 #CP853 3002 #CP856 3003 CP874 3004 WINDOWS-874 #CP922 3005 #CP1046 3006 #CP1124 3007 #CP1125 3008 WINDOWS-1125 #CP1129 3009 #CP1133 3010 IBM-CP1133 #CP1161 3011 IBM-1161 IBM1161 CSIBM1161 #CP1162 3012 IBM-1162 IBM1162 CSIBM1162 #CP1163 3013 IBM-1163 IBM1163 CSIBM1163 #GEORGIAN-ACADEMY 3014 #GEORGIAN-PS 3015 #KOI8-RU 3016 #KOI8-T 3017 #MACARABIC 3018 X-MAC-ARABIC MAC-ARABIC #MACCROATIAN 3019 X-MAC-CROATIAN MAC-CROATIAN #MACGREEK 3020 X-MAC-GREEK MAC-GREEK #MACHEBREW 3021 X-MAC-HEBREW MAC-HEBREW #MACICELAND 3022 X-MAC-ICELAND MAC-ICELAND #MACROMANIA 3023 X-MAC-ROMANIA MAC-ROMANIA #MACTHAI 3024 X-MAC-THAI MAC-THAI #MACTURKISH 3025 X-MAC-TURKISH MAC-TURKISH #MULELAO-1 3026 CP949 3027 WINDOWS-949 # From Unicode Lib ISO-IR-182 4000 ISO-IR-197 4002 ISO-2022-JP-1 4008 MACCYRILLIC 4009 X-MAC-CYRILLIC MAC-CYRILLIC MACUKRAINE 4010 X-MAC-UKRAINIAN MAC-UKRAINIAN MACCENTRALEUROPE 4011 X-MAC-CENTRALEURROMAN MAC-CENTRALEURROMAN JOHAB 4012 ISO-8859-11 4014 iso-ir-166 ISO_8859-11 ISO8859-11 8859_11 X-CURRENT 4999 X-SYSTEM X-ACORN-LATIN1 5001 X-ACORN-FUZZY 5002 ��������������������������������������������������������������������������netsurf-2.9/libparserutils-0.1.1/Makefile.config����������������������������������������������������0000664�0001750�0001750�00000000306�11554115215�020450� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Configuration Makefile fragment # Disable use of iconv in the input filter # CFLAGS := $(CFLAGS) -DWITHOUT_ICONV_FILTER # Cater for local configuration changes -include Makefile.config.override ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/Makefile��������������������������������������������������������������������������������0000664�0001750�0001750�00000006623�11734430227�013520� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/make # # NetSurf Source makefile for libraries and browser export TARGET ?= gtk export PKG_CONFIG_PATH = $(TMP_PREFIX)/lib/pkgconfig TMP_PREFIX := $(CURDIR)/prefix-$(TARGET) #NetSurf NETSURF_BASE := netsurf NETSURF_VERS := 2.9 NETSURF_TARG := $(NETSURF_BASE)-$(NETSURF_VERS) #NetSurf libraries LIBPARSERUTILS_BASE := libparserutils LIBPARSERUTILS_VERS := 0.1.1 LIBPARSERUTILS_TARG := $(LIBPARSERUTILS_BASE)-$(LIBPARSERUTILS_VERS) LIBWAPCAPLET_BASE := libwapcaplet LIBWAPCAPLET_VERS := 0.1.1 LIBWAPCAPLET_TARG := $(LIBWAPCAPLET_BASE)-$(LIBWAPCAPLET_VERS) LIBCSS_BASE := libcss LIBCSS_VERS := 0.1.2 LIBCSS_TARG := $(LIBCSS_BASE)-$(LIBCSS_VERS) LIBHUBBUB_BASE := hubbub LIBHUBBUB_VERS := 0.1.2 LIBHUBBUB_TARG := $(LIBHUBBUB_BASE)-$(LIBHUBBUB_VERS) LIBNSBMP_BASE := libnsbmp LIBNSBMP_VERS := 0.0.3 LIBNSBMP_TARG := $(LIBNSBMP_BASE)-$(LIBNSBMP_VERS) LIBNSGIF_BASE := libnsgif LIBNSGIF_VERS := 0.0.3 LIBNSGIF_TARG := $(LIBNSGIF_BASE)-$(LIBNSGIF_VERS) LIBNSFB_BASE := libnsfb LIBNSFB_VERS := 0.0.2 LIBNSFB_TARG := $(LIBNSFB_BASE)-$(LIBNSFB_VERS) LIBPENCIL_BASE := libpencil LIBPENCIL_VERS := 0.0.1 LIBPENCIL_TARG := $(LIBPENCIL_BASE)-$(LIBPENCIL_VERS) LIBROSPRITE_BASE := librosprite LIBROSPRITE_VERS := 0.0.2 LIBROSPRITE_TARG := $(LIBROSPRITE_BASE)-$(LIBROSPRITE_VERS) LIBRUFL_BASE := librufl LIBRUFL_VERS := 0.0.1 LIBRUFL_TARG := $(LIBRUFL_BASE)-$(LIBRUFL_VERS) LIBSVGTINY_BASE := libsvgtiny LIBSVGTINY_VERS := 0.0.2 LIBSVGTINY_TARG := $(LIBSVGTINY_BASE)-$(LIBSVGTINY_VERS) #Library Target list NSLIBTARG := $(LIBPARSERUTILS_TARG) $(LIBWAPCAPLET_TARG) $(LIBCSS_TARG) \ $(LIBHUBBUB_TARG) $(LIBNSBMP_TARG) $(LIBNSGIF_TARG) ABLIBS := $(NSLIBTARG) $(LIBSVGTINY_TARG) SOURCELIBS := $(ABLIBS) $(LIBNSFB_TARG) $(LIBPENCIL_TARG) \ $(LIBROSPRITE_TARG) $(LIBRUFL_TARG) SVNURI := svn://svn.netsurf-browser.org ABDIR := netsurfbuild-v$(NETSURF_VERS) define do_checkout svn checkout --quiet $(SVNURI)$1 $2 endef define do_export svn export --quiet $(SVNURI)$1 $2 endef define do_export_and_tar svn export --quiet $(SVNURI)$1 $(NETSURF_TARG)/$2 tar -C $(NETSURF_TARG) -czf $2-src.tar.gz $2 endef define do_clean $(MAKE) distclean --directory=$1 TARGET=$(TARGET) endef define do_prefix_install $(MAKE) install --directory=$1 TARGET=$(TARGET) PREFIX=$(TMP_PREFIX) DESTDIR= endef .PHONY: build install clean source autobuild build: $(TMP_PREFIX)/build-stamp $(TMP_PREFIX)/build-stamp: mkdir -p $(TMP_PREFIX)/include mkdir -p $(TMP_PREFIX)/lib $(foreach L,$(NSLIBTARG),$(call do_prefix_install,$(L))) $(MAKE) --directory=$(NETSURF_TARG) PREFIX=$(PREFIX) TARGET=$(TARGET) touch $@ install: $(TMP_PREFIX)/build-stamp $(MAKE) install --directory=$(NETSURF_TARG) TARGET=$(TARGET) PREFIX=$(PREFIX) DESTDIR=$(DESTDIR) clean: $(RM) -r $(TMP_PREFIX) $(foreach L,$(NSLIBTARG),$(call do_clean,$(L))) $(MAKE) clean --directory=$(NETSURF_TARG) TARGET=$(TARGET) source: $(NETSURF_TARG)-full-src.tar.gz $(NETSURF_TARG)-full-src.tar.gz: Makefile $(RM) -r $(NETSURF_TARG) mkdir $(NETSURF_TARG) cp Makefile $(NETSURF_TARG)/Makefile $(foreach L,$(SOURCELIBS) $(NETSURF_TARG), \ $(call do_export_and_tar,/tags/$(subst -,/,$(L)),$(L))) tar -czf $@ $(NETSURF_TARG) autobuild: $(call do_export,/trunk/netsurfbuild,$(ABDIR)) mkdir -p $(ABDIR)/downloads/releases $(call do_checkout,/trunk/netsurfweb,$(ABDIR)/netsurfweb) $(foreach L,$(ABLIBS) $(NETSURF_TARG), \ $(call do_checkout,/tags/$(subst -,/,$(L)),$(ABDIR)/$(firstword $(subst -, ,$(L))))) �������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/����������������������������������������������������������������������������0000775�0001750�0001750�00000000000�11734430321�014040� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/��������������������������������������������������������������������0000775�0001750�0001750�00000000000�11734430321�015511� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/download.h����������������������������������������������������������0000664�0001750�0001750�00000005223�11531055305�017473� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2010 John-Mark Bell * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file Core download context (interface) */ #ifndef NETSURF_DESKTOP_DOWNLOAD_H_ #define NETSURF_DESKTOP_DOWNLOAD_H_ #include "utils/errors.h" struct gui_window; struct llcache_handle; /** Type of a download context */ typedef struct download_context download_context; /** * Create a download context * * \param llcache Low-level cache handle for download * \param parent Parent window, for UI * \return NSERROR_OK on success, appropriate error otherwise * * This must only be called by the core browser window fetch infrastructure. * Ownership of the download context object created is passed to the frontend. */ nserror download_context_create(struct llcache_handle *llcache, struct gui_window *parent); /** * Destroy a download context * * \param ctx Context to destroy * * Called by the frontend when it has finished with a download context */ void download_context_destroy(download_context *ctx); /** * Abort a download fetch * * \param ctx Context to abort * * Called by the frontend to abort a download. * The context must be destroyed independently. */ void download_context_abort(download_context *ctx); /** * Retrieve the URL for a download * * \param ctx Context to retrieve URL from * \return URL string */ const char *download_context_get_url(const download_context *ctx); /** * Retrieve the MIME type for a download * * \param ctx Context to retrieve MIME type from * \return MIME type string */ const char *download_context_get_mime_type(const download_context *ctx); /** * Retrieve total byte length of download * * \param ctx Context to retrieve byte length from * \return Total length, in bytes, or 0 if unknown */ unsigned long download_context_get_total_length(const download_context *ctx); /** * Retrieve the filename for a download * * \param ctx Context to retrieve filename from * \return Filename string */ const char *download_context_get_filename(const download_context *ctx); #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/thumbnail.c���������������������������������������������������������0000664�0001750�0001750�00000005215�11625200212�017634� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2011 Michael Drake * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file * Core thumbnail handling (implementation). */ #include #include #include "content/content.h" #include "content/hlcache.h" #include "desktop/browser.h" #include "desktop/knockout.h" #include "desktop/options.h" #include "desktop/plotters.h" #include "desktop/thumbnail.h" #include "utils/log.h" /** * Get scale at which thumbnail will be rendered for a given content and * thumbnail size. * * \param content The content to redraw for thumbnail * \param width The thumbnail width * \return scale thumbnail will be rendered at * * Units for width and height are pixels. */ static float thumbnail_get_redraw_scale(struct hlcache_handle *content, int width) { assert(content); if (content_get_width(content)) return (float)width / (float)content_get_width(content); else return 1.0; } /* exported interface, documented in thumbnail.h */ bool thumbnail_redraw(struct hlcache_handle *content, int width, int height, const struct redraw_context *ctx) { struct redraw_context new_ctx = *ctx; struct rect clip; struct content_redraw_data data; float scale; bool plot_ok = true; assert(content); if (ctx->plot->option_knockout) knockout_plot_start(ctx, &new_ctx); /* Set clip rectangle to required thumbnail size */ clip.x0 = 0; clip.y0 = 0; clip.x1 = width; clip.y1 = height; new_ctx.plot->clip(&clip); /* Plot white background */ plot_ok &= new_ctx.plot->rectangle(clip.x0, clip.y0, clip.x1, clip.y1, plot_style_fill_white); /* Find the scale we're using */ scale = thumbnail_get_redraw_scale(content, width); /* Set up content redraw data */ data.x = 0; data.y = 0; data.width = width; data.height = height; data.background_colour = 0xFFFFFF; data.scale = scale; data.repeat_x = false; data.repeat_y = false; /* Render the content */ plot_ok &= content_redraw(content, &data, &clip, &new_ctx); if (ctx->plot->option_knockout) knockout_plot_end(); return plot_ok; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/save_pdf/�����������������������������������������������������������0000775�0001750�0001750�00000000000�11734430321�017300� 5����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/save_pdf/TODO�������������������������������������������������������0000664�0001750�0001750�00000001515�11024457557�020006� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������- finish all graphic primitives - allow adding raw bitmaps - make image-aware (embed the image in its native/original type if possible) - adjust content width to page width - divide output into multiple pages (not just the first one) - rearrange file structure - separate print-plotting as much as possible from window redrawing - add text-scaling (if not yet using the original font - make the default one have the same width) - add a save file.. dialogue - add utf support to Haru ( doable? ) - wait for browser to end fetching? - analyze and deal with performance issues(huge file hangs some pdf viewers, for example kpdf when viewing plotted http://www.onet.pl) - deal with to wide pages - when window layouting adds a horizontal scrollbar, we should treat it otherwise - either print horizontal or scale or, better, find a new layout.�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/save_pdf/font_haru.c������������������������������������������������0000664�0001750�0001750�00000022001�11232166276�021434� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2008 Adam Blokus * Copyright 2009 John Tytgat * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file * Font handling in Haru pdf documents (implementation). * * The functions were written to implement the same interface as the Pango ones * so that the usage of the latter wouldn't have to be modified. */ #include "utils/config.h" #ifdef WITH_PDF_EXPORT /*#define FONT_HARU_DEBUG */ #include #include #include #include #include #include "css/css.h" #include "css/utils.h" #include "desktop/options.h" #include "desktop/save_pdf/font_haru.h" #include "render/font.h" #include "utils/log.h" static bool haru_nsfont_init(HPDF_Doc *pdf, HPDF_Page *page, const char *string, char **string_nt, int length); static bool haru_nsfont_width(const plot_font_style_t *fstyle, const char *string, size_t length, int *width); static bool haru_nsfont_position_in_string(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x); static bool haru_nsfont_split(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x); static float pdf_text_scale = DEFAULT_EXPORT_SCALE; const struct font_functions haru_nsfont = { haru_nsfont_width, haru_nsfont_position_in_string, haru_nsfont_split }; /** * Haru error handler * for debugging purposes - it immediately exits the program on the first error, * as it would otherwise flood the user with all resulting complications, * covering the most important error source. */ static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void *user_data) { LOG(("ERROR: in font_haru \n\terror_no=%x\n\tdetail_no=%d\n", (HPDF_UINT)error_no, (HPDF_UINT)detail_no)); #ifdef FONT_HARU_DEBUG exit(1); #endif } static bool haru_nsfont_init(HPDF_Doc *pdf, HPDF_Page *page, const char *string, char **string_nt, int length) { *pdf = HPDF_New(error_handler, NULL); if (*pdf == NULL) return false; *page = HPDF_AddPage(*pdf); if (*page == NULL) { HPDF_Free(*pdf); return false; } *string_nt = malloc((length + 1) * sizeof(char)); if (*string_nt == NULL) { HPDF_Free(*pdf); return false; } memcpy(*string_nt, string, length); (*string_nt)[length] = '\0'; return true; } /** * Measure the width of a string. * * \param fstyle style for this text * \param string string to measure (no UTF-8 currently) * \param length length of string * \param width updated to width of string[0..length] * \return true on success, false on error and error reported */ bool haru_nsfont_width(const plot_font_style_t *fstyle, const char *string, size_t length, int *width) { HPDF_Doc pdf; HPDF_Page page; char *string_nt; HPDF_REAL width_real; *width = 0; if (length == 0) return true; if (!haru_nsfont_init(&pdf, &page, string, &string_nt, length)) return false; if (!haru_nsfont_apply_style(fstyle, pdf, page, NULL, NULL)) { free(string_nt); HPDF_Free(pdf); return false; } width_real = HPDF_Page_TextWidth(page, string_nt); *width = width_real; #ifdef FONT_HARU_DEBUG LOG(("Measuring string: %s ; Calculated width: %f %i",string_nt, width_real, *width)); #endif free(string_nt); HPDF_Free(pdf); return true; } /** * Find the position in a string where an x coordinate falls. * * \param fstyle style for this text * \param string string to measure (no UTF-8 currently) * \param length length of string * \param x x coordinate to search for * \param char_offset updated to offset in string of actual_x, [0..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported */ bool haru_nsfont_position_in_string(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { HPDF_Doc pdf; HPDF_Page page; char *string_nt; HPDF_UINT offset; HPDF_REAL real_width; if (!haru_nsfont_init(&pdf, &page, string, &string_nt, length)) return false; if (HPDF_Page_SetWidth(page, x) != HPDF_OK || !haru_nsfont_apply_style(fstyle, pdf, page, NULL, NULL)) { free(string_nt); HPDF_Free(pdf); return false; } offset = HPDF_Page_MeasureText(page, string_nt, x, HPDF_FALSE, &real_width); if (real_width < x) *char_offset = offset; else { assert(fabs(real_width - x) < FLT_EPSILON); assert(offset > 0); *char_offset = offset - 1; } /*TODO: this is only the right edge of the character*/ *actual_x = real_width; #ifdef FONT_HARU_DEBUG LOG(("Position in string: %s at x: %i; Calculated position: %i", string_nt, x, *char_offset)); #endif free(string_nt); HPDF_Free(pdf); return true; } /** * Find where to split a string to make it fit a width. * * \param fstyle style for this text * \param string string to measure (no UTF-8 currently) * \param length length of string * \param x width available * \param char_offset updated to offset in string of actual_x, [0..length] * \param actual_x updated to x coordinate of character closest to x * \return true on success, false on error and error reported */ bool haru_nsfont_split(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { HPDF_Doc pdf; HPDF_Page page; char *string_nt; HPDF_REAL real_width; HPDF_UINT offset; if (!haru_nsfont_init(&pdf, &page, string, &string_nt, length)) return false; if (HPDF_Page_SetWidth(page, x) != HPDF_OK || !haru_nsfont_apply_style(fstyle, pdf, page, NULL, NULL)) { free(string_nt); HPDF_Free(pdf); return false; } offset = HPDF_Page_MeasureText(page, string_nt, x, HPDF_TRUE, &real_width); #ifdef FONT_HARU_DEBUG LOG(("Splitting string: %s for width: %i ; Calculated position: %i Calculated real_width: %f", string_nt, x, *char_offset, real_width)); #endif *char_offset = offset - 1; /*TODO: this is only the right edge of the character*/ *actual_x = real_width; free(string_nt); HPDF_Free(pdf); return true; } /** * Apply font style to a Haru HPDF_Page * * \param fstyle plot style for this page * \param doc document owning the page * \param page the page to apply the style to * \param font if this is non NULL it is updated to the font based * on given style * \param font_size if this is non NULL it is updated to the font size * based on given style * \return true on success, false on error and error reported * * When both font and font_size are NULL, the HPDF_Page is updated for given * style, otherwise it is left to the called to do this. */ bool haru_nsfont_apply_style(const plot_font_style_t *fstyle, HPDF_Doc doc, HPDF_Page page, HPDF_Font *font, HPDF_REAL *font_size) { HPDF_Font pdf_font; HPDF_REAL size; char font_name[50]; bool roman = false; bool bold = false; bool styled = false; /*TODO: style handling, we are mapping the styles on the basic 14 fonts only */ switch (fstyle->family) { case PLOT_FONT_FAMILY_SERIF: strcpy(font_name, "Times"); roman = true; break; case PLOT_FONT_FAMILY_MONOSPACE: strcpy(font_name, "Courier"); break; case PLOT_FONT_FAMILY_SANS_SERIF: strcpy(font_name, "Helvetica"); break; case PLOT_FONT_FAMILY_CURSIVE: case PLOT_FONT_FAMILY_FANTASY: default: strcpy(font_name, "Times"); roman=true; break; } if (fstyle->weight == 700) { strcat(font_name, "-Bold"); bold = true; } if ((fstyle->flags & FONTF_ITALIC) || (fstyle->flags & FONTF_OBLIQUE)) { if (!bold) strcat(font_name,"-"); if (roman) strcat(font_name,"Italic"); else strcat(font_name,"Oblique"); styled = true; } if (roman && !styled && !bold) strcat(font_name, "-Roman"); #ifdef FONT_HARU_DEBUG LOG(("Setting font: %s", font_name)); #endif size = fstyle->size; if (font != NULL) size *= pdf_text_scale; if (size <= 0) return true; size /= FONT_SIZE_SCALE; if (size > HPDF_MAX_FONTSIZE) size = HPDF_MAX_FONTSIZE; if (font_size) *font_size = size; pdf_font = HPDF_GetFont(doc, font_name, "StandardEncoding"); if (pdf_font == NULL) return false; if (font != NULL) *font = pdf_font; if (font == NULL || font_size == NULL) HPDF_Page_SetFontAndSize(page, pdf_font, size); return true; } /** * Sync the text scale with the scale for the whole content */ void haru_nsfont_set_scale(float s) { pdf_text_scale = s; } #endif /* WITH_PDF_EXPORT */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/save_pdf/font_haru.h������������������������������������������������0000664�0001750�0001750�00000002334�11231317651�021442� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2008 Adam Blokus * Copyright 2009 John Tytgat * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file * Font handling in Haru pdf documents (interface). */ #ifndef _NETSURF_RENDER_FONT_HARU_H_ #define _NETSURF_RENDER_FONT_HARU_H_ #include #include "render/font.h" #include "desktop/plot_style.h" bool haru_nsfont_apply_style(const plot_font_style_t *fstyle, HPDF_Doc doc, HPDF_Page page, HPDF_Font *font, HPDF_REAL *font_size); void haru_nsfont_set_scale(float s); extern const struct font_functions haru_nsfont; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/save_pdf/pdf_plotters.c���������������������������������������������0000664�0001750�0001750�00000061477�11526323463�022177� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2008 Adam Blokus * Copyright 2009 John Tytgat * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file * Target independent PDF plotting using Haru Free PDF Library. */ #include "utils/config.h" #ifdef WITH_PDF_EXPORT #include #include #include #include #include "content/hlcache.h" #include "desktop/options.h" #include "desktop/plotters.h" #include "desktop/print.h" #include "desktop/printer.h" #include "desktop/save_pdf/pdf_plotters.h" #include "image/bitmap.h" #include "utils/log.h" #include "utils/utils.h" #include "utils/useragent.h" #include "font_haru.h" /* #define PDF_DEBUG */ /* #define PDF_DEBUG_DUMPGRID */ static bool pdf_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style); static bool pdf_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *pstyle); static bool pdf_plot_polygon(const int *p, unsigned int n, const plot_style_t *style); static bool pdf_plot_clip(const struct rect *clip); static bool pdf_plot_text(int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle); static bool pdf_plot_disc(int x, int y, int radius, const plot_style_t *style); static bool pdf_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style); static bool pdf_plot_bitmap_tile(int x, int y, int width, int height, struct bitmap *bitmap, colour bg, bitmap_flags_t flags); static bool pdf_plot_path(const float *p, unsigned int n, colour fill, float width, colour c, const float transform[6]); static HPDF_Image pdf_extract_image(struct bitmap *bitmap); static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void *user_data); #ifdef PDF_DEBUG_DUMPGRID static void pdf_plot_grid(int x_dist,int y_dist,unsigned int colour); #endif typedef enum { DashPattern_eNone, DashPattern_eDash, DashPattern_eDotted } DashPattern_e; /* Wrapper routines to minimize gstate updates in the produced PDF file. */ static void pdfw_gs_init(void); static void pdfw_gs_save(HPDF_Page page); static void pdfw_gs_restore(HPDF_Page page); static void pdfw_gs_fillcolour(HPDF_Page page, colour col); static void pdfw_gs_strokecolour(HPDF_Page page, colour col); static void pdfw_gs_linewidth(HPDF_Page page, float lineWidth); static void pdfw_gs_font(HPDF_Page page, HPDF_Font font, HPDF_REAL font_size); static void pdfw_gs_dash(HPDF_Page page, DashPattern_e dash); /** * Our PDF gstate mirror which we use to minimize gstate updates * in the PDF file. */ typedef struct { colour fillColour; /**< Current fill colour. */ colour strokeColour; /**< Current stroke colour. */ float lineWidth; /**< Current line width. */ HPDF_Font font; /**< Current font. */ HPDF_REAL font_size; /**< Current font size. */ DashPattern_e dash; /**< Current dash state. */ } PDFW_GState; static void apply_clip_and_mode(bool selectTextMode, colour fillCol, colour strokeCol, float lineWidth, DashPattern_e dash); #define PDFW_MAX_GSTATES 4 static PDFW_GState pdfw_gs[PDFW_MAX_GSTATES]; static unsigned int pdfw_gs_level; static HPDF_Doc pdf_doc; /**< Current PDF document. */ static HPDF_Page pdf_page; /**< Current page. */ /*PDF Page size*/ static HPDF_REAL page_height, page_width; static bool in_text_mode; /**< true if we're currently in text mode or not. */ static bool clip_update_needed; /**< true if pdf_plot_clip was invoked for current page and not yet synced with PDF output. */ static int last_clip_x0, last_clip_y0, last_clip_x1, last_clip_y1; static const struct print_settings *settings; static const struct plotter_table pdf_plotters = { .rectangle = pdf_plot_rectangle, .line = pdf_plot_line, .polygon = pdf_plot_polygon, .clip = pdf_plot_clip, .text = pdf_plot_text, .disc = pdf_plot_disc, .arc = pdf_plot_arc, .bitmap = pdf_plot_bitmap_tile, .path = pdf_plot_path, .option_knockout = false, }; const struct printer pdf_printer = { &pdf_plotters, pdf_begin, pdf_next_page, pdf_end }; static char *owner_pass; static char *user_pass; bool pdf_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *pstyle) { DashPattern_e dash; #ifdef PDF_DEBUG LOG(("%d %d %d %d %f %X", x0, y0, x1, y1, page_height - y0, pstyle->fill_colour)); #endif if (pstyle->fill_type != PLOT_OP_TYPE_NONE) { apply_clip_and_mode(false, pstyle->fill_colour, NS_TRANSPARENT, 0., DashPattern_eNone); /* Normalize boundaries of the area - to prevent overflows. It is needed only in a few functions, where integers are subtracted. When the whole browser window is meant min and max int values are used what must be handled in paged output. */ x0 = min(max(x0, 0), page_width); y0 = min(max(y0, 0), page_height); x1 = min(max(x1, 0), page_width); y1 = min(max(y1, 0), page_height); HPDF_Page_Rectangle(pdf_page, x0, page_height - y1, x1 - x0, y1 - y0); HPDF_Page_Fill(pdf_page); } if (pstyle->stroke_type != PLOT_OP_TYPE_NONE) { switch (pstyle->stroke_type) { case PLOT_OP_TYPE_DOT: dash = DashPattern_eDotted; break; case PLOT_OP_TYPE_DASH: dash = DashPattern_eDash; break; default: dash = DashPattern_eNone; break; } apply_clip_and_mode(false, NS_TRANSPARENT, pstyle->stroke_colour, pstyle->stroke_width, dash); HPDF_Page_Rectangle(pdf_page, x0, page_height - y0, x1 - x0, -(y1 - y0)); HPDF_Page_Stroke(pdf_page); } return true; } bool pdf_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *pstyle) { DashPattern_e dash; switch (pstyle->stroke_type) { case PLOT_OP_TYPE_DOT: dash = DashPattern_eDotted; break; case PLOT_OP_TYPE_DASH: dash = DashPattern_eDash; break; default: dash = DashPattern_eNone; break; } apply_clip_and_mode(false, NS_TRANSPARENT, pstyle->stroke_colour, pstyle->stroke_width, dash); HPDF_Page_MoveTo(pdf_page, x0, page_height - y0); HPDF_Page_LineTo(pdf_page, x1, page_height - y1); HPDF_Page_Stroke(pdf_page); return true; } bool pdf_plot_polygon(const int *p, unsigned int n, const plot_style_t *style) { unsigned int i; #ifdef PDF_DEBUG int pmaxx = p[0], pmaxy = p[1]; int pminx = p[0], pminy = p[1]; LOG((".")); #endif if (n == 0) return true; apply_clip_and_mode(false, style->fill_colour, NS_TRANSPARENT, 0., DashPattern_eNone); HPDF_Page_MoveTo(pdf_page, p[0], page_height - p[1]); for (i = 1 ; ix0, clip->y0, clip->x1, clip->y1)); #endif /*Normalize cllipping area - to prevent overflows. See comment in pdf_plot_fill. */ last_clip_x0 = min(max(clip->x0, 0), page_width); last_clip_y0 = min(max(clip->y0, 0), page_height); last_clip_x1 = min(max(clip->x1, 0), page_width); last_clip_y1 = min(max(clip->y1, 0), page_height); clip_update_needed = true; return true; } bool pdf_plot_text(int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle) { #ifdef PDF_DEBUG LOG((". %d %d %.*s", x, y, (int)length, text)); #endif char *word; HPDF_Font pdf_font; HPDF_REAL size; if (length == 0) return true; apply_clip_and_mode(true, fstyle->foreground, NS_TRANSPARENT, 0., DashPattern_eNone); haru_nsfont_apply_style(fstyle, pdf_doc, pdf_page, &pdf_font, &size); pdfw_gs_font(pdf_page, pdf_font, size); /* FIXME: UTF-8 to current font encoding needs to done. Or the font * encoding needs to be UTF-8 or other Unicode encoding. */ word = (char *)malloc( sizeof(char) * (length+1) ); if (word == NULL) return false; memcpy(word, text, length); word[length] = '\0'; HPDF_Page_TextOut (pdf_page, x, page_height - y, word); free(word); return true; } bool pdf_plot_disc(int x, int y, int radius, const plot_style_t *style) { #ifdef PDF_DEBUG LOG((".")); #endif if (style->fill_type != PLOT_OP_TYPE_NONE) { apply_clip_and_mode(false, style->fill_colour, NS_TRANSPARENT, 1., DashPattern_eNone); HPDF_Page_Circle(pdf_page, x, page_height - y, radius); HPDF_Page_Fill(pdf_page); } if (style->stroke_type != PLOT_OP_TYPE_NONE) { /* FIXME: line width 1 is ok ? */ apply_clip_and_mode(false, NS_TRANSPARENT, style->stroke_colour, 1., DashPattern_eNone); HPDF_Page_Circle(pdf_page, x, page_height - y, radius); HPDF_Page_Stroke(pdf_page); } return true; } bool pdf_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style) { #ifdef PDF_DEBUG LOG(("%d %d %d %d %d %X", x, y, radius, angle1, angle2, style->stroke_colour)); #endif /* FIXME: line width 1 is ok ? */ apply_clip_and_mode(false, NS_TRANSPARENT, style->fill_colour, 1., DashPattern_eNone); /* Normalize angles */ angle1 %= 360; angle2 %= 360; if (angle1 > angle2) angle1 -= 360; HPDF_Page_Arc(pdf_page, x, page_height - y, radius, angle1, angle2); HPDF_Page_Stroke(pdf_page); return true; } bool pdf_plot_bitmap_tile(int x, int y, int width, int height, struct bitmap *bitmap, colour bg, bitmap_flags_t flags) { HPDF_Image image; HPDF_REAL current_x, current_y ; HPDF_REAL max_width, max_height; #ifdef PDF_DEBUG LOG(("%d %d %d %d %p 0x%x", x, y, width, height, bitmap, bg)); #endif if (width == 0 || height == 0) return true; apply_clip_and_mode(false, NS_TRANSPARENT, NS_TRANSPARENT, 0., DashPattern_eNone); image = pdf_extract_image(bitmap); if (!image) return false; /*The position of the next tile*/ max_width = (flags & BITMAPF_REPEAT_X) ? page_width : width; max_height = (flags & BITMAPF_REPEAT_Y) ? page_height : height; for (current_y = 0; current_y < max_height; current_y += height) for (current_x = 0; current_x < max_width; current_x += width) HPDF_Page_DrawImage(pdf_page, image, current_x + x, page_height - current_y - y - height, width, height); return true; } HPDF_Image pdf_extract_image(struct bitmap *bitmap) { HPDF_Image image = NULL; hlcache_handle *content = NULL; /* TODO - get content from bitmap pointer */ if (content) { const char *source_data; unsigned long source_size; /*Not sure if I don't have to check if downloading has been finished. Other way - lock pdf plotting while fetching a website */ source_data = content_get_source_data(content, &source_size); switch(content_get_type(content)){ /*Handle "embeddable" types of images*/ case CONTENT_JPEG: image = HPDF_LoadJpegImageFromMem(pdf_doc, (const HPDF_BYTE *) source_data, source_size); break; /*Disabled until HARU PNG support will be more stable. case CONTENT_PNG: image = HPDF_LoadPngImageFromMem(pdf_doc, (const HPDF_BYTE *)content->source_data, content->total_size); break;*/ default: break; } } if (!image) { HPDF_Image smask; unsigned char *img_buffer, *rgb_buffer, *alpha_buffer; int img_width, img_height, img_rowstride; int i, j; /*Handle pixmaps*/ img_buffer = bitmap_get_buffer(bitmap); img_width = bitmap_get_width(bitmap); img_height = bitmap_get_height(bitmap); img_rowstride = bitmap_get_rowstride(bitmap); rgb_buffer = (unsigned char *)malloc(3 * img_width * img_height); alpha_buffer = (unsigned char *)malloc(img_width * img_height); if (rgb_buffer == NULL || alpha_buffer == NULL) { LOG(("Not enough memory to create RGB buffer")); free(rgb_buffer); free(alpha_buffer); return NULL; } for (i = 0; i < img_height; i++) for (j = 0; j < img_width; j++) { rgb_buffer[((i * img_width) + j) * 3] = img_buffer[(i * img_rowstride) + (j * 4)]; rgb_buffer[(((i * img_width) + j) * 3) + 1] = img_buffer[(i * img_rowstride) + (j * 4) + 1]; rgb_buffer[(((i * img_width) + j) * 3) + 2] = img_buffer[(i * img_rowstride) + (j * 4) + 2]; alpha_buffer[(i * img_width)+j] = img_buffer[(i * img_rowstride) + (j * 4) + 3]; } smask = HPDF_LoadRawImageFromMem(pdf_doc, alpha_buffer, img_width, img_height, HPDF_CS_DEVICE_GRAY, 8); image = HPDF_LoadRawImageFromMem(pdf_doc, rgb_buffer, img_width, img_height, HPDF_CS_DEVICE_RGB, 8); if (HPDF_Image_AddSMask(image, smask) != HPDF_OK) image = NULL; free(rgb_buffer); free(alpha_buffer); } return image; } /** * Enter/leave text mode and update PDF gstate for its clip, fill & stroke * colour, line width and dash pattern parameters. * \param selectTextMode true if text mode needs to be entered if required; * false otherwise. * \param fillCol Desired fill colour, use NS_TRANSPARENT if no update is * required. * \param strokeCol Desired stroke colour, use NS_TRANSPARENT if no update is * required. * \param lineWidth Desired line width. Only taken into account when strokeCol * is different from NS_TRANSPARENT. * \param dash Desired dash pattern. Only taken into account when strokeCol * is different from NS_TRANSPARENT. */ static void apply_clip_and_mode(bool selectTextMode, colour fillCol, colour strokeCol, float lineWidth, DashPattern_e dash) { /* Leave text mode when * 1) we're not setting text anymore * 2) or we need to update the current clippath * 3) or we need to update any fill/stroke colour, linewidth or dash. * Note: the test on stroke parameters (stroke colour, line width and * dash) is commented out as if these need updating we want to be * outside the text mode anyway (i.e. selectTextMode is false). */ if (in_text_mode && (!selectTextMode || clip_update_needed || (fillCol != NS_TRANSPARENT && fillCol != pdfw_gs[pdfw_gs_level].fillColour) /* || (strokeCol != NS_TRANSPARENT && (strokeCol != pdfw_gs[pdfw_gs_level].strokeColour || lineWidth != pdfw_gs[pdfw_gs_level].lineWidth || dash != pdfw_gs[pdfw_gs_level].dash)) */)) { HPDF_Page_EndText(pdf_page); in_text_mode = false; } if (clip_update_needed) pdfw_gs_restore(pdf_page); /* Update fill/stroke colour, linewidth and dash when needed. */ if (fillCol != NS_TRANSPARENT) pdfw_gs_fillcolour(pdf_page, fillCol); if (strokeCol != NS_TRANSPARENT) { pdfw_gs_strokecolour(pdf_page, strokeCol); pdfw_gs_linewidth(pdf_page, lineWidth); pdfw_gs_dash(pdf_page, dash); } if (clip_update_needed) { pdfw_gs_save(pdf_page); HPDF_Page_Rectangle(pdf_page, last_clip_x0, page_height - last_clip_y1, last_clip_x1 - last_clip_x0, last_clip_y1 - last_clip_y0); HPDF_Page_Clip(pdf_page); HPDF_Page_EndPath(pdf_page); clip_update_needed = false; } if (selectTextMode && !in_text_mode) { HPDF_Page_BeginText(pdf_page); in_text_mode = true; } } static inline float transform_x(const float transform[6], float x, float y) { return transform[0] * x + transform[2] * y + transform[4]; } static inline float transform_y(const float transform[6], float x, float y) { return page_height - (transform[1] * x + transform[3] * y + transform[5]); } bool pdf_plot_path(const float *p, unsigned int n, colour fill, float width, colour c, const float transform[6]) { unsigned int i; bool empty_path; #ifdef PDF_DEBUG LOG((".")); #endif if (n == 0) return true; if (c == NS_TRANSPARENT && fill == NS_TRANSPARENT) return true; if (p[0] != PLOTTER_PATH_MOVE) return false; apply_clip_and_mode(false, fill, c, width, DashPattern_eNone); empty_path = true; for (i = 0 ; i < n ; ) { if (p[i] == PLOTTER_PATH_MOVE) { HPDF_Page_MoveTo(pdf_page, transform_x(transform, p[i+1], p[i+2]), transform_y(transform, p[i+1], p[i+2])); i+= 3; } else if (p[i] == PLOTTER_PATH_CLOSE) { if (!empty_path) HPDF_Page_ClosePath(pdf_page); i++; } else if (p[i] == PLOTTER_PATH_LINE) { HPDF_Page_LineTo(pdf_page, transform_x(transform, p[i+1], p[i+2]), transform_y(transform, p[i+1], p[i+2])); i+=3; empty_path = false; } else if (p[i] == PLOTTER_PATH_BEZIER) { HPDF_Page_CurveTo(pdf_page, transform_x(transform, p[i+1], p[i+2]), transform_y(transform, p[i+1], p[i+2]), transform_x(transform, p[i+3], p[i+4]), transform_y(transform, p[i+3], p[i+4]), transform_x(transform, p[i+5], p[i+6]), transform_y(transform, p[i+5], p[i+6])); i += 7; empty_path = false; } else { LOG(("bad path command %f", p[i])); return false; } } if (empty_path) { HPDF_Page_EndPath(pdf_page); return true; } if (fill != NS_TRANSPARENT) { if (c != NS_TRANSPARENT) HPDF_Page_FillStroke(pdf_page); else HPDF_Page_Fill(pdf_page); } else HPDF_Page_Stroke(pdf_page); return true; } /** * Begin pdf plotting - initialize a new document * \param path Output file path * \param pg_width page width * \param pg_height page height */ bool pdf_begin(struct print_settings *print_settings) { pdfw_gs_init(); if (pdf_doc != NULL) HPDF_Free(pdf_doc); pdf_doc = HPDF_New(error_handler, NULL); if (!pdf_doc) { LOG(("Error creating pdf_doc")); return false; } settings = print_settings; page_width = settings->page_width - FIXTOFLT(FSUB(settings->margins[MARGINLEFT], settings->margins[MARGINRIGHT])); page_height = settings->page_height - FIXTOFLT(settings->margins[MARGINTOP]); #ifndef PDF_DEBUG if (option_enable_PDF_compression) HPDF_SetCompressionMode(pdf_doc, HPDF_COMP_ALL); /*Compression on*/ #endif HPDF_SetInfoAttr(pdf_doc, HPDF_INFO_CREATOR, user_agent_string()); pdf_page = NULL; #ifdef PDF_DEBUG LOG(("pdf_begin finishes")); #endif return true; } bool pdf_next_page(void) { #ifdef PDF_DEBUG LOG(("pdf_next_page begins")); #endif clip_update_needed = false; if (pdf_page != NULL) { apply_clip_and_mode(false, NS_TRANSPARENT, NS_TRANSPARENT, 0., DashPattern_eNone); pdfw_gs_restore(pdf_page); } #ifdef PDF_DEBUG_DUMPGRID if (pdf_page != NULL) { pdf_plot_grid(10, 10, 0xCCCCCC); pdf_plot_grid(100, 100, 0xCCCCFF); } #endif pdf_page = HPDF_AddPage(pdf_doc); if (pdf_page == NULL) return false; HPDF_Page_SetWidth (pdf_page, settings->page_width); HPDF_Page_SetHeight(pdf_page, settings->page_height); HPDF_Page_Concat(pdf_page, 1, 0, 0, 1, FIXTOFLT(settings->margins[MARGINLEFT]), 0); pdfw_gs_save(pdf_page); #ifdef PDF_DEBUG LOG(("%f %f", page_width, page_height)); #endif return true; } void pdf_end(void) { #ifdef PDF_DEBUG LOG(("pdf_end begins")); #endif clip_update_needed = false; if (pdf_page != NULL) { apply_clip_and_mode(false, NS_TRANSPARENT, NS_TRANSPARENT, 0., DashPattern_eNone); pdfw_gs_restore(pdf_page); } #ifdef PDF_DEBUG_DUMPGRID if (pdf_page != NULL) { pdf_plot_grid(10, 10, 0xCCCCCC); pdf_plot_grid(100, 100, 0xCCCCFF); } #endif assert(settings->output != NULL); /*Encryption on*/ if (option_enable_PDF_password) PDF_Password(&owner_pass, &user_pass, (void *)settings->output); else save_pdf(settings->output); #ifdef PDF_DEBUG LOG(("pdf_end finishes")); #endif } /** saves the pdf optionally encrypting it before*/ void save_pdf(const char *path) { bool success = false; if (option_enable_PDF_password && owner_pass != NULL ) { HPDF_SetPassword(pdf_doc, owner_pass, user_pass); HPDF_SetEncryptionMode(pdf_doc, HPDF_ENCRYPT_R3, 16); free(owner_pass); free(user_pass); } if (path != NULL) { if (HPDF_SaveToFile(pdf_doc, path) != HPDF_OK) remove(path); else success = true; } if (!success) warn_user("Unable to save PDF file.", 0); HPDF_Free(pdf_doc); pdf_doc = NULL; } /** * Haru error handler * for debugging purposes - it immediately exits the program on the first error, * as it would otherwise flood the user with all resulting complications, * covering the most important error source. */ static void error_handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void *user_data) { LOG(("ERROR:\n\terror_no=%x\n\tdetail_no=%d\n", (HPDF_UINT)error_no, (HPDF_UINT)detail_no)); #ifdef PDF_DEBUG exit(1); #endif } /** * This function plots a grid - used for debug purposes to check if all * elements' final coordinates are correct. */ #ifdef PDF_DEBUG_DUMPGRID void pdf_plot_grid(int x_dist, int y_dist, unsigned int colour) { for (int i = x_dist ; i < page_width ; i += x_dist) pdf_plot_line(i, 0, i, page_height, 1, colour, false, false); for (int i = y_dist ; i < page_height ; i += x_dist) pdf_plot_line(0, i, page_width, i, 1, colour, false, false); } #endif /** * Initialize the gstate wrapper code. */ void pdfw_gs_init() { pdfw_gs_level = 0; pdfw_gs[0].fillColour = 0x00000000; /* Default PDF fill colour is black. */ pdfw_gs[0].strokeColour = 0x00000000; /* Default PDF stroke colour is black. */ pdfw_gs[0].lineWidth = 1.0; /* Default PDF line width is 1. */ pdfw_gs[0].font = NULL; pdfw_gs[0].font_size = 0.; pdfw_gs[0].dash = DashPattern_eNone; /* Default dash state is a solid line. */ } /** * Increase gstate level. * \param page PDF page where the update needs to happen. */ void pdfw_gs_save(HPDF_Page page) { if (pdfw_gs_level == PDFW_MAX_GSTATES) abort(); pdfw_gs[pdfw_gs_level + 1] = pdfw_gs[pdfw_gs_level]; ++pdfw_gs_level; HPDF_Page_GSave(page); } /** * Decrease gstate level and restore the gstate to its value at last save * operation. * \param page PDF page where the update needs to happen. */ void pdfw_gs_restore(HPDF_Page page) { if (pdfw_gs_level == 0) abort(); --pdfw_gs_level; HPDF_Page_GRestore(page); } #define RBYTE(x) (((x) & 0x0000FF) >> 0) #define GBYTE(x) (((x) & 0x00FF00) >> 8) #define BBYTE(x) (((x) & 0xFF0000) >> 16) #define R(x) (RBYTE(x) / 255.) #define G(x) (GBYTE(x) / 255.) #define B(x) (BBYTE(x) / 255.) /** * Checks if given fill colour is already set in PDF gstate and if not, * update the gstate accordingly. * \param page PDF page where the update needs to happen. * \param col Wanted fill colour. */ void pdfw_gs_fillcolour(HPDF_Page page, colour col) { if (col == pdfw_gs[pdfw_gs_level].fillColour) return; pdfw_gs[pdfw_gs_level].fillColour = col; if (RBYTE(col) == GBYTE(col) && GBYTE(col) == BBYTE(col)) HPDF_Page_SetGrayFill(pdf_page, R(col)); else HPDF_Page_SetRGBFill(pdf_page, R(col), G(col), B(col)); } /** * Checks if given stroke colour is already set in PDF gstate and if not, * update the gstate accordingly. * \param page PDF page where the update needs to happen. * \param col Wanted stroke colour. */ void pdfw_gs_strokecolour(HPDF_Page page, colour col) { if (col == pdfw_gs[pdfw_gs_level].strokeColour) return; pdfw_gs[pdfw_gs_level].strokeColour = col; if (RBYTE(col) == GBYTE(col) && GBYTE(col) == BBYTE(col)) HPDF_Page_SetGrayStroke(pdf_page, R(col)); else HPDF_Page_SetRGBStroke(pdf_page, R(col), G(col), B(col)); } /** * Checks if given line width is already set in PDF gstate and if not, update * the gstate accordingly. * \param page PDF page where the update needs to happen. * \param lineWidth Wanted line width. */ void pdfw_gs_linewidth(HPDF_Page page, float lineWidth) { if (lineWidth == pdfw_gs[pdfw_gs_level].lineWidth) return; pdfw_gs[pdfw_gs_level].lineWidth = lineWidth; HPDF_Page_SetLineWidth(page, lineWidth); } /** * Checks if given font and font size is already set in PDF gstate and if not, * update the gstate accordingly. * \param page PDF page where the update needs to happen. * \param font Wanted PDF font. * \param font_size Wanted PDF font size. */ void pdfw_gs_font(HPDF_Page page, HPDF_Font font, HPDF_REAL font_size) { if (font == pdfw_gs[pdfw_gs_level].font && font_size == pdfw_gs[pdfw_gs_level].font_size) return; pdfw_gs[pdfw_gs_level].font = font; pdfw_gs[pdfw_gs_level].font_size = font_size; HPDF_Page_SetFontAndSize(page, font, font_size); } /** * Checks if given dash pattern is already set in PDF gstate and if not, * update the gstate accordingly. * \param page PDF page where the update needs to happen. * \param dash Wanted dash pattern. */ void pdfw_gs_dash(HPDF_Page page, DashPattern_e dash) { if (dash == pdfw_gs[pdfw_gs_level].dash) return; pdfw_gs[pdfw_gs_level].dash = dash; switch (dash) { case DashPattern_eNone: { HPDF_Page_SetDash(page, NULL, 0, 0); break; } case DashPattern_eDash: { const HPDF_UINT16 dash_ptn[] = {3}; HPDF_Page_SetDash(page, dash_ptn, 1, 1); break; } case DashPattern_eDotted: { const HPDF_UINT16 dash_ptn[] = {1}; HPDF_Page_SetDash(page, dash_ptn, 1, 1); break; } } } #endif /* WITH_PDF_EXPORT */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/save_pdf/pdf_plotters.h���������������������������������������������0000664�0001750�0001750�00000002230�11142447567�022170� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2008 Adam Blokus * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file PDF Plotting */ #ifndef NETSURF_PDF_PLOTTERS_H #define NETSURF_PDF_PLOTTERS_H #include "desktop/print.h" extern const struct printer pdf_printer; /**Start plotting a pdf file*/ bool pdf_begin(struct print_settings *settings); /**Finish the current page and start a new one*/ bool pdf_next_page(void); /**Close pdf document and save changes to file*/ void pdf_end(void); void save_pdf(const char *path); #endif /*NETSURF_PDF_PLOTTERS_H*/ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/searchweb.c���������������������������������������������������������0000664�0001750�0001750�00000017345�11666705066�017651� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2009 Mark Benjamin * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file * web search (core) */ #include "utils/config.h" #include #include #include "content/content.h" #include "content/hlcache.h" #include "desktop/browser.h" #include "desktop/gui.h" #include "desktop/options.h" #include "desktop/searchweb.h" #include "utils/config.h" #include "utils/log.h" #include "utils/messages.h" #include "utils/url.h" #include "utils/utils.h" static struct search_provider { char *name; /**< readable name such as 'google', 'yahoo', etc */ char *hostname; /**< host address such as www.google.com */ char *searchstring; /** < such as "www.google.com?search=%s" */ char *ico; /** < location of domain's favicon */ } current_search_provider; static hlcache_handle *search_ico = NULL; char *search_engines_file_location; char *search_default_ico_location; #ifdef WITH_BMP static nserror search_web_ico_callback(hlcache_handle *ico, const hlcache_event *event, void *pw); #endif /** * creates a new browser window according to the search term * \param searchterm such as "my search term" */ bool search_web_new_window(struct browser_window *bw, const char *searchterm) { char *encsearchterm; char *url; if (url_escape(searchterm,0, true, NULL, &encsearchterm) != URL_FUNC_OK) return false; url = search_web_get_url(encsearchterm); free(encsearchterm); browser_window_create(url, bw, NULL, true, true); free(url); return true; } /** simplistic way of checking whether an entry from the url bar is an * url / a search; could be improved to properly test terms */ bool search_is_url(const char *url) { /** \todo Implement this properly */ /* For now, everything is an URL */ return true; } /** * caches the details of the current web search provider * \param reference the enum value of the provider * browser init code [as well as changing preferences code] should call * search_web_provider_details(option_search_provider) */ void search_web_provider_details(int reference) { char buf[300]; int ref = 0; FILE *f; if (search_engines_file_location == NULL) return; f = fopen(search_engines_file_location, "r"); if (f == NULL) return; while (fgets(buf, sizeof(buf), f) != NULL) { if (buf[0] == '\0') continue; buf[strlen(buf)-1] = '\0'; if (ref++ == (int)reference) break; } fclose(f); if (current_search_provider.name != NULL) free(current_search_provider.name); current_search_provider.name = strdup(strtok(buf, "|")); if (current_search_provider.hostname != NULL) free(current_search_provider.hostname); current_search_provider.hostname = strdup(strtok(NULL, "|")); if (current_search_provider.searchstring != NULL) free(current_search_provider.searchstring); current_search_provider.searchstring = strdup(strtok(NULL, "|")); if (current_search_provider.ico != NULL) free(current_search_provider.ico); current_search_provider.ico = strdup(strtok(NULL, "|")); return; } /** * escapes a search term then creates the appropriate url from it */ char *search_web_from_term(const char *searchterm) { char *encsearchterm, *url; if (url_escape(searchterm, 0, true, NULL, &encsearchterm) != URL_FUNC_OK) return strdup(searchterm); url = search_web_get_url(encsearchterm); free(encsearchterm); return url; } /** accessor for global search provider name */ char *search_web_provider_name(void) { if (current_search_provider.name) return strdup(current_search_provider.name); return strdup("google"); } /** accessor for global search provider hostname */ char *search_web_provider_host(void) { if (current_search_provider.hostname) return strdup(current_search_provider.hostname); return strdup("www.google.com"); } /** accessor for global search provider ico name */ char *search_web_ico_name(void) { if (current_search_provider.ico) return strdup(current_search_provider.ico); return strdup("http://www.google.com/favicon.ico"); } /** * creates a full url from an encoded search term */ char *search_web_get_url(const char *encsearchterm) { char *pref, *ret; int len; if (current_search_provider.searchstring) pref = strdup(current_search_provider.searchstring); else pref = strdup("http://www.google.com/search?q=%s"); if (pref == NULL) { warn_user(messages_get("NoMemory"), 0); return NULL; } len = strlen(encsearchterm) + strlen(pref); ret = malloc(len -1); /* + '\0' - "%s" */ if (ret == NULL) { warn_user(messages_get("NoMemory"), 0); free(pref); return NULL; } snprintf(ret, len-1, pref, encsearchterm); free(pref); return ret; } /** * function to retrieve the search web ico, from cache / from local * filesystem / from the web * \param localdefault true when there is no appropriate favicon * update the search_ico cache else delay until fetcher callback */ void search_web_retrieve_ico(bool localdefault) { #if !defined(WITH_BMP) /* This function is of limited use when no BMP support * is enabled, given the icons it is fetching are BMPs * more often than not. This also avoids an issue where * all this code goes mad if BMP support is not enabled. */ return; #else content_type accept = CONTENT_IMAGE; char *url; nserror error; nsurl *icon_nsurl; if (localdefault) { if (search_default_ico_location == NULL) return; url = malloc(SLEN("file://") + strlen( search_default_ico_location) + 1); if (url == NULL) { warn_user(messages_get("NoMemory"), 0); return; } strcpy(url, "file://"); strcat(url, search_default_ico_location); } else { url = search_web_ico_name(); } if (url == NULL) { warn_user(messages_get("NoMemory"), 0); return; } error = nsurl_create(url, &icon_nsurl); if (error != NSERROR_OK) { free(url); search_ico = NULL; return; } error = hlcache_handle_retrieve(icon_nsurl, 0, NULL, NULL, search_web_ico_callback, NULL, NULL, accept, &search_ico); nsurl_unref(icon_nsurl); if (error != NSERROR_OK) search_ico = NULL; free(url); #endif /* WITH_BMP */ } /** * returns a reference to the static global search_ico [ / NULL] * caller may adjust ico's settings; clearing / free()ing is the core's * responsibility */ hlcache_handle *search_web_ico(void) { return search_ico; } /** * Cleans up any remaining resources during shutdown. */ void search_web_cleanup(void) { if (search_ico != NULL) { hlcache_handle_release(search_ico); search_ico = NULL; } } /** * callback function to cache ico then notify front when successful * else retry default from local file system */ #ifdef WITH_BMP nserror search_web_ico_callback(hlcache_handle *ico, const hlcache_event *event, void *pw) { switch (event->type) { case CONTENT_MSG_LOADING: case CONTENT_MSG_READY: break; case CONTENT_MSG_DONE: LOG(("got favicon '%s'", nsurl_access(hlcache_handle_get_url(ico)))); gui_window_set_search_ico(search_ico); break; case CONTENT_MSG_ERROR: LOG(("favicon %s error: %s", nsurl_access(hlcache_handle_get_url(ico)), event->data.error)); hlcache_handle_release(search_ico); search_ico = NULL; search_web_retrieve_ico(true); break; case CONTENT_MSG_STATUS: break; default: assert(0); } return NSERROR_OK; } #endif /* WITH_BMP */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������netsurf-2.9/netsurf-2.9/desktop/options.c�����������������������������������������������������������0000664�0001750�0001750�00000055741�11675155371�017401� 0����������������������������������������������������������������������������������������������������ustar �vince���������������������������vince������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * Copyright 2003 Phil Mellor * Copyright 2003 John M Bell * Copyright 2004 James Bursa * Copyright 2005 Richard Wilson * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file * Option reading and saving (implementation). * * Options are stored in the format key:value, one per line. For bool options, * value is "0" or "1". */ #include #include #include #include #include #include "css/css.h" #include "desktop/options.h" #include "desktop/plot_style.h" #include "utils/log.h" #include "utils/utils.h" #if defined(riscos) #include "riscos/options.h" #elif defined(nsgtk) #include "gtk/options.h" #elif defined(nsbeos) #include "beos/options.h" #elif defined(nsamiga) #include "amiga/options.h" #elif defined(nsframebuffer) #include "framebuffer/options.h" #elif defined(nsatari) #include "atari/options.h" #elif defined(nsmonkey) #include "monkey/options.h" #else #define EXTRA_OPTION_DEFINE #define EXTRA_OPTION_TABLE #endif /** An HTTP proxy should be used. */ bool option_http_proxy = false; /** Hostname of proxy. */ char *option_http_proxy_host = 0; /** Proxy port. */ int option_http_proxy_port = 8080; /** Proxy authentication method. */ int option_http_proxy_auth = OPTION_HTTP_PROXY_AUTH_NONE; /** Proxy authentication user name */ char *option_http_proxy_auth_user = 0; /** Proxy authentication password */ char *option_http_proxy_auth_pass = 0; /** Default font size / 0.1pt. */ int option_font_size = 128; /** Minimum font size. */ int option_font_min_size = 85; /** Default sans serif font */ char *option_font_sans; /** Default serif font */ char *option_font_serif; /** Default monospace font */ char *option_font_mono; /** Default cursive font */ char *option_font_cursive; /** Default fantasy font */ char *option_font_fantasy; /** Accept-Language header. */ char *option_accept_language = 0; /** Accept-Charset header. */ char *option_accept_charset = 0; /** Preferred maximum size of memory cache / bytes. */ int option_memory_cache_size = 12 * 1024 * 1024; /** Preferred expiry age of disc cache / days. */ int option_disc_cache_age = 28; /** Whether to block advertisements */ bool option_block_ads = false; /** Minimum GIF animation delay */ int option_minimum_gif_delay = 10; /** Whether to send the referer HTTP header */ bool option_send_referer = true; /** Whether to fetch foreground images */ bool option_foreground_images = true; /** Whether to fetch background images */ bool option_background_images = true; /** Whether to animate images */ bool option_animate_images = true; /** How many days to retain URL data for */ int option_expire_url = 28; /** Default font family */ int option_font_default = PLOT_FONT_FAMILY_SANS_SERIF; /** ca-bundle location */ char *option_ca_bundle = 0; /** ca-path location */ char *option_ca_path = 0; /** Cookie file location */ char *option_cookie_file = 0; /** Cookie jar location */ char *option_cookie_jar = 0; /** Home page location */ char *option_homepage_url = 0; /** search web from url bar */ bool option_search_url_bar = false; /** URL completion in url bar */ bool option_url_suggestion = true; /** default web search provider */ int option_search_provider = 0; /** default x position of new windows */ int option_window_x = 0; /** default y position of new windows */ int option_window_y = 0; /** default width of new windows */ int option_window_width = 0; /** default height of new windows */ int option_window_height = 0; /** width of screen when above options were saved */ int option_window_screen_width = 0; /** height of screen when above options were saved */ int option_window_screen_height = 0; /** default size of status bar vs. h scroll bar */ int option_toolbar_status_width = 6667; /** default window scale */ int option_scale = 100; /* Whether to reflow web pages while objects are fetching */ bool option_incremental_reflow = true; /* Minimum time between HTML reflows while objects are fetching */ #ifdef riscos unsigned int option_min_reflow_period = 100; /* time in cs */ #else unsigned int option_min_reflow_period = 25; /* time in cs */ #endif bool option_core_select_menu = false; /** top margin of exported page*/ int option_margin_top = DEFAULT_MARGIN_TOP_MM; /** bottom margin of exported page*/ int option_margin_bottom = DEFAULT_MARGIN_BOTTOM_MM; /** left margin of exported page*/ int option_margin_left = DEFAULT_MARGIN_LEFT_MM; /** right margin of exported page*/ int option_margin_right = DEFAULT_MARGIN_RIGHT_MM; /** scale of exported content*/ int option_export_scale = DEFAULT_EXPORT_SCALE * 100; /**suppressing images in printed content*/ bool option_suppress_images = false; /**turning off all backgrounds for printed content*/ bool option_remove_backgrounds = false; /**turning on content loosening for printed content*/ bool option_enable_loosening = true; /**compression of PDF documents*/ bool option_enable_PDF_compression = true; /**setting a password and encoding PDF documents*/ bool option_enable_PDF_password = false; /* Fetcher configuration */ /** Maximum simultaneous active fetchers */ int option_max_fetchers = 24; /** Maximum simultaneous active fetchers per host. * (<=option_max_fetchers else it makes no sense) * Note that rfc2616 section 8.1.4 says that there should be no more than * two keepalive connections per host. None of the main browsers follow this * as it slows page fetches down considerably. * See https://bugzilla.mozilla.org/show_bug.cgi?id=423377#c4 */ int option_max_fetchers_per_host = 5; /** Maximum number of inactive fetchers cached. * The total number of handles netsurf will therefore have open * is this plus option_max_fetchers. */ int option_max_cached_fetch_handles = 6; /** Suppress debug output from cURL. */ bool option_suppress_curl_debug = true; /** Whether to allow target="_blank" */ bool option_target_blank = true; /** Whether second mouse button opens in new tab */ bool option_button_2_tab = true; /* Interface colours */ colour option_gui_colour_bg_1 = 0xFFCCBB; /** Background (bbggrr) */ colour option_gui_colour_fg_1 = 0x000000; /** Foreground (bbggrr) */ colour option_gui_colour_fg_2 = 0xFFFBF8; /** Foreground selected (bbggrr) */ /* system colours */ colour option_sys_colour_ActiveBorder = 0x00000000; colour option_sys_colour_ActiveCaption = 0x00000000; colour option_sys_colour_AppWorkspace = 0x00000000; colour option_sys_colour_Background = 0x00000000; colour option_sys_colour_ButtonFace = 0x00000000; colour option_sys_colour_ButtonHighlight = 0x00000000; colour option_sys_colour_ButtonShadow = 0x00000000; colour option_sys_colour_ButtonText = 0x00000000; colour option_sys_colour_CaptionText = 0x0000000; colour option_sys_colour_GrayText = 0x00000000; colour option_sys_colour_Highlight = 0x00000000; colour option_sys_colour_HighlightText = 0x00000000; colour option_sys_colour_InactiveBorder = 0x00000000; colour option_sys_colour_InactiveCaption = 0x00000000; colour option_sys_colour_InactiveCaptionText = 0x00000000; colour option_sys_colour_InfoBackground = 0x00000000; colour option_sys_colour_InfoText = 0x00000000; colour option_sys_colour_Menu = 0x00000000; colour option_sys_colour_MenuText = 0x0000000; colour option_sys_colour_Scrollbar = 0x0000000; colour option_sys_colour_ThreeDDarkShadow = 0x000000; colour option_sys_colour_ThreeDFace = 0x000000; colour option_sys_colour_ThreeDHighlight = 0x000000; colour option_sys_colour_ThreeDLightShadow = 0x000000; colour option_sys_colour_ThreeDShadow = 0x000000; colour option_sys_colour_Window = 0x000000; colour option_sys_colour_WindowFrame = 0x000000; colour option_sys_colour_WindowText = 0x000000; EXTRA_OPTION_DEFINE enum option_type_e { OPTION_BOOL, OPTION_INTEGER, OPTION_STRING, OPTION_COLOUR } ; struct option_entry_s { const char *key; enum option_type_e type; void *p; }; struct option_entry_s option_table[] = { { "http_proxy", OPTION_BOOL, &option_http_proxy }, { "http_proxy_host", OPTION_STRING, &option_http_proxy_host }, { "http_proxy_port", OPTION_INTEGER, &option_http_proxy_port }, { "http_proxy_auth", OPTION_INTEGER, &option_http_proxy_auth }, { "http_proxy_auth_user", OPTION_STRING, &option_http_proxy_auth_user }, { "http_proxy_auth_pass", OPTION_STRING, &option_http_proxy_auth_pass }, { "font_size", OPTION_INTEGER, &option_font_size }, { "font_min_size", OPTION_INTEGER, &option_font_min_size }, { "font_sans", OPTION_STRING, &option_font_sans }, { "font_serif", OPTION_STRING, &option_font_serif }, { "font_mono", OPTION_STRING, &option_font_mono }, { "font_cursive", OPTION_STRING, &option_font_cursive }, { "font_fantasy", OPTION_STRING, &option_font_fantasy }, { "accept_language", OPTION_STRING, &option_accept_language }, { "accept_charset", OPTION_STRING, &option_accept_charset }, { "memory_cache_size", OPTION_INTEGER, &option_memory_cache_size }, { "disc_cache_age", OPTION_INTEGER, &option_disc_cache_age }, { "block_advertisements", OPTION_BOOL, &option_block_ads }, { "minimum_gif_delay", OPTION_INTEGER, &option_minimum_gif_delay }, { "send_referer", OPTION_BOOL, &option_send_referer }, { "foreground_images", OPTION_BOOL, &option_foreground_images }, { "background_images", OPTION_BOOL, &option_background_images }, { "animate_images", OPTION_BOOL, &option_animate_images }, { "expire_url", OPTION_INTEGER, &option_expire_url }, { "font_default", OPTION_INTEGER, &option_font_default }, { "ca_bundle", OPTION_STRING, &option_ca_bundle }, { "ca_path", OPTION_STRING, &option_ca_path }, { "cookie_file", OPTION_STRING, &option_cookie_file }, { "cookie_jar", OPTION_STRING, &option_cookie_jar }, { "homepage_url", OPTION_STRING, &option_homepage_url }, { "search_url_bar", OPTION_BOOL, &option_search_url_bar}, { "search_provider", OPTION_INTEGER, &option_search_provider}, { "url_suggestion", OPTION_BOOL, &option_url_suggestion }, { "window_x", OPTION_INTEGER, &option_window_x }, { "window_y", OPTION_INTEGER, &option_window_y }, { "window_width", OPTION_INTEGER, &option_window_width }, { "window_height", OPTION_INTEGER, &option_window_height }, { "window_screen_width", OPTION_INTEGER, &option_window_screen_width }, { "window_screen_height", OPTION_INTEGER, &option_window_screen_height }, { "toolbar_status_size", OPTION_INTEGER, &option_toolbar_status_width }, { "scale", OPTION_INTEGER, &option_scale }, { "incremental_reflow", OPTION_BOOL, &option_incremental_reflow }, { "min_reflow_period", OPTION_INTEGER, &option_min_reflow_period }, { "core_select_menu", OPTION_BOOL, &option_core_select_menu }, /* Fetcher options */ { "max_fetchers", OPTION_INTEGER, &option_max_fetchers }, { "max_fetchers_per_host", OPTION_INTEGER, &option_max_fetchers_per_host }, { "max_cached_fetch_handles", OPTION_INTEGER, &option_max_cached_fetch_handles }, { "suppress_curl_debug",OPTION_BOOL, &option_suppress_curl_debug }, { "target_blank", OPTION_BOOL, &option_target_blank }, { "button_2_tab", OPTION_BOOL, &option_button_2_tab }, /* PDF / Print options*/ { "margin_top", OPTION_INTEGER, &option_margin_top}, { "margin_bottom", OPTION_INTEGER, &option_margin_bottom}, { "margin_left", OPTION_INTEGER, &option_margin_left}, { "margin_right", OPTION_INTEGER, &option_margin_right}, { "export_scale", OPTION_INTEGER, &option_export_scale}, { "suppress_images", OPTION_BOOL, &option_suppress_images}, { "remove_backgrounds", OPTION_BOOL, &option_remove_backgrounds}, { "enable_loosening", OPTION_BOOL, &option_enable_loosening}, { "enable_PDF_compression", OPTION_BOOL, &option_enable_PDF_compression}, { "enable_PDF_password", OPTION_BOOL, &option_enable_PDF_password}, /* Interface colours */ { "gui_colour_bg_1", OPTION_COLOUR, &option_gui_colour_bg_1}, { "gui_colour_fg_1", OPTION_COLOUR, &option_gui_colour_fg_1}, { "gui_colour_fg_2", OPTION_COLOUR, &option_gui_colour_fg_2}, /* System colours */ { "sys_colour_ActiveBorder",OPTION_COLOUR,&option_sys_colour_ActiveBorder }, { "sys_colour_ActiveCaption",OPTION_COLOUR,&option_sys_colour_ActiveCaption }, { "sys_colour_AppWorkspace",OPTION_COLOUR,&option_sys_colour_AppWorkspace }, { "sys_colour_Background",OPTION_COLOUR,&option_sys_colour_Background }, { "sys_colour_ButtonFace",OPTION_COLOUR,&option_sys_colour_ButtonFace }, { "sys_colour_ButtonHighlight",OPTION_COLOUR,&option_sys_colour_ButtonHighlight }, { "sys_colour_ButtonShadow",OPTION_COLOUR,&option_sys_colour_ButtonShadow }, { "sys_colour_ButtonText",OPTION_COLOUR,&option_sys_colour_ButtonText }, { "sys_colour_CaptionText",OPTION_COLOUR,&option_sys_colour_CaptionText }, { "sys_colour_GrayText",OPTION_COLOUR,&option_sys_colour_GrayText }, { "sys_colour_Highlight",OPTION_COLOUR,&option_sys_colour_Highlight }, { "sys_colour_HighlightText",OPTION_COLOUR,&option_sys_colour_HighlightText }, { "sys_colour_InactiveBorder",OPTION_COLOUR,&option_sys_colour_InactiveBorder }, { "sys_colour_InactiveCaption",OPTION_COLOUR,&option_sys_colour_InactiveCaption }, { "sys_colour_InactiveCaptionText",OPTION_COLOUR,&option_sys_colour_InactiveCaptionText }, { "sys_colour_InfoBackground",OPTION_COLOUR,&option_sys_colour_InfoBackground }, { "sys_colour_InfoText",OPTION_COLOUR,&option_sys_colour_InfoText }, { "sys_colour_Menu",OPTION_COLOUR,&option_sys_colour_Menu }, { "sys_colour_MenuText",OPTION_COLOUR,&option_sys_colour_MenuText }, { "sys_colour_Scrollbar",OPTION_COLOUR,&option_sys_colour_Scrollbar }, { "sys_colour_ThreeDDarkShadow",OPTION_COLOUR,&option_sys_colour_ThreeDDarkShadow }, { "sys_colour_ThreeDFace",OPTION_COLOUR,&option_sys_colour_ThreeDFace }, { "sys_colour_ThreeDHighlight",OPTION_COLOUR,&option_sys_colour_ThreeDHighlight }, { "sys_colour_ThreeDLightShadow",OPTION_COLOUR,&option_sys_colour_ThreeDLightShadow }, { "sys_colour_ThreeDShadow",OPTION_COLOUR,&option_sys_colour_ThreeDShadow }, { "sys_colour_Window",OPTION_COLOUR,&option_sys_colour_Window }, { "sys_colour_WindowFrame",OPTION_COLOUR,&option_sys_colour_WindowFrame }, { "sys_colour_WindowText",OPTION_COLOUR,&option_sys_colour_WindowText }, EXTRA_OPTION_TABLE }; #define option_table_entries (sizeof option_table / sizeof option_table[0]) /** * Set an option value based on a string */ static bool strtooption(const char *value, struct option_entry_s *option_entry) { bool ret = false; colour rgbcolour; /* RRGGBB */ switch (option_entry->type) { case OPTION_BOOL: *((bool *)option_entry->p) = value[0] == '1'; ret = true; break; case OPTION_INTEGER: *((int *)option_entry->p) = atoi(value); ret = true; break; case OPTION_COLOUR: sscanf(value, "%x", &rgbcolour); *((colour *)option_entry->p) = ((0x000000FF & rgbcolour) << 16) | ((0x0000FF00 & rgbcolour) << 0) | ((0x00FF0000 & rgbcolour) >> 16); ret = true; break; case OPTION_STRING: free(*((char **)option_entry->p)); *((char **)option_entry->p) = strdup(value); ret = true; break; } return ret; } /* exported interface documented in options.h */ void options_read(const char *path) { char s[100]; FILE *fp; fp = fopen(path, "r"); if (!fp) { LOG(("failed to open file '%s'", path)); return; } while (fgets(s, 100, fp)) { char *colon, *value; unsigned int i; if (s[0] == 0 || s[0] == '#') continue; colon = strchr(s, ':'); if (colon == 0) continue; s[strlen(s) - 1] = 0; /* remove \n at end */ *colon = 0; /* terminate key */ value = colon + 1; for (i = 0; i != option_table_entries; i++) { if (strcasecmp(s, option_table[i].key) != 0) continue; strtooption(value, option_table + i); break; } } fclose(fp); if (option_font_size < 50) option_font_size = 50; if (1000 < option_font_size) option_font_size = 1000; if (option_font_min_size < 10) option_font_min_size = 10; if (500 < option_font_min_size) option_font_min_size = 500; if (option_memory_cache_size < 0) option_memory_cache_size = 0; } /* exported interface documented in options.h */ void options_write(const char *path) { unsigned int entry; FILE *fp; colour rgbcolour; /* RRGGBB */ fp = fopen(path, "w"); if (!fp) { LOG(("failed to open file '%s' for writing", path)); return; } for (entry = 0; entry != option_table_entries; entry++) { switch (option_table[entry].type) { case OPTION_BOOL: fprintf(fp, "%s:%c\n", option_table[entry].key, *((bool *) option_table[entry].p) ? '1' : '0'); break; case OPTION_INTEGER: fprintf(fp, "%s:%i\n", option_table[entry].key, *((int *) option_table[entry].p)); break; case OPTION_COLOUR: rgbcolour = ((0x000000FF & *((colour *) option_table[entry].p)) << 16) | ((0x0000FF00 & *((colour *) option_table[entry].p)) << 0) | ((0x00FF0000 & *((colour *) option_table[entry].p)) >> 16); fprintf(fp, "%s:%06x\n", option_table[entry].key, rgbcolour); break; case OPTION_STRING: if (((*((char **) option_table[entry].p)) != NULL) && (*(*((char **) option_table[entry].p)) != 0)) { fprintf(fp, "%s:%s\n", option_table[entry].key, *((char **) option_table[entry].p)); } break; } } fclose(fp); } /** * Output an option value into a string, in HTML format. * * \param option The option to output the value of. * \param size The size of the string buffer. * \param pos The current position in string * \param string The string in which to output the value. * \return The number of bytes written to string or -1 on error */ static size_t options_output_value_html(struct option_entry_s *option, size_t size, size_t pos, char *string) { size_t slen = 0; /* length added to string */ colour rgbcolour; /* RRGGBB */ switch (option->type) { case OPTION_BOOL: slen = snprintf(string + pos, size - pos, "%s", *((bool *)option->p) ? "true" : "false"); break; case OPTION_INTEGER: slen = snprintf(string + pos, size - pos, "%i", *((int *)option->p)); break; case OPTION_COLOUR: rgbcolour = ((0x000000FF & *((colour *) option->p)) << 16) | ((0x0000FF00 & *((colour *) option->p)) << 0) | ((0x00FF0000 & *((colour *) option->p)) >> 16); slen = snprintf(string + pos, size - pos, "#%06x", rgbcolour, (~rgbcolour) & 0xffffff, rgbcolour); break; case OPTION_STRING: if (*((char **)option->p) != NULL) { slen = snprintf(string + pos, size - pos, "%s", *((char **)option->p)); } else { slen = snprintf(string + pos, size - pos, "NULL" ""); } break; } return slen; } /** * Output an option value into a string, in plain text format. * * \param option The option to output the value of. * \param size The size of the string buffer. * \param pos The current position in string * \param string The string in which to output the value. * \return The number of bytes written to string or -1 on error */ static size_t options_output_value_text(struct option_entry_s *option, size_t size, size_t pos, char *string) { size_t slen = 0; /* length added to string */ colour rgbcolour; /* RRGGBB */ switch (option->type) { case OPTION_BOOL: slen = snprintf(string + pos, size - pos, "%c", *((bool *)option->p) ? '1' : '0'); break; case OPTION_INTEGER: slen = snprintf(string + pos, size - pos, "%i", *((int *)option->p)); break; case OPTION_COLOUR: rgbcolour = ((0x000000FF & *((colour *) option->p)) << 16) | ((0x0000FF00 & *((colour *) option->p)) << 0) | ((0x00FF0000 & *((colour *) option->p)) >> 16); slen = snprintf(string + pos, size - pos, "%06x", rgbcolour); break; case OPTION_STRING: if (*((char **)option->p) != NULL) { slen = snprintf(string + pos, size - pos, "%s", *((char **)option->p)); } break; } return slen; } /* exported interface documented in options.h */ void options_commandline(int *pargc, char **argv) { char *arg; char *val; int arglen; int idx = 1; int mv_loop; unsigned int entry_loop; while (idx < *pargc) { arg = argv[idx]; arglen = strlen(arg); /* check we have an option */ /* option must start -- and be as long as the shortest option*/ if ((arglen < (2+5) ) || (arg[0] != '-') || (arg[1] != '-')) break; arg += 2; /* skip -- */ val = strchr(arg, '='); if (val == NULL) { /* no equals sign - next parameter is val */ idx++; if (idx >= *pargc) break; val = argv[idx]; } else { /* equals sign */ arglen = val - arg ; val++; } /* arg+arglen is the option to set, val is the value */ LOG(("%.*s = %s",arglen,arg,val)); for (entry_loop = 0; entry_loop < option_table_entries; entry_loop++) { if (strncmp(arg, option_table[entry_loop].key, arglen) == 0) { strtooption(val, option_table + entry_loop); break; } } idx++; } /* remove processed options from argv */ for (mv_loop=0;mv_loop < (*pargc - idx); mv_loop++) { argv[mv_loop + 1] = argv[mv_loop + idx]; } *pargc -= (idx - 1); } /* exported interface documented in options.h */ int options_snoptionf(char *string, size_t size, unsigned int option, const char *fmt) { size_t slen = 0; /* current output string length */ int fmtc = 0; /* current index into format string */ struct option_entry_s *option_entry; if (option >= option_table_entries) return -1; option_entry = option_table + option; while((slen < size) && (fmt[fmtc] != 0)) { if (fmt[fmtc] == '%') { fmtc++; switch (fmt[fmtc]) { case 'k': slen += snprintf(string + slen, size - slen, "%s", option_entry->key); break; case 't': switch (option_entry->type) { case OPTION_BOOL: slen += snprintf(string + slen, size - slen, "boolean"); break; case OPTION_INTEGER: slen += snprintf(string + slen, size - slen, "integer"); break; case OPTION_COLOUR: slen += snprintf(string + slen, size - slen, "colour"); break; case OPTION_STRING: slen += snprintf(string + slen, size - slen, "string"); break; } break; case 'V': slen += options_output_value_html(option_entry, size, slen, string); break; case 'v': slen += options_output_value_text(option_entry, size, slen, string); break; } fmtc++; } else { string[slen] = fmt[fmtc]; slen++; fmtc++; } } /* Ensure that we NUL-terminate the output */ string[min(slen, size - 1)] = '\0'; return slen; } /* exported interface documented in options.h */ void options_dump(FILE *outf) { char buffer[256]; int opt_loop = 0; int res; do { res = options_snoptionf(buffer, sizeof buffer, opt_loop, "%k:%v\n"); if (res > 0) { fprintf(outf, "%s", buffer); } opt_loop++; } while (res > 0); } netsurf-2.9/netsurf-2.9/desktop/scrollbar.h0000664000175000017500000001443511673404206017661 0ustar vincevince/* * Copyright 2009 Paul Blokus * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file * Scrollbar widget (interface). */ #ifndef _NETSURF_DESKTOP_SCROLLBAR_H_ #define _NETSURF_DESKTOP_SCROLLBAR_H_ #include #include #include "desktop/browser.h" #define SCROLLBAR_WIDTH 16 /* Region dependent values for scrollbar_scroll function */ #define SCROLL_TOP INT_MIN #define SCROLL_PAGE_UP INT_MIN + 1 #define SCROLL_PAGE_DOWN INT_MAX - 1 #define SCROLL_BOTTOM INT_MAX struct scrollbar; typedef enum { SCROLLBAR_MSG_REDRAW, /* the scrollbar requests a redraw */ SCROLLBAR_MSG_MOVED, /* the scroll value has changed */ SCROLLBAR_MSG_SCROLL_START, /* a scrollbar drag has started, all * mouse events should be passed to * the scrollbar regardless of the * coordinates */ SCROLLBAR_MSG_SCROLL_FINISHED, /* cancel the above */ } scrollbar_msg; struct scrollbar_msg_data { struct scrollbar *scrollbar; scrollbar_msg msg; int scroll_offset; int x0, y0, x1, y1; }; /** * Client callback for the scrollbar. * * \param client_data user data passed at scroll creation * \param scrollbar_data scrollbar message data */ typedef void(*scrollbar_client_callback)(void *client_data, struct scrollbar_msg_data *scrollbar_data); /** * Create a scrollbar. * * \param horizontal true = horizontal scrollbar, false = vertical * \param length length of scrollbar widget * \param full_size length of contained scrollable area * \param visible_size length of visible part of scrollable area * \param client_data data for the client callback * \param client_callback client callback for scrollbar events * \param s updated to point at the newly created scrollbar * \return true if scrollbar has been created succesfully or false on * memory exhaustion */ bool scrollbar_create(bool horizontal, int length, int full_size, int visible_size, void *client_data, scrollbar_client_callback client_callback, struct scrollbar **s); /** * Destroy a scrollbar. * * \param s the scrollbar to be destroyed */ void scrollbar_destroy(struct scrollbar *s); /** * Redraw a part of the scrollbar. * * \param s the scrollbar to be redrawn * \param x the X coordinate to draw the scrollbar at * \param y the Y coordinate to draw the scrollbar at * \param clip the clipping rectangle * \param scale scale for the redraw * \param ctx current redraw context * \return true on succes false otherwise */ bool scrollbar_redraw(struct scrollbar *s, int x, int y, const struct rect *clip, float scale, const struct redraw_context *ctx); /** * Set the scroll value of the scrollbar. * * \param s the scrollbar to have the value set * \param value the new value to be set * \param bar_pos true if the value is for the scrollbar indication bar * position, false if it is for the scrolled area offset */ void scrollbar_set(struct scrollbar *s, int value, bool bar_pos); /** * Scroll the scrollbar by given amount. * * \param s the scrollbar to be scrolled * \param change the change in scroll offset required (in px) * \return true iff the scrollbar was moved. */ bool scrollbar_scroll(struct scrollbar *s, int change); /** * Get the current scroll offset to the visible part of the full area. * * \param s the scrollbar to get the scroll offset value from * \return current scroll offset */ int scrollbar_get_offset(struct scrollbar *s); /** * Set the length of the scrollbar widget, the size of the visible area, and the * size of the full area. * * \param s the scrollbar to set the values for * \param length -1 or the new scrollbar widget length * \param visible_size -1 or the new size of the visible area * \param full_size -1 or the new size of the full contained area */ void scrollbar_set_extents(struct scrollbar *s, int length, int visible_size, int full_size); /** * Check orientation of the scrollbar. * * \param s the scrollbar to check the orientation of * \return true for a horizontal scrollbar, else false (vertical) */ bool scrollbar_is_horizontal(struct scrollbar *s); /** * Handle mouse actions other then drag ends. * * \param s the scrollbar which gets the mouse action * \param mouse mouse state * \param x X coordinate of the mouse * \param y Y coordinate of the mouse * \return message for the status bar or NULL on failure */ const char *scrollbar_mouse_action(struct scrollbar *s, browser_mouse_state mouse, int x, int y); /** * Handle end of mouse drags. * * \param s the scrollbar for which the drag ends * \param mouse mouse state * \param x X coordinate of the mouse * \param y Y coordinate of the mouse */ void scrollbar_mouse_drag_end(struct scrollbar *s, browser_mouse_state mouse, int x, int y); /** * Called when the content is being dragged to the scrollbars have to adjust. * If the content has both scrollbars, and scrollbar_make_pair has beed called * before, only the one scroll which will receive further mouse events has to be * passed. * * \param s one of the the scrollbars owned by the dragged content * \param x X coordinate of mouse during drag start * \param y Y coordinate of mouse during drag start */ void scrollbar_start_content_drag(struct scrollbar *s, int x, int y); /** * Connect a horizontal and a vertical scrollbar into a pair so that they * co-operate during 2D drags. * * \param horizontal the scrollbar used for horizontal scrolling * \param vertical the scrollbar used for vertical scrolling */ void scrollbar_make_pair(struct scrollbar *horizontal, struct scrollbar *vertical); /** * Get the scrollbar's client data * * \param s the scrollbar to get the client data from * \return client data */ void *scrollbar_get_data(struct scrollbar *s); #endif netsurf-2.9/netsurf-2.9/desktop/save_complete.c0000664000175000017500000004660311666704733020533 0ustar vincevince/* * Copyright 2004 John M Bell * Copyright 2004-2007 James Bursa * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** \file * Save HTML document with dependencies (implementation). */ #include "utils/config.h" #include #include #include #include #include #include #include #include #include #include "utils/config.h" #include "content/content.h" #include "content/hlcache.h" #include "css/css.h" #include "render/box.h" #include "desktop/save_complete.h" #include "utils/log.h" #include "utils/url.h" #include "utils/utils.h" regex_t save_complete_import_re; /** An entry in save_complete_list. */ struct save_complete_entry { hlcache_handle *content; struct save_complete_entry *next; /**< Next entry in list */ }; static bool save_complete_html(hlcache_handle *c, const char *path, bool index, struct save_complete_entry **list); static bool save_imported_sheets(struct nscss_import *imports, uint32_t count, const char *path, struct save_complete_entry **list); static char * rewrite_stylesheet_urls(const char *source, unsigned int size, int *osize, const char *base, struct save_complete_entry *list); static bool rewrite_document_urls(xmlDoc *doc, const char *base, struct save_complete_entry *list); static bool rewrite_urls(xmlNode *n, const char *base, struct save_complete_entry *list); static bool rewrite_url(xmlNode *n, const char *attr, const char *base, struct save_complete_entry *list); static bool save_complete_list_add(hlcache_handle *content, struct save_complete_entry **list); static hlcache_handle * save_complete_list_find(const char *url, struct save_complete_entry *list); static bool save_complete_list_check(hlcache_handle *content, struct save_complete_entry *list); /* static void save_complete_list_dump(void); */ static bool save_complete_inventory(const char *path, struct save_complete_entry *list); /** * Save an HTML page with all dependencies. * * \param c CONTENT_HTML to save * \param path directory to save to (must exist) * \return true on success, false on error and error reported */ bool save_complete(hlcache_handle *c, const char *path) { bool result; struct save_complete_entry *list = NULL; result = save_complete_html(c, path, true, &list); if (result) result = save_complete_inventory(path, list); /* free save_complete_list */ while (list) { struct save_complete_entry *next = list->next; free(list); list = next; } return result; } /** * Save an HTML page with all dependencies, recursing through imported pages. * * \param c CONTENT_HTML to save * \param path directory to save to (must exist) * \param index true to save as "index" * \return true on success, false on error and error reported */ bool save_complete_html(hlcache_handle *c, const char *path, bool index, struct save_complete_entry **list) { struct html_stylesheet *sheets; struct content_html_object *object; char filename[256]; unsigned int i, count; xmlDocPtr doc; bool res; if (content_get_type(c) != CONTENT_HTML) return false; if (save_complete_list_check(c, *list)) return true; /* save stylesheets, ignoring the base and adblocking sheets */ sheets = html_get_stylesheets(c, &count); for (i = STYLESHEET_START; i != count; i++) { hlcache_handle *css; const char *css_data; unsigned long css_size; char *source; int source_len; struct nscss_import *imports; uint32_t import_count; lwc_string *type; if (sheets[i].type == HTML_STYLESHEET_INTERNAL) { if (save_imported_sheets( sheets[i].data.internal->imports, sheets[i].data.internal->import_count, path, list) == false) return false; continue; } css = sheets[i].data.external; if (!css) continue; if (save_complete_list_check(css, *list)) continue; if (!save_complete_list_add(css, list)) { warn_user("NoMemory", 0); return false; } imports = nscss_get_imports(css, &import_count); if (!save_imported_sheets(imports, import_count, path, list)) return false; snprintf(filename, sizeof filename, "%p", css); css_data = content_get_source_data(css, &css_size); source = rewrite_stylesheet_urls(css_data, css_size, &source_len, nsurl_access(hlcache_handle_get_url(css)), *list); if (!source) { warn_user("NoMemory", 0); return false; } type = content_get_mime_type(css); if (type == NULL) { free(source); return false; } res = save_complete_gui_save(path, filename, source_len, source, type); lwc_string_unref(type); free(source); if (res == false) return false; } /* save objects */ object = html_get_objects(c, &count); for (; object != NULL; object = object->next) { hlcache_handle *obj = object->content; const char *obj_data; unsigned long obj_size; lwc_string *type; if (obj == NULL || content_get_type(obj) == CONTENT_NONE) continue; obj_data = content_get_source_data(obj, &obj_size); if (obj_data == NULL) continue; if (save_complete_list_check(obj, *list)) continue; if (!save_complete_list_add(obj, list)) { warn_user("NoMemory", 0); return false; } if (content_get_type(obj) == CONTENT_HTML) { if (!save_complete_html(obj, path, false, list)) return false; continue; } snprintf(filename, sizeof filename, "%p", obj); type = content_get_mime_type(obj); if (type == NULL) return false; res = save_complete_gui_save(path, filename, obj_size, obj_data, type); lwc_string_unref(type); if(res == false) return false; } /*save_complete_list_dump();*/ /* copy document */ doc = xmlCopyDoc(html_get_document(c), 1); if (doc == NULL) { warn_user("NoMemory", 0); return false; } /* rewrite all urls we know about */ if (!rewrite_document_urls(doc, nsurl_access(html_get_base_url(c)), *list)) { xmlFreeDoc(doc); warn_user("NoMemory", 0); return false; } /* save the html file out last of all */ if (index) snprintf(filename, sizeof filename, "index"); else snprintf(filename, sizeof filename, "%p", c); errno = 0; if (save_complete_htmlSaveFileFormat(path, filename, doc, 0, 0) == -1) { if (errno) warn_user("SaveError", strerror(errno)); else warn_user("SaveError", "htmlSaveFileFormat failed"); xmlFreeDoc(doc); return false; } xmlFreeDoc(doc); return true; } /** * Save stylesheets imported by a CONTENT_CSS. * * \param imports Array of imports * \param count Number of imports in list * \param path Path to save to * \return true on success, false on error and error reported */ bool save_imported_sheets(struct nscss_import *imports, uint32_t count, const char *path, struct save_complete_entry **list) { char filename[256]; unsigned int j; char *source; int source_len; bool res; for (j = 0; j != count; j++) { hlcache_handle *css = imports[j].c; const char *css_data; unsigned long css_size; struct nscss_import *child_imports; uint32_t child_import_count; lwc_string *type; if (css == NULL) continue; if (save_complete_list_check(css, *list)) continue; if (!save_complete_list_add(css, list)) { warn_user("NoMemory", 0); return false; } child_imports = nscss_get_imports(css, &child_import_count); if (!save_imported_sheets(child_imports, child_import_count, path, list)) return false; snprintf(filename, sizeof filename, "%p", css); css_data = content_get_source_data(css, &css_size); source = rewrite_stylesheet_urls(css_data, css_size, &source_len, nsurl_access(hlcache_handle_get_url(css)), *list); if (!source) { warn_user("NoMemory", 0); return false; } if (lwc_intern_string("text/css", SLEN("text/css"), &type) != lwc_error_ok) { free(source); warn_user("NoMemory", 0); return false; } res = save_complete_gui_save(path, filename, source_len, source, type); lwc_string_unref(type); free(source); if (res == false) return false; } return true; } /** * Initialise the save_complete module. */ void save_complete_init(void) { /* Match an @import rule - see CSS 2.1 G.1. */ regcomp_wrapper(&save_complete_import_re, "@import" /* IMPORT_SYM */ "[ \t\r\n\f]*" /* S* */ /* 1 */ "(" /* [ */ /* 2 3 */ "\"(([^\"]|[\\]\")*)\"" /* STRING (approximated) */ "|" /* 4 5 */ "'(([^']|[\\]')*)'" "|" /* | */ "url\\([ \t\r\n\f]*" /* URI (approximated) */ /* 6 7 */ "\"(([^\"]|[\\]\")*)\"" "[ \t\r\n\f]*\\)" "|" "url\\([ \t\r\n\f]*" /* 8 9 */ "'(([^']|[\\]')*)'" "[ \t\r\n\f]*\\)" "|" "url\\([ \t\r\n\f]*" /* 10 */ "([^) \t\r\n\f]*)" "[ \t\r\n\f]*\\)" ")", /* ] */ REG_EXTENDED | REG_ICASE); } /** * Rewrite stylesheet \@import rules for save complete. * * @param source stylesheet source * @param size size of source * @param osize updated with the size of the result * @param base url of stylesheet * @return converted source, or 0 on out of memory */ char * rewrite_stylesheet_urls(const char *source, unsigned int size, int *osize, const char *base, struct save_complete_entry *list) { char *res; const char *url; char *url2; char buf[20]; unsigned int offset = 0; int url_len = 0; hlcache_handle *content; int m; unsigned int i; unsigned int imports = 0; regmatch_t match[11]; url_func_result result; /* count number occurences of @import to (over)estimate result size */ /* can't use strstr because source is not 0-terminated string */ for (i = 0; 7 < size && i != size - 7; i++) { if (source[i] == '@' && tolower(source[i + 1]) == 'i' && tolower(source[i + 2]) == 'm' && tolower(source[i + 3]) == 'p' && tolower(source[i + 4]) == 'o' && tolower(source[i + 5]) == 'r' && tolower(source[i + 6]) == 't') imports++; } res = malloc(size + imports * 20); if (!res) return 0; *osize = 0; while (offset < size) { m = regexec(&save_complete_import_re, source + offset, 11, match, 0); if (m) break; /*for (unsigned int i = 0; i != 11; i++) { if (match[i].rm_so == -1) continue; fprintf(stderr, "%i: '%.*s'\n", i, match[i].rm_eo - match[i].rm_so, source + offset + match[i].rm_so); }*/ url = 0; if (match[2].rm_so != -1) { url = source + offset + match[2].rm_so; url_len = match[2].rm_eo - match[2].rm_so; } else if (match[4].rm_so != -1) { url = source + offset + match[4].rm_so; url_len = match[4].rm_eo - match[4].rm_so; } else if (match[6].rm_so != -1) { url = source + offset + match[6].rm_so; url_len = match[6].rm_eo - match[6].rm_so; } else if (match[8].rm_so != -1) { url = source + offset + match[8].rm_so; url_len = match[8].rm_eo - match[8].rm_so; } else if (match[10].rm_so != -1) { url = source + offset + match[10].rm_so; url_len = match[10].rm_eo - match[10].rm_so; } assert(url); url2 = strndup(url, url_len); if (!url2) { free(res); return 0; } result = url_join(url2, base, (char**)&url); free(url2); if (result == URL_FUNC_NOMEM) { free(res); return 0; } /* copy data before match */ memcpy(res + *osize, source + offset, match[0].rm_so); *osize += match[0].rm_so; if (result == URL_FUNC_OK) { content = save_complete_list_find(url, list); if (content) { /* replace import */ snprintf(buf, sizeof buf, "@import '%p'", content); memcpy(res + *osize, buf, strlen(buf)); *osize += strlen(buf); } else { /* copy import */ memcpy(res + *osize, source + offset + match[0].rm_so, match[0].rm_eo - match[0].rm_so); *osize += match[0].rm_eo - match[0].rm_so; } } else { /* copy import */ memcpy(res + *osize, source + offset + match[0].rm_so, match[0].rm_eo - match[0].rm_so); *osize += match[0].rm_eo - match[0].rm_so; } assert(0 < match[0].rm_eo); offset += match[0].rm_eo; } /* copy rest of source */ if (offset < size) { memcpy(res + *osize, source + offset, size - offset); *osize += size - offset; } return res; } /** * Rewrite URLs in a HTML document to be relative. * * \param doc root of the document tree * \param base base url of document * \return true on success, false on out of memory */ bool rewrite_document_urls(xmlDoc *doc, const char *base, struct save_complete_entry *list) { xmlNode *node; for (node = doc->children; node; node = node->next) if (node->type == XML_ELEMENT_NODE) if (!rewrite_urls(node, base, list)) return false; return true; } /** * Traverse tree, rewriting URLs as we go. * * \param n xmlNode of type XML_ELEMENT_NODE to rewrite * \param base base url of document * \return true on success, false on out of memory * * URLs in the tree rooted at element n are rewritten. */ bool rewrite_urls(xmlNode *n, const char *base, struct save_complete_entry *list) { xmlNode *child; assert(n->type == XML_ELEMENT_NODE); /** * We only need to consider the following cases: * * Attribute: Elements: * * 1) data * 2) href * 3) src