1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2017 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "bookmaker.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOSPath.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic size_t count_indent(const string& text, size_t test, size_t end) {
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t result = test;
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (test < end) {
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (' ' != text[test]) {
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ++test;
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return test - result;
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void add_code(const string& text, int pos, int end,
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t outIndent, size_t textIndent, string& example) {
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot         // fix this to move whole paragraph in, out, but preserve doc indent
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int nextIndent = count_indent(text, pos, end);
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t len = text.find('\n', pos);
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (string::npos == len) {
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            len = end;
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if ((size_t) (pos + nextIndent) < len) {
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            size_t indent = outIndent + nextIndent;
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(indent >= textIndent);
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            indent -= textIndent;
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (size_t index = 0; index < indent; ++index) {
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                example += ' ';
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            pos += nextIndent;
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            while ((size_t) pos < len) {
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                example += '"' == text[pos] ? "\\\"" :
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    '\\' == text[pos] ? "\\\\" :
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    text.substr(pos, 1);
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                ++pos;
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "\\n";
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            pos += nextIndent;
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if ('\n' == text[pos]) {
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ++pos;
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (pos < end);
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef CONST
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef CONST
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef FRIEND
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef FRIEND
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef BLANK
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef BLANK
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef ANY
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef ANY
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef DEFOP
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef DEFOP
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define CONST 1
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define STATIC 2
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define BLANK  0
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define ANY -1
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define DEFOP Definition::Operator
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum class OpType : int8_t {
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kNone,
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kVoid,
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kBool,
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kChar,
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kFloat,
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kInt,
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kScalar,
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kSizeT,
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kThis,
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kAny,
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum class OpMod : int8_t {
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kNone,
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kArray,
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kMove,
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kPointer,
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kReference,
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kAny,
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst struct OperatorParser {
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    DEFOP fOperator;
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* fSymbol;
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* fName;
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int8_t fFriend;
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    OpType fReturnType;
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    OpMod fReturnMod;
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int8_t fConstMethod;
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct Param {
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int8_t fConst;
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        OpType fType;
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        OpMod fMod;
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } fParams[2];
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} opData[] = {
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kUnknown, "??", "???",    BLANK,  OpType::kNone,   OpMod::kNone,         BLANK,
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    { } },
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kAdd,     "+",  "add",    BLANK,  OpType::kThis,   OpMod::kNone,         BLANK,
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, },
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     { CONST,  OpType::kThis,   OpMod::kReference, }}},
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kAddTo,   "+=", "addto",  BLANK,  OpType::kVoid,   OpMod::kNone,         BLANK,
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, }}},
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kAddTo,   "+=", "addto1", BLANK,  OpType::kThis,   OpMod::kReference,    BLANK,
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, }}},
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kAddTo,   "+=", "addto2", BLANK,  OpType::kThis,   OpMod::kReference,    BLANK,
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kChar,   OpMod::kArray, }}},
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kAddTo,   "+=", "addto3", BLANK,  OpType::kThis,   OpMod::kReference,    BLANK,
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kChar,   OpMod::kNone, }}},
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kArray,   "[]", "array",  BLANK,  OpType::kScalar, OpMod::kNone,         CONST,
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ BLANK,  OpType::kInt,    OpMod::kNone, }}},
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kArray,   "[]", "array1", BLANK,  OpType::kScalar, OpMod::kReference,    BLANK,
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ BLANK,  OpType::kInt,    OpMod::kNone, }}},
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kArray,   "[]", "array2", BLANK,  OpType::kChar,   OpMod::kNone,         CONST,
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ BLANK,  OpType::kSizeT,  OpMod::kNone, }}},
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kArray,   "[]", "array3", BLANK,  OpType::kChar,   OpMod::kReference,    BLANK,
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ BLANK,  OpType::kSizeT,  OpMod::kNone, }}},
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kCast,    "()", "cast",   BLANK,  OpType::kAny,    OpMod::kAny,          ANY,
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ ANY,    OpType::kAny,    OpMod::kAny,  }}},
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kCopy,    "=",  "copy",   BLANK,  OpType::kThis,   OpMod::kReference,    BLANK,
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, }}},
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kCopy,    "=",  "copy1",  BLANK,  OpType::kThis,   OpMod::kReference,    BLANK,
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kChar,   OpMod::kArray, }}},
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kDelete,  "delete", "delete",  BLANK,  OpType::kVoid,   OpMod::kNone,    BLANK,
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ BLANK,  OpType::kVoid,   OpMod::kPointer, }}},
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kDereference, "->", "deref",  ANY,  OpType::kThis, OpMod::kPointer,      CONST,
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    { } },
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kDereference, "*", "deref", BLANK,  OpType::kThis, OpMod::kReference,    CONST,
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    { } },
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kEqual,   "==", "equal",  BLANK,  OpType::kBool,   OpMod::kNone,         BLANK,
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, },
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     { CONST,  OpType::kThis,   OpMod::kReference, }}},
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kEqual,   "==", "equal1",  BLANK,  OpType::kBool,   OpMod::kNone,         CONST,
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, }}},
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kEqual,   "==", "equal2", ANY,    OpType::kBool,   OpMod::kNone,         BLANK,
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, },
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     { CONST,  OpType::kThis,   OpMod::kReference, }}},
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kMinus,   "-",  "minus",  BLANK,  OpType::kThis,   OpMod::kNone,         CONST,
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    { } },
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kMove,    "=",  "move",   BLANK,  OpType::kThis,   OpMod::kReference,    BLANK,
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ BLANK,  OpType::kThis,   OpMod::kMove, }}},
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kMultiply, "*", "multiply", BLANK, OpType::kThis, OpMod::kNone,         CONST,
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ BLANK,  OpType::kScalar, OpMod::kNone, }}},
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kMultiply, "*", "multiply1", BLANK, OpType::kThis, OpMod::kNone,         BLANK,
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, },
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     { CONST,  OpType::kThis,   OpMod::kReference, }}},
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kMultiplyBy, "*=", "multiplyby", BLANK,  OpType::kThis, OpMod::kReference, BLANK,
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ BLANK,  OpType::kScalar, OpMod::kNone, }}},
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kNew,     "new", "new",   BLANK,  OpType::kVoid,   OpMod::kPointer,      BLANK,
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ BLANK,  OpType::kSizeT,  OpMod::kNone, }}},
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kNotEqual, "!=", "notequal", BLANK, OpType::kBool,   OpMod::kNone,      BLANK,
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, },
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     { CONST,  OpType::kThis,   OpMod::kReference, }}},
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kNotEqual, "!=", "notequal1", BLANK,  OpType::kBool,   OpMod::kNone,     CONST,
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, }}},
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kNotEqual, "!=", "notequal2", ANY, OpType::kBool,   OpMod::kNone,     BLANK,
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, },
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     { CONST,  OpType::kThis,   OpMod::kReference, }}},
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kSubtract, "-", "subtract", BLANK, OpType::kThis, OpMod::kNone,         BLANK,
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, },
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     { CONST,  OpType::kThis,   OpMod::kReference, }}},
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { DEFOP::kSubtractFrom, "-=", "subtractfrom",  BLANK,  OpType::kVoid,   OpMod::kNone, BLANK,
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                    {{ CONST,  OpType::kThis,   OpMod::kReference, }}},
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotOpType lookup_type(const string& typeWord, const string& name) {
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (typeWord == name || (typeWord == "SkIVector" && name == "SkIPoint")
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         || (typeWord == "SkVector" && name == "SkPoint")) {
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return OpType::kThis;
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* keyWords[] = { "void", "bool", "char", "float", "int", "SkScalar", "size_t" };
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (unsigned i = 0; i < SK_ARRAY_COUNT(keyWords); ++i) {
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (typeWord == keyWords[i]) {
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return (OpType) (i + 1);
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return OpType::kNone;
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotOpMod lookup_mod(TextParser& iParser) {
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    OpMod mod = OpMod::kNone;
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if ('&' == iParser.peek()) {
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        mod = OpMod::kReference;
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        iParser.next();
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if ('&' == iParser.peek()) {
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            mod = OpMod::kMove;
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            iParser.next();
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if ('*' == iParser.peek()) {
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        mod = OpMod::kPointer;
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        iParser.next();
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipWhiteSpace();
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return mod;
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::parseOperator(size_t doubleColons, string& result) {
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char operatorStr[] = "operator";
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t opPos = fName.find(operatorStr, doubleColons);
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (string::npos == opPos) {
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string className(fName, 0, doubleColons - 2);
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser iParser(fFileName, fStart, fContentStart, fLineCount);
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAssertResult(iParser.skipWord("#Method"));
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipExact("SK_API");
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipWhiteSpace();
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool isStatic = iParser.skipExact("static");
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipWhiteSpace();
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipExact("SK_API");
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipWhiteSpace();
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool returnsConst = iParser.skipExact("const");
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (returnsConst) {
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(0);  // incomplete
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(isStatic == false || returnsConst == false);
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipWhiteSpace();
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* returnTypeStart = iParser.fChar;
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipToNonAlphaNum();
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(iParser.fChar > returnTypeStart);
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string returnType(returnTypeStart, iParser.fChar - returnTypeStart);
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    OpType returnOpType = lookup_type(returnType, className);
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipWhiteSpace();
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    OpMod returnMod = lookup_mod(iParser);
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAssertResult(iParser.skipExact("operator"));
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    iParser.skipWhiteSpace();
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fMethodType = Definition::MethodType::kOperator;
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser::Save save(&iParser);
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto parser : opData) {
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        save.restore();
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!iParser.skipExact(parser.fSymbol)) {
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        iParser.skipWhiteSpace();
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if ('(' != iParser.peek()) {
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (parser.fFriend != ANY && (parser.fFriend == STATIC) != isStatic) {
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (parser.fReturnType != OpType::kAny && parser.fReturnType != returnOpType) {
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (parser.fReturnMod != OpMod::kAny && parser.fReturnMod != returnMod) {
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        iParser.next();  // skip '('
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        iParser.skipWhiteSpace();
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int parserCount = (parser.fParams[0].fType != OpType::kNone) +
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            (parser.fParams[1].fType != OpType::kNone);
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool countsMatch = true;
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int pIndex = 0; pIndex < 2; ++pIndex) {
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (')' == iParser.peek()) {
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                countsMatch = pIndex == parserCount;
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (',' == iParser.peek()) {
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                iParser.next();
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                iParser.skipWhiteSpace();
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            bool paramConst = iParser.skipExact("const");
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (parser.fParams[pIndex].fConst != ANY &&
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    paramConst != (parser.fParams[pIndex].fConst == CONST)) {
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                countsMatch = false;
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            iParser.skipWhiteSpace();
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const char* paramStart = iParser.fChar;
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            iParser.skipToNonAlphaNum();
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(iParser.fChar > paramStart);
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            string paramType(paramStart, iParser.fChar - paramStart);
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            OpType paramOpType = lookup_type(paramType, className);
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (parser.fParams[pIndex].fType != OpType::kAny &&
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    parser.fParams[pIndex].fType != paramOpType) {
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                countsMatch = false;
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            iParser.skipWhiteSpace();
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            OpMod paramMod = lookup_mod(iParser);
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (parser.fParams[pIndex].fMod != OpMod::kAny &&
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    parser.fParams[pIndex].fMod != paramMod) {
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                countsMatch = false;
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            iParser.skipToNonAlphaNum();
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if ('[' == iParser.peek()) {
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paramMod = OpMod::kArray;
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkAssertResult(iParser.skipExact("[]"));
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            iParser.skipWhiteSpace();
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!countsMatch) {
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (')' != iParser.peek()) {
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        iParser.next();
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool constMethod = iParser.skipExact("_const");
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (parser.fConstMethod != ANY && (parser.fConstMethod == CONST) != constMethod) {
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        result += parser.fName;
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        result += "_operator";
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fOperator = parser.fOperator;
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fOperatorConst = constMethod;
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0); // incomplete
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return false;
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if ('!' == fName[opPos]) {
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT('=' == fName[opPos + 1]);
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        result += "not_equal_operator";
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if ('=' == fName[opPos]) {
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if ('(' == fName[opPos + 1]) {
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            result += isMove ? "move_" : "copy_";
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            result += "assignment_operator";
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT('=' == fName[opPos + 1]);
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            result += "equal_operator";
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if ('[' == fName[opPos]) {
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        result += "subscript_operator";
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* end = fContentStart;
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (end > fStart && ' ' >= end[-1]) {
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            --end;
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        string constCheck(fStart, end - fStart);
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t constPos = constCheck.rfind("const");
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (constCheck.length() == constPos + 5) {
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            result += "_const";
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if ('*' == fName[opPos]) {
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        result += "multiply_operator";
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if ('-' == fName[opPos]) {
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        result += "subtract_operator";
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if ('+' == fName[opPos]) {
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        result += "add_operator";
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(0);  // todo: incomplete
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef CONST
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef FRIEND
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef BLANK
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#undef DEFOP
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::boilerplateIfDef(Definition* parent) {
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const Definition& label = fTokens.front();
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (Type::kWord != label.fType) {
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fName = string(label.fContentStart, label.fContentEnd - label.fContentStart);
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// todo: this is matching #ifndef SkXXX_DEFINED for no particular reason
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// it doesn't do anything useful with arbitrary input, e.g. #ifdef SK_SUPPORT_LEGACY_CANVAS_HELPERS
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// also doesn't know what to do with SK_REQUIRE_LOCAL_VAR()
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::boilerplateDef(Definition* parent) {
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!this->boilerplateIfDef(parent)) {
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* s = fName.c_str();
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* e = strchr(s, '_');
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true; // fixme: if this is trying to do something useful with define, do it here
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!e) {
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string prefix(s, e - s);
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* inName = strstr(parent->fName.c_str(), prefix.c_str());
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!inName) {
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if ('/' != inName[-1] && '\\' != inName[-1]) {
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (strcmp(inName + prefix.size(), ".h")) {
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// fixme: this will need to be more complicated to handle all of Skia
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// for now, just handle paint -- maybe fiddle will loosen naming restrictions
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid Definition::setCanonicalFiddle() {
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fMethodType = Definition::MethodType::kNone;
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t doubleColons = fName.find("::", 0);
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(string::npos != doubleColons);
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string base = fName.substr(0, doubleColons);
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string result = base + "_";
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    doubleColons += 2;
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (string::npos != fName.find('~', doubleColons)) {
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMethodType = Definition::MethodType::kDestructor;
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        result += "destructor";
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (!this->parseOperator(doubleColons, result)) {
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool isMove = string::npos != fName.find("&&", doubleColons);
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t parens = fName.find("()", doubleColons);
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (string::npos != parens) {
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            string methodName = fName.substr(doubleColons, parens - doubleColons);
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            do {
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                size_t nextDouble = methodName.find("::");
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (string::npos == nextDouble) {
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                base = methodName.substr(0, nextDouble);
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result += base + '_';
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                methodName = methodName.substr(nextDouble + 2);
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                doubleColons += nextDouble + 2;
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } while (true);
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (base == methodName) {
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fMethodType = Definition::MethodType::kConstructor;
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result += "empty_constructor";
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result += fName.substr(doubleColons, fName.length() - doubleColons - 2);
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            size_t openParen = fName.find('(', doubleColons);
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (string::npos == openParen) {
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result += fName.substr(doubleColons);
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                size_t comma = fName.find(',', doubleColons);
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (string::npos == comma) {
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    result += isMove ? "move_" : "copy_";
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fMethodType = Definition::MethodType::kConstructor;
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // name them by their param types,
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                //   e.g. SkCanvas__int_int_const_SkSurfaceProps_star
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // TODO: move forward until parens are balanced and terminator =,)
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                TextParser params("", &fName[openParen] + 1, &*fName.end(), 0);
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                bool underline = false;
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                while (!params.eof()) {
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//                    SkDEBUGCODE(const char* end = params.anyOf("(),="));  // unused for now
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//                    SkASSERT(end[0] != '(');  // fixme: put off handling nested parentheseses
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (params.startsWith("const") || params.startsWith("int")
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            || params.startsWith("Sk")) {
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        const char* wordStart = params.fChar;
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        params.skipToNonAlphaNum();
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        if (underline) {
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            result += '_';
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        } else {
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            underline = true;
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        result += string(wordStart, params.fChar - wordStart);
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } else {
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        params.skipToNonAlphaNum();
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (!params.eof() && '*' == params.peek()) {
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        if (underline) {
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            result += '_';
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        } else {
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            underline = true;
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        result += "star";
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        params.next();
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        params.skipSpace();
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    params.skipToAlpha();
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fFiddle = Definition::NormalizedName(result);
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid Definition::setWrapper() {
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char drawWrapper[] = "void draw(SkCanvas* canvas) {";
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char drawNoCanvas[] = "void draw(SkCanvas* ) {";
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string text = this->extractText(Definition::TrimExtract::kNo);
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t nonSpace = 0;
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (nonSpace < text.length() && ' ' >= text[nonSpace]) {
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ++nonSpace;
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool hasFunc = !text.compare(nonSpace, sizeof(drawWrapper) - 1, drawWrapper);
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool noCanvas = !text.compare(nonSpace, sizeof(drawNoCanvas) - 1, drawNoCanvas);
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool hasCanvas = string::npos != text.find("SkCanvas canvas");
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(!hasFunc || !noCanvas);
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool preprocessor = text[0] == '#';
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool wrapCode = !hasFunc && !noCanvas && !preprocessor;
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (wrapCode) {
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fWrapper = hasCanvas ? string(drawNoCanvas) : string(drawWrapper);
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::exampleToScript(string* result, ExampleOptions exampleOptions) const {
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool hasFiddle = true;
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const Definition* platform = this->hasChild(MarkType::kPlatform);
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (platform) {
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        TextParser platParse(platform);
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        hasFiddle = !platParse.strnstr("!fiddle", platParse.fEnd);
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!hasFiddle) {
517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *result = "";
518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string text = this->extractText(Definition::TrimExtract::kNo);
521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool textOut = string::npos != text.find("SkDebugf(")
522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            || string::npos != text.find("dump(")
523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            || string::npos != text.find("dumpHex(");
524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string heightStr = "256";
525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string widthStr = "256";
526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string normalizedName(fFiddle);
527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string code;
528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string imageStr = "0";
529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string srgbStr = "false";
530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string durationStr = "0";
531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto const& iter : fChildren) {
532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (iter->fMarkType) {
533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kDuration:
534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                durationStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kHeight:
537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                heightStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kWidth:
540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                widthStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kDescription:
543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // ignore for now
544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kFunction: {
546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // emit this, but don't wrap this in draw()
547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                string funcText(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                size_t pos = 0;
549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                while (pos < funcText.length() && ' ' > funcText[pos]) {
550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    ++pos;
551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                size_t indent = count_indent(funcText, pos, funcText.length());
553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                add_code(funcText, pos, funcText.length(), 0, indent, code);
554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                code += "\\n";
555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } break;
556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kComment:
557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kImage:
559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                imageStr = string(iter->fContentStart, iter->fContentEnd - iter->fContentStart);
560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kToDo:
562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kMarkChar:
564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kPlatform:
565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // ignore for now
566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kSet:
568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if ("sRGB" == string(iter->fContentStart,
569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     iter->fContentEnd - iter->fContentStart)) {
570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    srgbStr = "true";
571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkASSERT(0);   // more work to do
573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return false;
574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MarkType::kStdOut:
577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                textOut = true;
578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(0);  // more coding to do
581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string animatedStr = "0" != durationStr ? "true" : "false";
584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string textOutStr = textOut ? "true" : "false";
585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t pos = 0;
586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (pos < text.length() && ' ' > text[pos]) {
587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ++pos;
588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t end = text.length();
590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t outIndent = 0;
591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t textIndent = count_indent(text, pos, end);
592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fWrapper.length() > 0) {
593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        code += fWrapper;
594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        code += "\\n";
595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        outIndent = 4;
596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    add_code(text, pos, end, outIndent, textIndent, code);
598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fWrapper.length() > 0) {
599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        code += "}";
600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string example = "\"" + normalizedName + "\": {\n";
602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t nameStart = fFileName.find(SkOSPath::SEPARATOR, 0);
603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(string::npos != nameStart);
604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string baseFile = fFileName.substr(nameStart + 1, fFileName.length() - nameStart - 5);
605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (ExampleOptions::kText == exampleOptions) {
606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        example += "    \"code\": \"" + code + "\",\n";
607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        example += "    \"hash\": \"" + fHash + "\",\n";
608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        example += "    \"file\": \"" + baseFile + "\",\n";
609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        example += "    \"name\": \"" + fName + "\",";
610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        example += "    \"code\": \"" + code + "\",\n";
612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (ExampleOptions::kPng == exampleOptions) {
613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "    \"width\": " + widthStr + ",\n";
614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "    \"height\": " + heightStr + ",\n";
615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "    \"hash\": \"" + fHash + "\",\n";
616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "    \"file\": \"" + baseFile + "\",\n";
617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "    \"name\": \"" + fName + "\"\n";
618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "}";
619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot       } else {
620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "    \"options\": {\n";
621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "        \"width\": " + widthStr + ",\n";
622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "        \"height\": " + heightStr + ",\n";
623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "        \"source\": " + imageStr + ",\n";
624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "        \"srgb\": " + srgbStr + ",\n";
625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "        \"f16\": false,\n";
626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "        \"textOnly\": " + textOutStr + ",\n";
627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "        \"animated\": " + animatedStr + ",\n";
628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "        \"duration\": " + durationStr + "\n";
629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "    },\n";
630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            example += "    \"fast\": true";
631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    *result = example;
634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstring Definition::extractText(TrimExtract trimExtract) const {
638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string result;
639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser parser(fFileName, fContentStart, fContentEnd, fLineCount);
640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int childIndex = 0;
641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char mc = '#';
642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (parser.fChar < parser.fEnd) {
643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (TrimExtract::kYes == trimExtract && !parser.skipWhiteSpace()) {
644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (parser.next() == mc) {
647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (parser.next() == mc) {
648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (parser.next() == mc) {
649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    mc = parser.next();
650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // fixme : more work to do if # style comment is in text
653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // if in method definition, could be alternate method name
654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                --parser.fChar;
655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (' ' < parser.fChar[0]) {
656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (islower(parser.fChar[0])) {
657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        result += '\n';
658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        parser.skipLine();
659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } else {
660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkASSERT(isupper(parser.fChar[0]));
661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        parser.skipTo(fChildren[childIndex]->fTerminator);
662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        if (mc == parser.fChar[0] && mc == parser.fChar[1]) {
663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            parser.next();
664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            parser.next();
665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        childIndex++;
667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    parser.skipLine();
670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                continue;
672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            --parser.fChar;
675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* end = parser.fEnd;
677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* mark = parser.strnchr(mc, end);
678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (mark) {
679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            end = mark;
680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        string fragment(parser.fChar, end - parser.fChar);
682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        trim_end(fragment);
683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (TrimExtract::kYes == trimExtract) {
684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            trim_start(fragment);
685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (result.length()) {
686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result += '\n';
687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result += '\n';
688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (TrimExtract::kYes == trimExtract || has_nonwhitespace(fragment)) {
691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            result += fragment;
692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        parser.skipTo(end);
694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return result;
696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void space_pad(string* str) {
699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t len = str->length();
700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (len == 0) {
701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char last = (*str)[len - 1];
704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if ('~' == last || ' ' >= last) {
705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    *str += ' ';
708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//start here;
711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// see if it possible to abstract this a little bit so it can
712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// additionally be used to find params and return in method prototype that
713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// does not have corresponding doxygen comments
714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::checkMethod() const {
715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(MarkType::kMethod == fMarkType);
716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // if method returns a value, look for a return child
717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // for each parameter, look for a corresponding child
718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* end = fContentStart;
719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (end > fStart && ' ' >= end[-1]) {
720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        --end;
721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser methodParser(fFileName, fStart, end, fLineCount);
723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    methodParser.skipWhiteSpace();
724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(methodParser.startsWith("#Method"));
725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    methodParser.skipName("#Method");
726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    methodParser.skipSpace();
727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string name = this->methodName();
728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (MethodType::kNone == fMethodType && name.length() > 2 &&
729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            "()" == name.substr(name.length() - 2)) {
730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        name = name.substr(0, name.length() - 2);
731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool expectReturn = this->methodHasReturn(name, &methodParser);
733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool foundReturn = false;
734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool foundException = false;
735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto& child : fChildren) {
736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        foundException |= MarkType::kDeprecated == child->fMarkType
737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                || MarkType::kExperimental == child->fMarkType;
738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (MarkType::kReturn != child->fMarkType) {
739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (MarkType::kParam == child->fMarkType) {
740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                child->fVisited = false;
741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!expectReturn) {
745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return methodParser.reportError<bool>("no #Return expected");
746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (foundReturn) {
748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return methodParser.reportError<bool>("multiple #Return markers");
749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        foundReturn = true;
751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (expectReturn && !foundReturn && !foundException) {
753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return methodParser.reportError<bool>("missing #Return marker");
754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* paren = methodParser.strnchr('(', methodParser.fEnd);
756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!paren) {
757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return methodParser.reportError<bool>("missing #Method function definition");
758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* nextEnd = paren;
760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        string paramName;
762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        methodParser.fChar = nextEnd + 1;
763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        methodParser.skipSpace();
764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!this->nextMethodParam(&methodParser, &nextEnd, &paramName)) {
765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool foundParam = false;
768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (auto& child : fChildren) {
769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (MarkType::kParam != child->fMarkType) {
770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                continue;
771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (paramName != child->fName) {
773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                continue;
774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (child->fVisited) {
776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return methodParser.reportError<bool>("multiple #Method param with same name");
777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            child->fVisited = true;
779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (foundParam) {
780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                TextParser paramError(child);
781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return methodParser.reportError<bool>("multiple #Param with same name");
782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            foundParam = true;
784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!foundParam && !foundException) {
787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return methodParser.reportError<bool>("no #Param found");
788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (')' == nextEnd[0]) {
790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (')' != nextEnd[0]);
793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto& child : fChildren) {
794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (MarkType::kParam != child->fMarkType) {
795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!child->fVisited) {
798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            TextParser paramError(child);
799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return paramError.reportError<bool>("#Param without param in #Method");
800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::crossCheck2(const Definition& includeToken) const {
806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser parser(fFileName, fStart, fContentStart, fLineCount);
807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    parser.skipExact("#");
808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool isMethod = parser.skipName("Method");
809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* contentEnd;
810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (isMethod) {
811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        contentEnd = fContentStart;
812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (parser.skipName("DefinedBy")) {
813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        contentEnd = fContentEnd;
814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (parser.fChar < contentEnd && ' ' >= contentEnd[-1]) {
815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            --contentEnd;
816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (parser.fChar < contentEnd - 1 && ')' == contentEnd[-1] && '(' == contentEnd[-2]) {
818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            contentEnd -= 2;
819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return parser.reportError<bool>("unexpected crosscheck marktype");
822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return crossCheckInside(parser.fChar, contentEnd, includeToken);
824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::crossCheck(const Definition& includeToken) const {
827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return crossCheckInside(fContentStart, fContentEnd, includeToken);
828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::crossCheckInside(const char* start, const char* end,
831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const Definition& includeToken) const {
832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser def(fFileName, start, end, fLineCount);
833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser inc("", includeToken.fContentStart, includeToken.fContentEnd, 0);
834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (inc.startsWith("SK_API")) {
835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        inc.skipWord("SK_API");
836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (inc.startsWith("friend")) {
838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        inc.skipWord("friend");
839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (inc.startsWith("SK_API")) {
841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        inc.skipWord("SK_API");
842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    inc.skipExact("SkDEBUGCODE(");
844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool defEof;
846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool incEof;
847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        do {
848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            defEof = def.eof() || !def.skipWhiteSpace();
849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            incEof = inc.eof() || !inc.skipWhiteSpace();
850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (!incEof && '/' == inc.peek() && (defEof || '/' != def.peek())) {
851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                inc.next();
852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if ('*' == inc.peek()) {
853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    inc.skipToEndBracket("*/");
854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    inc.next();
855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else if ('/' == inc.peek()) {
856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    inc.skipToEndBracket('\n');
857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else if (!incEof && '#' == inc.peek() && (defEof || '#' != def.peek())) {
859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                inc.next();
860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (inc.startsWith("if")) {
861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    inc.skipToEndBracket("\n");
862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else if (inc.startsWith("endif")) {
863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    inc.skipToEndBracket("\n");
864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkASSERT(0); // incomplete
866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return false;
867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            inc.next();
872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } while (true);
873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (defEof || incEof) {
874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (defEof == incEof || (!defEof && ';' == def.peek())) {
875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;  // allow setting breakpoint on failure
878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char defCh;
880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        do {
881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            defCh = def.next();
882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            char incCh = inc.next();
883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (' ' >= defCh && ' ' >= incCh) {
884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (defCh != incCh) {
887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if ('_' != defCh || ' ' != incCh || !fOperatorConst || !def.startsWith("const")) {
888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return false;
889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (';' == defCh) {
892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } while (!def.eof() && !inc.eof());
895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (true);
896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return false;
897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstring Definition::formatFunction() const {
900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* end = fContentStart;
901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (end > fStart && ' ' >= end[-1]) {
902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        --end;
903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser methodParser(fFileName, fStart, end, fLineCount);
905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    methodParser.skipWhiteSpace();
906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(methodParser.startsWith("#Method"));
907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    methodParser.skipName("#Method");
908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    methodParser.skipSpace();
909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* lastStart = methodParser.fChar;
910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const int limit = 100;  // todo: allow this to be set by caller or in global or something
911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string name = this->methodName();
912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* nameInParser = methodParser.strnstr(name.c_str(), methodParser.fEnd);
913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    methodParser.skipTo(nameInParser);
914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* lastEnd = methodParser.fChar;
915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* paren = methodParser.strnchr('(', methodParser.fEnd);
916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t indent;
917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (paren) {
918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        indent = (size_t) (paren - lastStart) + 1;
919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else {
920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        indent = (size_t) (lastEnd - lastStart);
921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // trim indent so longest line doesn't exceed box width
923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser::Save savePlace(&methodParser);
924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* saveStart = lastStart;
925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ptrdiff_t maxLine = 0;
926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* nextStart = lastEnd;
928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* delimiter = methodParser.anyOf(",)");
929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* nextEnd = delimiter ? delimiter : methodParser.fEnd;
930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (delimiter) {
931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            while (nextStart < nextEnd && ' ' >= nextStart[0]) {
932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                ++nextStart;
933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (nextEnd > nextStart && ' ' >= nextEnd[-1]) {
936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            --nextEnd;
937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (delimiter) {
939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            nextEnd += 1;
940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            delimiter += 1;
941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (lastEnd > lastStart) {
943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            maxLine = SkTMax(maxLine, lastEnd - lastStart);
944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (delimiter) {
946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            methodParser.skipTo(delimiter);
947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        lastStart = nextStart;
949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        lastEnd = nextEnd;
950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (lastStart < lastEnd);
951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    savePlace.restore();
952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    lastStart = saveStart;
953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    lastEnd = methodParser.fChar;
954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    indent = SkTMin(indent, (size_t) (limit - maxLine));
955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // write string wtih trimmmed indent
956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string methodStr;
957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int written = 0;
958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* nextStart = lastEnd;
960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(written < limit);
961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* delimiter = methodParser.anyOf(",)");
962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* nextEnd = delimiter ? delimiter : methodParser.fEnd;
963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (delimiter) {
964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            while (nextStart < nextEnd && ' ' >= nextStart[0]) {
965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                ++nextStart;
966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (nextEnd > nextStart && ' ' >= nextEnd[-1]) {
969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            --nextEnd;
970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (delimiter) {
972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            nextEnd += 1;
973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            delimiter += 1;
974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (lastEnd > lastStart) {
976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (lastStart[0] != ' ') {
977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                space_pad(&methodStr);
978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            methodStr += string(lastStart, (size_t) (lastEnd - lastStart));
980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            written += (size_t) (lastEnd - lastStart);
981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (delimiter) {
983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (nextEnd - nextStart >= (ptrdiff_t) (limit - written)) {
984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                written = indent;
985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                methodStr += '\n';
986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                methodStr += string(indent, ' ');
987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            methodParser.skipTo(delimiter);
989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        lastStart = nextStart;
991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        lastEnd = nextEnd;
992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (lastStart < lastEnd);
993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return methodStr;
994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstring Definition::fiddleName() const {
997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string result;
998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t start = 0;
999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string parent;
1000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const Definition* parentDef = this;
1001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((parentDef = parentDef->fParent)) {
1002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (MarkType::kClass == parentDef->fMarkType || MarkType::kStruct == parentDef->fMarkType) {
1003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            parent = parentDef->fFiddle;
1004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
1005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (parent.length() && 0 == fFiddle.compare(0, parent.length(), parent)) {
1008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        start = parent.length();
1009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (start < fFiddle.length() && '_' == fFiddle[start]) {
1010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ++start;
1011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t end = fFiddle.find_first_of('(', start);
1014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return fFiddle.substr(start, end - start);
1015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst Definition* Definition::hasChild(MarkType markType) const {
1018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto iter : fChildren) {
1019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (markType == iter->fMarkType) {
1020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return iter;
1021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return nullptr;
1024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst Definition* Definition::hasParam(const string& ref) const {
1027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(MarkType::kMethod == fMarkType);
1028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto iter : fChildren) {
1029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (MarkType::kParam != iter->fMarkType) {
1030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
1031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (iter->fName == ref) {
1033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return &*iter;
1034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return nullptr;
1038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::hasMatch(const string& name) const {
1041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto child : fChildren) {
1042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (name == child->fName) {
1043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
1044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (child->hasMatch(name)) {
1046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
1047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return false;
1050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::isStructOrClass() const {
1053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (MarkType::kStruct != fMarkType && MarkType::kClass != fMarkType) {
1054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
1055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (string::npos != fFileName.find("undocumented.bmh")) {
1057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
1058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
1060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::methodHasReturn(const string& name, TextParser* methodParser) const {
1063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (methodParser->skipExact("static")) {
1064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        methodParser->skipWhiteSpace();
1065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* lastStart = methodParser->fChar;
1067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* nameInParser = methodParser->strnstr(name.c_str(), methodParser->fEnd);
1068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    methodParser->skipTo(nameInParser);
1069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* lastEnd = methodParser->fChar;
1070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* returnEnd = lastEnd;
1071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (returnEnd > lastStart && ' ' == returnEnd[-1]) {
1072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        --returnEnd;
1073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool expectReturn = 4 != returnEnd - lastStart || strncmp("void", lastStart, 4);
1075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (MethodType::kNone != fMethodType && MethodType::kOperator != fMethodType && !expectReturn) {
1076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return methodParser->reportError<bool>("unexpected void");
1077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (fMethodType) {
1079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case MethodType::kNone:
1080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case MethodType::kOperator:
1081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // either is fine
1082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
1083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case MethodType::kConstructor:
1084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            expectReturn = true;
1085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
1086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case MethodType::kDestructor:
1087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            expectReturn = false;
1088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
1089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return expectReturn;
1091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstring Definition::methodName() const {
1094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string result;
1095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t start = 0;
1096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string parent;
1097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const Definition* parentDef = this;
1098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((parentDef = parentDef->fParent)) {
1099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (MarkType::kClass == parentDef->fMarkType || MarkType::kStruct == parentDef->fMarkType) {
1100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            parent = parentDef->fName;
1101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
1102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (parent.length() && 0 == fName.compare(0, parent.length(), parent)) {
1105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        start = parent.length();
1106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (start < fName.length() && ':' == fName[start]) {
1107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ++start;
1108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (fClone) {
1111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int lastUnder = fName.rfind('_');
1112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fName.substr(start, (size_t) (lastUnder - start));
1113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    size_t end = fName.find_first_of('(', start);
1115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (string::npos == end) {
1116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fName.substr(start);
1117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return fName.substr(start, end - start);
1119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::nextMethodParam(TextParser* methodParser, const char** nextEndPtr,
1122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        string* paramName) const {
1123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int parenCount = 0;
1124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser::Save saveState(methodParser);
1125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (true) {
1126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (methodParser->eof()) {
1127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return methodParser->reportError<bool>("#Method function missing close paren");
1128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        char ch = methodParser->peek();
1130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if ('(' == ch) {
1131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ++parenCount;
1132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (parenCount == 0 && (')' == ch || ',' == ch)) {
1134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            *nextEndPtr = methodParser->fChar;
1135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
1136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (')' == ch) {
1138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (0 > --parenCount) {
1139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return this->reportError<bool>("mismatched parentheses");
1140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        methodParser->next();
1143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    saveState.restore();
1145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* nextEnd = *nextEndPtr;
1146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* paramEnd = nextEnd;
1147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* assign = methodParser->strnstr(" = ", paramEnd);
1148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (assign) {
1149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paramEnd = assign;
1150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* closeBracket = methodParser->strnstr("]", paramEnd);
1152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (closeBracket) {
1153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* openBracket = methodParser->strnstr("[", paramEnd);
1154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (openBracket && openBracket < closeBracket) {
1155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            while (openBracket < --closeBracket && isdigit(closeBracket[0]))
1156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                ;
1157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (openBracket == closeBracket) {
1158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paramEnd = openBracket;
1159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* function = methodParser->strnstr(")(", paramEnd);
1163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (function) {
1164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paramEnd = function;
1165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (paramEnd > methodParser->fChar && ' ' == paramEnd[-1]) {
1167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        --paramEnd;
1168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* paramStart = paramEnd;
1170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (paramStart > methodParser->fChar && isalnum(paramStart[-1])) {
1171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        --paramStart;
1172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (paramStart > methodParser->fChar && paramStart >= paramEnd) {
1174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return methodParser->reportError<bool>("#Method missing param name");
1175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    *paramName = string(paramStart, paramEnd - paramStart);
1177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!paramName->length()) {
1178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (')' != nextEnd[0]) {
1179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return methodParser->reportError<bool>("#Method malformed param");
1180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
1182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
1184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstring Definition::NormalizedName(string name) {
1187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    string normalizedName = name;
1188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    std::replace(normalizedName.begin(), normalizedName.end(), '-', '_');
1189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {
1190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        size_t doubleColon = normalizedName.find("::", 0);
1191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (string::npos == doubleColon) {
1192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
1193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        normalizedName = normalizedName.substr(0, doubleColon)
1195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            + '_' + normalizedName.substr(doubleColon + 2);
1196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (true);
1197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return normalizedName;
1198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool Definition::paramsMatch(const string& match, const string& name) const {
1201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser def(fFileName, fStart, fContentStart, fLineCount);
1202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* dName = def.strnstr(name.c_str(), fContentStart);
1203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!dName) {
1204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
1205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    def.skipTo(dName);
1207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextParser m(fFileName, &match.front(), &match.back() + 1, fLineCount);
1208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* mName = m.strnstr(name.c_str(), m.fEnd);
1209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!mName) {
1210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
1211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    m.skipTo(mName);
1213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (!def.eof() && ')' != def.peek() && !m.eof() && ')' != m.peek()) {
1214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* ds = def.fChar;
1215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* ms = m.fChar;
1216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* de = def.anyOf(") \n");
1217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const char* me = m.anyOf(") \n");
1218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        def.skipTo(de);
1219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        m.skipTo(me);
1220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (def.fChar - ds != m.fChar - ms) {
1221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
1222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (strncmp(ds, ms, (int) (def.fChar - ds))) {
1224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
1225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        def.skipWhiteSpace();
1227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        m.skipWhiteSpace();
1228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return !def.eof() && ')' == def.peek() && !m.eof() && ')' == m.peek();
1230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid RootDefinition::clearVisited() {
1233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fVisited = false;
1234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto& leaf : fLeaves) {
1235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        leaf.second.fVisited = false;
1236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto& branch : fBranches) {
1238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        branch.second->clearVisited();
1239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool RootDefinition::dumpUnVisited() {
1243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool success = true;
1244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto& leaf : fLeaves) {
1245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!leaf.second.fVisited) {
1246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // FIXME: bugs requiring long tail fixes, suppressed here:
1247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // SkBitmap::validate() is wrapped in SkDEBUGCODE in .h and not parsed
1248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if ("SkBitmap::validate()" == leaf.first) {
1249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                continue;
1250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // SkPath::pathRefIsValid in #ifdef ; prefer to remove chrome dependency to fix
1252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if ("SkPath::pathRefIsValid" == leaf.first) {
1253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                continue;
1254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // FIXME: end of long tail bugs
1256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("defined in bmh but missing in include: %s\n", leaf.first.c_str());
1257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            success = false;
1258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (auto& branch : fBranches) {
1261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        success &= branch.second->dumpUnVisited();
1262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return success;
1264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst Definition* RootDefinition::find(const string& ref, AllowParens allowParens) const {
1267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const auto leafIter = fLeaves.find(ref);
1268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (leafIter != fLeaves.end()) {
1269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return &leafIter->second;
1270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (AllowParens::kYes == allowParens && string::npos == ref.find("()")) {
1272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        string withParens = ref + "()";
1273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const auto parensIter = fLeaves.find(withParens);
1274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (parensIter != fLeaves.end()) {
1275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return &parensIter->second;
1276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const auto branchIter = fBranches.find(ref);
1279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (branchIter != fBranches.end()) {
1280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const RootDefinition* rootDef = branchIter->second;
1281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return rootDef;
1282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const Definition* result = nullptr;
1284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (const auto& branch : fBranches) {
1285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const RootDefinition* rootDef = branch.second;
1286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        result = rootDef->find(ref, allowParens);
1287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (result) {
1288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            break;
1289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return result;
1292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1293