7 #include <orc/orcparse.h>
16 * @short_description: Parse Orc source code
20 typedef struct _OrcParser OrcParser;
31 OrcOpcodeSet *opcode_set;
33 OrcProgram *error_program;
35 OrcProgram **programs;
44 static void orc_parse_get_line (OrcParser *parser);
45 static OrcStaticOpcode * get_opcode (OrcParser *parser, const char *opcode);
46 static void orc_parse_log (OrcParser *parser, const char *format, ...);
47 static int opcode_n_args (OrcStaticOpcode *opcode);
48 static void orc_parse_sanity_check (OrcParser *parser, OrcProgram *program);
52 orc_parse (const char *code, OrcProgram ***programs)
54 return orc_parse_full (code, programs, NULL);
58 orc_parse_full (const char *code, OrcProgram ***programs, char **log)
61 OrcParser *parser = &_parser;
62 char *init_function = NULL;
64 memset (parser, 0, sizeof(*parser));
67 parser->code_length = strlen (code);
68 parser->line_number = 0;
70 parser->opcode_set = orc_opcode_set_get ("sys");
71 parser->log = malloc(100);
72 parser->log_alloc = 100;
75 while (parser->p[0] != 0) {
81 orc_parse_get_line (parser);
85 //printf("%d: %s\n", parser->line_number, parser->line);
87 while (p[0] == ' ' || p[0] == '\t') p++;
94 //printf("comment: %s\n", p+1);
101 if (p[0] == ' ' || p[0] == '\t' || p[0] == ',') p++;
102 if (p[0] == 0 || p[0] == '#') break;
105 while (p[0] != 0 && p[0] != ' ' && p[0] != '\t' && p[0] != ',') p++;
118 for(i=0;i<n_tokens;i++){
119 //printf("'%s' ", token[i]);
124 if (token[0][0] == '.') {
125 if (strcmp (token[0], ".function") == 0) {
126 if (parser->program) {
127 orc_parse_sanity_check (parser, parser->program);
129 parser->program = orc_program_new ();
130 orc_program_set_name (parser->program, token[1]);
131 if (parser->n_programs == parser->n_programs_alloc) {
132 parser->n_programs_alloc += 32;
133 parser->programs = realloc (parser->programs,
134 sizeof(OrcProgram *)*parser->n_programs_alloc);
136 parser->programs[parser->n_programs] = parser->program;
137 parser->n_programs++;
138 parser->creg_index = 1;
139 } else if (strcmp (token[0], ".init") == 0) {
140 if (init_function) free (init_function);
142 orc_parse_log (parser, "error: line %d: .init without function name\n",
143 parser->line_number);
145 init_function = strdup (token[1]);
147 } else if (strcmp (token[0], ".flags") == 0) {
149 for(i=1;i<n_tokens;i++){
150 if (!strcmp (token[i], "2d")) {
151 orc_program_set_2d (parser->program);
154 } else if (strcmp (token[0], ".n") == 0) {
155 int size = strtol (token[1], NULL, 0);
156 orc_program_set_constant_n (parser->program, size);
157 } else if (strcmp (token[0], ".m") == 0) {
158 int size = strtol (token[1], NULL, 0);
159 orc_program_set_constant_m (parser->program, size);
160 } else if (strcmp (token[0], ".source") == 0) {
161 int size = strtol (token[1], NULL, 0);
163 var = orc_program_add_source (parser->program, size, token[2]);
165 orc_program_set_type_name (parser->program, var, token[3]);
167 } else if (strcmp (token[0], ".dest") == 0) {
168 int size = strtol (token[1], NULL, 0);
170 var = orc_program_add_destination (parser->program, size, token[2]);
172 orc_program_set_type_name (parser->program, var, token[3]);
174 } else if (strcmp (token[0], ".accumulator") == 0) {
175 int size = strtol (token[1], NULL, 0);
177 var = orc_program_add_accumulator (parser->program, size, token[2]);
179 orc_program_set_type_name (parser->program, var, token[3]);
181 } else if (strcmp (token[0], ".temp") == 0) {
182 int size = strtol (token[1], NULL, 0);
183 orc_program_add_temporary (parser->program, size, token[2]);
184 } else if (strcmp (token[0], ".param") == 0) {
185 int size = strtol (token[1], NULL, 0);
186 orc_program_add_parameter (parser->program, size, token[2]);
187 } else if (strcmp (token[0], ".longparam") == 0) {
188 int size = strtol (token[1], NULL, 0);
189 orc_program_add_parameter_int64 (parser->program, size, token[2]);
190 } else if (strcmp (token[0], ".const") == 0) {
191 int size = strtol (token[1], NULL, 0);
193 orc_program_add_constant_str (parser->program, size, token[3], token[2]);
194 } else if (strcmp (token[0], ".floatparam") == 0) {
195 int size = strtol (token[1], NULL, 0);
196 orc_program_add_parameter_float (parser->program, size, token[2]);
197 } else if (strcmp (token[0], ".doubleparam") == 0) {
198 int size = strtol (token[1], NULL, 0);
199 orc_program_add_parameter_double (parser->program, size, token[2]);
201 orc_parse_log (parser, "error: line %d: unknown directive: %s\n",
202 parser->line_number, token[0]);
206 unsigned int flags = 0;
209 if (strcmp (token[0], "x4") == 0) {
210 flags |= ORC_INSTRUCTION_FLAG_X4;
212 } else if (strcmp (token[0], "x2") == 0) {
213 flags |= ORC_INSTRUCTION_FLAG_X2;
217 o = get_opcode (parser, token[offset]);
220 int n_args = opcode_n_args (o);
223 if (n_tokens != 1 + offset + n_args) {
224 orc_parse_log (parser, "error: line %d: too %s arguments for %s (expected %d)\n",
225 parser->line_number, (n_tokens < 1+offset+n_args) ? "few" : "many",
226 token[offset], n_args);
229 for(i=offset+1;i<n_tokens;i++){
232 d = strtod (token[i], &end);
233 if (end != token[i]) {
234 orc_program_add_constant_str (parser->program, 0, token[i],
239 if (n_tokens - offset == 5) {
240 orc_program_append_str_2 (parser->program, token[offset], flags,
241 token[offset+1], token[offset+2], token[offset+3], token[offset+4]);
242 } else if (n_tokens - offset == 4) {
243 orc_program_append_str_2 (parser->program, token[offset], flags,
244 token[offset+1], token[offset+2], token[offset+3], NULL);
246 orc_program_append_str_2 (parser->program, token[offset], flags,
247 token[offset+1], token[offset+2], NULL, NULL);
250 orc_parse_log (parser, "error: line %d: unknown opcode: %s\n",
257 if (parser->program) {
258 orc_parse_sanity_check (parser, parser->program);
261 if (parser->line) free (parser->line);
268 if (parser->programs[0]) {
269 parser->programs[0]->init_function = init_function;
271 *programs = parser->programs;
272 return parser->n_programs;
275 static OrcStaticOpcode *
276 get_opcode (OrcParser *parser, const char *opcode)
280 for(i=0;i<parser->opcode_set->n_opcodes;i++){
281 if (strcmp (opcode, parser->opcode_set->opcodes[i].name) == 0) {
282 return parser->opcode_set->opcodes + i;
290 opcode_n_args (OrcStaticOpcode *opcode)
294 for(i=0;i<ORC_STATIC_OPCODE_N_DEST;i++){
295 if (opcode->dest_size[i] != 0) n++;
297 for(i=0;i<ORC_STATIC_OPCODE_N_SRC;i++){
298 if (opcode->src_size[i] != 0) n++;
304 orc_parse_log_valist (OrcParser *parser, const char *format, va_list args)
309 if (parser->error_program != parser->program) {
310 sprintf(s, "In function %s:\n", parser->program->name);
313 if (parser->log_size + len + 1 >= parser->log_alloc) {
314 parser->log_alloc += 100;
315 parser->log = realloc (parser->log, parser->log_alloc);
318 strcpy (parser->log + parser->log_size, s);
319 parser->log_size += len;
320 parser->error_program = parser->program;
323 vsprintf(s, format, args);
326 if (parser->log_size + len + 1 >= parser->log_alloc) {
327 parser->log_alloc += 100;
328 parser->log = realloc (parser->log, parser->log_alloc);
331 strcpy (parser->log + parser->log_size, s);
332 parser->log_size += len;
336 orc_parse_log (OrcParser *parser, const char *format, ...)
340 va_start (var_args, format);
341 orc_parse_log_valist (parser, format, var_args);
346 orc_parse_get_line (OrcParser *parser)
356 end = strchr (parser->p, '\n');
358 end = parser->code + parser->code_length;
362 parser->line = malloc (n + 1);
363 memcpy (parser->line, parser->p, n);
367 if (parser->p[0] == '\n') {
370 parser->line_number++;
375 orc_parse_sanity_check (OrcParser *parser, OrcProgram *program)
380 for(i=0;i<=ORC_VAR_T15;i++) {
381 if (program->vars[i].size == 0) continue;
382 for(j=i+1;j<=ORC_VAR_T15;j++) {
383 if (program->vars[j].size == 0) continue;
385 if (strcmp (program->vars[i].name, program->vars[j].name) == 0) {
386 orc_parse_log (parser, "error: duplicate variable name: %s\n",
387 program->vars[i].name);
392 for(i=0;i<program->n_insns;i++){
393 OrcInstruction *insn = program->insns + i;
394 OrcStaticOpcode *opcode = insn->opcode;
396 for(j=0;j<ORC_STATIC_OPCODE_N_DEST;j++){
397 if (opcode->dest_size[j] == 0) continue;
398 if (program->vars[insn->dest_args[j]].used &&
399 program->vars[insn->dest_args[j]].vartype == ORC_VAR_TYPE_DEST) {
400 orc_parse_log (parser, "error: destination \"%s\" written multiple times\n",
401 program->vars[insn->dest_args[j]].name);
403 program->vars[insn->dest_args[j]].used = TRUE;
406 for(j=0;j<ORC_STATIC_OPCODE_N_SRC;j++){
407 if (opcode->src_size[j] == 0) continue;
408 if (program->vars[insn->src_args[j]].used &&
409 program->vars[insn->src_args[j]].vartype == ORC_VAR_TYPE_SRC) {
410 orc_parse_log (parser, "error: source \"%s\" read multiple times\n",
411 program->vars[insn->src_args[j]].name);
413 if (!program->vars[insn->src_args[j]].used &&
414 program->vars[insn->src_args[j]].vartype == ORC_VAR_TYPE_TEMP) {
415 orc_parse_log (parser, "error: variable \"%s\" used before being written\n",
416 program->vars[insn->src_args[j]].name);
425 orc_parse_get_init_function (OrcProgram *program)
427 return program->init_function;