diff options
Diffstat (limited to 'src/dom/cssparser.cpp')
| -rw-r--r-- | src/dom/cssparser.cpp | 1670 |
1 files changed, 0 insertions, 1670 deletions
diff --git a/src/dom/cssparser.cpp b/src/dom/cssparser.cpp deleted file mode 100644 index 422c02e49..000000000 --- a/src/dom/cssparser.cpp +++ /dev/null @@ -1,1670 +0,0 @@ -/** - * Phoebe DOM Implementation. - * - * This is a C++ approximation of the W3C DOM model, which follows - * fairly closely the specifications in the various .idl files, copies of - * which are provided for reference. Most important is this one: - * - * http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/idl-definitions.html - * - * Authors: - * Bob Jamison - * - * Copyright (C) 2005-2008 Bob Jamison - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "cssparser.h" -#include "ucd.h" - -#include <stdio.h> -#include <stdarg.h> - -namespace org -{ -namespace w3c -{ -namespace dom -{ -namespace css -{ - -//######################################################################### -//# M E S S A G E S -//######################################################################### - -/** - * Get the column and row number of the given character position - */ -void CssParser::getColumnAndRow(int p, int &colResult, int &rowResult, int &lastNL) -{ - int col = 1; - int row = 1; - int lastnl = 0; - - for (int i=0 ; i<p ; i++) - { - XMLCh ch = parsebuf[i]; - if (ch == '\n') - { - lastnl = i; - row++; - col=0; - } - else - col++; - } - - colResult = col; - rowResult = row; - lastNL = lastnl; -} - -/** - * - */ -void CssParser::error(char const *fmt, ...) -{ - int lineNr; - int colNr; - int lastNL; - getColumnAndRow(lastPosition, colNr, lineNr, lastNL); - - va_list args; - fprintf(stderr, "CssParser:error at %d, line %d, column %d:", - lastPosition, lineNr, colNr); - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args) ; - fprintf(stderr, "\n"); - - /* - int lineLen = lastPosition - lastNL; - printf("lineLen:%d lastNL:%d\n", lineLen, lastNL); - for (int i=lastNL+1 ; i<lastPosition ; i++) - fprintf(stderr, "%c", parsebuf[i]); - fprintf(stderr, "\n"); - for (int i=0 ; i<lineLen-1 ; i++) - fprintf(stderr, " "); - fprintf(stderr, "^\n"); - */ - for (int i=0 ; i<lastPosition ; i++) - fprintf(stderr, "%c", parsebuf[i]); - fprintf(stderr, "\n"); -} - - - -//######################################################################### -//# P A R S I N G -//######################################################################### - -/** - * Get the character at the position and record the fact - */ -XMLCh CssParser::get(int p) -{ - if (p >= parselen) - return 0; - XMLCh ch = parsebuf[p]; - //printf("%c", ch); - lastPosition = p; - return ch; -} - - - -/** - * Test if the given substring exists at the given position - * in parsebuf. Use get() in case of out-of-bounds - */ -bool CssParser::match(int pos, const char *str) -{ - while (*str) - { - if (get(pos++) != (XMLCh) *str++) - return false; - } - return true; -} - -/** - * - */ -int CssParser::skipwhite(int p) -{ - while (p < parselen) - { - //# XML COMMENT - if (match(p, "<!--")) - { - p+=4; - bool done=false; - while (p<parselen) - { - if (match(p, "-->")) - { - p+=3; - done=true; - break; - } - p++; - } - lastPosition = p; - if (!done) - { - error("unterminated <!-- .. --> comment"); - return -1; - } - } - //# C comment - else if (match(p, "/*")) - { - p+=2; - bool done=false; - while (p<parselen) - { - if (match(p, "*/")) - { - p+=2; - done=true; - break; - } - p++; - } - lastPosition = p; - if (!done) - { - error("unterminated /* .. */ comment"); - return -1; - } - } - else if (!uni_is_space(get(p))) - break; - else - p++; - } - lastPosition = p; - return p; -} - -/** - * get a word from the buffer - */ -int CssParser::getWord(int p, DOMString &result) -{ - XMLCh ch = get(p); - if (!uni_is_letter(ch)) - return p; - DOMString str; - str.push_back(ch); - p++; - - while (p < parselen) - { - ch = get(p); - if (uni_is_letter_or_digit(ch) || ch=='-' || ch=='_') - { - str.push_back(ch); - p++; - } - else if (ch == '\\') - { - p+=2; - } - else - break; - } - result = str; - return p; -} - - -/** - * get a word from the buffer - */ -int CssParser::getNumber(int p0, double &result) -{ - int p=p0; - DOMString str; - while (p < parselen) - { - XMLCh ch = get(p); - if (ch<'0' || ch>'9') - break; - str.push_back(ch); - p++; - } - if (get(p) == '.' && get(p+1)>='0' && get(p+1)<='9') - { - p++; - str.push_back('.'); - while (p < parselen) - { - XMLCh ch = get(p); - if (ch<'0' || ch>'9') - break; - str.push_back(ch); - p++; - } - } - if (p>p0) - { - char *start = (char *)str.c_str(); - char *end = NULL; - double val = strtod(start, &end); - if (end > start) - { - result = val; - return p; - } - } - - //not a number - return p0; -} - - - -/** - * Assume that we are starting on a quote. Ends on the char - * after the final '"' - */ -int CssParser::getQuoted(int p0, DOMString &result) -{ - - int p = p0; - - XMLCh quoteChar = get(p); - if (quoteChar != '"' && quoteChar != '\'') - return p0; - - p++; - - DOMString buf; - - bool done = false; - while (p<parselen ) - { - XMLCh ch = get(p); - if (ch == quoteChar) - { - done = true; - p++; - break; - } - else - { - buf.push_back(ch); - } - p++; - } - - if (!done) - { - error("unterminated quoted string"); - return -1; - } - - result.append(buf); - - return p; -} - -/** - * Not in api. replaces URI return by lexer - */ -int CssParser::getUri(int p0, DOMString &str) -{ - int p = p0; - if (!match(p, "url(")) - return p0; - p+=4; - p = skipwhite(p); - DOMString buf; - XMLCh ch; - while (p < parselen) - { - ch = get(p); - if (isspace(ch) || ch==')') - break; - buf.push_back(ch); - p++; - } - p = skipwhite(p); - ch = get(p); - if (ch != ')') - { - error("no closing ')' on url spec"); - return -1; - } - p++; - str = buf; - return p; -} - -/** - * Skip to the end of the block - */ -int CssParser::skipBlock(int p0) -{ - int p = p0; - while (p < parselen) - { - XMLCh ch = get(p); - if (ch == '}') - { - p++; - break; - } - else - { - p++; - } - } - return p; -} - -//######################################################################### -//# P R O D U C T I O N S -//######################################################################### - -/** - * stylesheet - * : [ CHARSET_SYM S* STRING S* ';' ]? - * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]* - * [ [ ruleset | media | page ] [S|CDO|CDC]* ]* - * ; - */ -int CssParser::getStyleSheet(int p0) -{ - int p = p0; - int p2 = p; - XMLCh ch; - - //# CHARSET 0 or 1 - if (match(p, "@charset")) - { - p+=8; - p = skipwhite(p); - DOMString str; - p2 = getQuoted(p, str); - if (p2<=p) - { - error("quoted string required after @charset"); - return -1; - } - p = skipwhite(p2); - ch = get(p); - if (ch !=';') - { - error("';' required after @charset declaration"); - return -1; - } - p++; - p = skipwhite(p); - } - - //# IMPORT 0 to many - while (true) - { - p2 = getImport(p); - if (p2<0) - { - return -1; - } - if (p2<=p) - break; - p = p2; - } - - //# RULESET | MEDIA | PAGE 0 to many - while (true) - { - //Ruleset - p2 = getRuleSet(p); - if (p2<0) - { - return -1; - } - if (p2>p) - { - p = p2; - continue; - } - - //Media - p2 = getMedia(p); - if (p2<0) - { - return -1; - } - if (p2>p) - { - p = p2; - continue; - } - - //Page - p2 = getPage(p); - if (p2<0) - { - return -1; - } - if (p2>p) - { - p = p2; - continue; - } - - //none of the above - break; - } - - return p; -} - -/** - * import - * : IMPORT_SYM S* - * [STRING|URI] S* [ medium [ COMMA S* medium]* ]? ';' S* - * ; - */ -int CssParser::getImport(int p0) -{ - int p = p0; - if (!match(p, "@import")) - return p0; - p+=7; - p = skipwhite(p); - - //# STRING | URI - DOMString str; - int p2 = getQuoted(p, str); - if (p2<0) - { - return -1; - } - if (p2<=p) - { - p2 = getUri(p, str); - if (p2<0) - { - return -1; - } - if (p2<=p) - { - error("quoted string or URI required after @import"); - return -1; - } - } - p = p2; - p2 = getMedium(p); - if (p2<0) - return -1; - - p = p2; - p = skipwhite(p); - XMLCh ch = get(p); - if (ch != ';') - { - error("@import must be terminated with ';'"); - return -1; - } - p++; - return p; -} - -/** - * media - * : MEDIA_SYM S* medium [ COMMA S* medium ]* LBRACE S* ruleset* '}' S* - * ; - */ -int CssParser::getMedia(int p0) -{ - int p = p0; - XMLCh ch; - if (!match(p, "@media")) - return p0; - p+=6; - p = skipwhite(p); - - //# MEDIUM LIST - int p2 = getMedium(p); - if (p2<0) - return -1; - if (p2<=p) - { - error("@media must be followed by medium"); - return -1; - } - p = p2; - while (true) - { - ch = get(p); - if (ch != ',') - break; - p2 = getMedium(p); - if (p2<0) - return -1; - if (p2<=p) - { - error("',' in medium list must be followed by medium"); - return -1; - } - p = p2; - } - - p = skipwhite(p); - ch = get(p); - if (ch!='{') - { - error("@media requires '{' for ruleset"); - return -1; - } - p++; - p2 = getRuleSet(p); - if (p2<0) - return -1; - if (p2<=p) - { - error("@media requires ruleset after '{'"); - return -1; - } - p = p2; - ch = get(p); - if (ch != '}') - { - error("@media requires '}' after ruleset"); - return -1; - } - p++; - return p0; -} - -/** - * medium - * : IDENT S* - * ; - */ -int CssParser::getMedium(int p0) -{ - int p = p0; - p = skipwhite(p); - - DOMString ident; - int p2 = getWord(p, ident); - if (p2<0) - return -1; - if (p2<=p) - return p0; - p = p2; - - return p; -} - -/** - * page - * : PAGE_SYM S* pseudo_page? S* - * LBRACE S* declaration [ ';' S* declaration ]* '}' S* - * ; - */ -int CssParser::getPage(int p0) -{ - int p = p0; - - //# @PAGE - p = skipwhite(p); - if (!match(p, "@page")) - return p0; - p+= 5; - - //#PSEUDO PAGE 0 or 1 - p = skipwhite(p); - int p2 = getPseudoPage(p); - if (p2<0) - return -1; - if (p2>p) - { - p = p2; - } - - //# { - p=skipwhite(p); - XMLCh ch = get(p); - if (p != '{') - { - error("@page requires '{' before declarations"); - } - p++; - - //# DECLARATION LIST - p = skipwhite(p); - CSSStyleDeclaration declarationList; - p2 = getDeclaration(p, declarationList); - if (p2<0) - return -1; - if (p2<=p) - { - error("@page requires declaration(s) after '{'"); - return -1; - } - while (true) - { - p = skipwhite(p2); - ch = get(p); - if (ch != ';') - break; - p++; - p = skipwhite(p); - p2 = getDeclaration(p, declarationList); - if (p2<0) - return -1; - if (p2<= p) - { - error("@page requires declaration after ';'"); - return -1; - } - } - - //# } - p=skipwhite(p); - ch = get(p); - if (p != '}') - { - error("@page requires '}' after declarations"); - } - p++; - - return p; -} - -/** - * pseudo_page - * : ':' IDENT - * ; - */ -int CssParser::getPseudoPage(int p0) -{ - int p = p0; - if (!match(p, ":")) - return p0; - p++; - DOMString str; - int p2 = getWord(p, str); - if (p2<0) - return -1; - if (p2<=p) - { - error("pseudo-page requires identifier after ':'"); - return -1; - } - p = p2; - return p; -} - -/** - * ruleset - * : selector [ COMMA S* selector ]* - * LBRACE S* declaration [ ';' S* declaration ]* '}' S* - * ; - */ -int CssParser::getRuleSet(int p0) -{ - int p = p0; - XMLCh ch; - - //## SELECTOR - p = skipwhite(p); - int p2 = getSelector(p); - if (p2<0) - return -1; - if (p2<=p) //no selector - { - if (get(p) != '{')//check for selector-less rule - return p0;//not me - } - p = p2; - while (true) - { - p = skipwhite(p); - ch = get(p); - if (ch != ',') - break; - p++; - p = skipwhite(p); - int p2 = getSelector(p); - if (p2<0) - return -1; - if (p2<=p) - { - error("selector required after ',' in list"); - return -1; - } - p = p2; - } - - //## { - ch = get(p); - if (ch != '{') - { - error("'{' required before declarations of ruleset"); - return -1; - } - p++; - - //## DECLARATIONS ( 0 to many ) - CSSStyleDeclaration declarationList; - - p = skipwhite(p); - p2 = getDeclaration(p, declarationList); - if (p2<0) - return -1; - if (p2>p) - { - p = p2; - while (true) - { - p = skipwhite(p); - ch = get(p); - if (ch != ';') - break; - p++; - p = skipwhite(p); - p2 = getDeclaration(p, declarationList); - if (p2<0) - return -1; - if (p2<=p) - { - //apparently this is ok - //error("declaration required after ';' in ruleset"); - //return -1; - break; - } - p = p2; - } - } - //## } - ch = get(p); - if (ch != '}') - { - error("ruleset requires closing '}'"); - return -1; - } - p++; - p = skipwhite(p); - - return p; -} - -/** - * selector - * : simple_selector [ combinator simple_selector ]* - * ; - */ -int CssParser::getSelector(int p0) -{ - int p = p0; - - //## SIMPLE SELECTOR - p = skipwhite(p); - int p2 = getSimpleSelector(p); - if (p2<0) - return -1; - if (p2<=p) - return p0; //not me - p = p2; - - //## COMBINATORS + MORE SELECTORS - while (true) - { - XMLCh ch = get(p); - bool wasSpace = isspace(ch); - p = skipwhite(p); - ch = get(p); - //# Combinators - //easier to do here than have a getCombinator() - int visibleCombinator = false; - if (ch == '+') - { - visibleCombinator = true; - p++; - } - else if (ch == '>') - { - visibleCombinator = true; - p++; - } - else if (wasSpace) - { - } - else - { - break; - } - p = skipwhite(p); - p2 = getSimpleSelector(p); - if (p2<0) - return -1; - if (p2<=p) - { - if (visibleCombinator) - { - error("need simple selector after combinator"); - return -1; - } - else - { - break; - } - } - p = p2; - } - return p; -} - -/** - * simple_selector - * : element_name [ HASH | class | attrib | pseudo ]* - * | [ HASH | class | attrib | pseudo ]+ - * ; - */ -int CssParser::getSimpleSelector(int p0) -{ - int p = p0; - int p2; - - DOMString str; - - p = skipwhite(p); - - int selectorItems = 0; - - XMLCh ch = get(p); - - //###################### - //# Note: do NOT skipwhite between items. Only within the - //# pseudo function and attrib below - //###################### - - //#Element name 0 or 1 - if (uni_is_letter(ch)) - { - p2 = getWord(p, str); - if (p2<0) - return -1; - if (p2<=p) - { - error("null element name"); - return -1; - } - selectorItems++; - p = p2; - } - else if (ch == '*') - { - str = "*"; - p++; - selectorItems++; - } - - - - //## HASH, CLASS, ATTRIB, PSEUDO (0 to many with elem name, 1 to many without) - while (true) - { - XMLCh ch = get(p); - - //# HASH - if (ch == '#') - { - p++; - p2 = getWord(p, str); - if (p2<0) - return -1; - if (p2<=p) - { - error("no name for hash"); - return -1; - } - p = p2; - selectorItems++; - } - - //# CLASS - else if (ch == '.') - { - p++; - p2 = getWord(p, str); - if (p2<0) - return -1; - if (p2<=p) - { - error("no name for class"); - return -1; - } - p = p2; - selectorItems++; - } - - //# ATTRIB - else if (ch == '[') - { - p++; - p = skipwhite(p); - p2 = getWord(p, str); - if (p2<0) - return -1; - if (p2<=p) - { - error("no name for class"); - return -1; - } - p = skipwhite(p2); - bool getRHS=false; - if (match(p, "=")) - { - p++; - getRHS=true; - } - else if (match(p, "~=")) - { - p+=2; - getRHS=true; - } - else if (match(p, "|=")) - { - p+=2; - getRHS=true; - } - if (getRHS) - { - p = skipwhite(p); - ch = get(p); - if (uni_is_letter(ch)) - { - p2 = getWord(p, str); - if (p2<0) - return -1; - if (p2<=p) - { - error("null ident on rhs of attrib"); - return -1; - } - p = p2; - } - else if (ch == '\'' || ch =='"') - { - p2 = getQuoted(p, str); - if (p2<0) - return -1; - if (p2<=p) - { - error("null literal string on rhs of attrib"); - return -1; - } - p = p2; - } - }//getRHS - p = skipwhite(p); - ch = get(p); - if (ch != ']') - { - error("attrib needs closing ']'"); - //return -1; - p = skipBlock(p); - return p; - } - p++; - selectorItems++; - } - - //# PSEUDO - else if (ch == ':') - { - p++; - p2 = getWord(p, str); - if (p2<0) - return -1; - if (p2<=p) - { - error("no name for pseudo"); - return -1; - } - p = p2; - selectorItems++; - ch = get(p); - if (ch == '(') - { - p++; - p = skipwhite(p); - ch = get(p); - if (uni_is_letter(ch)) - { - p2 = getWord(p, str); - if (p2<0) - return -1; - if (p2<=p) - { - error("null function parameter in pseudo"); - return -1; - } - p = skipwhite(p2); - ch = get(p); - } - if (ch != ')') - { - error("function in pseudo needs ')'"); - return -1; - } - p++; - }// ch==( -function- - }//pseudo - - //# none of the above - else - { - break; - } - - }//while - - - if (selectorItems > 0) - return p; - return p0; -} - -/** - * declaration - * : property ':' S* expr prio? - * | {empty} - * ; - */ -int CssParser::getDeclaration(int p0, CSSStyleDeclaration &declarationList) -{ - int p = p0; - - //## PROPERTY - p = skipwhite(p); - XMLCh ch = get(p); - if (!uni_is_letter(ch)) - return p0; //not me - DOMString propName; - int p2 = getWord(p, propName); - if (p2<0) - return -1; - - //## ':' - p = skipwhite(p2); - ch = get(p); - if (ch != ':') - { - error("declaration requires ':' between name and value"); - return -1; - } - p++; - - //## EXPR - p = skipwhite(p); - p2 = getExpr(p); - if (p2<0) - return -1; - if (p2<=p) - { - error("declaration requires value after ':'"); - return -1; - } - DOMString propVal; - for (int i=p ; i<p2 ; i++) //get our substring - propVal.push_back(get(i)); - printf("propVal:%s\n", propVal.c_str()); - p = p2; - - //## PRIO (optional) - p = skipwhite(p); - DOMString prio; - p2 = getPrio(p, prio); - if (p2<0) - return -1; - if (p2>p) - { - //do something - p = p2; - } - - return p; -} - -/** - * prio - * : IMPORTANT_SYM S* - * ; - */ -int CssParser::getPrio(int p0, DOMString &val) -{ - int p = p0; - - //## '!" - p = skipwhite(p); - XMLCh ch = get(p); - if (ch != '!') - return p0; - p++; - - //## "important" - p = skipwhite(p); - if (!match(p, "important")) - { - error("priority symbol is 'important'"); - return -1; - } - p += 9; - val = "important"; - return p; -} - -/** - * expr - * : term [ operator term ]* - * ; - */ -int CssParser::getExpr(int p0) -{ - int p = p0; - - //## TERM - p = skipwhite(p); - int p2 = getTerm(p); - if (p2<0) - return -1; - if (p2<=p) - return p0; //not me - p = p2; - while (p < parselen) - { - p = skipwhite(p); - //#Operator. do this instead of getOperator() - XMLCh ch = get(p); - int visibleTerm = false; - if (ch == '/') - { - visibleTerm = true; - p++; - } - else if (ch == ',') - { - visibleTerm = true; - p++; - } - else - { - //just space. this is allowable between terms, - // so we still need to check for another term - } - p = skipwhite(p); - p2 = getTerm(p); - if (p2<0) - return -1; - if (p2<=p) - { - if (visibleTerm) - { - error("expression requires term after operator"); - return -1; - } - else - { - break; - } - } - p = p2; - } - - return p; -} - -/** - * term - * : unary_operator? - * [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* | - * TIME S* | FREQ S* | function ] - * | STRING S* | IDENT S* | URI S* | hexcolor - * ; - */ -int CssParser::getTerm(int p0) -{ - int p = p0; - p = skipwhite(p); - int unitType = CSSPrimitiveValue::CSS_UNKNOWN; - //# Unary operator - XMLCh ch = get(p); - bool hasUnary = false; - if (ch == '-') - { - p++; - hasUnary = true; - } - else if (ch == '+') - { - p++; - hasUnary = true; - } - //# NUMERIC - double numVal; - int p2 = getNumber(p, numVal); - if (p2<0) - return -1; - if (p2>p) - { - p = p2; - if (match(p, "%")) - { - unitType = CSSPrimitiveValue::CSS_PERCENTAGE; - p++; - } - else if (match(p, "em")) - { - unitType = CSSPrimitiveValue::CSS_EMS; - p+=2; - } - else if (match(p, "ex")) - { - unitType = CSSPrimitiveValue::CSS_EXS; - p+=2; - } - else if (match(p, "px")) - { - unitType = CSSPrimitiveValue::CSS_PX; - p+=2; - } - else if (match(p, "cm")) - { - unitType = CSSPrimitiveValue::CSS_CM; - p+=2; - } - else if (match(p, "mm")) - { - unitType = CSSPrimitiveValue::CSS_MM; - p+=2; - } - else if (match(p, "in")) - { - unitType = CSSPrimitiveValue::CSS_IN; - p+=2; - } - else if (match(p, "pt")) - { - unitType = CSSPrimitiveValue::CSS_PT; - p+=2; - } - else if (match(p, "pc")) - { - unitType = CSSPrimitiveValue::CSS_PC; - p+=2; - } - else if (match(p, "deg")) - { - unitType = CSSPrimitiveValue::CSS_DEG; - p+=3; - } - else if (match(p, "rad")) - { - unitType = CSSPrimitiveValue::CSS_RAD; - p+=3; - } - else if (match(p, "grad")) - { - unitType = CSSPrimitiveValue::CSS_GRAD; - p+=4; - } - else if (match(p, "ms")) - { - unitType = CSSPrimitiveValue::CSS_MS; - p+=2; - } - else if (match(p, "s")) - { - unitType = CSSPrimitiveValue::CSS_S; - p+=1; - } - else if (match(p, "Hz")) - { - unitType = CSSPrimitiveValue::CSS_HZ; - p+=2; - } - else if (match(p, "kHz")) - { - unitType = CSSPrimitiveValue::CSS_KHZ; - p+=2; - } - else if (uni_is_letter(get(p)))//some other string - { - DOMString suffix; - p2 = getWord(p, suffix); - if (p2<0) - return -1; - unitType = CSSPrimitiveValue::CSS_DIMENSION; - p = p2; - } - else //plain number - { - unitType = CSSPrimitiveValue::CSS_NUMBER; - } - return p; - } - - DOMString str; - - //## URI --do before function, as syntax is similar - p2 = getUri(p, str); - if (p2<0) - return -1; - if (p2>p) - { - if (hasUnary) - { - error("+ or - not allowed on URI"); - return -1; - } - p = p2; - unitType = CSSPrimitiveValue::CSS_URI; - return p; - } - - //## FUNCTION - p2 = getFunction(p); - if (p2<0) - return -1; - if (p2>p) - { - p = p2; - return p; - } - - //## STRING - ch = get(p); - if (ch == '"' || ch == '\'') - { - p2 = getQuoted(p, str); - if (p2<0) - return -1; - if (p2>p) - { - if (hasUnary) - { - error("+ or - not allowed on a string"); - return -1; - } - p = p2; - unitType = CSSPrimitiveValue::CSS_STRING; - return p; - } - } - - //## IDENT - ch = get(p); - if (uni_is_letter(ch)) - { - p2 = getWord(p, str); - if (p2<0) - return -1; - if (p2>p) - { - if (hasUnary) - { - error("+ or - not allowed on an identifier"); - return -1; - } - p = p2; - unitType = CSSPrimitiveValue::CSS_IDENT; - return p; - } - } - - - //## HEXCOLOR - p2 = getHexColor(p); - if (p2<0) - return -1; - if (p2>p) - { - if (hasUnary) - { - error("+ or - not allowed on hex color"); - return -1; - } - p = p2; - unitType = CSSPrimitiveValue::CSS_RGBCOLOR; - return p; - } - - - return p0; -} - -/** - * function - * : FUNCTION S* expr ')' S* - * ; - */ -int CssParser::getFunction(int p0) -{ - int p = p0; - - //## IDENT + ( (both) - DOMString name; - p = skipwhite(p); - int p2 = getWord(p, name); - if (p2<0) - return -1; - if (p2<=p) - return p0; //not me - if (name == "uri" || name=="url") - return p0; //not me - p = skipwhite(p2); - XMLCh ch = get(p); - if (ch != '(') - return p0; //still not me - p++; - - //## EXPR - p = skipwhite(p); - p2 = getExpr(p); - if (p2<0) - return -1; - if (p2<=p) - { - error("function requires expression"); - return -1; - } - p = p2; - - //## ')' - p = skipwhite(p); - ch = get(p); - if (ch != ')') - { - error("function requires closing ')'"); - return -1; - } - p++; - p = skipwhite(p); - - return p; -} - -/** - * There is a constraint on the color that it must - * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) - * after the "#"; e.g., "#000" is OK, but "#abcd" is not. - * hexcolor - * : HASH S* - * ; - */ -int CssParser::getHexColor(int p0) -{ - int p = p0; - - //## '#' - p = skipwhite(p); - if (!match(p, "#")) - return p0; - p++; - - //## HEX - DOMString hex; - long hexVal = 0; - while (p < parselen) - { - XMLCh b = get(p); - if (b>='0' && b<='9') - { - hexVal = (hexVal << 4) + (b - '0'); - hex.push_back(b); - p++; - } - else if (b>='a' && b<='f') - { - hexVal = (hexVal << 4) + (b - 'a' + 10); - hex.push_back(b); - p++; - } - else if (b>='A' && b<='F') - { - hexVal = (hexVal << 4) + (b - 'A' + 10); - hex.push_back(b); - p++; - } - else - { - break; - } - } - - if (hex.size() != 3 && hex.size() != 6) - { - error("exactly 3 or 6 hex digits are required after '#'"); - return -1; - } - - return p; -} - - - -/** - * - */ -bool CssParser::parse(const DOMString &str) -{ - /* - int len = str.size(); - for (int i=0 ; i<len ; i++) - { - XMLCh ch = str[i]; - if (ch == '\\' && i<(len-1)) //escape! - { - i++; - } - else - parsebuf.push_back(ch); - } - */ - parsebuf = str; - - parselen = parsebuf.size(); - //printf("==============================\n%s\n========================\n", str.c_str()); - - lastPosition = 0; - - int p = getStyleSheet(0); - if (p < parselen) - { - error("Not everything parsed"); - return false; - } - - return true; -} - - -/** - * - */ -bool CssParser::parseFile(const DOMString &fileName) -{ - DOMString tmp = fileName; - char *fname = (char *)tmp.c_str(); - FILE *f = fopen(fname, "r"); - if (!f) - { - printf("Could not open %s for reading\n", fname); - return false; - } - - DOMString str; - while (!feof(f)) - { - int ch = fgetc(f); - if (ch<0) - break; - str.push_back((XMLCh)ch); - } - fclose(f); - - bool ret = parse(str); - - return ret; -} - - - - - - - -} // namespace css -} // namespace dom -} // namespace w3c -} // namespace org - - -#ifdef TEST - -int main(int argc, char **argv) -{ - org::w3c::dom::css::CssParser parser; - char *fileName; - fileName = "001.css"; - //fileName = "acid.css"; - //fileName = "base.css"; - //fileName = "inkscape.css"; - //fileName = "meyerweb.css"; - if (!parser.parseFile(fileName)) - { - printf("Test failed\n"); - return 1; - } - return 0; -} - -#endif /* TEST */ - -//######################################################################### -//# E N D O F F I L E -//######################################################################### - |
