Blender V4.3
text_format_osl.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
12#include <cstring>
13
14#include "BLI_blenlib.h"
15
16#include "DNA_space_types.h"
17#include "DNA_text_types.h"
18
19#include "BKE_text.h"
20
21#include "text_format.hh"
22
23/* -------------------------------------------------------------------- */
33 /* Force single column, sorted list. */
34 /* clang-format off */
35 "break",
36 "closure",
37 "color",
38 "continue",
39 "do",
40 "else",
41 "emit",
42 "float",
43 "for",
44 "if",
45 "illuminance",
46 "illuminate",
47 "int",
48 "matrix",
49 "normal",
50 "output",
51 "point",
52 "public",
53 "return",
54 "string",
55 "struct",
56 "vector",
57 "void",
58 "while",
59 /* clang-format on */
60};
64
71 /* Force single column, sorted list. */
72 /* clang-format off */
73 "bool",
74 "case",
75 "catch",
76 "char",
77 "const",
78 "default",
79 "delete",
80 "double",
81 "enum",
82 "extern",
83 "false",
84 "friend",
85 "goto",
86 "inline",
87 "long",
88 "new",
89 "operator",
90 "private",
91 "protected",
92 "short",
93 "signed",
94 "sizeof",
95 "static",
96 "switch",
97 "template",
98 "this",
99 "throw",
100 "true",
101 "try",
102 "typedef",
103 "uniform",
104 "union",
105 "unsigned",
106 "varying",
107 "virtual",
108 "volatile",
109 /* clang-format on */
110};
113
114/* OSL shader types */
116 /* Force single column, sorted list. */
117 /* clang-format off */
118 "displacement",
119 "shader",
120 "surface",
121 "volume",
122 /* clang-format on */
123};
127
130/* -------------------------------------------------------------------- */
134static int txtfmt_osl_find_builtinfunc(const char *string)
135{
137
138 /* If next source char is an identifier (eg. 'i' in "definite") no match */
139 if (i == 0 || text_check_identifier(string[i])) {
140 return -1;
141 }
142 return i;
143}
144
145static int txtfmt_osl_find_reserved(const char *string)
146{
148
149 /* If next source char is an identifier (eg. 'i' in "definite") no match */
150 if (i == 0 || text_check_identifier(string[i])) {
151 return -1;
152 }
153 return i;
154}
155
156static int txtfmt_osl_find_specialvar(const char *string)
157{
159
160 /* If next source char is an identifier (eg. 'i' in "definite") no match */
161 if (i == 0 || text_check_identifier(string[i])) {
162 return -1;
163 }
164 return i;
165}
166
167/* matches py 'txtfmt_osl_find_decorator' */
168static int txtfmt_osl_find_preprocessor(const char *string)
169{
170 if (string[0] == '#') {
171 int i = 1;
172 /* White-space is ok '# foo'. */
173 while (text_check_whitespace(string[i])) {
174 i++;
175 }
176 while (text_check_identifier(string[i])) {
177 i++;
178 }
179 return i;
180 }
181 return -1;
182}
183
184static char txtfmt_osl_format_identifier(const char *str)
185{
186 char fmt;
187
188 /* Keep aligned args for readability. */
189 /* clang-format off */
190
192 } else if (txtfmt_osl_find_builtinfunc(str) != -1) { fmt = FMT_TYPE_KEYWORD;
193 } else if (txtfmt_osl_find_reserved(str) != -1) { fmt = FMT_TYPE_RESERVED;
194 } else if (txtfmt_osl_find_preprocessor(str) != -1) { fmt = FMT_TYPE_DIRECTIVE;
195 } else { fmt = FMT_TYPE_DEFAULT;
196 }
197
198 /* clang-format on */
199
200 return fmt;
201}
202
205/* -------------------------------------------------------------------- */
209static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const bool do_next)
210{
211 FlattenString fs;
212 const char *str;
213 char *fmt;
214 char cont_orig, cont, find, prev = ' ';
215 int len, i;
216
217 /* Get continuation from previous line */
218 if (line->prev && line->prev->format != nullptr) {
219 fmt = line->prev->format;
220 cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
221 BLI_assert((FMT_CONT_ALL & cont) == cont);
222 }
223 else {
224 cont = FMT_CONT_NOP;
225 }
226
227 /* Get original continuation from this line */
228 if (line->format != nullptr) {
229 fmt = line->format;
230 cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
231 BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
232 }
233 else {
234 cont_orig = 0xFF;
235 }
236
237 len = flatten_string(st, &fs, line->line);
238 str = fs.buf;
239 if (!text_check_format_len(line, len)) {
241 return;
242 }
243 fmt = line->format;
244
245 while (*str) {
246 /* Handle escape sequences by skipping both \ and next char */
247 if (*str == '\\') {
248 *fmt = prev;
249 fmt++;
250 str++;
251 if (*str == '\0') {
252 break;
253 }
254 *fmt = prev;
255 fmt++;
257 continue;
258 }
259 /* Handle continuations */
260 if (cont) {
261 /* C-Style comments */
262 if (cont & FMT_CONT_COMMENT_C) {
263 if (*str == '*' && *(str + 1) == '/') {
264 *fmt = FMT_TYPE_COMMENT;
265 fmt++;
266 str++;
267 *fmt = FMT_TYPE_COMMENT;
268 cont = FMT_CONT_NOP;
269 }
270 else {
271 *fmt = FMT_TYPE_COMMENT;
272 }
273 /* Handle other comments */
274 }
275 else {
276 find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
277 if (*str == find) {
278 cont = 0;
279 }
280 *fmt = FMT_TYPE_STRING;
281 }
282
284 }
285 /* Not in a string... */
286 else {
287 /* Deal with comments first */
288 if (*str == '/' && *(str + 1) == '/') {
289 /* fill the remaining line */
290 text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - int(fmt - line->format));
291 }
292 /* C-Style (multi-line) comments */
293 else if (*str == '/' && *(str + 1) == '*') {
294 cont = FMT_CONT_COMMENT_C;
295 *fmt = FMT_TYPE_COMMENT;
296 fmt++;
297 str++;
298 *fmt = FMT_TYPE_COMMENT;
299 }
300 else if (ELEM(*str, '"', '\'')) {
301 /* Strings */
302 find = *str;
303 cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
304 *fmt = FMT_TYPE_STRING;
305 }
306 /* White-space (all white-space has been converted to spaces). */
307 else if (*str == ' ') {
308 *fmt = FMT_TYPE_WHITESPACE;
309 }
310 /* Numbers (digits not part of an identifier and periods followed by digits) */
311 else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
312 (*str == '.' && text_check_digit(*(str + 1))))
313 {
314 *fmt = FMT_TYPE_NUMERAL;
315 }
316 /* Punctuation */
317 else if ((*str != '#') && text_check_delim(*str)) {
318 *fmt = FMT_TYPE_SYMBOL;
319 }
320 /* Identifiers and other text (no previous white-space or delimiters. so text continues). */
321 else if (prev == FMT_TYPE_DEFAULT) {
323 *fmt = FMT_TYPE_DEFAULT;
324 }
325 /* Not white-space, a digit, punctuation, or continuing text.
326 * Must be new, check for special words. */
327 else {
328 /* Keep aligned arguments for readability. */
329 /* clang-format off */
330
331 /* Special vars(v) or built-in keywords(b) */
332 /* keep in sync with `txtfmt_osl_format_identifier()`. */
333 if ((i = txtfmt_osl_find_specialvar(str)) != -1) { prev = FMT_TYPE_SPECIAL;
334 } else if ((i = txtfmt_osl_find_builtinfunc(str)) != -1) { prev = FMT_TYPE_KEYWORD;
335 } else if ((i = txtfmt_osl_find_reserved(str)) != -1) { prev = FMT_TYPE_RESERVED;
336 } else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) { prev = FMT_TYPE_DIRECTIVE;
337 }
338 /* clang-format on */
339
340 if (i > 0) {
341 if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */
342 text_format_fill(&str, &fmt, prev, i);
343 }
344 else {
345 text_format_fill_ascii(&str, &fmt, prev, i);
346 }
347 }
348 else {
350 *fmt = FMT_TYPE_DEFAULT;
351 }
352 }
353 }
354 prev = *fmt;
355 fmt++;
356 str++;
357 }
358
359 /* Terminate and add continuation char */
360 *fmt = '\0';
361 fmt++;
362 *fmt = cont;
363
364 /* If continuation has changed and we're allowed, process the next line */
365 if (cont != cont_orig && do_next && line->next) {
366 txtfmt_osl_format_line(st, line->next, do_next);
367 }
368
370}
371
374/* -------------------------------------------------------------------- */
394
bool text_check_digit(char ch)
Definition text.cc:2303
bool text_check_identifier(char ch)
Definition text.cc:2314
bool text_check_delim(char ch)
Definition text.cc:2287
bool text_check_whitespace(char ch)
Definition text.cc:2369
#define BLI_assert(a)
Definition BLI_assert.h:50
int BLI_str_utf8_size_safe(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define ARRAY_SIZE(arr)
#define ELEM(...)
int len
#define str(s)
SpaceLink * next
const char * comment_line
char(* format_identifier)(const char *string)
const char ** ext
void(* format_line)(SpaceText *st, TextLine *line, bool do_next)
int flatten_string(const SpaceText *st, FlattenString *fs, const char *in)
void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len)
void flatten_string_free(FlattenString *fs)
const bool text_format_string_literals_check_sorted_array(const Span< const char * > string_literals)
int text_format_string_literal_find(const Span< const char * > string_literals, const char *text)
void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len)
void ED_text_format_register(TextFormatType *tft)
int text_check_format_len(TextLine *line, uint len)
@ FMT_CONT_QUOTEDOUBLE
@ FMT_CONT_QUOTESINGLE
@ FMT_CONT_NOP
@ FMT_CONT_COMMENT_C
@ FMT_TYPE_DIRECTIVE
@ FMT_TYPE_STRING
@ FMT_TYPE_COMMENT
@ FMT_TYPE_SPECIAL
@ FMT_TYPE_DEFAULT
@ FMT_TYPE_KEYWORD
@ FMT_TYPE_WHITESPACE
@ FMT_TYPE_NUMERAL
@ FMT_TYPE_RESERVED
@ FMT_TYPE_SYMBOL
#define FMT_CONT_ALL
static char txtfmt_osl_format_identifier(const char *str)
static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const bool do_next)
static int txtfmt_osl_find_builtinfunc(const char *string)
static const char * text_format_osl_literals_specialvar_data[]
static int txtfmt_osl_find_preprocessor(const char *string)
static const Span< const char * > text_format_osl_literals_reserved(text_format_osl_literals_reserved_data, ARRAY_SIZE(text_format_osl_literals_reserved_data))
void ED_text_format_register_osl()
static int txtfmt_osl_find_specialvar(const char *string)
static int txtfmt_osl_find_reserved(const char *string)
static const char * text_format_osl_literals_reserved_data[]
static const char * text_format_osl_literals_builtinfunc_data[]
static const Span< const char * > text_format_osl_literals_builtinfunc(text_format_osl_literals_builtinfunc_data, ARRAY_SIZE(text_format_osl_literals_builtinfunc_data))
static const Span< const char * > text_format_osl_literals_specialvar(text_format_osl_literals_specialvar_data, ARRAY_SIZE(text_format_osl_literals_specialvar_data))