home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libstyle / css.y < prev    next >
Encoding:
Text File  |  1998-04-08  |  37.1 KB  |  1,364 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. %{
  19.  
  20. #include <stdio.h>
  21. #include "cssI.h"
  22.  
  23. %}
  24.  
  25. %token  NUMBER STRING PERCENTAGE LENGTH EMS
  26. %token  EXS IDENT HEXCOLOR URL RGB
  27. %token  CDO CDC
  28. %token  IMPORTANT_SYM
  29. %token  IMPORT_SYM
  30. %token  DOT_AFTER_IDENT DOT
  31. %token  LINK_PSCLASS VISITED_PSCLASS ACTIVE_PSCLASS
  32. %token  LEADING_LINK_PSCLASS
  33. %token  LEADING_VISITED_PSCLASS
  34. %token  LEADING_ACTIVE_PSCLASS
  35. %token  FIRST_LINE
  36. %token  FIRST_LETTER
  37. %token  WILD
  38. %token  BACKGROUND
  39. %token  BG_COLOR BG_IMAGE BG_REPEAT BG_ATTACHMENT BG_POSITION
  40. %token  FONT
  41. %token  FONT_STYLE FONT_VARIANT FONT_WEIGHT FONT_SIZE
  42. %token  FONT_NORMAL LINE_HEIGHT
  43. %token  LIST_STYLE LS_TYPE LS_NONE LS_POSITION
  44. %token  BORDER BORDER_STYLE BORDER_WIDTH
  45. %token  FONT_SIZE_PROPERTY
  46. %token  FONTDEF
  47.  
  48. %type   <binary_node> stylesheet
  49. %type   <binary_node> import ruleset unary_operator operator property
  50. %type   <binary_node> import_value
  51. %type   <binary_node> selector_list declaration_list declaration selector
  52. %type   <binary_node> pseudo_element simple_selector
  53. %type   <binary_node> contextual_selector
  54. %type   <binary_node> contextual_selector_list
  55. %type   <binary_node> element_name pseudo_class class id
  56. %type   <binary_node> leading_pseudo_class
  57. %type   <binary_node> expr prio term optional_priority
  58. %type   <binary_node> numeric_const unsigned_numeric_const
  59. %type   <binary_node> numeric_unit unsigned_numeric_unit
  60. %type   <binary_node> unsigned_symbol color_code
  61. %type   <binary_node> url
  62. %type   <binary_node> background_property
  63. %type   <binary_node> background_values_list
  64. %type   <binary_node> background_value
  65. %type   <binary_node> background_values
  66. %type   <binary_node> background_position_expr
  67. %type   <binary_node> background_position_value
  68. %type   <binary_node> background_position_keyword
  69. %type   <binary_node> font_property font_size_property
  70. %type   <binary_node> font_values_list
  71. %type   <binary_node> font_size_value font_family_value line_height_value
  72. %type   <binary_node> font_optional_value font_optional_values_list
  73. %type   <binary_node> font_family_operator font_family_expr
  74. %type   <binary_node> list_style_property
  75. %type   <binary_node> list_style_values_list list_style_value
  76. %type   <binary_node> border_property
  77. %type   <binary_node> border_values_list border_value
  78. %type   <binary_node> atrule fontdef
  79.  
  80. %union {
  81.   css_node binary_node;
  82. }
  83.  
  84.  
  85. %{
  86.  
  87.                  /* Background Shorthand Property */
  88.  
  89. typedef struct backgroundShorthandRecord {
  90.     css_node color;
  91.     css_node image;
  92.     css_node repeat;
  93.     css_node attachment;
  94.     css_node position;
  95.     int    parse_error;
  96. } BackgroundShorthandRecord, *BackgroundShorthand;
  97.  
  98. #define BackgroundColor      1
  99. #define BackgroundImage      2
  100. #define BackgroundRepeat     3
  101. #define BackgroundAttachment 4
  102. #define BackgroundPosition   5
  103.  
  104. static void ClearBackground(void);
  105. static void AddBackground(int node_type, css_node node);
  106. static css_node AssembleBackground(void);
  107.  
  108. static BackgroundShorthandRecord bg;
  109.  
  110. /* background property names */
  111. static char * bg_image = "background-image";
  112. static char * bg_color = "background-color";
  113. static char * bg_repeat = "background-repeat";
  114. static char * bg_attachment = "background-attachment";
  115. static char * bg_position = "background-position";
  116. /* background property initial values */
  117. static char * css_none = "none";
  118. static char * css_transparent = "transparent";
  119. static char * css_repeat = "repeat";
  120. static char * css_scroll = "scroll";
  121. static char * css_origin = "0% 0%";
  122.  
  123.  
  124.                     /* Font Shorthand Property */
  125.  
  126. typedef struct fontShorthandRecord {
  127.     css_node style;
  128.     css_node variant;
  129.     css_node weight;
  130.     css_node size;
  131.     css_node leading;
  132.     css_node family;
  133.     int normal_count;
  134.     int parse_error;
  135. } FontShorthandRecord, *FontShorthand;
  136.  
  137. #define FontStyle    6
  138. #define FontVariant  7
  139. #define FontWeight   8
  140. #define FontNormal   9
  141. #define FontSize    10
  142. #define FontLeading 11
  143. #define FontFamily  12
  144.  
  145. static void ClearFont(void);
  146. static void AddFont(int node_type, css_node node);
  147. static css_node AssembleFont(void);
  148.  
  149. static FontShorthandRecord font;
  150.  
  151. /* font property names */
  152. static char * line_height = "line-height";
  153. static char * font_family = "font-family";
  154. static char * font_style = "font-style";
  155. static char * font_variant = "font-variant";
  156. static char * font_weight = "font-weight";
  157. static char * font_size = "font-size";
  158. /* font property initial values */
  159. static char * css_normal = "normal";
  160.  
  161.  
  162.                  /* List-Style Shorthand Property */
  163.  
  164. typedef struct listStyleShorthandRecord {
  165.     css_node marker;
  166.     css_node image;
  167.     css_node position;
  168.     int none_count;
  169.     int parse_error;
  170. } ListStyleShorthandRecord, *ListStyleShorthand;
  171.  
  172. #define ListStyleMarker        13
  173. #define ListStyleImage        14
  174. #define ListStylePosition    15
  175. #define ListStyleNone        16
  176.  
  177. static void ClearListStyle(void);
  178. static void AddListStyle(int node_type, css_node node);
  179. static css_node AssembleListStyle(void);
  180.  
  181. static ListStyleShorthandRecord ls;
  182.  
  183. /* list-style property names */
  184. static char * list_style_type = "list-style-type";
  185. static char * list_style_image = "list-style-image";
  186. static char * list_style_position = "list-style-position";
  187. /* list-style initial values */
  188. static char * css_disc = "disc";
  189. static char * css_outside = "outside";
  190.  
  191.  
  192.                    /* Border Shorthand Property */
  193.  
  194. typedef struct borderShorthandRecord {
  195.     css_node width;
  196.     css_node style;
  197.     css_node color;
  198.     int parse_error;
  199. } BorderShorthandRecord, *BorderShorthand;
  200.  
  201. #define BorderWidth    17
  202. #define BorderStyle    18
  203. #define BorderColor    19
  204.  
  205. static void ClearBorder(void);
  206. static void AddBorder(int node_type, css_node node);
  207. static css_node AssembleBorder(void);
  208.  
  209. static BorderShorthandRecord border;
  210.  
  211. /* border property names */
  212. static char * border_width = "border-width";
  213. static char * border_style = "border-style";
  214. static char * border_color = "border-color";
  215. /* border initial values */
  216. static char * css_medium = "medium";
  217.  
  218.  
  219. /* Define yyoverflow and the forward declarations for bison. */
  220. #define yyoverflow css_overflow
  221. static void css_overflow(const char *message, short **yyss1, int yyss1_size, 
  222.                          YYSTYPE **yyvs1, int yyvs1_size, int *yystacksize);
  223. static css_node NewNode(int node_id, char *ss, css_node left, css_node right);
  224. static void LeftAppendNode(css_node head, css_node new_node);
  225. static css_node NewDeclarationNode(int node_id, char *ss, char *prop);
  226. static css_node NewComponentNode(css_node value, char *prop);
  227.  
  228. css_node css_tree_root;
  229.  
  230. /* pseudo-classes */
  231. static char * css_link = "link";
  232. static char * css_visited = "visited";
  233. static char * css_active = "active";
  234.  
  235. #ifdef CSS_PARSE_DEBUG
  236. #define TRACE1(str) trace1(str)
  237. #define TRACE2(format, str) trace2(format, str)
  238. static trace1(const char * str)
  239. {
  240.     printf("%s", str);
  241. }
  242.  
  243. static trace2(const char *fmt, char *str)
  244. {
  245.     printf(fmt, str);
  246. }
  247. #else
  248. #define TRACE1(str)
  249. #define TRACE2(format, str)
  250. #endif
  251.  
  252. int css_error(const char * diagnostic)
  253. {
  254. #ifdef CSS_PARSE_REPORT_ERRORS
  255.     char * identifier = "CSS1 parser message:";
  256.     (void) fprintf(stderr,
  257.                    "%s error, text ='%s', diagnostic ='%s'\n",
  258.                    identifier, css_text, diagnostic ? diagnostic : "");
  259. #endif
  260.     return 1;
  261. }
  262.  
  263.  
  264. int css_wrap(void)
  265. {
  266. #ifdef CSS_PARSE_DEBUG
  267.     printf("css_wrap() was called.\n");
  268. #endif
  269.     return 1;
  270. }
  271.  
  272. %}
  273. %%
  274.  
  275. stylesheet
  276.     :   {
  277.         $$ = NULL;
  278.         }
  279.     | stylesheet CDO {
  280.         TRACE1("-cdo\n");
  281.         $$ = $1;
  282.         }
  283.     | stylesheet atrule {
  284.         $$ = $1;
  285.         if ($$ == NULL) {
  286.             css_tree_root = $2;
  287.             $$ = css_tree_root;
  288.         }
  289.         else
  290.             LeftAppendNode($$, $2);
  291.         }
  292.     | stylesheet ruleset {
  293.         css_node tmp;
  294.         tmp = NewNode(NODE_RULESET_LIST, NULL, NULL, $2);
  295.         
  296.         $$ = $1;
  297.         if ($$ == NULL) {
  298.             css_tree_root = tmp;
  299.             $$ = css_tree_root;
  300.         }
  301.         else
  302.             LeftAppendNode($$, tmp);
  303.         }
  304.     | stylesheet CDC {
  305.         TRACE1("-cdc\n");
  306.         $$ = $1;
  307.         }
  308.     | stylesheet error {
  309.         yyerrok;
  310.         yyclearin;
  311.         }        
  312.     ;
  313.  
  314. atrule
  315.     : import {
  316.         $$ = NewNode(NODE_IMPORT_LIST, NULL, NULL, $1);
  317.         }
  318.     | fontdef {
  319.         $$ = NewNode(NODE_FONTDEF_LIST, NULL, NULL, $1);
  320.         }
  321.     ;
  322.  
  323. import 
  324.  : IMPORT_SYM import_value ';' { 
  325.      $$ = $2;
  326.    }
  327.  ;
  328.  
  329. fontdef
  330.     : FONTDEF import_value ';' { 
  331.         $$ = $2;
  332.         }
  333.     ;
  334.  
  335. import_value
  336.  : STRING {
  337.     $$ = NewNode(NODE_IMPORT_STRING, css_text, NULL, NULL);
  338.    }
  339.  | url {
  340.      TRACE1("-import url\n");
  341.      $1->node_id = NODE_IMPORT_URL;
  342.      $$ = $1;
  343.    }
  344.  ;
  345.  
  346. unary_operator
  347.  : '-' { 
  348.      TRACE1("-unary_op '-'\n");
  349.      $$ = NewNode(NODE_UNARY_OP, css_text, NULL, NULL);
  350.    }
  351.  | '+' {
  352.      TRACE1("-unary_op '+'\n");
  353.      $$ = NewNode(NODE_UNARY_OP, css_text, NULL, NULL);
  354.    }
  355.  ;
  356.  
  357. operator
  358.  :       { 
  359.      TRACE1("-empty operator\n");
  360.      $$ = NewNode(NODE_EMPTY_OP, NULL, NULL, NULL);
  361.    }
  362.  | '/'    { 
  363.      TRACE1("-operator : '/'\n"); 
  364.      $$ = NewNode(NODE_EXPR_OP, css_text, NULL, NULL);
  365.    }
  366.  | ','     { 
  367.      TRACE1("-operator : ','\n"); 
  368.      $$ = NewNode(NODE_EXPR_OP, css_text, NULL, NULL);
  369.    }
  370.  ;
  371.  
  372. property
  373.  : IDENT   {
  374.      TRACE2("-property : IDENT '%s'\n", css_text); 
  375.      $$ = NewNode(NODE_PROPERTY, css_text, NULL, NULL);
  376.    }
  377.  ;
  378.  
  379. font_size_property
  380.  : FONT_SIZE_PROPERTY {
  381.      $$ = NewNode(NODE_PROPERTY, css_text, NULL, NULL);
  382.    }
  383.  ;
  384.  
  385. background_property
  386.  : BACKGROUND {
  387.      TRACE2("-property : BACKGROUND '%s'\n", css_text);
  388.      ClearBackground();
  389.      $$ = NULL;
  390.      /* This shorthand property will generate five component properties. */
  391.    }
  392.  ;
  393.  
  394. font_property
  395.  : FONT {
  396.      TRACE2("-property : FONT '%s'\n", css_text);
  397.      ClearFont();
  398.      $$ = NULL;
  399.      /* This shorthand property will generate six component properties. */
  400.    }
  401.  ;
  402.  
  403. list_style_property
  404.  : LIST_STYLE {
  405.      ClearListStyle();
  406.      $$ = NULL;
  407.      /* This shorthand property will generate three component properties. */
  408.    }
  409.  ;
  410.  
  411. border_property
  412.  : BORDER {
  413.      ClearBorder();
  414.      $$ = NULL;
  415.      /* This shorthand property will generate 2 or 3 component properties. */
  416.    }
  417.  ;
  418.  
  419. ruleset
  420.  : selector_list '{' declaration_list '}'  { 
  421.      TRACE1("-selector_list { declaration_list }\n"); 
  422.      $$ = NewNode(NODE_RULESET, NULL, $1, $3);
  423.    }
  424.  ;
  425.  
  426. selector_list
  427.  : selector { 
  428.      TRACE1("-selector\n"); 
  429.      $$ = NewNode(NODE_SELECTOR_LIST, NULL, NULL, $1);
  430.    }
  431.  | selector_list ',' selector { 
  432.      css_node tmp;
  433.      TRACE1("-selector_list , selector\n"); 
  434.      tmp = NewNode(NODE_SELECTOR_LIST, NULL, NULL, $3);
  435.      
  436.      $$ = $1;
  437.      if( $$ == NULL )
  438.        $$ = tmp;
  439.      else
  440.        LeftAppendNode( $$, tmp );
  441.    }
  442.  ;
  443.  
  444. selector
  445. : simple_selector {
  446.     TRACE1("-simple_selector\n");
  447.     $$ = NewNode(NODE_SELECTOR, NULL, $1, NULL);
  448. }
  449. | simple_selector pseudo_element {
  450.     TRACE1("-simple_selector : pseudo_element\n");
  451.     $$ = NewNode(NODE_SELECTOR, NULL, $1, $2);
  452. }
  453. | contextual_selector {
  454.     TRACE1("-contextual_selector\n");
  455.     $$ = NewNode(NODE_SELECTOR, NULL, $1, NULL);
  456. }
  457. | contextual_selector pseudo_element {
  458.     TRACE1("-contextual_selector : pseudo_element\n");
  459.      $$ = NewNode(NODE_SELECTOR, NULL, $1, $2);
  460. }
  461. ;
  462.  
  463.          /*
  464.          * A simple_selector is something like H1, PRE.FOO,
  465.          * .FOO, etc., or it is an ID: #p004
  466.          */
  467.  
  468. contextual_selector
  469. : contextual_selector_list simple_selector {
  470.     TRACE1("-contextual_selector_list simple_selector\n");
  471.     $$ = NewNode(NODE_SELECTOR_CONTEXTUAL, NULL, $1, $2);
  472. }
  473. ;
  474.  
  475. contextual_selector_list
  476.  : simple_selector {
  477.      TRACE1("-simple_selector\n");
  478.      $$ = NewNode(NODE_SELECTOR_CONTEXTUAL, NULL, NULL, $1);
  479.    }
  480.  | contextual_selector_list simple_selector {
  481.      TRACE1("-contextual_selector_list simple_selector\n");
  482.      $$ = NewNode(NODE_SELECTOR_CONTEXTUAL, NULL, $1, $2);
  483.    }
  484.  ;
  485.  
  486. simple_selector
  487.  : element_name { 
  488.      TRACE1("-element_name\n");
  489.      $$ = NewNode(NODE_SIMPLE_SELECTOR_NAME_ONLY, NULL, $1, NULL);
  490.    }
  491.  | DOT class {
  492.      TRACE1("-dot class\n");
  493.      $$ = NewNode(NODE_SIMPLE_SELECTOR_DOT_AND_CLASS, NULL, $2, NULL);
  494.    }
  495.  | id {
  496.      TRACE1("-id\n");
  497.      $$ = NewNode(NODE_SIMPLE_SELECTOR_ID_SELECTOR, NULL, $1, NULL);
  498.    }
  499.  | element_name DOT_AFTER_IDENT class {
  500.      TRACE1("-element dot class\n");
  501.      $$ = NewNode(NODE_SIMPLE_SELECTOR_NAME_AND_CLASS, NULL, $1, $3);
  502.    }
  503.  | element_name pseudo_class {
  504.      TRACE1("-element pseudo_class\n");
  505.      $$ = NewNode(NODE_SIMPLE_SELECTOR_NAME_PSEUDO_CLASS, NULL, $1, $2);
  506.    }
  507.  | element_name DOT_AFTER_IDENT class pseudo_class {
  508.      TRACE2("-element_name '%s' dot class pseudo_class\n", $1->string);
  509.      $1->node_id = NODE_SIMPLE_SELECTOR_NAME_CLASS_PSEUDO_CLASS;
  510.      $1->left = $3;
  511.      $1->right = $4;
  512.      $$ = $1;
  513.    }
  514.  | DOT class pseudo_class {
  515.      TRACE1("-dot class pseudo_class\n");
  516.      $$ = NewNode(NODE_SIMPLE_SELECTOR_NAME_CLASS_PSEUDO_CLASS, "A", $2, $3);
  517.    }
  518.  | leading_pseudo_class {
  519.      css_node tmp;
  520.      TRACE1("solitary pseudo_class\n");
  521.      /* See CSS1 spec of 17 December 1996 section 2.1 Anchor pseudo-classes */
  522.      tmp = NewNode(NODE_ELEMENT_NAME, "A", NULL, NULL);
  523.      $$ = NewNode(NODE_SIMPLE_SELECTOR_NAME_PSEUDO_CLASS, NULL, tmp, $1);
  524.    }
  525.  | WILD {
  526.      $$ = NewNode(NODE_WILD, NULL, NULL, NULL);
  527.    }
  528.  ;
  529.  
  530. element_name
  531.  : IDENT { 
  532.      TRACE2("-IDENT '%s' to element_name\n", css_text); 
  533.      $$ = NewNode(NODE_ELEMENT_NAME, css_text, NULL, NULL);
  534.    }
  535.  ;
  536.  
  537. class
  538.     : IDENT {
  539.         TRACE2("-IDENT '%s' to class\n", css_text);
  540.         $$ = NewNode(NODE_CLASS, css_text, NULL, NULL);
  541.       }
  542.     ;
  543.  
  544. id
  545.     : '#' IDENT {
  546.         TRACE2("-IDENT '%s' to id\n", css_text);
  547.         $$ = NewNode(NODE_ID_SELECTOR, css_text, NULL, NULL);
  548.       }
  549.     ;
  550.  
  551. pseudo_class
  552.  : LINK_PSCLASS {
  553.      $$ = NewNode(NODE_LINK_PSCLASS, css_link, NULL, NULL);
  554.    }
  555.  | VISITED_PSCLASS {
  556.      $$ = NewNode(NODE_VISITED_PSCLASS, css_visited, NULL, NULL);
  557.    }
  558.  | ACTIVE_PSCLASS {
  559.      $$ = NewNode(NODE_ACTIVE_PSCLASS, css_active, NULL, NULL);
  560.    }
  561.  ;
  562.  
  563. leading_pseudo_class
  564.  : LEADING_LINK_PSCLASS {
  565.      $$ = NewNode(NODE_LINK_PSCLASS, css_link, NULL, NULL);
  566.    }
  567.  | LEADING_VISITED_PSCLASS {
  568.      $$ = NewNode(NODE_VISITED_PSCLASS, css_visited, NULL, NULL);
  569.    }
  570.  | LEADING_ACTIVE_PSCLASS {
  571.      $$ = NewNode(NODE_ACTIVE_PSCLASS, css_active, NULL, NULL);
  572.    }
  573.  ;
  574.  
  575. pseudo_element
  576.  : FIRST_LINE { 
  577.      TRACE2("-IDENT '%s' to pseudo_element\n", css_text);
  578.      $$ = NewNode(NODE_PSEUDO_ELEMENT, "first-Line", NULL, NULL);
  579.    }
  580.  | FIRST_LETTER { 
  581.      TRACE2("-IDENT '%s' to pseudo_element\n", css_text);
  582.      $$ = NewNode(NODE_PSEUDO_ELEMENT, "first-Letter", NULL, NULL);
  583.    }
  584.  ;
  585.  
  586. declaration_list 
  587.  : declaration {
  588.      TRACE1("-declaration\n");
  589.      $$ = $1;
  590.    }
  591.  | declaration_list ';' declaration {
  592.      /* to keep the order, append the new node to the end. */
  593.      TRACE1("-declaration_list ';' declaration\n");
  594.      $$ = $1;
  595.      if (NULL == $$)
  596.        $$ = $3;
  597.      else
  598.        LeftAppendNode($$, $3);
  599.    }
  600.  ;
  601.  
  602. declaration
  603.  :       { 
  604.      TRACE1("-empty declaration\n");
  605.      $$ = NewNode(NODE_DECLARATION_LIST, NULL, NULL, NULL);
  606.    } 
  607.  | property ':' expr optional_priority {
  608.      css_node dcl;
  609.      TRACE1("-property : expr\n");
  610.      dcl = NewNode(NODE_DECLARATION_PROPERTY_EXPR, NULL, $1, $3);
  611.      $$ = NewNode(NODE_DECLARATION_LIST, NULL, NULL, dcl);
  612.    }
  613.  | font_size_property ':' font_size_value optional_priority {
  614.      css_node expr, dcl;
  615.      expr = NewNode(NODE_EXPR, NULL, NULL, $3);
  616.      dcl = NewNode(NODE_DECLARATION_PROPERTY_EXPR, NULL, $1, expr);
  617.      $$ = NewNode(NODE_DECLARATION_LIST, NULL, NULL, dcl);
  618.     }
  619.  | background_property ':' background_values_list optional_priority {
  620.      /* The priority notation is ignored by the translator
  621.       * so we conveniently ignore it here, too.
  622.       */
  623.      TRACE1("-background property : background_values_list\n");
  624.      $$ = AssembleBackground();
  625.    }
  626.  | font_property ':' font_values_list optional_priority {
  627.      TRACE1("-font property : font_values_list prio\n");
  628.      /* The priority notation is ignored by the translator
  629.       * so we conveniently ignore it here, too.
  630.       */
  631.      $$ = AssembleFont();
  632.    }
  633.   | list_style_property ':' list_style_values_list optional_priority {
  634.      $$ = AssembleListStyle();
  635.    }
  636.   | border_property ':' border_values_list optional_priority {
  637.      $$ = AssembleBorder();
  638.     }
  639.  ;
  640.  
  641. optional_priority
  642.     : { /* nothing */ }
  643.     | prio
  644.     ;
  645.  
  646. prio
  647.  : IMPORTANT_SYM {                       /* !important */
  648.      TRACE1("-IMPORTANT_SYM\n");
  649.      $$ = NULL;
  650.    }
  651.  ;
  652.  
  653. expr
  654.  : term {
  655.      TRACE1("-term\n");
  656.      $$ = NewNode(NODE_EXPR, NULL, NULL, $1);
  657.    }
  658.  | expr operator term  {
  659.      TRACE1("-expr op term\n");
  660.  
  661.      $$ = $1;
  662.      /* put the new term at the end */
  663.      $2->right = $3;
  664.  
  665.      if ($$ == NULL)
  666.        $$ = $2;
  667.      else
  668.        LeftAppendNode( $$, $2 ); 
  669.    }
  670.  ;
  671.  
  672. term
  673.  : unsigned_symbol
  674.  | color_code
  675.  | url
  676.  | numeric_unit
  677.  | numeric_const
  678.  ;
  679.  
  680. numeric_const
  681.  : unsigned_numeric_const
  682.  | unary_operator unsigned_numeric_const {
  683.      TRACE1("-unary_operator signed_const to term\n"); 
  684.      $$ = $1;
  685.      $$->left = $2;
  686.    }
  687.  ;
  688.  
  689. unsigned_numeric_const
  690.  : NUMBER {
  691.      $$ = NewNode(NODE_NUMBER, css_text, NULL, NULL);
  692.    }
  693.  ;
  694.  
  695. numeric_unit
  696.  : unsigned_numeric_unit
  697.  | unary_operator unsigned_numeric_unit {
  698.      $$ = $1;
  699.      $$->left = $2;
  700.    }
  701.  ;
  702.  
  703. unsigned_numeric_unit
  704.  : PERCENTAGE {
  705.      $$ = NewNode(NODE_PERCENTAGE, css_text, NULL, NULL);
  706.    }
  707.  | LENGTH {
  708.      $$ = NewNode(NODE_LENGTH, css_text, NULL, NULL);
  709.    }
  710.  | EMS {
  711.      $$ = NewNode(NODE_EMS, css_text, NULL, NULL);
  712.    }
  713.  | EXS{
  714.      $$ = NewNode(NODE_EMS, css_text, NULL, NULL);
  715.    }
  716.  ;
  717.  
  718. unsigned_symbol
  719.  : STRING {
  720.      $$ = NewNode(NODE_STRING, css_text, NULL, NULL);
  721.    }
  722.  | IDENT { 
  723.      TRACE2("-IDENT '%s' to unsigned_symbol\n", css_text);
  724.      $$ = NewNode(NODE_IDENT, css_text, NULL, NULL);
  725.    }
  726.  ;
  727.  
  728. url
  729.  : URL {
  730.      $$ = NewNode(NODE_URL, css_text, NULL, NULL);
  731.    }
  732.  ;
  733.  
  734. color_code
  735.  : HEXCOLOR {
  736.      $$ = NewNode(NODE_HEXCOLOR, css_text, NULL, NULL);
  737.    }
  738.  | RGB {
  739.      $$ = NewNode(NODE_RGB, css_text, NULL, NULL);
  740.    }
  741.  ;
  742.  
  743. background_values_list
  744.     : background_values
  745.     | background_position_value
  746.     | background_values background_position_value
  747.     | background_position_value background_values
  748.     | background_values background_position_value background_values
  749.     ;
  750.  
  751. background_values
  752.     : background_value
  753.     | background_values background_value
  754.     ;
  755.  
  756. background_value
  757.     : URL {
  758.         $$ = NewDeclarationNode(NODE_URL, css_text, bg_image);
  759.         AddBackground(BackgroundImage, $$);
  760.       }
  761.     | BG_IMAGE {
  762.         $$ = NewDeclarationNode(NODE_IDENT, css_text, bg_image);
  763.         AddBackground(BackgroundImage, $$);
  764.       }
  765.     | color_code {
  766.         $$ = NewComponentNode($1, bg_color);
  767.         AddBackground(BackgroundColor, $$);
  768.       }
  769.     | IDENT {
  770.         $$ = NewDeclarationNode(NODE_IDENT, css_text, bg_color);
  771.         AddBackground(BackgroundColor, $$);
  772.       }
  773.     | BG_COLOR {
  774.         $$ = NewDeclarationNode(NODE_IDENT, css_text, bg_color);
  775.         AddBackground(BackgroundColor, $$);
  776.       }
  777.     | BG_REPEAT {
  778.         $$ = NewDeclarationNode(NODE_IDENT, css_text, "background-repeat");
  779.         AddBackground(BackgroundRepeat, $$);
  780.       }
  781.     | BG_ATTACHMENT {
  782.         $$ = NewDeclarationNode(NODE_IDENT, css_text, "background-attachment");
  783.         AddBackground(BackgroundAttachment, $$);
  784.       }
  785.     ;
  786.  
  787. background_position_value
  788.     : background_position_expr {
  789.         css_node property, declaration;
  790.         property = NewNode(NODE_PROPERTY, bg_position, NULL, NULL);
  791.         declaration = NewNode(NODE_DECLARATION_PROPERTY_EXPR, NULL,
  792.                               property, $1);
  793.         AddBackground(BackgroundPosition, declaration);
  794.       }
  795.     ;
  796.  
  797. background_position_expr
  798.     : numeric_unit {
  799.         $$ = NewNode(NODE_EXPR, NULL, NULL, $1);
  800.       }
  801.     | numeric_unit numeric_unit {
  802.         css_node operator;
  803.         $$ = NewNode(NODE_EXPR, NULL, NULL, $1);
  804.         operator = NewNode(NODE_EMPTY_OP, NULL, NULL, $2);
  805.         if ($$ == NULL)
  806.             $$ = operator;
  807.         else
  808.             LeftAppendNode($$, operator);
  809.       }
  810.     | background_position_keyword {
  811.         $$ = NewNode(NODE_EXPR, NULL, NULL, $1);
  812.       }
  813.     | background_position_keyword background_position_keyword {
  814.         css_node operator;
  815.         $$ = $1;
  816.         operator = NewNode(NODE_EMPTY_OP, NULL, NULL, $2);
  817.         if ($$ == NULL)
  818.             $$ = operator;
  819.         else
  820.             LeftAppendNode($$, operator);
  821.       }
  822.     ;
  823.  
  824. background_position_keyword
  825.     : BG_POSITION {
  826.         $$ = NewNode(NODE_IDENT, css_text, NULL, NULL);
  827.       }
  828.     ;
  829.  
  830. font_values_list
  831.     : font_optional_values_list font_size_value font_family_value {
  832.         css_node tmp;
  833.         tmp = NewComponentNode($2, font_size);
  834.         AddFont(FontSize, tmp);
  835.         AddFont(FontFamily, $3);
  836.         $$ = NULL;
  837.       }
  838.    | font_optional_values_list font_size_value '/' line_height_value font_family_value {
  839.         css_node tmp;
  840.         tmp = NewComponentNode($2, font_size);
  841.         AddFont(FontSize, tmp);
  842.         tmp = NewComponentNode($4, line_height);
  843.         AddFont(FontLeading, tmp);
  844.         AddFont(FontFamily, $5);
  845.         $$ = NULL;
  846.       }
  847.     ;
  848.  
  849. font_family_operator
  850.  :       { 
  851.      TRACE1("-empty operator\n");
  852.      $$ = NewNode(NODE_EMPTY_OP, NULL, NULL, NULL);
  853.    }
  854.  | ','     { 
  855.      TRACE1("-operator : ','\n"); 
  856.      $$ = NewNode(NODE_EXPR_OP, css_text, NULL, NULL);
  857.    }
  858.  ;
  859.  
  860. font_family_value
  861.  : font_family_expr {
  862.      css_node property;
  863.      TRACE1("-font_family_expr to font_family_value\n");
  864.      property = NewNode(NODE_PROPERTY, font_family, NULL, NULL);
  865.      $$ = NewNode(NODE_DECLARATION_PROPERTY_EXPR, NULL, property, $1);
  866.     }
  867.   ;
  868.  
  869. font_family_expr
  870.  : unsigned_symbol {
  871.      TRACE1("-unsigned_symbol\n");
  872.      $$ = NewNode(NODE_EXPR, NULL, NULL, $1);
  873.    }
  874.  | font_family_expr font_family_operator unsigned_symbol  {
  875.      TRACE1("-font_family_value font_family_op unsigned_symbol\n");
  876.  
  877.      $$ = $1;
  878.      /* put the new term at the end */
  879.      $2->right = $3;
  880.  
  881.      if ($$ == NULL)
  882.        $$ = $2;
  883.      else
  884.        LeftAppendNode( $$, $2 ); 
  885.    }
  886.  ;
  887.  
  888. font_optional_values_list
  889.     : { /* empty */
  890.         $$ = NULL;
  891.       }
  892.     | font_optional_values_list font_optional_value {
  893.         $$ = NULL;
  894.       }
  895.     ;
  896.  
  897. font_optional_value
  898.     : FONT_STYLE {
  899.     TRACE2("-FONT_STYLE '%s' to font_optional_value\n", css_text);
  900.         $$ = NewDeclarationNode(NODE_IDENT, css_text, font_style);
  901.         AddFont(FontStyle, $$);
  902.       }
  903.     | FONT_VARIANT {
  904.     TRACE2("-FONT_VARIANT '%s' to font_optional_value\n", css_text);
  905.         $$ = NewDeclarationNode(NODE_IDENT, css_text, font_variant);
  906.         AddFont(FontVariant, $$);
  907.       }
  908.     | FONT_WEIGHT {
  909.     TRACE2("-FONT_WEIGHT '%s' to font_optional_value\n", css_text);
  910.         $$ = NewDeclarationNode(NODE_IDENT, css_text, font_weight);
  911.         AddFont(FontWeight, $$);
  912.       }
  913.     | FONT_NORMAL {
  914.         AddFont(FontNormal, NULL);
  915.       }
  916.     ;
  917.  
  918. font_size_value
  919.     : unsigned_numeric_unit
  920.     | FONT_SIZE {
  921.         $$ = NewNode(NODE_IDENT, css_text, NULL, NULL);
  922.       }
  923.     | '+' unsigned_numeric_unit {
  924.         /* just drop the '+' on the floor */
  925.         $$ = $2;
  926.       }
  927.     ;
  928.  
  929. line_height_value
  930.     : numeric_unit
  931.     | numeric_const
  932.     | LINE_HEIGHT {
  933.         /* The only valid identifier is the word "normal".
  934.          * There's an idea that a normal leading value is font-specific,
  935.          * so the identifier is passed upwards.
  936.          */
  937.     $$ = NewNode(NODE_IDENT, css_text, NULL, NULL);
  938.       }
  939.     ;
  940.  
  941. list_style_values_list
  942.     : list_style_value
  943.     | list_style_values_list list_style_value
  944.     ;
  945.  
  946. list_style_value
  947.     : LS_TYPE {
  948.         $$ = NewDeclarationNode(NODE_IDENT, css_text, list_style_type);
  949.         AddListStyle(ListStyleMarker, $$);
  950.         $$ = NULL;
  951.       }
  952.     | LS_NONE {
  953.         AddListStyle(ListStyleNone, NULL);
  954.         $$ = NULL;
  955.       }
  956.     | LS_POSITION {
  957.         $$ = NewDeclarationNode(NODE_IDENT, css_text, list_style_position);
  958.         AddListStyle(ListStylePosition, $$);
  959.         $$ = NULL;
  960.       }
  961.     | url {
  962.         $$ = NewComponentNode($1, list_style_image);
  963.         AddListStyle(ListStyleImage, $$);
  964.         $$ = NULL;
  965.       }
  966.     ;
  967.  
  968. border_values_list
  969.     : border_value
  970.     | border_values_list border_value
  971.     ;
  972.  
  973. border_value
  974.     : BORDER_STYLE {
  975.         $$ = NewDeclarationNode(NODE_IDENT, css_text, border_style);
  976.         AddBorder(BorderStyle, $$);
  977.         $$ = NULL;
  978.       }
  979.     | BORDER_WIDTH {
  980.         $$ = NewDeclarationNode(NODE_IDENT, css_text, border_width);
  981.         AddBorder(BorderWidth, $$);
  982.         $$ = NULL;
  983.       }
  984.     | numeric_unit {
  985.         $$ = NewComponentNode($1, border_width);
  986.         AddBorder(BorderWidth, $$);
  987.         $$ = NULL;
  988.       }
  989.     | color_code {
  990.         $$ = NewComponentNode($1, border_color);
  991.         AddBorder(BorderColor, $$);
  992.         $$ = NULL;
  993.       }
  994.     | IDENT {
  995.         $$ = NewDeclarationNode(NODE_IDENT, css_text, border_color);
  996.         AddBorder(BorderColor, $$);
  997.         $$ = NULL;
  998.       }
  999.     ;
  1000. %%
  1001.  
  1002. #include "xp_mem.h"
  1003. #include "xpassert.h"
  1004.  
  1005. /* Memory allocated here will be freed by css_FreeNode in csstojs.c */
  1006. static css_node NewNode(int node_id, char *ss, css_node left, css_node right)
  1007. {
  1008.     register css_node pp;
  1009.  
  1010.     if ((pp = XP_NEW(css_nodeRecord)) == NULL)
  1011.         return NULL;
  1012.  
  1013.     pp->node_id = node_id;
  1014.     pp->string = NULL;
  1015.     if (ss) {
  1016.         if ((pp->string = (char *) XP_ALLOC(strlen(ss) + 1)) != NULL)
  1017.             (void) strcpy(pp->string, ss);
  1018.     }
  1019.     pp->left   = left;
  1020.     pp->right  = right;
  1021.     return pp;
  1022. }
  1023.  
  1024.  
  1025. /* Append new_node to the leftmost leaf of head */
  1026. static void LeftAppendNode(css_node head, css_node new_node)
  1027. {
  1028.     if (head == NULL)
  1029.         return;
  1030.     
  1031.     while (head->left != NULL)
  1032.         head = head->left;
  1033.     head->left = new_node;         
  1034. }
  1035.  
  1036.  
  1037. static css_node NewDeclarationNode(int node_id, char *ss, char *prop)
  1038. {
  1039.     css_node value, expression, property;
  1040.     value = NewNode(node_id, ss, NULL, NULL);
  1041.     expression = NewNode(NODE_EXPR, NULL, NULL, value);
  1042.     property = NewNode(NODE_PROPERTY, prop, NULL, NULL);
  1043.     return NewNode(NODE_DECLARATION_PROPERTY_EXPR, NULL, property, expression);
  1044. }
  1045.  
  1046.  
  1047. static css_node NewComponentNode(css_node value, char *prop)
  1048. {
  1049.     css_node expression, property;
  1050.     expression = NewNode(NODE_EXPR, NULL, NULL, value);
  1051.     property = NewNode(NODE_PROPERTY, prop, NULL, NULL);
  1052.     return NewNode(NODE_DECLARATION_PROPERTY_EXPR, NULL, property, expression);
  1053. }
  1054.  
  1055.  
  1056. static void ClearFont(void)
  1057. {
  1058.     font.style = font.variant = font.weight = NULL;
  1059.     font.size = font.leading = font.family = NULL;
  1060.     font.normal_count = font.parse_error = 0;
  1061. }
  1062.  
  1063.  
  1064. static void AddFont(int node_type, css_node node)
  1065. {
  1066.     if (FontStyle == node_type && (! font.style))
  1067.         font.style = node;
  1068.     else if (FontVariant == node_type && (! font.variant))
  1069.         font.variant = node;
  1070.     else if (FontWeight == node_type && (!  font.weight))
  1071.         font.weight = node;
  1072.     else if (FontNormal == node_type)
  1073.         font.normal_count++;
  1074.     else if (FontSize == node_type && (! font.size))
  1075.         font.size = node;
  1076.     else if (FontLeading == node_type && (! font.leading))
  1077.         font.leading = node;
  1078.     else if (FontFamily == node_type && (! font.family))
  1079.         font.family = node;
  1080.     else {
  1081.         font.parse_error++;
  1082.         if (node) css_FreeNode(node);
  1083.     }
  1084. }
  1085.  
  1086.  
  1087. static css_node AssembleFont(void)
  1088. {
  1089.     css_node head, element;
  1090.     int count;
  1091.  
  1092.     count = 0;
  1093.     if (font.style)       count++;
  1094.     if (font.variant)     count++;
  1095.     if (font.weight)      count++;
  1096.     if (font.normal_count > (3 - count))
  1097.         font.parse_error++;
  1098.  
  1099.     if (font.parse_error) {
  1100.         if (font.style)    css_FreeNode(font.style);
  1101.         if (font.variant)  css_FreeNode(font.variant);
  1102.         if (font.weight)   css_FreeNode(font.weight);
  1103.         if (font.size)     css_FreeNode(font.size);
  1104.         if (font.leading)  css_FreeNode(font.leading);
  1105.         if (font.family)   css_FreeNode(font.family);
  1106.         ClearFont();
  1107.         return NULL;
  1108.     }
  1109.  
  1110.     if (! font.style)
  1111.         font.style = NewDeclarationNode(NODE_IDENT, css_normal, font_style);
  1112.     if (! font.variant)
  1113.         font.variant = NewDeclarationNode(NODE_IDENT, css_normal, font_variant);
  1114.     if (! font.weight)
  1115.         font.weight = NewDeclarationNode(NODE_IDENT, css_normal, font_weight);
  1116.     if (! font.leading)
  1117.         font.leading = NewDeclarationNode(NODE_IDENT, css_normal, line_height);
  1118.  
  1119.     head = NewNode(NODE_DECLARATION_LIST, NULL, NULL, font.style);
  1120.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, font.variant);
  1121.     LeftAppendNode(head, element);
  1122.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, font.weight);
  1123.     LeftAppendNode(head, element);
  1124.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, font.size);
  1125.     LeftAppendNode(head, element);
  1126.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, font.leading);
  1127.     LeftAppendNode(head, element);
  1128.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, font.family);
  1129.     LeftAppendNode(head, element);
  1130.  
  1131.     ClearFont();
  1132.     return head;
  1133. }
  1134.  
  1135.  
  1136. static void ClearBackground(void)
  1137. {
  1138.     bg.color = bg.image = bg.repeat = NULL;
  1139.     bg.attachment = bg.position = NULL;
  1140.     bg.parse_error = 0;
  1141. }
  1142.  
  1143.  
  1144. static void AddBackground(int node_type, css_node node)
  1145. {
  1146.     if (BackgroundColor == node_type && (! bg.color))
  1147.         bg.color = node;
  1148.     else if (BackgroundImage == node_type && (! bg.image))
  1149.         bg.image = node;
  1150.     else if (BackgroundRepeat == node_type && (!  bg.repeat))
  1151.         bg.repeat = node;
  1152.     else if (BackgroundAttachment == node_type && (! bg.attachment))
  1153.         bg.attachment = node;
  1154.     else if (BackgroundPosition == node_type && (! bg.position))
  1155.         bg.position = node;
  1156.     else {
  1157.         bg.parse_error++;
  1158.         css_FreeNode(node);
  1159.     }
  1160. }
  1161.  
  1162.  
  1163. static css_node AssembleBackground(void)
  1164. {
  1165.     css_node head, element;
  1166.  
  1167.     if (bg.parse_error) {
  1168.         if (bg.color)
  1169.             css_FreeNode(bg.color);
  1170.         if (bg.image)
  1171.             css_FreeNode(bg.image);
  1172.         if (bg.repeat)
  1173.             css_FreeNode(bg.repeat);
  1174.         if (bg.attachment)
  1175.             css_FreeNode(bg.attachment);
  1176.         if (bg.position)
  1177.             css_FreeNode(bg.position);
  1178.         ClearBackground();
  1179.         return NULL;
  1180.     }
  1181.  
  1182.     if (! bg.color)
  1183.         bg.color = NewDeclarationNode(NODE_IDENT, css_transparent, bg_color);
  1184.     if (! bg.image)
  1185.         bg.image = NewDeclarationNode(NODE_IDENT, css_none, bg_image);
  1186.     if (! bg.repeat)
  1187.         bg.repeat = NewDeclarationNode(NODE_IDENT, css_repeat, bg_repeat);
  1188.     if (! bg.attachment)
  1189.         bg.attachment = NewDeclarationNode(NODE_IDENT, css_scroll, bg_attachment);
  1190.     if (! bg.position)
  1191.         bg.position = NewDeclarationNode(NODE_PERCENTAGE, css_origin,
  1192.                                          bg_position);
  1193.  
  1194.     head = NewNode(NODE_DECLARATION_LIST, NULL, NULL, bg.color);
  1195.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, bg.image);
  1196.     LeftAppendNode(head, element);
  1197.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, bg.repeat);
  1198.     LeftAppendNode(head, element);
  1199.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, bg.attachment);
  1200.     LeftAppendNode(head, element);
  1201.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, bg.position);
  1202.     LeftAppendNode(head, element);
  1203.  
  1204.     ClearBackground();
  1205.     return head;
  1206. }                                      
  1207.         
  1208.  
  1209. static void ClearListStyle(void)
  1210. {
  1211.     ls.marker = ls.image = ls.position = NULL;
  1212.     ls.none_count = ls.parse_error = 0;
  1213. }
  1214.  
  1215. static void AddListStyle(int node_type, css_node node)
  1216. {
  1217.     if (ListStyleMarker == node_type && (! ls.marker))
  1218.         ls.marker = node;
  1219.     else if (ListStyleImage == node_type && (! ls.image))
  1220.         ls.image = node;
  1221.     else if (ListStylePosition == node_type && (! ls.position))
  1222.         ls.position = node;
  1223.     else if (ListStyleNone == node_type)
  1224.         ls.none_count++;
  1225.     else {
  1226.         ls.parse_error++;
  1227.         if (node) css_FreeNode(node);
  1228.     }
  1229. }
  1230.  
  1231. static css_node AssembleListStyle(void)
  1232. {
  1233.     css_node head, element;
  1234.     int count;
  1235.     char * marker_value;
  1236.  
  1237.     count = 0;
  1238.     if (ls.marker)    count++;
  1239.     if (ls.image)    count++;
  1240.     if (ls.none_count > (2 - count))
  1241.         ls.parse_error++;
  1242.  
  1243.     if (ls.parse_error) {
  1244.         if (ls.marker)    css_FreeNode(ls.marker);
  1245.         if (ls.image)    css_FreeNode(ls.image);
  1246.         if (ls.position)    css_FreeNode(ls.position);
  1247.         ClearListStyle();
  1248.         return NULL;
  1249.     }
  1250.  
  1251.     if (! ls.marker) {
  1252.         /* list-style: none
  1253.          * could mean marker or image.  It should set the marker;
  1254.          * the image will default to none.
  1255.          */
  1256.         marker_value = ls.none_count ? css_none : css_disc;
  1257.         ls.marker = NewDeclarationNode(NODE_IDENT, marker_value,
  1258.                                        list_style_type);
  1259.     }
  1260.     if (! ls.image)
  1261.         ls.image = NewDeclarationNode(NODE_IDENT, css_none, list_style_image);
  1262.     if (! ls.position)
  1263.         ls.position = NewDeclarationNode(NODE_IDENT, css_outside,
  1264.                                          list_style_position);
  1265.  
  1266.     head = NewNode(NODE_DECLARATION_LIST, NULL, NULL, ls.marker);
  1267.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, ls.image);
  1268.     LeftAppendNode(head, element);
  1269.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, ls.position);
  1270.     LeftAppendNode(head, element);
  1271.  
  1272.     ClearListStyle();
  1273.     return head;
  1274. }
  1275.  
  1276.  
  1277. static void ClearBorder(void)
  1278. {
  1279.     border.width = border.style = border.color = (css_node) NULL;
  1280.     border.parse_error = 0;
  1281. }
  1282.  
  1283. static void AddBorder(int node_type, css_node node)
  1284. {
  1285.     if (BorderWidth == node_type && (! border.width))
  1286.         border.width = node;
  1287.     else if (BorderStyle == node_type && (! border.style))
  1288.         border.style = node;
  1289.     else if (BorderColor == node_type && (! border.color))
  1290.         border.color = node;
  1291.     else {
  1292.         border.parse_error++;
  1293.         if (node) css_FreeNode(node);
  1294.     }
  1295. }
  1296.  
  1297. static css_node AssembleBorder(void)
  1298. {
  1299.     css_node head, element;
  1300.  
  1301.     if (border.parse_error) {
  1302.         if (border.width) css_FreeNode(border.width);
  1303.         if (border.style) css_FreeNode(border.style);
  1304.         if (border.color) css_FreeNode(border.color);
  1305.         ClearBorder();
  1306.         return (css_node) NULL;
  1307.     }
  1308.  
  1309.     if (! border.width)
  1310.         border.width = NewDeclarationNode(NODE_IDENT, css_medium, border_width);
  1311.     if (! border.style)
  1312.         border.style = NewDeclarationNode(NODE_IDENT, css_none, border_style);
  1313.  
  1314.     head = NewNode(NODE_DECLARATION_LIST, NULL, NULL, border.width);
  1315.     element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, border.style);
  1316.     LeftAppendNode(head, element);
  1317.     if (border.color) {
  1318.         element = NewNode(NODE_DECLARATION_LIST, NULL, NULL, border.color);
  1319.         LeftAppendNode(head, element);
  1320.     }
  1321.  
  1322.     ClearBorder();
  1323.     return head;
  1324. }
  1325.  
  1326. /* css_overflow is only for parsers generated by bison. */
  1327. static void css_overflow(const char *message, short **yyss1, int yyss1_size, 
  1328.                          YYSTYPE **yyvs1, int yyvs1_size, int *yystacksize)
  1329. {
  1330.     short * yyss2;
  1331.     YYSTYPE * yyvs2;
  1332.     int new_size;
  1333.  
  1334.  
  1335.     if (*yystacksize >= YYMAXDEPTH)
  1336.         return;
  1337.  
  1338.     new_size = *yystacksize * 2;
  1339.     if (new_size > YYMAXDEPTH)
  1340.         new_size = YYMAXDEPTH;
  1341.  
  1342.     if (*yystacksize == YYINITDEPTH) {
  1343.         /* First time allocating from the heap. */
  1344.         yyss2 = (short *) XP_ALLOC(new_size * sizeof(short));
  1345.         if (yyss2)
  1346.             (void) memcpy((void *)yyss2, (void *) *yyss1, yyss1_size);
  1347.         yyvs2 = XP_ALLOC(new_size * sizeof(YYSTYPE));
  1348.         if (yyvs2)
  1349.             (void) memcpy((void *)yyvs2, (void *) *yyvs1, yyvs1_size);
  1350.     } else {
  1351.         yyss2 = (short *) XP_REALLOC(*yyss1, new_size * sizeof(short));
  1352.         yyvs2 = XP_REALLOC(*yyvs1, new_size * sizeof(YYSTYPE));
  1353.     }
  1354.  
  1355.     if (yyss2 && yyvs2) {
  1356.         *yyss1 = yyss2;
  1357.         *yyvs1 = yyvs2;
  1358.         *yystacksize = new_size;
  1359.     }
  1360.  
  1361.     /* Any failure to allocate will be noticed by the caller. */
  1362. }
  1363.  
  1364.