/
mojoshader-compiler.c
974 lines (841 loc) · 31 KB
1
2
3
4
5
6
7
8
9
10
11
/**
* MojoShader; generate shader programs from bytecode of compiled
* Direct3D shaders.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
#include <stdio.h>
#include <stdlib.h>
12
#include <string.h>
13
14
#include <assert.h>
15
16
#include "mojoshader.h"
17
18
19
20
#ifndef _WIN32
#define stricmp(a,b) strcasecmp(a,b)
#endif
21
22
23
static const char **include_paths = NULL;
static unsigned int include_path_count = 0;
24
#define MOJOSHADER_DEBUG_MALLOC 0
25
26
#if MOJOSHADER_DEBUG_MALLOC
27
static void *Malloc(int len, void *d)
28
29
30
31
32
33
34
35
36
37
{
void *ptr = malloc(len + sizeof (int));
int *store = (int *) ptr;
printf("malloc() %d bytes (%p)\n", len, ptr);
if (ptr == NULL) return NULL;
*store = len;
return (void *) (store + 1);
} // Malloc
38
static void Free(void *_ptr, void *d)
39
40
41
42
43
44
45
46
47
48
{
int *ptr = (((int *) _ptr) - 1);
int len = *ptr;
printf("free() %d bytes (%p)\n", len, ptr);
free(ptr);
} // Free
#else
#define Malloc NULL
#define Free NULL
#endif
49
50
51
52
53
54
55
56
static void fail(const char *err)
{
printf("%s.\n", err);
exit(1);
} // fail
57
static void print_unroll_attr(FILE *io, const int unroll)
58
59
{
if (unroll == 0)
60
fprintf(io, "[loop] ");
61
else if (unroll < 0)
62
fprintf(io, "[unroll] ");
63
else
64
fprintf(io, "[unroll(%d)] ", unroll);
65
66
67
} // print_unroll_attr
// !!! FIXME: this screws up on order of operations.
68
static void print_ast(FILE *io, const int substmt, const void *_ast)
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
{
const MOJOSHADER_astNode *ast = (const MOJOSHADER_astNode *) _ast;
const char *nl = substmt ? "" : "\n";
int typeint = 0;
static int indent = 0;
int isblock = 0;
int i;
// These _HAVE_ to be in the same order as MOJOSHADER_astNodeType!
static const char *binary[] =
{
",", "*", "/", "%", "+", "-", "<<", ">>", "<", ">", "<=", ">=", "==",
"!=", "&", "^", "|", "&&", "||", "=", "*=", "/=", "%=", "+=", "-=",
"<<=", ">>=", "&=", "^=", "|="
};
static const char *pre_unary[] = { "++", "--", "-", "~", "!" };
static const char *post_unary[] = { "++", "--" };
static const char *simple_stmt[] = { "", "break", "continue", "discard" };
static const char *inpmod[] = { "", "in ", "out ", "in out ", "uniform " };
static const char *fnstorage[] = { "", "inline " };
static const char *interpmod[] = {
"", " linear", " centroid", " nointerpolation",
" noperspective", " sample"
};
if (!ast) return;
typeint = (int) ast->ast.type;
#define DO_INDENT do { \
101
if (!substmt) { for (i = 0; i < indent; i++) fprintf(io, " "); } \
102
103
104
105
106
107
108
109
110
} while (0)
switch (ast->ast.type)
{
case MOJOSHADER_AST_OP_PREINCREMENT:
case MOJOSHADER_AST_OP_PREDECREMENT:
case MOJOSHADER_AST_OP_NEGATE:
case MOJOSHADER_AST_OP_COMPLEMENT:
case MOJOSHADER_AST_OP_NOT:
111
112
fprintf(io, "%s", pre_unary[(typeint-MOJOSHADER_AST_OP_START_RANGE_UNARY)-1]);
print_ast(io, 0, ast->unary.operand);
113
114
115
116
break;
case MOJOSHADER_AST_OP_POSTINCREMENT:
case MOJOSHADER_AST_OP_POSTDECREMENT:
117
118
print_ast(io, 0, ast->unary.operand);
fprintf(io, "%s", post_unary[typeint-MOJOSHADER_AST_OP_POSTINCREMENT]);
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
break;
case MOJOSHADER_AST_OP_MULTIPLY:
case MOJOSHADER_AST_OP_DIVIDE:
case MOJOSHADER_AST_OP_MODULO:
case MOJOSHADER_AST_OP_ADD:
case MOJOSHADER_AST_OP_SUBTRACT:
case MOJOSHADER_AST_OP_LSHIFT:
case MOJOSHADER_AST_OP_RSHIFT:
case MOJOSHADER_AST_OP_LESSTHAN:
case MOJOSHADER_AST_OP_GREATERTHAN:
case MOJOSHADER_AST_OP_LESSTHANOREQUAL:
case MOJOSHADER_AST_OP_GREATERTHANOREQUAL:
case MOJOSHADER_AST_OP_EQUAL:
case MOJOSHADER_AST_OP_NOTEQUAL:
case MOJOSHADER_AST_OP_BINARYAND:
case MOJOSHADER_AST_OP_BINARYXOR:
case MOJOSHADER_AST_OP_BINARYOR:
case MOJOSHADER_AST_OP_LOGICALAND:
case MOJOSHADER_AST_OP_LOGICALOR:
case MOJOSHADER_AST_OP_ASSIGN:
case MOJOSHADER_AST_OP_MULASSIGN:
case MOJOSHADER_AST_OP_DIVASSIGN:
case MOJOSHADER_AST_OP_MODASSIGN:
case MOJOSHADER_AST_OP_ADDASSIGN:
case MOJOSHADER_AST_OP_SUBASSIGN:
case MOJOSHADER_AST_OP_LSHIFTASSIGN:
case MOJOSHADER_AST_OP_RSHIFTASSIGN:
case MOJOSHADER_AST_OP_ANDASSIGN:
case MOJOSHADER_AST_OP_XORASSIGN:
case MOJOSHADER_AST_OP_ORASSIGN:
case MOJOSHADER_AST_OP_COMMA:
151
print_ast(io, 0, ast->binary.left);
152
153
if (ast->ast.type != MOJOSHADER_AST_OP_COMMA)
fprintf(io, " "); // no space before the comma.
154
fprintf(io, "%s ", binary[
155
(typeint - MOJOSHADER_AST_OP_START_RANGE_BINARY) - 1]);
156
print_ast(io, 0, ast->binary.right);
157
158
159
break;
case MOJOSHADER_AST_OP_DEREF_ARRAY:
160
161
162
163
print_ast(io, 0, ast->binary.left);
fprintf(io, "[");
print_ast(io, 0, ast->binary.right);
fprintf(io, "]");
164
165
166
break;
case MOJOSHADER_AST_OP_DEREF_STRUCT:
167
168
169
print_ast(io, 0, ast->derefstruct.identifier);
fprintf(io, ".");
fprintf(io, "%s", ast->derefstruct.member);
170
171
172
break;
case MOJOSHADER_AST_OP_CONDITIONAL:
173
174
175
176
177
print_ast(io, 0, ast->ternary.left);
fprintf(io, " ? ");
print_ast(io, 0, ast->ternary.center);
fprintf(io, " : ");
print_ast(io, 0, ast->ternary.right);
178
179
180
break;
case MOJOSHADER_AST_OP_IDENTIFIER:
181
fprintf(io, "%s", ast->identifier.identifier);
182
183
184
break;
case MOJOSHADER_AST_OP_INT_LITERAL:
185
fprintf(io, "%d", ast->intliteral.value);
186
187
188
189
190
191
192
break;
case MOJOSHADER_AST_OP_FLOAT_LITERAL:
{
const float f = ast->floatliteral.value;
const long long flr = (long long) f;
if (((float) flr) == f)
193
fprintf(io, "%lld.0", flr);
194
else
195
fprintf(io, "%.16g", f);
196
197
198
199
break;
} // case
case MOJOSHADER_AST_OP_STRING_LITERAL:
200
fprintf(io, "\"%s\"", ast->stringliteral.string);
201
202
203
break;
case MOJOSHADER_AST_OP_BOOLEAN_LITERAL:
204
fprintf(io, "%s", ast->boolliteral.value ? "true" : "false");
205
206
207
break;
case MOJOSHADER_AST_ARGUMENTS:
208
print_ast(io, 0, ast->arguments.argument);
209
210
if (ast->arguments.next != NULL)
{
211
212
fprintf(io, ", ");
print_ast(io, 0, ast->arguments.next);
213
214
215
216
} // if
break;
case MOJOSHADER_AST_OP_CALLFUNC:
217
218
219
220
print_ast(io, 0, ast->callfunc.identifier);
fprintf(io, "(");
print_ast(io, 0, ast->callfunc.args);
fprintf(io, ")");
221
222
223
break;
case MOJOSHADER_AST_OP_CONSTRUCTOR:
224
225
226
fprintf(io, "%s(", ast->constructor.datatype);
print_ast(io, 0, ast->constructor.args);
fprintf(io, ")");
227
228
229
break;
case MOJOSHADER_AST_OP_CAST:
230
231
232
fprintf(io, "(%s) (", ast->cast.datatype);
print_ast(io, 0, ast->cast.operand);
fprintf(io, ")");
233
234
235
236
break;
case MOJOSHADER_AST_STATEMENT_EXPRESSION:
DO_INDENT;
237
238
239
print_ast(io, 0, ast->exprstmt.expr); // !!! FIXME: This is named badly...
fprintf(io, ";%s", nl);
print_ast(io, 0, ast->exprstmt.next);
240
241
242
243
break;
case MOJOSHADER_AST_STATEMENT_IF:
DO_INDENT;
244
245
246
fprintf(io, "if (");
print_ast(io, 0, ast->ifstmt.expr);
fprintf(io, ")\n");
247
248
isblock = ast->ifstmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
249
print_ast(io, 0, ast->ifstmt.statement);
250
if (!isblock) indent--;
251
print_ast(io, 0, ast->ifstmt.next);
252
253
254
255
break;
case MOJOSHADER_AST_STATEMENT_TYPEDEF:
DO_INDENT;
256
257
258
print_ast(io, 1, ast->typedefstmt.type_info);
fprintf(io, "%s", nl);
print_ast(io, 0, ast->typedefstmt.next);
259
260
261
262
263
264
265
break;
case MOJOSHADER_AST_STATEMENT_SWITCH:
DO_INDENT;
switch ( ast->switchstmt.attributes )
{
case MOJOSHADER_AST_SWITCHATTR_NONE: break;
266
267
268
269
case MOJOSHADER_AST_SWITCHATTR_FLATTEN: fprintf(io, "[flatten] "); break;
case MOJOSHADER_AST_SWITCHATTR_BRANCH: fprintf(io, "[branch] "); break;
case MOJOSHADER_AST_SWITCHATTR_FORCECASE: fprintf(io, "[forcecase] "); break;
case MOJOSHADER_AST_SWITCHATTR_CALL: fprintf(io, "[call] "); break;
270
271
} // switch
272
273
274
fprintf(io, "switch (");
print_ast(io, 0, ast->switchstmt.expr);
fprintf(io, ")\n");
275
DO_INDENT;
276
fprintf(io, "{\n");
277
indent++;
278
print_ast(io, 0, ast->switchstmt.cases);
279
indent--;
280
fprintf(io, "\n");
281
DO_INDENT;
282
283
fprintf(io, "}\n");
print_ast(io, 0, ast->switchstmt.next);
284
285
286
287
break;
case MOJOSHADER_AST_SWITCH_CASE:
DO_INDENT;
288
289
290
fprintf(io, "case ");
print_ast(io, 0, ast->cases.expr);
fprintf(io, ":\n");
291
292
isblock = ast->cases.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
293
print_ast(io, 0, ast->cases.statement);
294
if (!isblock) indent--;
295
print_ast(io, 0, ast->cases.next);
296
297
298
299
break;
case MOJOSHADER_AST_STATEMENT_STRUCT:
DO_INDENT;
300
301
302
print_ast(io, 0, ast->structstmt.struct_info);
fprintf(io, ";%s%s", nl, nl); // always space these out.
print_ast(io, 0, ast->structstmt.next);
303
304
305
306
break;
case MOJOSHADER_AST_STATEMENT_VARDECL:
DO_INDENT;
307
308
309
print_ast(io, 1, ast->vardeclstmt.declaration);
fprintf(io, ";%s", nl);
print_ast(io, 0, ast->vardeclstmt.next);
310
311
312
313
break;
case MOJOSHADER_AST_STATEMENT_BLOCK:
DO_INDENT;
314
fprintf(io, "{\n");
315
indent++;
316
print_ast(io, 0, ast->blockstmt.statements);
317
318
indent--;
DO_INDENT;
319
320
fprintf(io, "}\n");
print_ast(io, 0, ast->blockstmt.next);
321
322
323
324
break;
case MOJOSHADER_AST_STATEMENT_FOR:
DO_INDENT;
325
326
327
print_unroll_attr(io, ast->forstmt.unroll);
fprintf(io, "for (");
print_ast(io, 1, ast->forstmt.var_decl);
328
329
if (ast->forstmt.initializer != NULL)
{
330
331
fprintf(io, " = ");
print_ast(io, 1, ast->forstmt.initializer);
332
} // if
333
334
335
336
fprintf(io, "; ");
print_ast(io, 1, ast->forstmt.looptest);
fprintf(io, "; ");
print_ast(io, 1, ast->forstmt.counter);
337
338
fprintf(io, ")\n");
339
340
isblock = ast->forstmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
341
print_ast(io, 0, ast->forstmt.statement);
342
343
if (!isblock) indent--;
344
print_ast(io, 0, ast->forstmt.next);
345
346
347
348
break;
case MOJOSHADER_AST_STATEMENT_DO:
DO_INDENT;
349
350
print_unroll_attr(io, ast->dostmt.unroll);
fprintf(io, "do\n");
351
352
353
isblock = ast->dostmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
354
print_ast(io, 0, ast->dostmt.statement);
355
356
357
if (!isblock) indent--;
DO_INDENT;
358
359
360
fprintf(io, "while (");
print_ast(io, 0, ast->dostmt.expr);
fprintf(io, ");\n");
361
362
print_ast(io, 0, ast->dostmt.next);
363
364
365
366
break;
case MOJOSHADER_AST_STATEMENT_WHILE:
DO_INDENT;
367
368
369
370
print_unroll_attr(io, ast->whilestmt.unroll);
fprintf(io, "while (");
print_ast(io, 0, ast->whilestmt.expr);
fprintf(io, ")\n");
371
372
373
isblock = ast->whilestmt.statement->ast.type == MOJOSHADER_AST_STATEMENT_BLOCK;
if (!isblock) indent++;
374
print_ast(io, 0, ast->whilestmt.statement);
375
376
if (!isblock) indent--;
377
print_ast(io, 0, ast->whilestmt.next);
378
379
380
381
break;
case MOJOSHADER_AST_STATEMENT_RETURN:
DO_INDENT;
382
fprintf(io, "return");
383
384
if (ast->returnstmt.expr)
{
385
386
fprintf(io, " ");
print_ast(io, 0, ast->returnstmt.expr);
387
} // if
388
389
fprintf(io, ";%s", nl);
print_ast(io, 0, ast->returnstmt.next);
390
391
392
393
394
395
396
break;
case MOJOSHADER_AST_STATEMENT_EMPTY:
case MOJOSHADER_AST_STATEMENT_BREAK:
case MOJOSHADER_AST_STATEMENT_CONTINUE:
case MOJOSHADER_AST_STATEMENT_DISCARD:
DO_INDENT;
397
fprintf(io, "%s;%s",
398
399
simple_stmt[(typeint-MOJOSHADER_AST_STATEMENT_START_RANGE)-1],
nl);
400
print_ast(io, 0, ast->stmt.next);
401
402
403
404
break;
case MOJOSHADER_AST_COMPUNIT_FUNCTION:
DO_INDENT;
405
print_ast(io, 0, ast->funcunit.declaration);
406
if (ast->funcunit.definition == NULL)
407
fprintf(io, ";%s", nl);
408
409
else
{
410
411
412
fprintf(io, "%s", nl);
print_ast(io, 0, ast->funcunit.definition);
fprintf(io, "%s", nl);
413
} // else
414
print_ast(io, 0, ast->funcunit.next);
415
416
417
418
break;
case MOJOSHADER_AST_COMPUNIT_TYPEDEF:
DO_INDENT;
419
420
421
print_ast(io, 0, ast->typedefunit.type_info);
fprintf(io, "%s", nl);
print_ast(io, 0, ast->typedefunit.next);
422
423
424
425
break;
case MOJOSHADER_AST_COMPUNIT_STRUCT:
DO_INDENT;
426
427
428
print_ast(io, 0, ast->structunit.struct_info);
fprintf(io, ";%s%s", nl, nl); // always space these out.
print_ast(io, 0, ast->structunit.next);
429
430
431
432
break;
case MOJOSHADER_AST_COMPUNIT_VARIABLE:
DO_INDENT;
433
434
print_ast(io, 1, ast->varunit.declaration);
fprintf(io, ";%s", nl);
435
436
437
if (ast->varunit.next &&
ast->varunit.next->ast.type!=MOJOSHADER_AST_COMPUNIT_VARIABLE)
{
438
fprintf(io, "%s", nl); // group vars together, and space out other things.
439
} // if
440
print_ast(io, 0, ast->varunit.next);
441
442
443
break;
case MOJOSHADER_AST_SCALAR_OR_ARRAY:
444
fprintf(io, "%s", ast->soa.identifier);
445
446
if (ast->soa.isarray)
{
447
448
449
fprintf(io, "[");
print_ast(io, 0, ast->soa.dimension);
fprintf(io, "]");
450
451
452
453
454
} // if
break;
case MOJOSHADER_AST_TYPEDEF:
DO_INDENT;
455
fprintf(io, "typedef %s%s ",
456
ast->typdef.isconst ? "const " : "", ast->typdef.datatype);
457
458
print_ast(io, 0, ast->typdef.details);
fprintf(io, ";%s", nl);
459
460
461
break;
case MOJOSHADER_AST_FUNCTION_PARAMS:
462
463
fprintf(io, "%s", inpmod[(int) ast->params.input_modifier]);
fprintf(io, "%s %s", ast->params.datatype, ast->params.identifier);
464
if (ast->params.semantic)
465
466
fprintf(io, " : %s", ast->params.semantic);
fprintf(io, "%s", interpmod[(int) ast->params.interpolation_modifier]);
467
468
469
if (ast->params.initializer)
{
470
471
fprintf(io, " = ");
print_ast(io, 0, ast->params.initializer);
472
473
474
475
} // if
if (ast->params.next)
{
476
477
fprintf(io, ", ");
print_ast(io, 0, ast->params.next);
478
479
480
481
} // if
break;
case MOJOSHADER_AST_FUNCTION_SIGNATURE:
482
483
fprintf(io, "%s", fnstorage[(int) ast->funcsig.storage_class]);
fprintf(io, "%s %s(",
484
485
ast->funcsig.datatype ? ast->funcsig.datatype : "void",
ast->funcsig.identifier);
486
487
print_ast(io, 0, ast->funcsig.params);
fprintf(io, ")");
488
if (ast->funcsig.semantic)
489
fprintf(io, " : %s", ast->funcsig.semantic);
490
491
492
break;
case MOJOSHADER_AST_STRUCT_DECLARATION:
493
fprintf(io, "struct %s\n", ast->structdecl.name);
494
DO_INDENT;
495
fprintf(io, "{\n");
496
indent++;
497
print_ast(io, 0, ast->structdecl.members);
498
499
indent--;
DO_INDENT;
500
fprintf(io, "}");
501
502
503
504
break;
case MOJOSHADER_AST_STRUCT_MEMBER:
DO_INDENT;
505
506
507
fprintf(io, "%s", interpmod[(int)ast->structmembers.interpolation_mod]);
fprintf(io, "%s ", ast->structmembers.datatype);
print_ast(io, 0, ast->structmembers.details);
508
if (ast->structmembers.semantic)
509
510
511
fprintf(io, " : %s", ast->structmembers.semantic);
fprintf(io, ";%s", nl);
print_ast(io, 0, ast->structmembers.next);
512
513
514
515
516
break;
case MOJOSHADER_AST_VARIABLE_DECLARATION:
DO_INDENT;
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_EXTERN)
517
fprintf(io, "extern ");
518
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_NOINTERPOLATION)
519
fprintf(io, "nointerpolation ");
520
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_SHARED)
521
fprintf(io, "shared");
522
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_STATIC)
523
fprintf(io, "static ");
524
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_UNIFORM)
525
fprintf(io, "uniform ");
526
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_VOLATILE)
527
fprintf(io, "nointerpolation ");
528
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_CONST)
529
fprintf(io, "const ");
530
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_ROWMAJOR)
531
fprintf(io, "rowmajor ");
532
if (ast->vardecl.attributes & MOJOSHADER_AST_VARATTR_COLUMNMAJOR)
533
fprintf(io, "columnmajor ");
534
535
if (ast->vardecl.datatype)
536
fprintf(io, "%s", ast->vardecl.datatype);
537
else
538
539
540
print_ast(io, 0, ast->vardecl.anonymous_datatype);
fprintf(io, " ");
print_ast(io, 0, ast->vardecl.details);
541
if (ast->vardecl.semantic)
542
fprintf(io, " : %s", ast->vardecl.semantic);
543
544
if (ast->vardecl.annotations)
{
545
546
fprintf(io, " ");
print_ast(io, 0, ast->vardecl.annotations);
547
548
549
} // if
if (ast->vardecl.initializer != NULL)
{
550
551
fprintf(io, " = ");
print_ast(io, 0, ast->vardecl.initializer);
552
} // if
553
print_ast(io, 0, ast->vardecl.lowlevel);
554
555
if (ast->vardecl.next == NULL)
556
fprintf(io, "%s", nl);
557
558
559
else
{
const int attr = ast->vardecl.next->attributes;
560
fprintf(io, ", ");
561
ast->vardecl.next->attributes = 0;
562
print_ast(io, 1, ast->vardecl.next);
563
564
565
566
567
ast->vardecl.next->attributes = attr;
} // if
break;
case MOJOSHADER_AST_PACK_OFFSET:
568
fprintf(io, " : packoffset(%s%s%s)", ast->packoffset.ident1,
569
570
571
572
573
ast->packoffset.ident2 ? "." : "",
ast->packoffset.ident2 ? ast->packoffset.ident2 : "");
break;
case MOJOSHADER_AST_VARIABLE_LOWLEVEL:
574
print_ast(io, 0, ast->varlowlevel.packoffset);
575
if (ast->varlowlevel.register_name)
576
fprintf(io, " : register(%s)", ast->varlowlevel.register_name);
577
578
579
580
581
break;
case MOJOSHADER_AST_ANNOTATION:
{
const MOJOSHADER_astAnnotations *a = &ast->annotations;
582
fprintf(io, "<");
583
584
while (a)
{
585
fprintf(io, " %s ", a->datatype);
586
587
if (a->initializer != NULL)
{
588
589
fprintf(io, " = ");
print_ast(io, 0, a->initializer);
590
591
} // if
if (a->next)
592
fprintf(io, ",");
593
594
a = a->next;
} // while
595
fprintf(io, " >");
596
597
598
599
600
601
602
603
604
605
606
break;
} // case
default:
assert(0 && "unexpected type");
break;
} // switch
#undef DO_INDENT
} // print_ast
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
static int open_include(MOJOSHADER_includeType inctype, const char *fname,
const char *parent, const char **outdata,
unsigned int *outbytes, MOJOSHADER_malloc m,
MOJOSHADER_free f, void *d)
{
int i;
for (i = 0; i < include_path_count; i++)
{
const char *path = include_paths[i];
const size_t len = strlen(path) + strlen(fname) + 2;
char *buf = (char *) m(len, d);
if (buf == NULL)
return 0;
snprintf(buf, len, "%s/%s", path, fname);
FILE *io = fopen(buf, "rb");
f(buf, d);
if (io == NULL)
continue;
if (fseek(io, 0, SEEK_END) != -1)
{
const long fsize = ftell(io);
if ((fsize == -1) || (fseek(io, 0, SEEK_SET) == -1))
{
fclose(io);
return 0;
} // if
char *data = (char *) m(fsize, d);
if (data == NULL)
{
fclose(io);
return 0;
} // if
if (fread(data, fsize, 1, io) != 1)
{
f(data, d);
fclose(io);
return 0;
} // if
fclose(io);
*outdata = data;
*outbytes = (unsigned int) fsize;
return 1;
} // if
} // for
return 0;
} // open_include
662
663
static void close_include(const char *data, MOJOSHADER_malloc m,
MOJOSHADER_free f, void *d)
664
665
666
667
668
{
f((void *) data, d);
} // close_include
669
static int preprocess(const char *fname, const char *buf, int len,
670
671
const char *outfile,
const MOJOSHADER_preprocessorDefine *defs,
672
unsigned int defcount, FILE *io)
673
674
675
676
{
const MOJOSHADER_preprocessData *pd;
int retval = 0;
677
678
pd = MOJOSHADER_preprocess(fname, buf, len, defs, defcount, open_include,
close_include, Malloc, Free, NULL);
679
680
681
682
683
684
if (pd->error_count > 0)
{
int i;
for (i = 0; i < pd->error_count; i++)
{
685
fprintf(stderr, "%s:%d: ERROR: %s\n",
686
pd->errors[i].filename ? pd->errors[i].filename : "???",
687
688
689
690
691
692
693
694
pd->errors[i].error_position,
pd->errors[i].error);
} // for
} // if
else
{
if (pd->output != NULL)
{
695
696
const int len = pd->output_len;
if ((len) && (fwrite(pd->output, len, 1, io) != 1))
697
printf(" ... fwrite('%s') failed.\n", outfile);
698
else if ((outfile != NULL) && (fclose(io) == EOF))
699
700
701
702
703
704
705
706
printf(" ... fclose('%s') failed.\n", outfile);
else
retval = 1;
} // if
} // else
MOJOSHADER_freePreprocessData(pd);
return retval;
707
} // preprocess
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
static int assemble(const char *fname, const char *buf, int len,
const char *outfile,
const MOJOSHADER_preprocessorDefine *defs,
unsigned int defcount, FILE *io)
{
const MOJOSHADER_parseData *pd;
int retval = 0;
pd = MOJOSHADER_assemble(fname, buf, len, NULL, 0, NULL, 0,
defs, defcount, open_include, close_include,
Malloc, Free, NULL);
if (pd->error_count > 0)
{
int i;
for (i = 0; i < pd->error_count; i++)
{
727
fprintf(stderr, "%s:%d: ERROR: %s\n",
728
729
730
731
732
733
734
735
736
pd->errors[i].filename ? pd->errors[i].filename : "???",
pd->errors[i].error_position,
pd->errors[i].error);
} // for
} // if
else
{
if (pd->output != NULL)
{
737
738
const int len = pd->output_len;
if ((len) && (fwrite(pd->output, len, 1, io) != 1))
739
740
741
742
743
744
745
746
747
748
749
750
printf(" ... fwrite('%s') failed.\n", outfile);
else if ((outfile != NULL) && (fclose(io) == EOF))
printf(" ... fclose('%s') failed.\n", outfile);
else
retval = 1;
} // if
} // else
MOJOSHADER_freeParseData(pd);
return retval;
} // assemble
751
752
753
754
static int ast(const char *fname, const char *buf, int len,
const char *outfile, const MOJOSHADER_preprocessorDefine *defs,
unsigned int defcount, FILE *io)
{
755
756
const MOJOSHADER_astData *ad;
int retval = 0;
757
758
ad = MOJOSHADER_parseAst(MOJOSHADER_SRC_PROFILE_HLSL_PS_1_1, // !!! FIXME
759
760
fname, buf, len, defs, defcount,
open_include, close_include, Malloc, Free, NULL);
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
if (ad->error_count > 0)
{
int i;
for (i = 0; i < ad->error_count; i++)
{
fprintf(stderr, "%s:%d: ERROR: %s\n",
ad->errors[i].filename ? ad->errors[i].filename : "???",
ad->errors[i].error_position,
ad->errors[i].error);
} // for
} // if
else
{
print_ast(io, 0, ad->ast);
if ((outfile != NULL) && (fclose(io) == EOF))
printf(" ... fclose('%s') failed.\n", outfile);
else
retval = 1;
} // else
781
MOJOSHADER_freeAstData(ad);
782
783
return retval;
784
} // ast
785
786
787
788
789
790
static int compile(const char *fname, const char *buf, int len,
const char *outfile,
const MOJOSHADER_preprocessorDefine *defs,
unsigned int defcount, FILE *io)
{
791
792
793
// !!! FIXME: write me.
//const MOJOSHADER_parseData *pd;
//int retval = 0;
794
795
796
MOJOSHADER_compile(MOJOSHADER_SRC_PROFILE_HLSL_PS_1_1, // !!! FIXME
fname, buf, len, defs, defcount,
797
798
799
800
open_include, close_include,
Malloc, Free, NULL);
return 1;
} // compile
801
802
803
804
typedef enum
{
ACTION_UNKNOWN,
805
ACTION_VERSION,
806
807
ACTION_PREPROCESS,
ACTION_ASSEMBLE,
808
ACTION_AST,
809
ACTION_COMPILE,
810
811
812
} Action;
813
814
int main(int argc, char **argv)
{
815
Action action = ACTION_UNKNOWN;
816
int retval = 1;
817
818
819
const char *infile = NULL;
const char *outfile = NULL;
int i;
820
821
822
823
MOJOSHADER_preprocessorDefine *defs = NULL;
unsigned int defcount = 0;
824
825
826
827
include_paths = (const char **) malloc(sizeof (char *));
include_paths[0] = ".";
include_path_count = 1;
828
// !!! FIXME: clean this up.
829
830
831
832
for (i = 1; i < argc; i++)
{
const char *arg = argv[i];
833
834
if (strcmp(arg, "-P") == 0)
{
835
if ((action != ACTION_UNKNOWN) && (action != ACTION_PREPROCESS))
836
837
838
839
840
841
fail("Multiple actions specified");
action = ACTION_PREPROCESS;
} // if
else if (strcmp(arg, "-A") == 0)
{
842
if ((action != ACTION_UNKNOWN) && (action != ACTION_ASSEMBLE))
843
844
845
846
fail("Multiple actions specified");
action = ACTION_ASSEMBLE;
} // else if
847
848
849
850
851
852
853
else if (strcmp(arg, "-T") == 0)
{
if ((action != ACTION_UNKNOWN) && (action != ACTION_AST))
fail("Multiple actions specified");
action = ACTION_AST;
} // else if
854
855
856
857
858
859
860
else if (strcmp(arg, "-C") == 0)
{
if ((action != ACTION_UNKNOWN) && (action != ACTION_COMPILE))
fail("Multiple actions specified");
action = ACTION_COMPILE;
} // else if
861
862
863
864
865
866
867
else if ((strcmp(arg, "-V") == 0) || (strcmp(arg, "--version") == 0))
{
if ((action != ACTION_UNKNOWN) && (action != ACTION_VERSION))
fail("Multiple actions specified");
action = ACTION_VERSION;
} // else if
868
else if (strcmp(arg, "-o") == 0)
869
870
{
if (outfile != NULL)
871
fail("multiple output files specified");
872
873
874
arg = argv[++i];
if (arg == NULL)
875
fail("no filename after '-o'");
876
877
878
outfile = arg;
} // if
879
else if (strcmp(arg, "-I") == 0)
880
881
882
{
arg = argv[++i];
if (arg == NULL)
883
884
fail("no path after '-I'");
885
886
887
888
889
890
include_paths = (const char **) realloc(include_paths,
(include_path_count+1) * sizeof (char *));
include_paths[include_path_count] = arg;
include_path_count++;
} // if
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
else if (strncmp(arg, "-D", 2) == 0)
{
arg += 2;
char *ident = strdup(arg);
char *ptr = strchr(ident, '=');
const char *val = "";
if (ptr)
{
*ptr = '\0';
val = ptr+1;
} // if
defs = (MOJOSHADER_preprocessorDefine *) realloc(defs,
(defcount+1) * sizeof (MOJOSHADER_preprocessorDefine));
defs[defcount].identifier = ident;
defs[defcount].definition = val;
defcount++;
} // else if
else
{
if (infile != NULL)
913
fail("multiple input files specified");
914
915
916
917
infile = arg;
} // else
} // for
918
919
920
if (action == ACTION_UNKNOWN)
action = ACTION_ASSEMBLE;
921
922
923
924
925
926
if (action == ACTION_VERSION)
{
printf("mojoshader-compiler, changeset %s\n", MOJOSHADER_CHANGESET);
return 0;
} // if
927
if (infile == NULL)
928
fail("no input file specified");
929
930
931
FILE *io = fopen(infile, "rb");
if (io == NULL)
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
fail("failed to open input file");
fseek(io, 0, SEEK_END);
long fsize = ftell(io);
fseek(io, 0, SEEK_SET);
if (fsize == -1)
fsize = 1000000;
char *buf = (char *) malloc(fsize);
const int rc = fread(buf, 1, fsize, io);
fclose(io);
if (rc == EOF)
fail("failed to read input file");
FILE *outio = outfile ? fopen(outfile, "wb") : stdout;
if (outio == NULL)
fail("failed to open output file");
if (action == ACTION_PREPROCESS)
retval = (!preprocess(infile, buf, rc, outfile, defs, defcount, outio));
else if (action == ACTION_ASSEMBLE)
retval = (!assemble(infile, buf, rc, outfile, defs, defcount, outio));
954
955
else if (action == ACTION_AST)
retval = (!ast(infile, buf, rc, outfile, defs, defcount, outio));
956
957
else if (action == ACTION_COMPILE)
retval = (!compile(infile, buf, rc, outfile, defs, defcount, outio));
958
959
960
961
962
if ((retval != 0) && (outfile != NULL))
remove(outfile);
free(buf);
963
964
for (i = 0; i < defcount; i++)
965
free((void *) defs[i].identifier);
966
967
free(defs);
968
969
free(include_paths);
970
971
972
return retval;
} // main
973
// end of mojoshader-compiler.c ...