Blender V4.3
text_format_glsl.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 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/* -------------------------------------------------------------------- */
32 /* Force single column, sorted list. */
33 /* clang-format off */
34 "EmitStreamVertex",
35 "EmitVertex",
36 "EndPrimitive",
37 "EndStreamPrimitive",
38 "abs",
39 "acos",
40 "acosh",
41 "all",
42 "any",
43 "asin",
44 "asinh",
45 "atan",
46 "atanh",
47 "atomicAdd",
48 "atomicAnd",
49 "atomicCompSwap",
50 "atomicCounter",
51 "atomicCounterDecrement",
52 "atomicCounterIncrement",
53 "atomicExchange",
54 "atomicMax",
55 "atomicMin",
56 "atomicOr",
57 "atomicXor",
58 "barrier",
59 "bitCount",
60 "bitfieldExtract",
61 "bitfieldInsert",
62 "bitfieldReverse",
63 "bool",
64 "break",
65 "bvec2",
66 "bvec3",
67 "bvec4",
68 "case",
69 "ceil",
70 "clamp",
71 "continue",
72 "cos",
73 "cosh",
74 "cross",
75 "dFdx",
76 "dFdxCoarse",
77 "dFdxFine",
78 "dFdy",
79 "dFdyCoarse",
80 "dFdyFine",
81 "degrees",
82 "determinant",
83 "discard",
84 "distance",
85 "dmat2",
86 "dmat2x2",
87 "dmat2x3",
88 "dmat2x4",
89 "dmat3",
90 "dmat3x2",
91 "dmat3x3",
92 "dmat3x4",
93 "dmat4",
94 "dmat4x2",
95 "dmat4x3",
96 "dmat4x4",
97 "do",
98 "dot",
99 "double",
100 "else",
101 "equal",
102 "exp",
103 "exp2",
104 "faceforward",
105 "findLSB",
106 "findMSB",
107 "float",
108 "floatBitsToInt",
109 "floatBitsToUint",
110 "floor",
111 "fma",
112 "for",
113 "fract",
114 "frexp",
115 "fwidth",
116 "greaterThan",
117 "greaterThanEqual",
118 "groupMemoryBarrier",
119 "if",
120 "imageAtomicAdd",
121 "imageAtomicAnd",
122 "imageAtomicCompSwap",
123 "imageAtomicExchange",
124 "imageAtomicMax",
125 "imageAtomicMin",
126 "imageAtomicOr",
127 "imageAtomicXor",
128 "imageLoad",
129 "imageSamples",
130 "imageSize",
131 "imageStore",
132 "int",
133 "intBitsToFloat",
134 "interpolateAtCentriod",
135 "interpolateAtOffset",
136 "interpolateAtSample",
137 "inverse",
138 "inversesqrt",
139 "isinf",
140 "isnan",
141 "ivec2",
142 "ivec3",
143 "ivec4",
144 "ldexp",
145 "length",
146 "lessThan",
147 "lessThanEqual",
148 "log",
149 "log2",
150 "mat2",
151 "mat2x2",
152 "mat2x3",
153 "mat2x4",
154 "mat3",
155 "mat3x2",
156 "mat3x3",
157 "mat3x4",
158 "mat4",
159 "mat4x2",
160 "mat4x3",
161 "mat4x4",
162 "matrixCompMult",
163 "max",
164 "memoryBarrier",
165 "memoryBarrierAtomicCounter",
166 "memoryBarrierBuffer",
167 "memoryBarrierImage",
168 "memoryBarrierShared",
169 "min",
170 "mix",
171 "mod",
172 "modf",
173 "noise",
174 "normalize",
175 "not",
176 "notEqual",
177 "outerProduct",
178 "packDouble2x32",
179 "packHalf2x16",
180 "packUnorm",
181 "pow",
182 "radians",
183 "reflect",
184 "refract",
185 "return",
186 "round",
187 "roundEven",
188 "sampler1D",
189 "sampler1DArray",
190 "sampler1DArrayShadow",
191 "sampler1DShadow",
192 "sampler2D",
193 "sampler2DArray",
194 "sampler2DArrayShadow",
195 "sampler2DMS",
196 "sampler2DMSArray",
197 "sampler2DRect",
198 "sampler2DShadow",
199 "sampler3D",
200 "samplerBuffer",
201 "samplerCube",
202 "samplerCubeArray",
203 "samplerCubeArrayShadow",
204 "samplerCubeShadow",
205 "sign",
206 "sin",
207 "sinh",
208 "smoothstep",
209 "sqrt",
210 "step",
211 "struct",
212 "switch",
213 "tan",
214 "tanh",
215 "texelFetch",
216 "texelFetchOffset",
217 "texture",
218 "textureGather",
219 "textureGatherOffset",
220 "textureGatherOffsets",
221 "textureGrad",
222 "textureGradOffset",
223 "textureLod",
224 "textureLodOffset",
225 "textureOffset",
226 "textureProj",
227 "textureProjGrad",
228 "textureProjGradOffset",
229 "textureProjLod",
230 "textureProjLodOffset",
231 "textureProjOffset",
232 "textureQueryLevels",
233 "textureQueryLod",
234 "textureSamples",
235 "textureSize",
236 "transpose",
237 "trunc",
238 "uaddCarry",
239 "uint",
240 "uintBitsToFloat",
241 "umulExtended",
242 "unpackDouble2x32",
243 "unpackHalf2x16",
244 "unpackUnorm2x16",
245 "unpackUnorm4x8",
246 "usubBorrow",
247 "uvec2",
248 "uvec3",
249 "uvec4",
250 "vec2",
251 "vec3",
252 "vec4",
253 "void",
254 "while",
255 /* clang-format on */
256};
260
266 /* Force single column, sorted list. */
267 /* clang-format off */
268 "buffer",
269 "coherent",
270 "default",
271 "false",
272 "flat",
273 "in",
274 "inout",
275 "layout",
276 "out",
277 "readonly",
278 "restrict",
279 "sampler",
280 "smooth",
281 "true",
282 "uniform",
283 "varying",
284 "volatile",
285 "writeonly",
286 /* clang-format on */
287};
290
296 /* Force single column, sorted list */
297 /* clang-format off */
298 "gl_ClipDistance",
299 "gl_FragCoord",
300 "gl_FragDepth",
301 "gl_FrontFacing",
302 "gl_GlobalInvocationID",
303 "gl_InstanceID",
304 "gl_InvocationID",
305 "gl_Layer",
306 "gl_LocalInvocationID",
307 "gl_LocalInvocationIndex",
308 "gl_NumSamples",
309 "gl_NumWorkGroups",
310 "gl_PatchVerticesIn",
311 "gl_PointCoord",
312 "gl_PointSize",
313 "gl_Position",
314 "gl_PrimitiveID",
315 "gl_PrimitiveIDIn",
316 "gl_SampleID",
317 "gl_SampleMask",
318 "gl_SampleMaskIn",
319 "gl_SamplePosition",
320 "gl_TessCoord",
321 "gl_TessLevelInner",
322 "gl_TessLevelOuter",
323 "gl_VertexID",
324 "gl_ViewportIndex",
325 "gl_WorkGroupID",
326 "gl_WorkGroupSize",
327 /* clang-format on */
328};
332
335/*---------------------------------------------------------------------*/
336/* name local functions
337 */
338
339static int txtfmt_glsl_find_builtinfunc(const char *string)
340{
342
343 if (i == 0 || text_check_identifier(string[i])) {
344 return -1;
345 }
346 return i;
347}
348
349static int txtfmt_glsl_find_reserved(const char *string)
350{
352
353 if (i == 0 || text_check_identifier(string[i])) {
354 return -1;
355 }
356 return i;
357}
358static int txtfmt_glsl_find_specialvar(const char *string)
359{
361
362 if (i == 0 || text_check_identifier(string[i])) {
363 return -1;
364 }
365 return i;
366}
367static int txtfmt_glsl_find_preprocessor(const char *string)
368{
369 if (string[0] == '#') {
370 int i = 1;
371 /* White-space is ok '# foo'. */
372 while (text_check_whitespace(string[i])) {
373 i++;
374 }
375 while (text_check_identifier(string[i])) {
376 i++;
377 }
378 return i;
379 }
380 return -1;
381}
382static char txtfmt_glsl_format_identifier(const char *str)
383{
384 char fmt;
385
386 /* clang-format off */
387
389 } else if (txtfmt_glsl_find_builtinfunc(str) != -1) {fmt = FMT_TYPE_KEYWORD;
390 } else if (txtfmt_glsl_find_reserved(str) != -1) {fmt = FMT_TYPE_RESERVED;
391 } else if (txtfmt_glsl_find_preprocessor(str) != -1) {fmt = FMT_TYPE_DIRECTIVE;
392 } else {fmt = FMT_TYPE_DEFAULT;
393 }
394
395 /* clang-format on */
396
397 return fmt;
398}
399
402/* -------------------------------------------------------------------- */
406static void txtfmt_glsl_format_line(SpaceText *st, TextLine *line, const bool do_next)
407{
408 FlattenString fs;
409 const char *str;
410 char *fmt;
411 char cont_orig, cont, find, prev = ' ';
412 int len, i;
413
414 /* Get continuation from previous line */
415 if (line->prev && line->prev->format != nullptr) {
416 fmt = line->prev->format;
417 cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
418 BLI_assert((FMT_CONT_ALL & cont) == cont);
419 }
420 else {
421 cont = FMT_CONT_NOP;
422 }
423
424 /* Get original continuation from this line */
425 if (line->format != nullptr) {
426 fmt = line->format;
427 cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */
428 BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig);
429 }
430 else {
431 cont_orig = 0xFF;
432 }
433
434 len = flatten_string(st, &fs, line->line);
435 str = fs.buf;
436 if (!text_check_format_len(line, len)) {
438 return;
439 }
440 fmt = line->format;
441
442 while (*str) {
443 /* Handle escape sequences by skipping both \ and next char */
444 if (*str == '\\') {
445 *fmt = prev;
446 fmt++;
447 str++;
448 if (*str == '\0') {
449 break;
450 }
451 *fmt = prev;
452 fmt++;
454 continue;
455 }
456 /* Handle continuations */
457 if (cont) {
458 /* C-Style comments */
459 if (cont & FMT_CONT_COMMENT_C) {
460 if (*str == '*' && *(str + 1) == '/') {
461 *fmt = FMT_TYPE_COMMENT;
462 fmt++;
463 str++;
464 *fmt = FMT_TYPE_COMMENT;
465 cont = FMT_CONT_NOP;
466 }
467 else {
468 *fmt = FMT_TYPE_COMMENT;
469 }
470 /* Handle other comments */
471 }
472 else {
473 find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\'';
474 if (*str == find) {
475 cont = 0;
476 }
477 *fmt = FMT_TYPE_STRING;
478 }
479
481 }
482 /* Not in a string... */
483 else {
484 /* Deal with comments first */
485 if (*str == '/' && *(str + 1) == '/') {
486 /* fill the remaining line */
487 text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - int(fmt - line->format));
488 }
489 /* C-Style (multi-line) comments */
490 else if (*str == '/' && *(str + 1) == '*') {
491 cont = FMT_CONT_COMMENT_C;
492 *fmt = FMT_TYPE_COMMENT;
493 fmt++;
494 str++;
495 *fmt = FMT_TYPE_COMMENT;
496 }
497 else if (ELEM(*str, '"', '\'')) {
498 /* Strings */
499 find = *str;
500 cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE;
501 *fmt = FMT_TYPE_STRING;
502 }
503 /* White-space (all white-space has been converted to spaces). */
504 else if (*str == ' ') {
505 *fmt = FMT_TYPE_WHITESPACE;
506 }
507 /* Numbers (digits not part of an identifier and periods followed by digits) */
508 else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) ||
509 (*str == '.' && text_check_digit(*(str + 1))))
510 {
511 *fmt = FMT_TYPE_NUMERAL;
512 }
513 /* Punctuation */
514 else if ((*str != '#') && text_check_delim(*str)) {
515 *fmt = FMT_TYPE_SYMBOL;
516 }
517 /* Identifiers and other text (no previous white-space or delimiters. so text continues). */
518 else if (prev == FMT_TYPE_DEFAULT) {
520 *fmt = FMT_TYPE_DEFAULT;
521 }
522 /* Not white-space, a digit, punctuation, or continuing text.
523 * Must be new, check for special words. */
524 else {
525 /* Keep aligned arguments for readability. */
526 /* clang-format off */
527
528 /* Special vars(v) or built-in keywords(b) */
529 /* keep in sync with `txtfmt_glsl_format_identifier()`. */
530 if ((i = txtfmt_glsl_find_specialvar(str)) != -1) { prev = FMT_TYPE_SPECIAL;
531 } else if ((i = txtfmt_glsl_find_builtinfunc(str)) != -1) { prev = FMT_TYPE_KEYWORD;
532 } else if ((i = txtfmt_glsl_find_reserved(str)) != -1) { prev = FMT_TYPE_RESERVED;
533 } else if ((i = txtfmt_glsl_find_preprocessor(str)) != -1) { prev = FMT_TYPE_DIRECTIVE;
534 }
535 /* clang-format on */
536
537 if (i > 0) {
538 if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */
539 text_format_fill(&str, &fmt, prev, i);
540 }
541 else {
542 text_format_fill_ascii(&str, &fmt, prev, i);
543 }
544 }
545 else {
547 *fmt = FMT_TYPE_DEFAULT;
548 }
549 }
550 }
551 prev = *fmt;
552 fmt++;
553 str++;
554 }
555
556 /* Terminate and add continuation char. */
557 *fmt = '\0';
558 fmt++;
559 *fmt = cont;
560
561 /* If continuation has changed and we're allowed, process the next line */
562 if (cont != cont_orig && do_next && line->next) {
563 txtfmt_glsl_format_line(st, line->next, do_next);
564 }
565
567}
568
571/* -------------------------------------------------------------------- */
592
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_glsl_format_identifier(const char *str)
static const char * text_format_glsl_literals_reserved_data[]
static int txtfmt_glsl_find_builtinfunc(const char *string)
static void txtfmt_glsl_format_line(SpaceText *st, TextLine *line, const bool do_next)
void ED_text_format_register_glsl()
static const Span< const char * > text_format_glsl_literals_builtinfunc(text_format_glsl_literals_builtinfunc_data, ARRAY_SIZE(text_format_glsl_literals_builtinfunc_data))
static int txtfmt_glsl_find_preprocessor(const char *string)
static const char * text_format_glsl_literals_builtinfunc_data[]
static int txtfmt_glsl_find_specialvar(const char *string)
static const char * text_format_glsl_literals_specialvar_data[]
static const Span< const char * > text_format_glsl_literals_reserved(text_format_glsl_literals_reserved_data, ARRAY_SIZE(text_format_glsl_literals_reserved_data))
static int txtfmt_glsl_find_reserved(const char *string)
static const Span< const char * > text_format_glsl_literals_specialvar(text_format_glsl_literals_specialvar_data, ARRAY_SIZE(text_format_glsl_literals_specialvar_data))