michael@0: #!/usr/bin/env python michael@0: michael@0: # This Source Code Form is subject to the terms of the Mozilla Public michael@0: # License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: # file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: # This script generates nsStyleStructList.h, which contains macro invocations michael@0: # that can be used for three things: michael@0: # michael@0: # 1. To generate code for each inherited style struct. michael@0: # 2. To generate code for each reset style struct. michael@0: # 3. To generate a tree of nested if statements that can be used to run michael@0: # some code on each style struct. michael@0: # michael@0: # As an example, if we assume that we have only four style structs, the michael@0: # generated tree of nested if statements looks like this: michael@0: # michael@0: # if (STYLE_STRUCT_TEST < 4) { michael@0: # if (STYLE_STRUCT_TEST < 2) { michael@0: # if (STYLE_STRUCT_TEST == 0) { michael@0: # ... code for style struct with id 0 ... michael@0: # } else { michael@0: # ... code for style struct with id 1 ... michael@0: # } michael@0: # } else { michael@0: # if (STYLE_STRUCT_TEST == 2) { michael@0: # ... code for style struct with id 2 ... michael@0: # } else { michael@0: # ... code for style struct with id 3 ... michael@0: # } michael@0: # } michael@0: # } michael@0: # michael@0: # The TOPLEVELBRANCHES variable controls how widely we branch on the outermost michael@0: # if statement. In the example above, it splits the search space in 2, but with michael@0: # a larger number of style structs to test -- particularly when the number is michael@0: # closer to one power of two than the next higher one -- the average number of michael@0: # comparisons can be reduced by splitting the top level check into more than 2. michael@0: michael@0: import math michael@0: michael@0: # List of style structs and their corresponding Check callback functions, michael@0: # if any. michael@0: STYLE_STRUCTS = [("INHERITED",) + x for x in [ michael@0: # Inherited style structs. michael@0: ("Font", "CheckFontCallback"), michael@0: ("Color", "CheckColorCallback"), michael@0: ("List", "nullptr"), michael@0: ("Text", "CheckTextCallback"), michael@0: ("Visibility", "nullptr"), michael@0: ("Quotes", "nullptr"), michael@0: ("UserInterface", "nullptr"), michael@0: ("TableBorder", "nullptr"), michael@0: ("SVG", "nullptr"), michael@0: ("Variables", "CheckVariablesCallback"), michael@0: ]] + [("RESET",) + x for x in [ michael@0: # Reset style structs. michael@0: ("Background", "nullptr"), michael@0: ("Position", "nullptr"), michael@0: ("TextReset", "nullptr"), michael@0: ("Display", "nullptr"), michael@0: ("Content", "nullptr"), michael@0: ("UIReset", "nullptr"), michael@0: ("Table", "nullptr"), michael@0: ("Margin", "nullptr"), michael@0: ("Padding", "nullptr"), michael@0: ("Border", "nullptr"), michael@0: ("Outline", "nullptr"), michael@0: ("XUL", "nullptr"), michael@0: ("SVGReset", "nullptr"), michael@0: ("Column", "nullptr"), michael@0: ]] michael@0: michael@0: # How widely to branch on the outermost if statement. michael@0: TOPLEVELBRANCHES = 4 michael@0: michael@0: michael@0: # ---- Generate nsStyleStructList.h ---- michael@0: michael@0: count = len(STYLE_STRUCTS) michael@0: michael@0: def nextPowerOf2(x): michael@0: return int(pow(2, math.ceil(math.log(x, 2)))) michael@0: michael@0: def printEntry(i): michael@0: print "STYLE_STRUCT_%s(%s, %s)" % STYLE_STRUCTS[i] michael@0: michael@0: def printTestTree(min, max, depth, branches): michael@0: indent = " " * depth michael@0: if min == count - 1 and max >= count: michael@0: print " STYLE_STRUCT_TEST_CODE(%sNS_ASSERTION(STYLE_STRUCT_TEST == %d, \"out of range\");)" % (indent, min) michael@0: printEntry(min) michael@0: elif max - min == 2: michael@0: print " STYLE_STRUCT_TEST_CODE(%sif (STYLE_STRUCT_TEST == %d) {)" % (indent, min) michael@0: printEntry(min) michael@0: print " STYLE_STRUCT_TEST_CODE(%s} else {)" % indent michael@0: printEntry(min + 1) michael@0: print " STYLE_STRUCT_TEST_CODE(%s})" % indent michael@0: elif min < count: michael@0: mid = min + (max - min) / branches michael@0: print " STYLE_STRUCT_TEST_CODE(%sif (STYLE_STRUCT_TEST < %d) {)" % (indent, mid) michael@0: printTestTree(min, mid, depth + 1, 2) michael@0: for branch in range(1, branches): michael@0: lo = min + branch * (max - min) / branches michael@0: hi = min + (branch + 1) * (max - min) / branches michael@0: if lo >= count: michael@0: break michael@0: if branch == branches - 1 or hi >= count: michael@0: print " STYLE_STRUCT_TEST_CODE(%s} else {)" % indent michael@0: else: michael@0: print " STYLE_STRUCT_TEST_CODE(%s} else if (STYLE_STRUCT_TEST < %d) {)" % (indent, hi) michael@0: printTestTree(lo, hi, depth + 1, 2) michael@0: print " STYLE_STRUCT_TEST_CODE(%s})" % indent michael@0: michael@0: HEADER = """/* THIS FILE IS AUTOGENERATED BY generate-stylestructlist.py - DO NOT EDIT */ michael@0: michael@0: // IWYU pragma: private, include "nsStyleStructFwd.h" michael@0: michael@0: /* michael@0: * list of structs that contain the data provided by nsStyleContext, the michael@0: * internal API for computed style data for an element michael@0: */ michael@0: michael@0: /* michael@0: * This file is intended to be used by different parts of the code, with michael@0: * the STYLE_STRUCT macro (or the STYLE_STRUCT_INHERITED and michael@0: * STYLE_STRUCT_RESET pair of macros) defined in different ways. michael@0: */ michael@0: michael@0: #ifndef STYLE_STRUCT_INHERITED michael@0: #define STYLE_STRUCT_INHERITED(name, checkdata_cb) \\ michael@0: STYLE_STRUCT(name, checkdata_cb) michael@0: #define UNDEF_STYLE_STRUCT_INHERITED michael@0: #endif michael@0: michael@0: #ifndef STYLE_STRUCT_RESET michael@0: #define STYLE_STRUCT_RESET(name, checkdata_cb) \\ michael@0: STYLE_STRUCT(name, checkdata_cb) michael@0: #define UNDEF_STYLE_STRUCT_RESET michael@0: #endif michael@0: michael@0: #ifdef STYLE_STRUCT_TEST michael@0: #define STYLE_STRUCT_TEST_CODE(c) c michael@0: #else michael@0: #define STYLE_STRUCT_TEST_CODE(c) michael@0: #endif michael@0: michael@0: // The inherited structs are listed before the Reset structs. michael@0: // nsStyleStructID assumes this is the case, and callers other than michael@0: // nsStyleStructFwd.h that want the structs in id-order just define michael@0: // STYLE_STRUCT rather than including the file twice. michael@0: michael@0: """ michael@0: FOOTER = """ michael@0: #ifdef UNDEF_STYLE_STRUCT_INHERITED michael@0: #undef STYLE_STRUCT_INHERITED michael@0: #undef UNDEF_STYLE_STRUCT_INHERITED michael@0: #endif michael@0: michael@0: #ifdef UNDEF_STYLE_STRUCT_RESET michael@0: #undef STYLE_STRUCT_RESET michael@0: #undef UNDEF_STYLE_STRUCT_RESET michael@0: #endif michael@0: michael@0: #undef STYLE_STRUCT_TEST_CODE michael@0: """ michael@0: michael@0: print HEADER michael@0: printTestTree(0, nextPowerOf2(count), 0, TOPLEVELBRANCHES) michael@0: print FOOTER