glsl/apps: Add GLSL compiler that translates source text into binary stream.
[mesa.git] / src / glsl / apps / compile.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <assert.h>
32 #include "../pp/sl_pp_public.h"
33 #include "../cl/sl_cl_parse.h"
34
35
36 int
37 main(int argc,
38 char *argv[])
39 {
40 FILE *in;
41 long size;
42 char *inbuf;
43 struct sl_pp_purify_options options;
44 char *outbuf;
45 char errmsg[100] = "";
46 unsigned int errline = 0;
47 struct sl_pp_context *context;
48 struct sl_pp_token_info *tokens;
49 unsigned int version;
50 unsigned int tokens_eaten;
51 struct sl_pp_token_info *outtokens;
52 FILE *out;
53 unsigned int i, j;
54 unsigned char *outbytes;
55 unsigned int cboutbytes;
56 unsigned int shader_type;
57
58 if (argc != 4) {
59 return 1;
60 }
61
62 if (!strcmp(argv[1], "fragment")) {
63 shader_type = 1;
64 } else if (!strcmp(argv[1], "vertex")) {
65 shader_type = 2;
66 } else {
67 return 1;
68 }
69
70 in = fopen(argv[2], "rb");
71 if (!in) {
72 return 1;
73 }
74
75 fseek(in, 0, SEEK_END);
76 size = ftell(in);
77 fseek(in, 0, SEEK_SET);
78
79 out = fopen(argv[3], "w");
80 if (!out) {
81 fclose(in);
82 return 1;
83 }
84
85 inbuf = malloc(size + 1);
86 if (!inbuf) {
87 fprintf(out, "$OOMERROR\n");
88
89 fclose(out);
90 fclose(in);
91 return 1;
92 }
93
94 if (fread(inbuf, 1, size, in) != size) {
95 fprintf(out, "$READERROR\n");
96
97 free(inbuf);
98 fclose(out);
99 fclose(in);
100 return 1;
101 }
102 inbuf[size] = '\0';
103
104 fclose(in);
105
106 memset(&options, 0, sizeof(options));
107
108 if (sl_pp_purify(inbuf, &options, &outbuf, errmsg, sizeof(errmsg), &errline)) {
109 fprintf(out, "$PURIFYERROR %s\n", errmsg);
110
111 free(inbuf);
112 fclose(out);
113 return 1;
114 }
115
116 free(inbuf);
117
118 context = sl_pp_context_create();
119 if (!context) {
120 fprintf(out, "$CONTEXERROR\n");
121
122 free(outbuf);
123 fclose(out);
124 return 1;
125 }
126
127 if (sl_pp_tokenise(context, outbuf, &tokens)) {
128 fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
129
130 sl_pp_context_destroy(context);
131 free(outbuf);
132 fclose(out);
133 return 1;
134 }
135
136 free(outbuf);
137
138 if (sl_pp_version(context, tokens, &version, &tokens_eaten)) {
139 fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
140
141 sl_pp_context_destroy(context);
142 free(tokens);
143 fclose(out);
144 return -1;
145 }
146
147 if (sl_pp_process(context, &tokens[tokens_eaten], &outtokens)) {
148 fprintf(out, "$ERROR: `%s'\n", sl_pp_context_error_message(context));
149
150 sl_pp_context_destroy(context);
151 free(tokens);
152 fclose(out);
153 return -1;
154 }
155
156 free(tokens);
157
158 for (i = j = 0; outtokens[i].token != SL_PP_EOF; i++) {
159 switch (outtokens[i].token) {
160 case SL_PP_NEWLINE:
161 case SL_PP_EXTENSION_REQUIRE:
162 case SL_PP_EXTENSION_ENABLE:
163 case SL_PP_EXTENSION_WARN:
164 case SL_PP_EXTENSION_DISABLE:
165 case SL_PP_LINE:
166 break;
167 default:
168 outtokens[j++] = outtokens[i];
169 }
170 }
171 outtokens[j] = outtokens[i];
172
173 if (sl_cl_compile(context, outtokens, shader_type, &outbytes, &cboutbytes) == 0) {
174 unsigned int i;
175 unsigned int line = 0;
176
177 fprintf(out, "\n/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED FROM THE FOLLOWING FILE: */");
178 fprintf(out, "\n/* %s */", argv[2]);
179 fprintf(out, "\n\n");
180
181 for (i = 0; i < cboutbytes; i++) {
182 unsigned int a;
183
184 if (outbytes[i] < 10) {
185 a = 1;
186 } else if (outbytes[i] < 100) {
187 a = 2;
188 } else {
189 a = 3;
190 }
191 if (i < cboutbytes - 1) {
192 a++;
193 }
194 if (line + a >= 100) {
195 fprintf (out, "\n");
196 line = 0;
197 }
198 line += a;
199 fprintf (out, "%u", outbytes[i]);
200 if (i < cboutbytes - 1) {
201 fprintf (out, ",");
202 }
203 }
204 fprintf (out, "\n");
205 free(outbytes);
206 }
207
208 sl_pp_context_destroy(context);
209 free(outtokens);
210 fclose(out);
211
212 return 0;
213 }