Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of LibCSS.
  3.  * Licensed under the MIT License,
  4.  *                http://www.opensource.org/licenses/mit-license.php
  5.  * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
  6.  */
  7.  
  8. #include <assert.h>
  9. #include <string.h>
  10.  
  11. #include "bytecode/bytecode.h"
  12. #include "bytecode/opcodes.h"
  13. #include "parse/properties/properties.h"
  14. #include "parse/properties/utils.h"
  15.  
  16.  
  17. /**
  18.  * Parse content
  19.  *
  20.  * \param c       Parsing context
  21.  * \param vector  Vector of tokens to process
  22.  * \param ctx     Pointer to vector iteration context
  23.  * \param result  Pointer to location to receive resulting style
  24.  * \return CSS_OK on success,
  25.  *         CSS_NOMEM on memory exhaustion,
  26.  *         CSS_INVALID if the input is not valid
  27.  *
  28.  * Post condition: \a *ctx is updated with the next token to process
  29.  *                 If the input is invalid, then \a *ctx remains unchanged.
  30.  */
  31. css_error css__parse_content(css_language *c,
  32.                 const parserutils_vector *vector, int *ctx,
  33.                 css_style *result)
  34. {
  35.         int orig_ctx = *ctx;
  36.         css_error error;
  37.         const css_token *token;
  38.         bool match;
  39.  
  40.         /* IDENT(normal, none, inherit) | [ ... ]+ */
  41.         token = parserutils_vector_iterate(vector, ctx);
  42.         if (token == NULL) {
  43.                 *ctx = orig_ctx;
  44.                 return CSS_INVALID;
  45.         }
  46.  
  47.  
  48.         if ((token->type == CSS_TOKEN_IDENT) &&
  49.             (lwc_string_caseless_isequal(token->idata,
  50.                                          c->strings[INHERIT],
  51.                                          &match) == lwc_error_ok && match)) {
  52.                 error = css_stylesheet_style_inherit(result, CSS_PROP_CONTENT);
  53.         } else if ((token->type == CSS_TOKEN_IDENT) &&
  54.                    (lwc_string_caseless_isequal(token->idata,
  55.                                                 c->strings[NORMAL],
  56.                                                 &match) == lwc_error_ok && match)) {
  57.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NORMAL);
  58.         } else if ((token->type == CSS_TOKEN_IDENT) &&
  59.                    (lwc_string_caseless_isequal(token->idata,
  60.                                                 c->strings[NONE],
  61.                                                 &match) == lwc_error_ok && match)) {
  62.                 error = css__stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NONE);
  63.         } else {
  64.  
  65. /* Macro to output the value marker, awkward because we need to check
  66.  * first to determine how the value is constructed.
  67.  */
  68. #define CSS_APPEND(CSSVAL) css__stylesheet_style_append(result, first?buildOPV(CSS_PROP_CONTENT, 0, CSSVAL):CSSVAL)
  69.  
  70.                 bool first = true;
  71.                 int prev_ctx = orig_ctx;
  72.  
  73.                 /* [
  74.                  *   IDENT(open-quote, close-quote, no-open-quote,
  75.                  *         no-close-quote) |
  76.                  *   STRING |
  77.                  *   URI |
  78.                  *   FUNCTION(attr) IDENT ')' |
  79.                  *   FUNCTION(counter) IDENT IDENT? ')' |
  80.                  *   FUNCTION(counters) IDENT STRING IDENT? ')'
  81.                  * ]+
  82.                  */
  83.  
  84.                 while (token != NULL) {
  85.                         if ((token->type == CSS_TOKEN_IDENT) &&
  86.                             (lwc_string_caseless_isequal(
  87.                                     token->idata, c->strings[OPEN_QUOTE],
  88.                                     &match) == lwc_error_ok && match)) {
  89.  
  90.                                 error = CSS_APPEND(CONTENT_OPEN_QUOTE);
  91.  
  92.                         } else if (token->type == CSS_TOKEN_IDENT &&
  93.                                    (lwc_string_caseless_isequal(
  94.                                            token->idata, c->strings[CLOSE_QUOTE],
  95.                                            &match) == lwc_error_ok && match)) {
  96.  
  97.                                 error = CSS_APPEND(CONTENT_CLOSE_QUOTE);
  98.                         } else if (token->type == CSS_TOKEN_IDENT &&
  99.                                    (lwc_string_caseless_isequal(
  100.                                            token->idata, c->strings[NO_OPEN_QUOTE],
  101.                                            &match) == lwc_error_ok && match)) {
  102.                                 error = CSS_APPEND(CONTENT_NO_OPEN_QUOTE);
  103.                         } else if (token->type == CSS_TOKEN_IDENT &&
  104.                                    (lwc_string_caseless_isequal(
  105.                                            token->idata, c->strings[NO_CLOSE_QUOTE],
  106.                                            &match) == lwc_error_ok && match)) {
  107.                                 error = CSS_APPEND(CONTENT_NO_CLOSE_QUOTE);
  108.                         } else if (token->type == CSS_TOKEN_STRING) {
  109.                                 uint32_t snumber;
  110.  
  111.                                 error = css__stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
  112.                                 if (error != CSS_OK) {
  113.                                         *ctx = orig_ctx;
  114.                                         return error;
  115.                                 }
  116.  
  117.                                 error = CSS_APPEND(CONTENT_STRING);
  118.                                 if (error != CSS_OK) {
  119.                                         *ctx = orig_ctx;
  120.                                         return error;
  121.                                 }
  122.  
  123.                                 error = css__stylesheet_style_append(result, snumber);
  124.                         } else if (token->type == CSS_TOKEN_URI) {
  125.                                 lwc_string *uri;
  126.                                 uint32_t uri_snumber;
  127.  
  128.                                 error = c->sheet->resolve(c->sheet->resolve_pw,
  129.                                                           c->sheet->url,
  130.                                                           token->idata,
  131.                                                           &uri);
  132.                                 if (error != CSS_OK) {
  133.                                         *ctx = orig_ctx;
  134.                                         return error;
  135.                                 }
  136.  
  137.                                 error = css__stylesheet_string_add(c->sheet,
  138.                                                                   uri,
  139.                                                                   &uri_snumber);
  140.                                 if (error != CSS_OK) {
  141.                                         *ctx = orig_ctx;
  142.                                         return error;
  143.                                 }
  144.  
  145.                                 error = CSS_APPEND(CONTENT_URI);
  146.                                 if (error != CSS_OK) {
  147.                                         *ctx = orig_ctx;
  148.                                         return error;
  149.                                 }
  150.  
  151.                                 error = css__stylesheet_style_append(result, uri_snumber);
  152.                         } else if (token->type == CSS_TOKEN_FUNCTION &&
  153.                                    (lwc_string_caseless_isequal(
  154.                                            token->idata, c->strings[ATTR],
  155.                                            &match) == lwc_error_ok && match)) {
  156.                                 uint32_t snumber;
  157.  
  158.                                 consumeWhitespace(vector, ctx);
  159.  
  160.                                 /* Expect IDENT */
  161.                                 token = parserutils_vector_iterate(vector, ctx);
  162.                                 if (token == NULL || token->type != CSS_TOKEN_IDENT) {
  163.                                         *ctx = orig_ctx;
  164.                                         return CSS_INVALID;
  165.                                 }
  166.  
  167.                                 error = css__stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
  168.                                 if (error != CSS_OK) {
  169.                                         *ctx = orig_ctx;
  170.                                         return error;
  171.                                 }
  172.  
  173.                                 error = CSS_APPEND(CONTENT_ATTR);
  174.                                 if (error != CSS_OK) {
  175.                                         *ctx = orig_ctx;
  176.                                         return error;
  177.                                 }
  178.  
  179.                                 error = css__stylesheet_style_append(result, snumber);
  180.  
  181.                                 consumeWhitespace(vector, ctx);
  182.  
  183.                                 /* Expect ')' */
  184.                                 token = parserutils_vector_iterate(vector, ctx);
  185.                                 if (token == NULL || tokenIsChar(token, ')') == false) {
  186.                                         *ctx = orig_ctx;
  187.                                         return CSS_INVALID;
  188.                                 }
  189.                         } else if (token->type == CSS_TOKEN_FUNCTION &&
  190.                                    (lwc_string_caseless_isequal(
  191.                                            token->idata, c->strings[COUNTER],
  192.                                            &match) == lwc_error_ok && match)) {
  193.                                 lwc_string *name;
  194.                                 uint32_t snumber;
  195.                                 uint32_t opv;
  196.  
  197.                                 opv = CONTENT_COUNTER;
  198.  
  199.                                 consumeWhitespace(vector, ctx);
  200.  
  201.                                 /* Expect IDENT */
  202.                                 token = parserutils_vector_iterate(vector, ctx);
  203.                                 if (token == NULL || token->type != CSS_TOKEN_IDENT) {
  204.                                         *ctx = orig_ctx;
  205.                                         return CSS_INVALID;
  206.                                 }
  207.  
  208.                                 name = token->idata;
  209.  
  210.                                 consumeWhitespace(vector, ctx);
  211.  
  212.                                 /* Possible ',' */
  213.                                 token = parserutils_vector_peek(vector, *ctx);
  214.                                 if (token == NULL ||
  215.                                     (tokenIsChar(token, ',') == false &&
  216.                                      tokenIsChar(token, ')') == false)) {
  217.                                         *ctx = orig_ctx;
  218.                                         return CSS_INVALID;
  219.                                 }
  220.  
  221.                                 if (tokenIsChar(token, ',')) {
  222.                                         uint16_t v;
  223.  
  224.                                         parserutils_vector_iterate(vector, ctx);
  225.  
  226.                                         consumeWhitespace(vector, ctx);
  227.  
  228.                                         /* Expect IDENT */
  229.                                         token = parserutils_vector_peek(vector, *ctx);
  230.                                         if (token == NULL || token->type !=
  231.                                             CSS_TOKEN_IDENT) {
  232.                                                 *ctx = orig_ctx;
  233.                                                 return CSS_INVALID;
  234.                                         }
  235.  
  236.                                         error = css__parse_list_style_type_value(c, token, &v);
  237.                                         if (error != CSS_OK) {
  238.                                                 *ctx = orig_ctx;
  239.                                                 return error;
  240.                                         }
  241.  
  242.                                         opv |= v << CONTENT_COUNTER_STYLE_SHIFT;
  243.  
  244.                                         parserutils_vector_iterate(vector, ctx);
  245.  
  246.                                         consumeWhitespace(vector, ctx);
  247.                                 } else {
  248.                                         opv |= LIST_STYLE_TYPE_DECIMAL <<
  249.                                                 CONTENT_COUNTER_STYLE_SHIFT;
  250.                                 }
  251.  
  252.                                 /* Expect ')' */
  253.                                 token = parserutils_vector_iterate(vector, ctx);
  254.                                 if (token == NULL || tokenIsChar(token, ')') == false) {
  255.                                         *ctx = orig_ctx;
  256.                                         return CSS_INVALID;
  257.                                 }
  258.  
  259.  
  260.                                 error = css__stylesheet_string_add(c->sheet, lwc_string_ref(name), &snumber);
  261.                                 if (error != CSS_OK) {
  262.                                         *ctx = orig_ctx;
  263.                                         return error;
  264.                                 }
  265.  
  266.                                 error = CSS_APPEND(opv);
  267.                                 if (error != CSS_OK) {
  268.                                         *ctx = orig_ctx;
  269.                                         return error;
  270.                                 }
  271.  
  272.                                 error = css__stylesheet_style_append(result, snumber);
  273.                         } else if (token->type == CSS_TOKEN_FUNCTION &&
  274.                                    (lwc_string_caseless_isequal(
  275.                                            token->idata, c->strings[COUNTERS],
  276.                                            &match) == lwc_error_ok && match)) {
  277.                                 lwc_string *name;
  278.                                 lwc_string *sep;
  279.                                 uint32_t name_snumber;
  280.                                 uint32_t sep_snumber;
  281.                                 uint32_t opv;
  282.  
  283.                                 opv = CONTENT_COUNTERS;
  284.  
  285.                                 consumeWhitespace(vector, ctx);
  286.  
  287.                                 /* Expect IDENT */
  288.                                 token = parserutils_vector_iterate(vector, ctx);
  289.                                 if (token == NULL || token->type != CSS_TOKEN_IDENT) {
  290.                                         *ctx = orig_ctx;
  291.                                         return CSS_INVALID;
  292.                                 }
  293.  
  294.                                 name = token->idata;
  295.  
  296.                                 consumeWhitespace(vector, ctx);
  297.  
  298.                                 /* Expect ',' */
  299.                                 token = parserutils_vector_iterate(vector, ctx);
  300.                                 if (token == NULL || tokenIsChar(token, ',') == false) {
  301.                                         *ctx = orig_ctx;
  302.                                         return CSS_INVALID;
  303.                                 }
  304.  
  305.                                 consumeWhitespace(vector, ctx);
  306.  
  307.                                 /* Expect STRING */
  308.                                 token = parserutils_vector_iterate(vector, ctx);
  309.                                 if (token == NULL || token->type != CSS_TOKEN_STRING) {
  310.                                         *ctx = orig_ctx;
  311.                                         return CSS_INVALID;
  312.                                 }
  313.  
  314.                                 sep = token->idata;
  315.  
  316.                                 consumeWhitespace(vector, ctx);
  317.  
  318.                                 /* Possible ',' */
  319.                                 token = parserutils_vector_peek(vector, *ctx);
  320.                                 if (token == NULL ||
  321.                                     (tokenIsChar(token, ',') == false &&
  322.                                      tokenIsChar(token, ')') == false)) {
  323.                                         *ctx = orig_ctx;
  324.                                         return CSS_INVALID;
  325.                                 }
  326.  
  327.                                 if (tokenIsChar(token, ',')) {
  328.                                         uint16_t v;
  329.  
  330.                                         parserutils_vector_iterate(vector, ctx);
  331.  
  332.                                         consumeWhitespace(vector, ctx);
  333.  
  334.                                         /* Expect IDENT */
  335.                                         token = parserutils_vector_peek(vector, *ctx);
  336.                                         if (token == NULL || token->type !=
  337.                                             CSS_TOKEN_IDENT) {
  338.                                                 *ctx = orig_ctx;
  339.                                                 return CSS_INVALID;
  340.                                         }
  341.  
  342.                                         error = css__parse_list_style_type_value(c,
  343.                                                                             token, &v);
  344.                                         if (error != CSS_OK) {
  345.                                                 *ctx = orig_ctx;
  346.                                                 return error;
  347.                                         }
  348.  
  349.                                         opv |= v << CONTENT_COUNTERS_STYLE_SHIFT;
  350.  
  351.                                         parserutils_vector_iterate(vector, ctx);
  352.  
  353.                                         consumeWhitespace(vector, ctx);
  354.                                 } else {
  355.                                         opv |= LIST_STYLE_TYPE_DECIMAL <<
  356.                                                 CONTENT_COUNTERS_STYLE_SHIFT;
  357.                                 }
  358.  
  359.                                 /* Expect ')' */
  360.                                 token = parserutils_vector_iterate(vector, ctx);
  361.                                 if (token == NULL || tokenIsChar(token, ')') == false) {
  362.                                         *ctx = orig_ctx;
  363.                                         return CSS_INVALID;
  364.                                 }
  365.  
  366.  
  367.                                 error = css__stylesheet_string_add(c->sheet, lwc_string_ref(name), &name_snumber);
  368.                                 if (error != CSS_OK) {
  369.                                         *ctx = orig_ctx;
  370.                                         return error;
  371.                                 }
  372.  
  373.                                 error = css__stylesheet_string_add(c->sheet, lwc_string_ref(sep), &sep_snumber);
  374.                                 if (error != CSS_OK) {
  375.                                         *ctx = orig_ctx;
  376.                                         return error;
  377.                                 }
  378.  
  379.                                 error = CSS_APPEND(opv);
  380.                                 if (error != CSS_OK) {
  381.                                         *ctx = orig_ctx;
  382.                                         return error;
  383.                                 }
  384.  
  385.                                 error = css__stylesheet_style_append(result, name_snumber);
  386.                                 if (error != CSS_OK) {
  387.                                         *ctx = orig_ctx;
  388.                                         return error;
  389.                                 }
  390.  
  391.                                 error = css__stylesheet_style_append(result, sep_snumber);
  392.                         } else if (first) {
  393.                                 /* Invalid if this is the first iteration */
  394.                                 error = CSS_INVALID;
  395.                         } else {
  396.                                 /* Give up, ensuring current token is reprocessed */
  397.                                 *ctx = prev_ctx;
  398.                                 error = CSS_OK;
  399.                                 break;
  400.                         }
  401.  
  402.                         /* if there was an error bail */
  403.                         if (error != CSS_OK) {
  404.                                 *ctx = orig_ctx;
  405.                                 return error;
  406.                         }
  407.  
  408.                         first = false;
  409.  
  410.                         consumeWhitespace(vector, ctx);
  411.  
  412.                         prev_ctx = *ctx;
  413.                         token = parserutils_vector_iterate(vector, ctx);
  414.                 } /* while */
  415.  
  416.                 /* Write list terminator */
  417.                 css__stylesheet_style_append(result, CONTENT_NORMAL);
  418.         }
  419.  
  420.         if (error != CSS_OK)
  421.                 *ctx = orig_ctx;
  422.  
  423.         return error;
  424. }
  425.  
  426.