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