1#!/usr/bin/env python
2
3# This Source Code Form is subject to the terms of the Mozilla Public
4# License, v. 2.0. If a copy of the MPL was not distributed with this
5# file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7# This script generates nsStyleStructList.h, which contains macro invocations
8# that can be used for three things:
9#
10# 1. To generate code for each inherited style struct.
11# 2. To generate code for each reset style struct.
12# 3. To generate the dependency of each style struct.
13
14from __future__ import print_function
15
16import math
17
18NORMAL_DEP = ["Variables"]
19COLOR_DEP = ["Color"]
20LENGTH_DEP = ["Font", "Visibility"]
21
22# List of style structs and their corresponding Check callback functions,
23# if any.
24STYLE_STRUCTS = [("INHERITED",) + x for x in [
25    # Inherited style structs.
26    ("Font",           "CheckFontCallback",     NORMAL_DEP + ["Visibility"]),
27    ("Color",          "CheckColorCallback",    NORMAL_DEP),
28    ("List",           "nullptr",               NORMAL_DEP + LENGTH_DEP),
29    ("Text",           "CheckTextCallback",     NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
30    ("Visibility",     "nullptr",               NORMAL_DEP),
31    ("UserInterface",  "nullptr",               NORMAL_DEP),
32    ("TableBorder",    "nullptr",               NORMAL_DEP + LENGTH_DEP),
33    ("SVG",            "nullptr",               NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
34    ("Variables",      "CheckVariablesCallback",[]),
35]] + [("RESET",) + x for x in [
36    # Reset style structs.
37    ("Background",     "nullptr",   NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
38    ("Position",       "nullptr",   NORMAL_DEP + LENGTH_DEP),
39    ("TextReset",      "nullptr",   NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
40    ("Display",        "nullptr",   NORMAL_DEP + LENGTH_DEP),
41    ("Content",        "nullptr",   NORMAL_DEP + LENGTH_DEP),
42    ("UIReset",        "nullptr",   NORMAL_DEP),
43    ("Table",          "nullptr",   NORMAL_DEP),
44    ("Margin",         "nullptr",   NORMAL_DEP + LENGTH_DEP),
45    ("Padding",        "nullptr",   NORMAL_DEP + LENGTH_DEP),
46    ("Border",         "nullptr",   NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
47    ("Outline",        "nullptr",   NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
48    ("XUL",            "nullptr",   NORMAL_DEP),
49    ("SVGReset",       "nullptr",   NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
50    ("Column",         "nullptr",   NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
51    ("Effects",        "nullptr",   NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
52]]
53
54
55# ---- Generate nsStyleStructList.h ----
56
57count = len(STYLE_STRUCTS)
58
59# Check for problems with style struct dependencies
60resolved_items = []
61# This whole loop tries to sort the style structs in topological order
62# according to the dependencies. A topological order exists iff there
63# are no cyclic dependencies between the style structs. It resolves one
64# struct each iteration, and append the resolved one to |resolved_items|.
65for i in range(count):
66    # This inner loop picks one style struct which does not have
67    # unsolved dependencies. If nothing can be picked, then we
68    # must have some cyclic dependencies.
69    for j in range(count):
70        _, name, _, dependencies = STYLE_STRUCTS[j]
71        if name in resolved_items:
72            continue
73        # Check whether all dependencies of this item have been placed
74        for dep in dependencies:
75            if dep not in resolved_items:
76                break
77        else:
78            resolved_items.append(name)
79            break
80    else:
81        import sys
82        print("ERROR: Cannot resolve style struct dependencies", file=sys.stderr)
83        print("Resolved items:", " ".join(resolved_items), file=sys.stderr)
84        unsolved_items = [name for _, name, _, _ in STYLE_STRUCTS
85                          if name not in resolved_items]
86        print("There exist cyclic dependencies between " +
87                  "the following structs:", " ".join(unsolved_items), file=sys.stderr)
88        exit(1)
89
90def printEntry(header, i):
91    print("STYLE_STRUCT_%s(%s, %s)" % STYLE_STRUCTS[i][:3], file=header)
92    for dep in STYLE_STRUCTS[i][3]:
93        print("STYLE_STRUCT_DEP(%s)" % (dep,), file=header)
94    print("STYLE_STRUCT_END()", file=header)
95
96HEADER = """/* THIS FILE IS AUTOGENERATED BY generate-stylestructlist.py - DO NOT EDIT */
97
98// IWYU pragma: private, include "nsStyleStructFwd.h"
99
100/*
101 * list of structs that contain the data provided by nsStyleContext, the
102 * internal API for computed style data for an element
103 */
104
105/*
106 * This file is intended to be used by different parts of the code, with
107 * the STYLE_STRUCT macro (or the STYLE_STRUCT_INHERITED and
108 * STYLE_STRUCT_RESET pair of macros) defined in different ways.
109 */
110
111#ifndef STYLE_STRUCT_INHERITED
112#define STYLE_STRUCT_INHERITED(name, checkdata_cb) \\
113  STYLE_STRUCT(name, checkdata_cb)
114#define UNDEF_STYLE_STRUCT_INHERITED
115#endif
116
117#ifndef STYLE_STRUCT_RESET
118#define STYLE_STRUCT_RESET(name, checkdata_cb) \\
119  STYLE_STRUCT(name, checkdata_cb)
120#define UNDEF_STYLE_STRUCT_RESET
121#endif
122
123#ifndef STYLE_STRUCT_DEP
124#define STYLE_STRUCT_DEP(dep)
125#define UNDEF_STYLE_STRUCT_DEP
126#endif
127
128#ifndef STYLE_STRUCT_END
129#define STYLE_STRUCT_END()
130#define UNDEF_STYLE_STRUCT_END
131#endif
132
133// The inherited structs are listed before the Reset structs.
134// nsStyleStructID assumes this is the case, and callers other than
135// nsStyleStructFwd.h that want the structs in id-order just define
136// STYLE_STRUCT rather than including the file twice.
137
138"""
139FOOTER = """
140#ifdef UNDEF_STYLE_STRUCT_INHERITED
141#undef STYLE_STRUCT_INHERITED
142#undef UNDEF_STYLE_STRUCT_INHERITED
143#endif
144
145#ifdef UNDEF_STYLE_STRUCT_RESET
146#undef STYLE_STRUCT_RESET
147#undef UNDEF_STYLE_STRUCT_RESET
148#endif
149
150#ifdef UNDEF_STYLE_STRUCT_DEP
151#undef STYLE_STRUCT_DEP
152#undef UNDEF_STYLE_STRUCT_DEP
153#endif
154
155#ifdef UNDEF_STYLE_STRUCT_END
156#undef STYLE_STRUCT_END
157#undef UNDEF_STYLE_STRUCT_END
158#endif
159"""
160
161def main(header):
162    print(HEADER, file=header)
163    for i in range(count):
164        printEntry(header, i)
165    print(FOOTER, file=header)
166