1#!/usr/bin/env python
2#
3# Copyright (C) 2014 Apple Inc. All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8# 1. Redistributions of source code must retain the above copyright
9#    notice, this list of conditions and the following disclaimer.
10# 2. Redistributions in binary form must reproduce the above copyright
11#    notice, this list of conditions and the following disclaimer in the
12#    documentation and/or other materials provided with the distribution.
13#
14# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24# THE POSSIBILITY OF SUCH DAMAGE.
25
26import os
27import sys
28
29
30def enumerablePseudoType(stringPseudoType):
31    output = ['CSSSelector::PseudoClass']
32
33    if stringPseudoType.endswith('('):
34        stringPseudoType = stringPseudoType[:-1]
35
36    webkitPrefix = '-webkit-'
37    if (stringPseudoType.startswith(webkitPrefix)):
38        stringPseudoType = stringPseudoType[len(webkitPrefix):]
39
40    khtmlPrefix = '-khtml-'
41    if (stringPseudoType.startswith(khtmlPrefix)):
42        stringPseudoType = stringPseudoType[len(khtmlPrefix):]
43
44    substring_start = 0
45    next_dash_position = stringPseudoType.find('-')
46    while (next_dash_position != -1):
47        output.append(stringPseudoType[substring_start].upper())
48        output.append(stringPseudoType[substring_start + 1:next_dash_position])
49        substring_start = next_dash_position + 1
50        next_dash_position = stringPseudoType.find('-', substring_start)
51
52    output.append(stringPseudoType[substring_start].upper())
53    output.append(stringPseudoType[substring_start + 1:])
54    return ''.join(output)
55
56
57def expand_ifdef_condition(condition):
58    return condition.replace('(', '_').replace(')', '')
59
60output_file = open('SelectorPseudoClassAndCompatibilityElementMap.gperf', 'w')
61
62output_file.write("""
63%{
64/*
65 * Copyright (C) 2014 Apple Inc. All rights reserved.
66 *
67 * Redistribution and use in source and binary forms, with or without
68 * modification, are permitted provided that the following conditions
69 * are met:
70 * 1. Redistributions of source code must retain the above copyright
71 *    notice, this list of conditions and the following disclaimer.
72 * 2. Redistributions in binary form must reproduce the above copyright
73 *    notice, this list of conditions and the following disclaimer in the
74 *    documentation and/or other materials provided with the distribution.
75 *
76 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
77 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
78 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
79 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
80 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
81 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
82 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
83 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
84 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
85 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
86 * THE POSSIBILITY OF SUCH DAMAGE.
87 */
88
89// This file is automatically generated from SelectorPseudoTypeMap.in by makeprop, do not edit by hand.
90
91#include "config.h"
92#include "SelectorPseudoTypeMap.h"
93
94#if defined(__clang__)
95#pragma clang diagnostic push
96#pragma clang diagnostic ignored "-Wunknown-pragmas"
97#pragma clang diagnostic ignored "-Wdeprecated-register"
98#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
99#endif
100
101namespace WebCore {
102
103struct SelectorPseudoClassOrCompatibilityPseudoElementEntry {
104    const char* name;
105    PseudoClassOrCompatibilityPseudoElement pseudoTypes;
106};
107
108%}
109%struct-type
110%define initializer-suffix ,{CSSSelector::PseudoClassUnknown,CSSSelector::PseudoElementUnknown}
111%define class-name SelectorPseudoClassAndCompatibilityElementMapHash
112%omit-struct-type
113%language=C++
114%readonly-tables
115%global-table
116%ignore-case
117%compare-strncmp
118%enum
119
120struct SelectorPseudoClassOrCompatibilityPseudoElementEntry;
121
122%%
123""")
124
125webcore_defines = [i.strip() for i in sys.argv[-1].split(' ')]
126
127longest_keyword = 0
128
129ignore_until_endif = False
130input_file = open(sys.argv[1], 'r')
131for line in input_file:
132    line = line.strip()
133    if not line:
134        continue
135
136    if line.startswith('#if '):
137        condition = line[4:].strip()
138        if expand_ifdef_condition(condition) not in webcore_defines:
139            ignore_until_endif = True
140        continue
141
142    if line.startswith('#endif'):
143        ignore_until_endif = False
144        continue
145
146    if ignore_until_endif:
147        continue
148
149    keyword_definition = line.split(',')
150    if len(keyword_definition) == 1:
151        keyword = keyword_definition[0].strip()
152        output_file.write('"%s", {%s, CSSSelector::PseudoElementUnknown}\n' % (keyword, enumerablePseudoType(keyword)))
153    else:
154        output_file.write('"%s", {CSSSelector::%s, CSSSelector::%s}\n' % (keyword_definition[0].strip(), keyword_definition[1].strip(), keyword_definition[2].strip()))
155
156    longest_keyword = max(longest_keyword, len(keyword))
157
158output_file.write("""%%
159
160static inline const SelectorPseudoClassOrCompatibilityPseudoElementEntry* parsePseudoClassAndCompatibilityElementString(const LChar* characters, unsigned length)
161{
162    return SelectorPseudoClassAndCompatibilityElementMapHash::in_word_set(reinterpret_cast<const char*>(characters), length);
163}""")
164
165output_file.write("""
166
167static inline const SelectorPseudoClassOrCompatibilityPseudoElementEntry* parsePseudoClassAndCompatibilityElementString(const UChar* characters, unsigned length)
168{
169    const unsigned maxKeywordLength = %s;
170    LChar buffer[maxKeywordLength];
171    if (length > maxKeywordLength)
172        return nullptr;
173
174    for (unsigned i = 0; i < length; ++i) {
175        UChar character = characters[i];
176        if (character & ~0xff)
177            return nullptr;
178
179        buffer[i] = static_cast<LChar>(character);
180    }
181    return parsePseudoClassAndCompatibilityElementString(buffer, length);
182}
183""" % longest_keyword)
184
185output_file.write("""
186PseudoClassOrCompatibilityPseudoElement parsePseudoClassAndCompatibilityElementString(const CSSParserString& pseudoTypeString)
187{
188    const SelectorPseudoClassOrCompatibilityPseudoElementEntry* entry;
189    if (pseudoTypeString.is8Bit())
190        entry = parsePseudoClassAndCompatibilityElementString(pseudoTypeString.characters8(), pseudoTypeString.length());
191    else
192        entry = parsePseudoClassAndCompatibilityElementString(pseudoTypeString.characters16(), pseudoTypeString.length());
193
194    if (entry)
195        return entry->pseudoTypes;
196    return { CSSSelector::PseudoClassUnknown, CSSSelector::PseudoElementUnknown };
197}
198
199} // namespace WebCore
200
201#if defined(__clang__)
202#pragma clang diagnostic pop
203#endif
204
205""")
206output_file.close()
207
208gperf_command = 'gperf'
209if 'GPERF' in os.environ:
210    gperf_command = os.environ['GPERF']
211
212gperf_return = os.system("%s --key-positions='*' -m 10 -s 2 SelectorPseudoClassAndCompatibilityElementMap.gperf --output-file=SelectorPseudoClassAndCompatibilityElementMap.cpp" % gperf_command)
213if gperf_return != 0:
214    print("Error when generating SelectorPseudoClassAndCompatibilityElementMap.cpp from SelectorPseudoClassAndCompatibilityElementMap.gperf :(")
215    sys.exit(gperf_return)
216