xref: /aosp_15_r20/external/libxml2/tools/genChRanges.py (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1*7c568831SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*7c568831SAndroid Build Coastguard Worker#
3*7c568831SAndroid Build Coastguard Worker# Portions of this script have been (shamelessly) stolen from the
4*7c568831SAndroid Build Coastguard Worker# prior work of Daniel Veillard (genUnicode.py)
5*7c568831SAndroid Build Coastguard Worker#
6*7c568831SAndroid Build Coastguard Worker# I, however, take full credit for any bugs, errors or difficulties :-)
7*7c568831SAndroid Build Coastguard Worker#
8*7c568831SAndroid Build Coastguard Worker# William Brack
9*7c568831SAndroid Build Coastguard Worker# October 2003
10*7c568831SAndroid Build Coastguard Worker#
11*7c568831SAndroid Build Coastguard Worker# 18 October 2003
12*7c568831SAndroid Build Coastguard Worker# Modified to maintain binary compatibility with previous library versions
13*7c568831SAndroid Build Coastguard Worker# by adding a suffix 'Q' ('quick') to the macro generated for the original,
14*7c568831SAndroid Build Coastguard Worker# function, and adding generation of a function (with the original name) which
15*7c568831SAndroid Build Coastguard Worker# instantiates the macro.
16*7c568831SAndroid Build Coastguard Worker#
17*7c568831SAndroid Build Coastguard Worker
18*7c568831SAndroid Build Coastguard Workerimport sys
19*7c568831SAndroid Build Coastguard Workerimport time
20*7c568831SAndroid Build Coastguard Worker
21*7c568831SAndroid Build Coastguard Worker#
22*7c568831SAndroid Build Coastguard Worker# A routine to take a list of yes/no (1, 0) values and turn it
23*7c568831SAndroid Build Coastguard Worker# into a list of ranges.  This will later be used to determine whether
24*7c568831SAndroid Build Coastguard Worker# to generate single-byte lookup tables, or inline comparisons
25*7c568831SAndroid Build Coastguard Worker#
26*7c568831SAndroid Build Coastguard Workerdef makeRange(lst):
27*7c568831SAndroid Build Coastguard Worker    ret = []
28*7c568831SAndroid Build Coastguard Worker    pos = 0
29*7c568831SAndroid Build Coastguard Worker    while pos < len(lst):
30*7c568831SAndroid Build Coastguard Worker        try:            # index generates exception if not present
31*7c568831SAndroid Build Coastguard Worker            s = lst[pos:].index(1)      # look for start of next range
32*7c568831SAndroid Build Coastguard Worker        except:
33*7c568831SAndroid Build Coastguard Worker            break                       # if no more, finished
34*7c568831SAndroid Build Coastguard Worker        pos += s                        # pointer to start of possible range
35*7c568831SAndroid Build Coastguard Worker        try:
36*7c568831SAndroid Build Coastguard Worker            e = lst[pos:].index(0)      # look for end of range
37*7c568831SAndroid Build Coastguard Worker            e += pos
38*7c568831SAndroid Build Coastguard Worker        except:                         # if no end, set to end of list
39*7c568831SAndroid Build Coastguard Worker            e = len(lst)
40*7c568831SAndroid Build Coastguard Worker        ret.append((pos, e-1))          # append range tuple to list
41*7c568831SAndroid Build Coastguard Worker        pos = e + 1                     # ready to check for next range
42*7c568831SAndroid Build Coastguard Worker    return ret
43*7c568831SAndroid Build Coastguard Worker
44*7c568831SAndroid Build Coastguard Workersources = "chvalid.def"                 # input filename
45*7c568831SAndroid Build Coastguard Worker
46*7c568831SAndroid Build Coastguard Worker# minTableSize gives the minimum number of ranges which must be present
47*7c568831SAndroid Build Coastguard Worker# before a 256-byte lookup table is produced.  If there are less than this
48*7c568831SAndroid Build Coastguard Worker# number, a macro with inline comparisons is generated
49*7c568831SAndroid Build Coastguard WorkerminTableSize = 6
50*7c568831SAndroid Build Coastguard Worker
51*7c568831SAndroid Build Coastguard Worker# dictionary of functions, key=name, element contains char-map and range-list
52*7c568831SAndroid Build Coastguard WorkerFuncts = {}
53*7c568831SAndroid Build Coastguard Worker
54*7c568831SAndroid Build Coastguard Workerstate = 0
55*7c568831SAndroid Build Coastguard Worker
56*7c568831SAndroid Build Coastguard Workertry:
57*7c568831SAndroid Build Coastguard Worker    defines = open("chvalid.def", "r")
58*7c568831SAndroid Build Coastguard Workerexcept:
59*7c568831SAndroid Build Coastguard Worker    print("Missing chvalid.def, aborting ...")
60*7c568831SAndroid Build Coastguard Worker    sys.exit(1)
61*7c568831SAndroid Build Coastguard Worker
62*7c568831SAndroid Build Coastguard Worker#
63*7c568831SAndroid Build Coastguard Worker# The lines in the .def file have three types:-
64*7c568831SAndroid Build Coastguard Worker#   name:   Defines a new function block
65*7c568831SAndroid Build Coastguard Worker#   ur:     Defines individual or ranges of unicode values
66*7c568831SAndroid Build Coastguard Worker#   end:    Indicates the end of the function block
67*7c568831SAndroid Build Coastguard Worker#
68*7c568831SAndroid Build Coastguard Worker# These lines are processed below.
69*7c568831SAndroid Build Coastguard Worker#
70*7c568831SAndroid Build Coastguard Workerfor line in defines.readlines():
71*7c568831SAndroid Build Coastguard Worker    # ignore blank lines, or lines beginning with '#'
72*7c568831SAndroid Build Coastguard Worker    if line[0] == '#':
73*7c568831SAndroid Build Coastguard Worker        continue
74*7c568831SAndroid Build Coastguard Worker    line = line.strip()
75*7c568831SAndroid Build Coastguard Worker    if line == '':
76*7c568831SAndroid Build Coastguard Worker        continue
77*7c568831SAndroid Build Coastguard Worker    # split line into space-separated fields, then split on type
78*7c568831SAndroid Build Coastguard Worker    try:
79*7c568831SAndroid Build Coastguard Worker        fields = line.split(' ')
80*7c568831SAndroid Build Coastguard Worker        #
81*7c568831SAndroid Build Coastguard Worker        # name line:
82*7c568831SAndroid Build Coastguard Worker        #   validate any previous function block already ended
83*7c568831SAndroid Build Coastguard Worker        #   validate this function not already defined
84*7c568831SAndroid Build Coastguard Worker        #   initialize an entry in the function dicitonary
85*7c568831SAndroid Build Coastguard Worker        #       including a mask table with no values yet defined
86*7c568831SAndroid Build Coastguard Worker        #
87*7c568831SAndroid Build Coastguard Worker        if fields[0] == 'name':
88*7c568831SAndroid Build Coastguard Worker            name = fields[1]
89*7c568831SAndroid Build Coastguard Worker            if state != 0:
90*7c568831SAndroid Build Coastguard Worker                print("'name' %s found before previous name" \
91*7c568831SAndroid Build Coastguard Worker                      "completed" % (fields[1]))
92*7c568831SAndroid Build Coastguard Worker                continue
93*7c568831SAndroid Build Coastguard Worker            state = 1
94*7c568831SAndroid Build Coastguard Worker            if name in Functs:
95*7c568831SAndroid Build Coastguard Worker                print("name '%s' already present - may give" \
96*7c568831SAndroid Build Coastguard Worker                      " wrong results" % (name))
97*7c568831SAndroid Build Coastguard Worker            else:
98*7c568831SAndroid Build Coastguard Worker                # dict entry with two list elements (chdata, rangedata)
99*7c568831SAndroid Build Coastguard Worker                Functs[name] = [ [], [] ]
100*7c568831SAndroid Build Coastguard Worker                for v in range(256):
101*7c568831SAndroid Build Coastguard Worker                    Functs[name][0].append(0)
102*7c568831SAndroid Build Coastguard Worker        #
103*7c568831SAndroid Build Coastguard Worker        # end line:
104*7c568831SAndroid Build Coastguard Worker        #   validate there was a preceding function name line
105*7c568831SAndroid Build Coastguard Worker        #   set state to show no current function active
106*7c568831SAndroid Build Coastguard Worker        #
107*7c568831SAndroid Build Coastguard Worker        elif fields[0] == 'end':
108*7c568831SAndroid Build Coastguard Worker            if state == 0:
109*7c568831SAndroid Build Coastguard Worker                print("'end' found outside of function block")
110*7c568831SAndroid Build Coastguard Worker                continue
111*7c568831SAndroid Build Coastguard Worker            state = 0
112*7c568831SAndroid Build Coastguard Worker
113*7c568831SAndroid Build Coastguard Worker        #
114*7c568831SAndroid Build Coastguard Worker        # ur line:
115*7c568831SAndroid Build Coastguard Worker        #   validate function has been defined
116*7c568831SAndroid Build Coastguard Worker        #   process remaining fields on the line, which may be either
117*7c568831SAndroid Build Coastguard Worker        #       individual unicode values or ranges of values
118*7c568831SAndroid Build Coastguard Worker        #
119*7c568831SAndroid Build Coastguard Worker        elif fields[0] == 'ur':
120*7c568831SAndroid Build Coastguard Worker            if state != 1:
121*7c568831SAndroid Build Coastguard Worker                raise Exception("'ur' found outside of 'name' block")
122*7c568831SAndroid Build Coastguard Worker            for el in fields[1:]:
123*7c568831SAndroid Build Coastguard Worker                pos = el.find('..')
124*7c568831SAndroid Build Coastguard Worker                # pos <=0 means not a range, so must be individual value
125*7c568831SAndroid Build Coastguard Worker                if pos <= 0:
126*7c568831SAndroid Build Coastguard Worker                    # cheap handling of hex or decimal values
127*7c568831SAndroid Build Coastguard Worker                    if el[0:2] == '0x':
128*7c568831SAndroid Build Coastguard Worker                        value = int(el[2:],16)
129*7c568831SAndroid Build Coastguard Worker                    elif el[0] == "'":
130*7c568831SAndroid Build Coastguard Worker                        value = ord(el[1])
131*7c568831SAndroid Build Coastguard Worker                    else:
132*7c568831SAndroid Build Coastguard Worker                        value = int(el)
133*7c568831SAndroid Build Coastguard Worker                    if ((value < 0) | (value > 0x1fffff)):
134*7c568831SAndroid Build Coastguard Worker                        raise Exception('Illegal value (%s) in ch for'\
135*7c568831SAndroid Build Coastguard Worker                                ' name %s' % (el,name))
136*7c568831SAndroid Build Coastguard Worker                    # for ur we have only ranges (makes things simpler),
137*7c568831SAndroid Build Coastguard Worker                    # so convert val to range
138*7c568831SAndroid Build Coastguard Worker                    currange = (value, value)
139*7c568831SAndroid Build Coastguard Worker                # pos > 0 means this is a range, so isolate/validate
140*7c568831SAndroid Build Coastguard Worker                # the interval
141*7c568831SAndroid Build Coastguard Worker                else:
142*7c568831SAndroid Build Coastguard Worker                    # split the range into it's first-val, last-val
143*7c568831SAndroid Build Coastguard Worker                    (first, last) = el.split("..")
144*7c568831SAndroid Build Coastguard Worker                    # convert values from text into binary
145*7c568831SAndroid Build Coastguard Worker                    if first[0:2] == '0x':
146*7c568831SAndroid Build Coastguard Worker                        start = int(first[2:],16)
147*7c568831SAndroid Build Coastguard Worker                    elif first[0] == "'":
148*7c568831SAndroid Build Coastguard Worker                        start = ord(first[1])
149*7c568831SAndroid Build Coastguard Worker                    else:
150*7c568831SAndroid Build Coastguard Worker                        start = int(first)
151*7c568831SAndroid Build Coastguard Worker                    if last[0:2] == '0x':
152*7c568831SAndroid Build Coastguard Worker                        end = int(last[2:],16)
153*7c568831SAndroid Build Coastguard Worker                    elif last[0] == "'":
154*7c568831SAndroid Build Coastguard Worker                        end = ord(last[1])
155*7c568831SAndroid Build Coastguard Worker                    else:
156*7c568831SAndroid Build Coastguard Worker                        end = int(last)
157*7c568831SAndroid Build Coastguard Worker                    if (start < 0) | (end > 0x1fffff) | (start > end):
158*7c568831SAndroid Build Coastguard Worker                        raise Exception("Invalid range '%s'" % el)
159*7c568831SAndroid Build Coastguard Worker                    currange = (start, end)
160*7c568831SAndroid Build Coastguard Worker                # common path - 'currange' has the range, now take care of it
161*7c568831SAndroid Build Coastguard Worker                # We split on single-byte values vs. multibyte
162*7c568831SAndroid Build Coastguard Worker                if currange[1] < 0x100: # single-byte
163*7c568831SAndroid Build Coastguard Worker                    for ch in range(currange[0],currange[1]+1):
164*7c568831SAndroid Build Coastguard Worker                        # validate that value not previously defined
165*7c568831SAndroid Build Coastguard Worker                        if Functs[name][0][ch]:
166*7c568831SAndroid Build Coastguard Worker                            msg = "Duplicate ch value '%s' for name '%s'" % (el, name)
167*7c568831SAndroid Build Coastguard Worker                            raise Exception(msg)
168*7c568831SAndroid Build Coastguard Worker                        Functs[name][0][ch] = 1
169*7c568831SAndroid Build Coastguard Worker                else:                   # multi-byte
170*7c568831SAndroid Build Coastguard Worker                    if currange in Functs[name][1]:
171*7c568831SAndroid Build Coastguard Worker                        raise Exception("range already defined in" \
172*7c568831SAndroid Build Coastguard Worker                                " function")
173*7c568831SAndroid Build Coastguard Worker                    else:
174*7c568831SAndroid Build Coastguard Worker                        Functs[name][1].append(currange)
175*7c568831SAndroid Build Coastguard Worker
176*7c568831SAndroid Build Coastguard Worker    except:
177*7c568831SAndroid Build Coastguard Worker        print("Failed to process line: %s" % (line))
178*7c568831SAndroid Build Coastguard Worker        raise
179*7c568831SAndroid Build Coastguard Worker#
180*7c568831SAndroid Build Coastguard Worker# At this point, the entire definition file has been processed.  Now we
181*7c568831SAndroid Build Coastguard Worker# enter the output phase, where we generate the two files chvalid.c and'
182*7c568831SAndroid Build Coastguard Worker# chvalid.h
183*7c568831SAndroid Build Coastguard Worker#
184*7c568831SAndroid Build Coastguard Worker# To do this, we first output the 'static' data (heading, fixed
185*7c568831SAndroid Build Coastguard Worker# definitions, etc.), then output the 'dynamic' data (the results
186*7c568831SAndroid Build Coastguard Worker# of the above processing), and finally output closing 'static' data
187*7c568831SAndroid Build Coastguard Worker# (e.g. the subroutine to process the ranges)
188*7c568831SAndroid Build Coastguard Worker#
189*7c568831SAndroid Build Coastguard Worker
190*7c568831SAndroid Build Coastguard Worker#
191*7c568831SAndroid Build Coastguard Worker# Generate the headings:
192*7c568831SAndroid Build Coastguard Worker#
193*7c568831SAndroid Build Coastguard Workertry:
194*7c568831SAndroid Build Coastguard Worker    header = open("include/libxml/chvalid.h", "w")
195*7c568831SAndroid Build Coastguard Workerexcept:
196*7c568831SAndroid Build Coastguard Worker    print("Failed to open include/libxml/chvalid.h")
197*7c568831SAndroid Build Coastguard Worker    sys.exit(1)
198*7c568831SAndroid Build Coastguard Worker
199*7c568831SAndroid Build Coastguard Workertry:
200*7c568831SAndroid Build Coastguard Worker    output = open("chvalid.c", "w")
201*7c568831SAndroid Build Coastguard Workerexcept:
202*7c568831SAndroid Build Coastguard Worker    print("Failed to open chvalid.c")
203*7c568831SAndroid Build Coastguard Worker    sys.exit(1)
204*7c568831SAndroid Build Coastguard Worker
205*7c568831SAndroid Build Coastguard Workerdate = time.asctime(time.localtime(time.time()))
206*7c568831SAndroid Build Coastguard Worker
207*7c568831SAndroid Build Coastguard Workerheader.write(
208*7c568831SAndroid Build Coastguard Worker"""/*
209*7c568831SAndroid Build Coastguard Worker * Summary: Unicode character range checking
210*7c568831SAndroid Build Coastguard Worker * Description: this module exports interfaces for the character
211*7c568831SAndroid Build Coastguard Worker *               range validation APIs
212*7c568831SAndroid Build Coastguard Worker *
213*7c568831SAndroid Build Coastguard Worker * This file is automatically generated from the cvs source
214*7c568831SAndroid Build Coastguard Worker * definition files using the genChRanges.py Python script
215*7c568831SAndroid Build Coastguard Worker *
216*7c568831SAndroid Build Coastguard Worker * Generation date: %s
217*7c568831SAndroid Build Coastguard Worker * Sources: %s
218*7c568831SAndroid Build Coastguard Worker * Author: William Brack <[email protected]>
219*7c568831SAndroid Build Coastguard Worker */
220*7c568831SAndroid Build Coastguard Worker
221*7c568831SAndroid Build Coastguard Worker#ifndef __XML_CHVALID_H__
222*7c568831SAndroid Build Coastguard Worker#define __XML_CHVALID_H__
223*7c568831SAndroid Build Coastguard Worker
224*7c568831SAndroid Build Coastguard Worker#include <libxml/xmlversion.h>
225*7c568831SAndroid Build Coastguard Worker#include <libxml/xmlstring.h>
226*7c568831SAndroid Build Coastguard Worker
227*7c568831SAndroid Build Coastguard Worker#ifdef __cplusplus
228*7c568831SAndroid Build Coastguard Workerextern "C" {
229*7c568831SAndroid Build Coastguard Worker#endif
230*7c568831SAndroid Build Coastguard Worker
231*7c568831SAndroid Build Coastguard Worker/*
232*7c568831SAndroid Build Coastguard Worker * Define our typedefs and structures
233*7c568831SAndroid Build Coastguard Worker *
234*7c568831SAndroid Build Coastguard Worker */
235*7c568831SAndroid Build Coastguard Workertypedef struct _xmlChSRange xmlChSRange;
236*7c568831SAndroid Build Coastguard Workertypedef xmlChSRange *xmlChSRangePtr;
237*7c568831SAndroid Build Coastguard Workerstruct _xmlChSRange {
238*7c568831SAndroid Build Coastguard Worker    unsigned short\tlow;
239*7c568831SAndroid Build Coastguard Worker    unsigned short\thigh;
240*7c568831SAndroid Build Coastguard Worker};
241*7c568831SAndroid Build Coastguard Worker
242*7c568831SAndroid Build Coastguard Workertypedef struct _xmlChLRange xmlChLRange;
243*7c568831SAndroid Build Coastguard Workertypedef xmlChLRange *xmlChLRangePtr;
244*7c568831SAndroid Build Coastguard Workerstruct _xmlChLRange {
245*7c568831SAndroid Build Coastguard Worker    unsigned int\tlow;
246*7c568831SAndroid Build Coastguard Worker    unsigned int\thigh;
247*7c568831SAndroid Build Coastguard Worker};
248*7c568831SAndroid Build Coastguard Worker
249*7c568831SAndroid Build Coastguard Workertypedef struct _xmlChRangeGroup xmlChRangeGroup;
250*7c568831SAndroid Build Coastguard Workertypedef xmlChRangeGroup *xmlChRangeGroupPtr;
251*7c568831SAndroid Build Coastguard Workerstruct _xmlChRangeGroup {
252*7c568831SAndroid Build Coastguard Worker    int\t\t\tnbShortRange;
253*7c568831SAndroid Build Coastguard Worker    int\t\t\tnbLongRange;
254*7c568831SAndroid Build Coastguard Worker    const xmlChSRange\t*shortRange;\t/* points to an array of ranges */
255*7c568831SAndroid Build Coastguard Worker    const xmlChLRange\t*longRange;
256*7c568831SAndroid Build Coastguard Worker};
257*7c568831SAndroid Build Coastguard Worker
258*7c568831SAndroid Build Coastguard Worker/**
259*7c568831SAndroid Build Coastguard Worker * Range checking routine
260*7c568831SAndroid Build Coastguard Worker */
261*7c568831SAndroid Build Coastguard WorkerXMLPUBFUN int
262*7c568831SAndroid Build Coastguard Worker\t\txmlCharInRange(unsigned int val, const xmlChRangeGroup *group);
263*7c568831SAndroid Build Coastguard Worker
264*7c568831SAndroid Build Coastguard Worker""" % (date, sources));
265*7c568831SAndroid Build Coastguard Workeroutput.write(
266*7c568831SAndroid Build Coastguard Worker"""/*
267*7c568831SAndroid Build Coastguard Worker * chvalid.c:\tthis module implements the character range
268*7c568831SAndroid Build Coastguard Worker *\t\tvalidation APIs
269*7c568831SAndroid Build Coastguard Worker *
270*7c568831SAndroid Build Coastguard Worker * This file is automatically generated from the cvs source
271*7c568831SAndroid Build Coastguard Worker * definition files using the genChRanges.py Python script
272*7c568831SAndroid Build Coastguard Worker *
273*7c568831SAndroid Build Coastguard Worker * Generation date: %s
274*7c568831SAndroid Build Coastguard Worker * Sources: %s
275*7c568831SAndroid Build Coastguard Worker * William Brack <[email protected]>
276*7c568831SAndroid Build Coastguard Worker */
277*7c568831SAndroid Build Coastguard Worker
278*7c568831SAndroid Build Coastguard Worker#define IN_LIBXML
279*7c568831SAndroid Build Coastguard Worker#include "libxml.h"
280*7c568831SAndroid Build Coastguard Worker#include <libxml/chvalid.h>
281*7c568831SAndroid Build Coastguard Worker
282*7c568831SAndroid Build Coastguard Worker#include <stddef.h>
283*7c568831SAndroid Build Coastguard Worker
284*7c568831SAndroid Build Coastguard Worker/*
285*7c568831SAndroid Build Coastguard Worker * The initial tables ({func_name}_tab) are used to validate whether a
286*7c568831SAndroid Build Coastguard Worker * single-byte character is within the specified group.  Each table
287*7c568831SAndroid Build Coastguard Worker * contains 256 bytes, with each byte representing one of the 256
288*7c568831SAndroid Build Coastguard Worker * possible characters.  If the table byte is set, the character is
289*7c568831SAndroid Build Coastguard Worker * allowed.
290*7c568831SAndroid Build Coastguard Worker *
291*7c568831SAndroid Build Coastguard Worker */
292*7c568831SAndroid Build Coastguard Worker""" % (date, sources));
293*7c568831SAndroid Build Coastguard Worker
294*7c568831SAndroid Build Coastguard Worker#
295*7c568831SAndroid Build Coastguard Worker# Now output the generated data.
296*7c568831SAndroid Build Coastguard Worker# We try to produce the best execution times.  Tests have shown that validation
297*7c568831SAndroid Build Coastguard Worker# with direct table lookup is, when there are a "small" number of valid items,
298*7c568831SAndroid Build Coastguard Worker# still not as fast as a sequence of inline compares.  So, if the single-byte
299*7c568831SAndroid Build Coastguard Worker# portion of a range has a "small" number of ranges, we output a macro for inline
300*7c568831SAndroid Build Coastguard Worker# compares, otherwise we output a 256-byte table and a macro to use it.
301*7c568831SAndroid Build Coastguard Worker#
302*7c568831SAndroid Build Coastguard Worker
303*7c568831SAndroid Build Coastguard Workerfkeys = sorted(Functs.keys())
304*7c568831SAndroid Build Coastguard Worker
305*7c568831SAndroid Build Coastguard Workerfor f in fkeys:
306*7c568831SAndroid Build Coastguard Worker
307*7c568831SAndroid Build Coastguard Worker# First we convert the specified single-byte values into a group of ranges.
308*7c568831SAndroid Build Coastguard Worker# If the total number of such ranges is less than minTableSize, we generate
309*7c568831SAndroid Build Coastguard Worker# an inline macro for direct comparisons; if greater, we generate a lookup
310*7c568831SAndroid Build Coastguard Worker# table.
311*7c568831SAndroid Build Coastguard Worker    if max(Functs[f][0]) > 0:   # only check if at least one entry
312*7c568831SAndroid Build Coastguard Worker        rangeTable = makeRange(Functs[f][0])
313*7c568831SAndroid Build Coastguard Worker        numRanges = len(rangeTable)
314*7c568831SAndroid Build Coastguard Worker        if numRanges >= minTableSize:   # table is worthwhile
315*7c568831SAndroid Build Coastguard Worker            header.write("XMLPUBVAR const unsigned char %s_tab[256];\n" % f)
316*7c568831SAndroid Build Coastguard Worker            header.write("""
317*7c568831SAndroid Build Coastguard Worker/**
318*7c568831SAndroid Build Coastguard Worker * %s_ch:
319*7c568831SAndroid Build Coastguard Worker * @c: char to validate
320*7c568831SAndroid Build Coastguard Worker *
321*7c568831SAndroid Build Coastguard Worker * Automatically generated by genChRanges.py
322*7c568831SAndroid Build Coastguard Worker */
323*7c568831SAndroid Build Coastguard Worker""" % f)
324*7c568831SAndroid Build Coastguard Worker            header.write("#define %s_ch(c)\t(%s_tab[(c)])\n" % (f, f))
325*7c568831SAndroid Build Coastguard Worker
326*7c568831SAndroid Build Coastguard Worker            # write the constant data to the code file
327*7c568831SAndroid Build Coastguard Worker            output.write("const unsigned char %s_tab[256] = {\n" % f)
328*7c568831SAndroid Build Coastguard Worker            pline = "   "
329*7c568831SAndroid Build Coastguard Worker            for n in range(255):
330*7c568831SAndroid Build Coastguard Worker                pline += " 0x%02x," % Functs[f][0][n]
331*7c568831SAndroid Build Coastguard Worker                if len(pline) > 72:
332*7c568831SAndroid Build Coastguard Worker                    output.write(pline + "\n")
333*7c568831SAndroid Build Coastguard Worker                    pline = "   "
334*7c568831SAndroid Build Coastguard Worker            output.write(pline + " 0x%02x };\n\n" % Functs[f][0][255])
335*7c568831SAndroid Build Coastguard Worker
336*7c568831SAndroid Build Coastguard Worker        else:           # inline check is used
337*7c568831SAndroid Build Coastguard Worker            # first another little optimisation - if space is present,
338*7c568831SAndroid Build Coastguard Worker            # put it at the front of the list so it is checked first
339*7c568831SAndroid Build Coastguard Worker            try:
340*7c568831SAndroid Build Coastguard Worker                ix = rangeTable.remove((0x20, 0x20))
341*7c568831SAndroid Build Coastguard Worker                rangeTable.insert(0, (0x20, 0x20))
342*7c568831SAndroid Build Coastguard Worker            except:
343*7c568831SAndroid Build Coastguard Worker                pass
344*7c568831SAndroid Build Coastguard Worker            firstFlag = 1
345*7c568831SAndroid Build Coastguard Worker
346*7c568831SAndroid Build Coastguard Worker            header.write("""
347*7c568831SAndroid Build Coastguard Worker/**
348*7c568831SAndroid Build Coastguard Worker * %s_ch:
349*7c568831SAndroid Build Coastguard Worker * @c: char to validate
350*7c568831SAndroid Build Coastguard Worker *
351*7c568831SAndroid Build Coastguard Worker * Automatically generated by genChRanges.py
352*7c568831SAndroid Build Coastguard Worker */
353*7c568831SAndroid Build Coastguard Worker""" % f)
354*7c568831SAndroid Build Coastguard Worker            # okay, I'm tired of the messy lineup - let's automate it!
355*7c568831SAndroid Build Coastguard Worker            pline = "#define %s_ch(c)" % f
356*7c568831SAndroid Build Coastguard Worker            # 'ntab' is number of tabs needed to position to col. 33 from name end
357*7c568831SAndroid Build Coastguard Worker            ntab = 4 - (len(pline)) // 8
358*7c568831SAndroid Build Coastguard Worker            if ntab < 0:
359*7c568831SAndroid Build Coastguard Worker                ntab = 0
360*7c568831SAndroid Build Coastguard Worker            just = ""
361*7c568831SAndroid Build Coastguard Worker            for i in range(ntab):
362*7c568831SAndroid Build Coastguard Worker                just += "\t"
363*7c568831SAndroid Build Coastguard Worker            pline = pline + just + "("
364*7c568831SAndroid Build Coastguard Worker            for rg in rangeTable:
365*7c568831SAndroid Build Coastguard Worker                if not firstFlag:
366*7c568831SAndroid Build Coastguard Worker                    pline += " || \\\n\t\t\t\t "
367*7c568831SAndroid Build Coastguard Worker                else:
368*7c568831SAndroid Build Coastguard Worker                    firstFlag = 0
369*7c568831SAndroid Build Coastguard Worker                if rg[0] == rg[1]:              # single value - check equal
370*7c568831SAndroid Build Coastguard Worker                    pline += "((c) == 0x%x)" % rg[0]
371*7c568831SAndroid Build Coastguard Worker                else:                           # value range
372*7c568831SAndroid Build Coastguard Worker                # since we are doing char, also change range ending in 0xff
373*7c568831SAndroid Build Coastguard Worker                    if rg[1] != 0xff:
374*7c568831SAndroid Build Coastguard Worker                        pline += "((0x%x <= (c)) &&" % rg[0]
375*7c568831SAndroid Build Coastguard Worker                        pline += " ((c) <= 0x%x))" % rg[1]
376*7c568831SAndroid Build Coastguard Worker                    else:
377*7c568831SAndroid Build Coastguard Worker                        pline += " (0x%x <= (c))" % rg[0]
378*7c568831SAndroid Build Coastguard Worker            pline += ")\n"
379*7c568831SAndroid Build Coastguard Worker            header.write(pline)
380*7c568831SAndroid Build Coastguard Worker
381*7c568831SAndroid Build Coastguard Worker    header.write("""
382*7c568831SAndroid Build Coastguard Worker/**
383*7c568831SAndroid Build Coastguard Worker * %sQ:
384*7c568831SAndroid Build Coastguard Worker * @c: char to validate
385*7c568831SAndroid Build Coastguard Worker *
386*7c568831SAndroid Build Coastguard Worker * Automatically generated by genChRanges.py
387*7c568831SAndroid Build Coastguard Worker */
388*7c568831SAndroid Build Coastguard Worker""" % f)
389*7c568831SAndroid Build Coastguard Worker    pline = "#define %sQ(c)" % f
390*7c568831SAndroid Build Coastguard Worker    ntab = 4 - (len(pline)) // 8
391*7c568831SAndroid Build Coastguard Worker    if ntab < 0:
392*7c568831SAndroid Build Coastguard Worker        ntab = 0
393*7c568831SAndroid Build Coastguard Worker    just = ""
394*7c568831SAndroid Build Coastguard Worker    for i in range(ntab):
395*7c568831SAndroid Build Coastguard Worker        just += "\t"
396*7c568831SAndroid Build Coastguard Worker    header.write(pline + just + "(((c) < 0x100) ? \\\n\t\t\t\t ")
397*7c568831SAndroid Build Coastguard Worker    if max(Functs[f][0]) > 0:
398*7c568831SAndroid Build Coastguard Worker        header.write("%s_ch((c)) :" % f)
399*7c568831SAndroid Build Coastguard Worker    else:
400*7c568831SAndroid Build Coastguard Worker        header.write("0 :")
401*7c568831SAndroid Build Coastguard Worker
402*7c568831SAndroid Build Coastguard Worker    # if no ranges defined, value invalid if >= 0x100
403*7c568831SAndroid Build Coastguard Worker    numRanges = len(Functs[f][1])
404*7c568831SAndroid Build Coastguard Worker    if numRanges == 0:
405*7c568831SAndroid Build Coastguard Worker        header.write(" 0)\n\n")
406*7c568831SAndroid Build Coastguard Worker    else:
407*7c568831SAndroid Build Coastguard Worker        if numRanges >= minTableSize:
408*7c568831SAndroid Build Coastguard Worker            header.write(" \\\n\t\t\t\t xmlCharInRange((c), &%sGroup))\n\n"  % f)
409*7c568831SAndroid Build Coastguard Worker        else:           # if < minTableSize, generate inline code
410*7c568831SAndroid Build Coastguard Worker            firstFlag = 1
411*7c568831SAndroid Build Coastguard Worker            for rg in Functs[f][1]:
412*7c568831SAndroid Build Coastguard Worker                if not firstFlag:
413*7c568831SAndroid Build Coastguard Worker                    pline += " || \\\n\t\t\t\t "
414*7c568831SAndroid Build Coastguard Worker                else:
415*7c568831SAndroid Build Coastguard Worker                    firstFlag = 0
416*7c568831SAndroid Build Coastguard Worker                    pline = "\\\n\t\t\t\t("
417*7c568831SAndroid Build Coastguard Worker                if rg[0] == rg[1]:              # single value - check equal
418*7c568831SAndroid Build Coastguard Worker                    pline += "((c) == 0x%x)" % rg[0]
419*7c568831SAndroid Build Coastguard Worker                else:                           # value range
420*7c568831SAndroid Build Coastguard Worker                    pline += "((0x%x <= (c)) &&" % rg[0]
421*7c568831SAndroid Build Coastguard Worker                    pline += " ((c) <= 0x%x))" % rg[1]
422*7c568831SAndroid Build Coastguard Worker            pline += "))\n\n"
423*7c568831SAndroid Build Coastguard Worker            header.write(pline)
424*7c568831SAndroid Build Coastguard Worker
425*7c568831SAndroid Build Coastguard Worker
426*7c568831SAndroid Build Coastguard Worker    if len(Functs[f][1]) > 0:
427*7c568831SAndroid Build Coastguard Worker        header.write("XMLPUBVAR const xmlChRangeGroup %sGroup;\n" % f)
428*7c568831SAndroid Build Coastguard Worker
429*7c568831SAndroid Build Coastguard Worker
430*7c568831SAndroid Build Coastguard Worker#
431*7c568831SAndroid Build Coastguard Worker# Next we do the unicode ranges
432*7c568831SAndroid Build Coastguard Worker#
433*7c568831SAndroid Build Coastguard Worker
434*7c568831SAndroid Build Coastguard Workerfor f in fkeys:
435*7c568831SAndroid Build Coastguard Worker    if len(Functs[f][1]) > 0:   # only generate if unicode ranges present
436*7c568831SAndroid Build Coastguard Worker        rangeTable = Functs[f][1]
437*7c568831SAndroid Build Coastguard Worker        rangeTable.sort()       # ascending tuple sequence
438*7c568831SAndroid Build Coastguard Worker        numShort = 0
439*7c568831SAndroid Build Coastguard Worker        numLong  = 0
440*7c568831SAndroid Build Coastguard Worker        for rg in rangeTable:
441*7c568831SAndroid Build Coastguard Worker            if rg[1] < 0x10000: # if short value
442*7c568831SAndroid Build Coastguard Worker                if numShort == 0:       # first occurrence
443*7c568831SAndroid Build Coastguard Worker                    pline = "static const xmlChSRange %s_srng[] = {" % f
444*7c568831SAndroid Build Coastguard Worker                else:
445*7c568831SAndroid Build Coastguard Worker                    pline += ","
446*7c568831SAndroid Build Coastguard Worker                numShort += 1
447*7c568831SAndroid Build Coastguard Worker                if len(pline) > 60:
448*7c568831SAndroid Build Coastguard Worker                    output.write(pline + "\n")
449*7c568831SAndroid Build Coastguard Worker                    pline = "    "
450*7c568831SAndroid Build Coastguard Worker                else:
451*7c568831SAndroid Build Coastguard Worker                    pline += " "
452*7c568831SAndroid Build Coastguard Worker                pline += "{0x%x, 0x%x}" % (rg[0], rg[1])
453*7c568831SAndroid Build Coastguard Worker            else:               # if long value
454*7c568831SAndroid Build Coastguard Worker                if numLong == 0:        # first occurrence
455*7c568831SAndroid Build Coastguard Worker                    if numShort > 0:    # if there were shorts, finish them off
456*7c568831SAndroid Build Coastguard Worker                        output.write(pline + "};\n")
457*7c568831SAndroid Build Coastguard Worker                    pline = "static const xmlChLRange %s_lrng[] = { " % f
458*7c568831SAndroid Build Coastguard Worker                else:
459*7c568831SAndroid Build Coastguard Worker                    pline += ", "
460*7c568831SAndroid Build Coastguard Worker                numLong += 1
461*7c568831SAndroid Build Coastguard Worker                if len(pline) > 60:
462*7c568831SAndroid Build Coastguard Worker                    output.write(pline + "\n")
463*7c568831SAndroid Build Coastguard Worker                    pline = "    "
464*7c568831SAndroid Build Coastguard Worker                pline += "{0x%x, 0x%x}" % (rg[0], rg[1])
465*7c568831SAndroid Build Coastguard Worker        output.write(pline + "};\n")    # finish off last group
466*7c568831SAndroid Build Coastguard Worker
467*7c568831SAndroid Build Coastguard Worker        pline = "const xmlChRangeGroup %sGroup =\n\t{%d, %d, " % (f, numShort, numLong)
468*7c568831SAndroid Build Coastguard Worker        if numShort > 0:
469*7c568831SAndroid Build Coastguard Worker            pline += "%s_srng" % f
470*7c568831SAndroid Build Coastguard Worker        else:
471*7c568831SAndroid Build Coastguard Worker            pline += "(xmlChSRangePtr)0"
472*7c568831SAndroid Build Coastguard Worker        if numLong > 0:
473*7c568831SAndroid Build Coastguard Worker            pline += ", %s_lrng" % f
474*7c568831SAndroid Build Coastguard Worker        else:
475*7c568831SAndroid Build Coastguard Worker            pline += ", (xmlChLRangePtr)0"
476*7c568831SAndroid Build Coastguard Worker
477*7c568831SAndroid Build Coastguard Worker        output.write(pline + "};\n\n")
478*7c568831SAndroid Build Coastguard Worker
479*7c568831SAndroid Build Coastguard Workeroutput.write(
480*7c568831SAndroid Build Coastguard Worker"""
481*7c568831SAndroid Build Coastguard Worker/**
482*7c568831SAndroid Build Coastguard Worker * xmlCharInRange:
483*7c568831SAndroid Build Coastguard Worker * @val: character to be validated
484*7c568831SAndroid Build Coastguard Worker * @rptr: pointer to range to be used to validate
485*7c568831SAndroid Build Coastguard Worker *
486*7c568831SAndroid Build Coastguard Worker * Does a binary search of the range table to determine if char
487*7c568831SAndroid Build Coastguard Worker * is valid
488*7c568831SAndroid Build Coastguard Worker *
489*7c568831SAndroid Build Coastguard Worker * Returns: true if character valid, false otherwise
490*7c568831SAndroid Build Coastguard Worker */
491*7c568831SAndroid Build Coastguard Workerint
492*7c568831SAndroid Build Coastguard WorkerxmlCharInRange (unsigned int val, const xmlChRangeGroup *rptr) {
493*7c568831SAndroid Build Coastguard Worker    int low, high, mid;
494*7c568831SAndroid Build Coastguard Worker    const xmlChSRange *sptr;
495*7c568831SAndroid Build Coastguard Worker    const xmlChLRange *lptr;
496*7c568831SAndroid Build Coastguard Worker
497*7c568831SAndroid Build Coastguard Worker    if (rptr == NULL) return(0);
498*7c568831SAndroid Build Coastguard Worker    if (val < 0x10000) {\t/* is val in 'short' or 'long'  array? */
499*7c568831SAndroid Build Coastguard Worker\tif (rptr->nbShortRange == 0)
500*7c568831SAndroid Build Coastguard Worker\t    return 0;
501*7c568831SAndroid Build Coastguard Worker\tlow = 0;
502*7c568831SAndroid Build Coastguard Worker\thigh = rptr->nbShortRange - 1;
503*7c568831SAndroid Build Coastguard Worker\tsptr = rptr->shortRange;
504*7c568831SAndroid Build Coastguard Worker\twhile (low <= high) {
505*7c568831SAndroid Build Coastguard Worker\t    mid = (low + high) / 2;
506*7c568831SAndroid Build Coastguard Worker\t    if ((unsigned short) val < sptr[mid].low) {
507*7c568831SAndroid Build Coastguard Worker\t\thigh = mid - 1;
508*7c568831SAndroid Build Coastguard Worker\t    } else {
509*7c568831SAndroid Build Coastguard Worker\t\tif ((unsigned short) val > sptr[mid].high) {
510*7c568831SAndroid Build Coastguard Worker\t\t    low = mid + 1;
511*7c568831SAndroid Build Coastguard Worker\t\t} else {
512*7c568831SAndroid Build Coastguard Worker\t\t    return 1;
513*7c568831SAndroid Build Coastguard Worker\t\t}
514*7c568831SAndroid Build Coastguard Worker\t    }
515*7c568831SAndroid Build Coastguard Worker\t}
516*7c568831SAndroid Build Coastguard Worker    } else {
517*7c568831SAndroid Build Coastguard Worker\tif (rptr->nbLongRange == 0) {
518*7c568831SAndroid Build Coastguard Worker\t    return 0;
519*7c568831SAndroid Build Coastguard Worker\t}
520*7c568831SAndroid Build Coastguard Worker\tlow = 0;
521*7c568831SAndroid Build Coastguard Worker\thigh = rptr->nbLongRange - 1;
522*7c568831SAndroid Build Coastguard Worker\tlptr = rptr->longRange;
523*7c568831SAndroid Build Coastguard Worker\twhile (low <= high) {
524*7c568831SAndroid Build Coastguard Worker\t    mid = (low + high) / 2;
525*7c568831SAndroid Build Coastguard Worker\t    if (val < lptr[mid].low) {
526*7c568831SAndroid Build Coastguard Worker\t\thigh = mid - 1;
527*7c568831SAndroid Build Coastguard Worker\t    } else {
528*7c568831SAndroid Build Coastguard Worker\t\tif (val > lptr[mid].high) {
529*7c568831SAndroid Build Coastguard Worker\t\t    low = mid + 1;
530*7c568831SAndroid Build Coastguard Worker\t\t} else {
531*7c568831SAndroid Build Coastguard Worker\t\t    return 1;
532*7c568831SAndroid Build Coastguard Worker\t\t}
533*7c568831SAndroid Build Coastguard Worker\t    }
534*7c568831SAndroid Build Coastguard Worker\t}
535*7c568831SAndroid Build Coastguard Worker    }
536*7c568831SAndroid Build Coastguard Worker    return 0;
537*7c568831SAndroid Build Coastguard Worker}
538*7c568831SAndroid Build Coastguard Worker
539*7c568831SAndroid Build Coastguard Worker""");
540*7c568831SAndroid Build Coastguard Worker
541*7c568831SAndroid Build Coastguard Worker#
542*7c568831SAndroid Build Coastguard Worker# finally, generate the ABI compatibility functions
543*7c568831SAndroid Build Coastguard Worker#
544*7c568831SAndroid Build Coastguard Workerfor f in fkeys:
545*7c568831SAndroid Build Coastguard Worker    output.write("""
546*7c568831SAndroid Build Coastguard Worker/**
547*7c568831SAndroid Build Coastguard Worker * %s:
548*7c568831SAndroid Build Coastguard Worker * @ch:  character to validate
549*7c568831SAndroid Build Coastguard Worker *
550*7c568831SAndroid Build Coastguard Worker * This function is DEPRECATED.
551*7c568831SAndroid Build Coastguard Worker""" % f);
552*7c568831SAndroid Build Coastguard Worker    if max(Functs[f][0]) > 0:
553*7c568831SAndroid Build Coastguard Worker        output.write(" * Use %s_ch or %sQ instead" % (f, f))
554*7c568831SAndroid Build Coastguard Worker    else:
555*7c568831SAndroid Build Coastguard Worker        output.write(" * Use %sQ instead" % f)
556*7c568831SAndroid Build Coastguard Worker    output.write("""
557*7c568831SAndroid Build Coastguard Worker *
558*7c568831SAndroid Build Coastguard Worker * Returns true if argument valid, false otherwise
559*7c568831SAndroid Build Coastguard Worker */
560*7c568831SAndroid Build Coastguard Worker""")
561*7c568831SAndroid Build Coastguard Worker    output.write("int\n%s(unsigned int ch) {\n    return(%sQ(ch));\n}\n\n" % (f,f))
562*7c568831SAndroid Build Coastguard Worker    header.write("XMLPUBFUN int\n\t\t%s(unsigned int ch);\n" % f);
563*7c568831SAndroid Build Coastguard Worker#
564*7c568831SAndroid Build Coastguard Worker# Run complete - write trailers and close the output files
565*7c568831SAndroid Build Coastguard Worker#
566*7c568831SAndroid Build Coastguard Worker
567*7c568831SAndroid Build Coastguard Workerheader.write("""
568*7c568831SAndroid Build Coastguard Worker#ifdef __cplusplus
569*7c568831SAndroid Build Coastguard Worker}
570*7c568831SAndroid Build Coastguard Worker#endif
571*7c568831SAndroid Build Coastguard Worker#endif /* __XML_CHVALID_H__ */
572*7c568831SAndroid Build Coastguard Worker""")
573*7c568831SAndroid Build Coastguard Worker
574*7c568831SAndroid Build Coastguard Workerheader.close()
575*7c568831SAndroid Build Coastguard Worker
576*7c568831SAndroid Build Coastguard Workeroutput.close()
577*7c568831SAndroid Build Coastguard Worker
578