/*
** SWISH++
** mod/html/elements.c
**
** Copyright (C) 1998 Paul J. Lucas
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef MOD_html
// local
#include "elements.h"
//*****************************************************************************
//
// SYNOPSIS
//
element_map::element_map()
//
// DESCRIPTION
//
// Construct (initialize) an element_map.
//
// SEE ALSO
//
// Shane McCarron, et al. "XHTML 2.0," World Wide Web Consortium,
// August 2002.
// http://www.w3.org/TR/xhtml2/
//
// Dave Raggett, Arnaud Le Hors, and Ian Jacobs. "Index of Elements,"
// HTML 4.0 Specification, World Wide Web Consortium, April 1998.
// http://www.w3.org/TR/REC-html40/index/elements.html
//
// Marcin Sawicki, et al. "Ruby Annotation," World Wide Web Consortium,
// April 6, 2001.
// http://www.w3.org/TR/2001/PR-ruby-20010406/
//
// Netscape Communications Corporation. "HTML Tag Reference," January
// 1998.
// http://developer.netscape.com/docs/manuals/htmlguid/index.htm
//
//*****************************************************************************
{
typedef char const *const cpcc;
//
// Declare character pointers having values equal to element's end_tag_type
// enum so that we can have a simple array of strings below where each
// "row" has varying length. It's kind of a hack, but it works.
//
cpcc F = reinterpret_cast< char const* >( element::et_forbidden );
cpcc O = reinterpret_cast< char const* >( element::et_optional );
cpcc R = reinterpret_cast< char const* >( element::et_required );
//
// Elements that have forbidden end tags (obviously) have no tags listed
// for them in the rows below.
//
// Elements that have optional end tags have a null-terminated list of tags
// that close them, either explicitly (their own end tag) or implicitly (a
// tag from some other element).
//
// Elements that have required end tags simply list their single end tag.
// Yes, it's easy, given a start tag, to know what it's end tag is (the
// same tag, but with a leading '/'); however, the code in parse_html_tag()
// in mod_html.c is made simpler by explicitly giving the end tag here
// rather than having to construct a temporary string prepending a '/' to
// the tag.
//
static char const *const end_tag_table[] = {
// element end tag tags that close it status
// ------------ ------- ------------------ ---------------
"a", R, "/a",
"abbr", R, "/abbr",
"acronym", R, "/acronym",
"address", R, "/address",
"applet", R, "/applet", // deprecated
"area", F,
"b", R, "/b",
"base", F,
"basefont", F, // deprecated
"bdo", R, "/bdo",
"big", R, "/big",
"blink", R, "/blink", // nonstandard
"blockquote", R, "/blockquote",
"body", O, "/body", "/html", 0,
"br", F,
"button", R, "/button",
"caption", R, "/caption",
"center", R, "/center", // deprecated
"cite", R, "/cite",
"code", R, "/code",
"col", F,
"colgroup", O, "colgroup", "/colgroup",
"tbody", "tfoot", "thead",
"tr",
"/table",
0,
"dd", O, "dd", "/dd", "/dl", "dt", "/dt", 0,
"del", R, "/del",
"dfn", R, "/dfn",
"dir", R, "/dir", // deprecated
"div", R, "/div",
"dl", R, "/dl",
"dt", O, "dt", "/dt", "/dl", 0,
"em", R, "/em",
"embed", R, "/embed", // nonstandard
"fieldset", R, "/fieldset",
"font", R, "/font", // deprecated
"form", R, "/form",
"frame", F,
"frameset", R, "/frameset",
"h", R, "/h", // XHTML 2.0
"h1", R, "/h1",
"h2", R, "/h2",
"h3", R, "/h3",
"h4", R, "/h4",
"h5", R, "/h5",
"h6", R, "/h6",
"head", O, "body", "/body", "/head", "/html", 0,
"hr", F,
"html", O, "/html", 0,
"i", R, "/i",
"iframe", R, "/iframe",
"ilayer", R, "/ilayer", // nonstandard
"img", F,
"input", F,
"ins", R, "/ins",
"isindex", F, // deprecated
"kbd", R, "/kbd",
"keygen", F, // nonstandard
"label", R, "/label",
"layer", R, "/layer", // nonstandard
"legend", R, "/legend",
"li", O, "li", "/li", "/ol", "/ul", 0,
"line", R, "/line", // XHTML 2.0
"link", F,
"map", R, "/map",
"menu", R, "/menu", // deprecated
"meta", F,
"multicol", R, "/multicol", // nonstandard
"name", R, "/name", // XHTML 2.0
"nl", R, "/nl", // XHTML 2.0
"nobr", F, // nonstandard
"noembed", R, "/noembed", // nonstandard
"noframes", R, "/noframes",
"nolayer", R, "/nolayer", // nonstandard
"noscript", R, "/noscript",
"object", R, "/object",
"ol", R, "/ol",
"optgroup", R, "/optgroup",
"option", O, "/optgroup",
"option", "/option",
"/select",
0,
"p", O, "address", "/address",
"applet", "/applet",
"blockquote", "/blockquote",
"/body",
"br",
"caption", "/caption",
"center", "/center",
"dd", "/dd",
"div", "/div",
"dl", "/dl",
"dt", "/dt",
"embed", "/embed",
"form", "/form",
"frame", "/frame",
"frameset", "/frameset",
"h1", "/h1",
"h2", "/h2",
"h3", "/h3",
"h4", "/h4",
"h5", "/h5",
"h6", "/h6",
"hr",
"/html",
"layer", "/layer",
"li", "/li",
"map", "/map",
"multicol", "/multicol",
"noembed", "/noembed",
"noframes", "/noframes",
"nolayer", "/nolayer",
"noscript", "/noscript",
"object", "/object",
"ol", "/ol",
"p", "/p",
"plaintext",
"pre", "/pre",
"script", "/script",
"select", "/select",
"style", "/style",
"table", "/table",
"tbody", "/tbody"
"td", "/td",
"tfoot", "/tfoot"
"th", "/th",
"thead", "/thead"
"tr", "/tr",
"ul", "/ul",
"xmp", "/xmp",
0,
"param", F,
"plaintext", F, // deprecated
"pre", R, "/pre",
"q", R, "/q", // deprecated
"quote", R, "/quote", // XHTML 2.0
"ruby", R, "/ruby", // ruby elements
"rb", R, "/rb",
"rbc", R, "/rbc",
"rp", R, "/rp",
"rt", R, "/rt",
"rtc", R, "/rtc",
"s", R, "/s", // deprecated
"samp", R, "/samp",
"script", R, "/script",
"section", R, "/section", // XHTML 2.0
"select", R, "/select",
"server", R, "/server", // nonstandard
"small", R, "/small",
"spacer", F, // nonstandard
"span", R, "/span",
"strike", R, "/strike", // deprecated
"strong", R, "/strong",
"style", R, "/style",
"sub", R, "/sub",
"sup", R, "/sup",
"table", R, "/table",
"tbody", O, "tbody", "/tbody", 0,
"td", O, "tbody", "/tbody",
"td", "/td",
"tfoot", "/tfoot",
"th",
"/table",
"tr", "/tr",
0,
"textarea", R, "/textarea",
"tfoot", O, "tbody", "/tfoot", "thead", 0,
"th", O, "tbody", "/tbody",
"td",
"tfoot", "/tfoot",
"th", "/th",
"/table",
"tr", "/tr",
0,
"thead", O, "tbody", "tfoot", "/thead", 0,
"title", R, "/title",
"tr", O, "tbody", "/tbody",
"tfoot", "/tfoot",
"/thead",
"tr", "/tr",
"/table",
0,
"tt", R, "/tt",
"u", R, "/u", // deprecated
"ul", R, "/ul",
"var", R, "/var",
"wbr", F, // nonstandard
"xmp", R, "/xmp", // deprecated
0
};
for ( register char const *const *p = end_tag_table; *p; ++p ) {
//
// The ugly double, old-style casts below are necessary because C++ has
// become overly pedantic about casting to enums.
//
element::end_tag_type const
v = (element::end_tag_type const)(intptr_t const)(p[1]);
element &e = insert( value_type( *p++, element( v ) ) ).first->second;
switch ( v ) {
case element::et_forbidden:
// do nothing
break;
case element::et_optional:
//
// Elements that have optional end tags have a null-terminated
// list of closing tags.
//
while ( *++p )
e.close_tags.insert( *p );
break;
case element::et_required:
//
// Elements that have required and tags have a single closing
// tag.
//
e.close_tags.insert( *++p );
break;
}
}
}
//*****************************************************************************
//
// SYNOPSIS
//
element_map const& element_map::instance()
//
// DESCRIPTION
//
// Define and initialize (exactly once) a static instance of element_map
// and return a reference to it. The reason for this function is to
// guarantee that there is exactly one instance of it and that it is
// initialized before its first use across all translation units,
// something that would not guaranteed if it were defined and initialized
// at file scope.
//
// RETURN VALUE
//
// Returns a reference to a static instance of an initialized element_map.
//
// SEE ALSO
//
// Margaret A. Ellis and Bjarne Stroustrup. "The Annotated C++ Reference
// Manual." Addison-Wesley, Reading, MA, 1990. p. 19.
//
//*****************************************************************************
{
static element_map const m;
return m;
}
#endif /* MOD_html */
/* vim:set et sw=4 ts=4: */