Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / hypervisor / src / support / mdgen / mdparse.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: mdparse.c
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
46 * Use is subject to license terms.
47 */
48
49#pragma ident "@(#)mdparse.c 1.7 07/06/07 SMI"
50
51#include <stdio.h>
52#include <stdlib.h>
53#include <unistd.h>
54#include <fcntl.h>
55#include <sys/types.h>
56#include <ctype.h>
57#include <strings.h>
58
59#include <md/md_impl.h>
60
61#include "basics.h"
62#include "allocate.h"
63#include "fatal.h"
64#include "lexer.h"
65
66#include "dagtypes.h"
67
68
69static bool_t get_token_value(pair_entry_t *pep, lexer_tok_t tok);
70
71
72#if ENABLE_LOOKUP /* { */
73void
74parse_lookup(pair_entry_t *pep)
75{
76 dag_node_t *src;
77 pair_entry_t *prop;
78
79 src = grab_node("lookup(<node>, <property): bad node");
80 lex_get(T_Comma);
81 prop = grab_prop("lookup(<node>, <property): bad property", src);
82 lex_get(T_R_Bracket);
83 pep->utype = prop->utype;
84 pep->u = prop->u;
85}
86#endif /* } */
87
88#define EXPR_ANY 0
89#define EXPR_OP 1
90#define EXPR_INT 2
91#define EXPR_STR 3
92#define EXPR_EVAL_INT 4
93#define EXPR_EVAL_STR 5
94
95void
96parse_expr(pair_entry_t *ipep)
97{
98 lexer_tok_t tok, op;
99 uint64_t lval = 0;
100 char *lstr = "";
101 uint64_t n[2];
102 char *str[2];
103 int idx = 0;
104 int type = EXPR_ANY;
105 int done = 0;
106 int getop = 1;
107 int invert = 0;
108 pair_entry_t mypp, pp, *opep = &pp, *pep = &mypp;
109
110 pep->namep = ipep->namep;
111 pep->utype = PE_none;
112 pep->u.data.len = 0;
113 opep->namep = ipep->namep;
114 opep->utype = PE_none;
115 opep->u.data.len = 0;
116 tok = 0;
117 op = 0;
118 while (!done) {
119 if (getop) {
120 tok = lex_get_token();
121 lval = lex.val;
122 lstr = lex.strp;
123 }
124 switch (type) {
125 case EXPR_ANY:
126 case EXPR_INT:
127 case EXPR_STR:
128 switch (tok) {
129 case T_Not:
130 if (type == EXPR_STR)
131 goto error;
132 invert = 1;
133 break;
134
135 case T_Number:
136 if (type == EXPR_STR)
137 goto error;
138 n[idx] = lval;
139 if (invert) {
140 n[idx] = ~n[idx];
141 invert = 0;
142 }
143 pep->utype = PE_int;
144 if (idx) {
145 type = EXPR_EVAL_INT;
146 getop = 0;
147 } else {
148 type = EXPR_OP;
149 idx = 1;
150 getop = 1;
151 }
152 break;
153
154 case T_String:
155 if (type == EXPR_INT)
156 goto error;
157 str[idx] = Xstrdup(lstr);
158 pep->utype = PE_string;
159 if (idx) {
160 type = EXPR_EVAL_STR;
161 getop = 0;
162 } else {
163 type = EXPR_OP;
164 idx = 1;
165 getop = 1;
166 }
167 break;
168
169#if ENABLE_LOOKUP
170 case T_KW_lookup:
171 parse_lookup(opep);
172 goto cont_assign;
173#endif
174
175 case T_KW_expr:
176 parse_expr(opep);
177#if ENABLE_LOOKUP
178cont_assign:;
179#endif
180 switch (opep->utype) {
181 case PE_int:
182 type = (((pep->utype == PE_int) ||
183 (pep->utype == PE_none)) ?
184 EXPR_INT : EXPR_STR);
185 tok = T_Number;
186 lval = opep->u.val;
187 break;
188 case PE_string:
189 type = (((pep->utype == PE_string) ||
190 (pep->utype == PE_none)) ?
191 EXPR_STR : EXPR_INT);
192 tok = T_String;
193 lstr = opep->u.strp;
194 break;
195 default:
196 lex_fatal("Bad EXPR type: %d\n",
197 opep->utype);
198 }
199 getop = 0;
200 break;
201
202 default:
203 lex_fatal("Bad expression: %s", lex.strp);
204 break;
205 }
206 break;
207
208 case EXPR_OP:
209 if (tok == T_R_Bracket) {
210 if (idx == 1) {
211 if (pep->utype == PE_int) {
212 pep->u.val = n[0];
213 } else {
214 pep->u.strp = Xstrdup(str[0]);
215 }
216 } else {
217 printf("EXPR_OP: idx == 0???\n");
218 goto error;
219 }
220 done = 1;
221 break;
222 }
223 op = tok;
224 type = ((pep->utype == PE_int) ?
225 EXPR_INT : EXPR_STR);
226 break;
227
228 case EXPR_EVAL_INT:
229 pep->utype = PE_int;
230 switch (op) {
231 case T_Minus:
232 pep->u.val = n[0] - n[1];
233 break;
234 case T_Xor:
235 pep->u.val = n[0] ^ n[1];
236 break;
237 case T_Or:
238 pep->u.val = n[0] | n[1];
239 break;
240 case T_And:
241 pep->u.val = n[0] & n[1];
242 break;
243 case T_Plus:
244 pep->u.val = n[0] + n[1];
245 break;
246 case T_Multiply:
247 pep->u.val = n[0] * n[1];
248 break;
249 case T_LShift:
250 pep->u.val = n[0] << n[1];
251 break;
252
253 default:
254 goto error;
255 }
256 idx = 1;
257 getop = 1;
258 n[0] = pep->u.val;
259 type = EXPR_OP;
260 break;
261
262 case EXPR_EVAL_STR:
263 pep->utype = PE_string;
264 if (op == T_Plus) {
265 char *dst = Xmalloc(strlen(str[0]) +
266 strlen(str[1]) + 1);
267 sprintf(dst, "%s%s", str[0], str[1]);
268 free(str[1]);
269 free(str[0]);
270 pep->u.strp = dst;
271 } else {
272 goto error;
273 }
274 idx = 1;
275 str[0] = pep->u.strp;
276 type = EXPR_OP;
277 break;
278
279 default:
280 error:
281 lex_fatal("Expression syntax error");
282 }
283 }
284#if 0
285 if (pep->utype == PE_int) {
286 printf("Int Expr: %llx\n", pep->u.val);
287 } else {
288 printf("Str Expr: [%s]\n", pep->u.strp);
289 }
290#endif
291 *ipep = mypp;
292}
293
294
295
296#if ENABLE_PROTO /* { */
297
298void
299clone_pair_entry(pair_list_t *plp, pair_entry_t *pep)
300{
301 pair_entry_t *np;
302
303 np = add_pair_entry(plp);
304 np->namep = Xstrdup(pep->namep);
305 np->utype = pep->utype;
306 switch (np->utype) {
307 case PE_int:
308 np->u.val = pep->u.val;
309 break;
310 case PE_string:
311 case PE_noderef:
312 np->u.strp = Xstrdup(pep->u.strp);
313 break;
314 case PE_data:
315 memmove(np->u.data.buffer, pep->u.data.buffer, pep->u.data.len);
316 np->u.data.len = pep->u.data.len;
317 break;
318 default:
319 fatal("clone_pair_entry: Internal error: unexpected type %d\n",
320 np->utype);
321 }
322}
323
324void
325parse_include(dag_node_t *dnp)
326{
327 lexer_tok_t tok;
328 dag_node_t *src;
329 pair_entry_t *pep;
330 pair_list_t *plp;
331 int i, n;
332
333 src = grab_node("include <node>: bad node");
334 tok = lex_get_token();
335 switch (tok) {
336 case T_Comma:
337 pep = grab_prop("lookup(<node>, <property>): bad property",
338 src);
339 /* be careful.. clone_pair_entry does a Realloc */
340 clone_pair_entry(&dnp->properties, pep);
341
342 lex_get(T_S_Colon);
343 break;
344
345 case T_S_Colon:
346 break;
347
348 default:
349 lex_fatal("include: <node>[, <property>]; syntax error");
350 }
351
352 plp = &src->properties;
353 n = plp->num;
354 for (i = 0; i < n; i++) {
355 /* be careful.. clone_pair_entry does a Realloc */
356 clone_pair_entry(&dnp->properties, &(plp->listp[i]));
357 }
358}
359#endif /* } */
360
361static void
362parse_data(pair_entry_t *pep)
363{
364 pair_entry_t pp;
365 lexer_tok_t tok;
366
367 pep->utype = PE_data;
368 pep->u.data.len = 0;
369
370 /*
371 * FIXME: not true anymore.
372 * represented as ints, upper zero bytes are discarded.
373 * [0] is a single zero byte
374 * [01020304] is 01,02,03,04, the upper 32bits were discarded.
375 */
376 do {
377 int n;
378 bool_t ok;
379
380 pp.utype = PE_none; /* SANITY */
381
382 tok = lex_get_token();
383
384 ok = get_token_value(&pp, tok);
385 if (!ok) lex_fatal("Illegal assignment expression");
386
387 switch (pp.utype) {
388 case PE_int:
389 for (n = 7; n > 0; n--) {
390 if ((pp.u.val >> (8*n)) != 0) break;
391 }
392
393 if (pep->u.data.len+n+1 >= MAX_DATALEN)
394 lex_fatal("Internal error; out of data space");
395
396 for (; n >= 0; n--) {
397 pep->u.data.buffer[pep->u.data.len++] =
398 (uint8_t)(pp.u.val >> (8*n));
399 }
400 break;
401
402 case PE_string:
403 n = strlen(pp.u.strp)+1;
404 if (pep->u.data.len+n >= MAX_DATALEN)
405 lex_fatal("Internal error; out of data space");
406 memmove(&(pep->u.data.buffer[pep->u.data.len]),
407 pp.u.strp, n);
408 pep->u.data.len += n;
409 Xfree(pp.u.strp);
410 break;
411
412 case PE_data:
413 lex_fatal("data concat unimplemented !");
414
415 default:
416 lex_fatal("invalid data entry");
417 }
418
419 /* Look for a comma, or R brace */
420 tok = lex_get_token();
421 if (tok != T_Comma && tok != T_R_Brace)
422 lex_fatal("Syntax error; comma or } expected");
423
424 } while (tok != T_R_Brace);
425
426 if (pep->u.data.len == 0) {
427 lex_fatal("Empty data encoding");
428 }
429}
430
431
432static bool_t
433get_token_value(pair_entry_t *pep, lexer_tok_t tok)
434{
435 switch (tok) {
436 case T_Number:
437 pep->utype = PE_int;
438 pep->u.val = lex.val;
439 break;
440 case T_String:
441 pep->utype = PE_string;
442 pep->u.strp = Xstrdup(lex.strp);
443 break;
444 case T_KW_expr:
445 parse_expr(pep);
446 break;
447#if ENABLE_LOOKUP
448 case T_KW_lookup:
449 parse_lookup(pep);
450 break;
451#endif
452 case T_L_Brace:
453 parse_data(pep);
454 break;
455
456 default:
457 return (0);
458 }
459 return (1);
460}
461
462static void
463do_assignment(pair_entry_t *pep, bool_t fn)
464{
465 int done = 0;
466 pair_entry_t pp, mypp;
467 lexer_tok_t tok;
468 uint8_t *dest;
469 char *src;
470 int len;
471 uint64_t d;
472
473 pp.namep = pep->namep;
474 pp.utype = PE_none;
475 pp.u.data.len = 0;
476
477 mypp.namep = pep->namep;
478 mypp.utype = PE_none;
479 mypp.u.data.len = 0;
480
481 tok = lex_get_token();
482 if (tok == T_S_Colon) lex_fatal("empty assignment");
483 if (tok == T_Comma) lex_fatal("invalid compound data");
484 if (fn && (tok == T_R_Bracket)) lex_fatal("missing argument");
485
486 while (!done) {
487 bool_t ok;
488
489 ok = get_token_value(&pp, tok);
490 if (!ok) lex_fatal("Illegal assignment expression");
491
492 switch (mypp.utype) {
493 case PE_none:
494 /*
495 * first iteration, copy data,
496 * this is the 'normal' path.
497 */
498 mypp = pp;
499 pp.namep = NULL; /* cleanup */
500 pp.utype = PE_none; /* cleanup */
501 pp.u.strp = NULL; /* cleanup in case of a str */
502 break;
503
504 case PE_int:
505 /*
506 * an append onto an int.
507 */
508 mypp.utype = PE_data;
509 len = sizeof (uint64_t);
510 /* FIXME: memory order !! */
511 d = mypp.u.val; /* move to be copy safe */
512 memmove(mypp.u.data.buffer, &d, len);
513 mypp.u.data.len = len;
514 goto do_data;
515
516 case PE_string:
517 /*
518 * an append onto a string.
519 */
520 mypp.utype = PE_data;
521 src = mypp.u.strp;
522 len = strlen(src) + 1;
523 memmove(mypp.u.data.buffer, src, len);
524 free(src);
525 mypp.u.data.len = len;
526 goto do_data;
527
528 case PE_data:
529 do_data:
530 ASSERT(mypp.utype == PE_data);
531
532 /* ensure no overflow */
533 switch (pp.utype) {
534 case PE_int:
535 len = sizeof (uint64_t);
536 break;
537 case PE_string:
538 len = strlen(pp.u.strp) + 1;
539 break;
540 case PE_data:
541 len = pp.u.data.len;
542 break;
543 default:
544 lex_fatal("improper concatination");
545 break;
546 }
547
548 if ((mypp.u.data.len + len) >= MAX_DATALEN)
549 lex_fatal("compound data too long");
550 dest = &(mypp.u.data.buffer[mypp.u.data.len]);
551
552 switch (pp.utype) {
553 case PE_int:
554 memmove(dest, &pp.u.val, len);
555 break;
556
557 case PE_string:
558 memmove(dest, pp.u.strp, len);
559 free(pp.u.strp);
560 pp.u.strp = NULL;
561 break;
562
563 case PE_data:
564 memmove(dest, pp.u.data.buffer, len);
565 break;
566
567 default:
568 break;
569 }
570 mypp.u.data.len += len;
571 break;
572
573 default:
574 lex_fatal("improper concatination");
575 }
576
577 tok = lex_get_token();
578 if (tok == T_Comma) {
579 tok = lex_get_token();
580 } else
581 if ((tok == T_S_Colon) || (fn && (tok == T_R_Bracket))) {
582 *pep = mypp;
583 done = 1;
584 } else {
585 lex_fatal("invalid compound expression");
586 }
587 }
588}
589
590#if ENABLE_SETPROP /* { */
591void
592parse_setprop(void)
593{
594 dag_node_t *src;
595 pair_entry_t *pep;
596
597 src = grab_node("setprop(<node>, <property>, <value>): bad node");
598 lex_get(T_Comma);
599 pep = grab_prop("setprop(<node>, <property>, <value>): bad property",
600 src);
601 lex_get(T_Comma);
602 do_assignment(pep, true);
603}
604#endif /* } */
605
606void
607parse_dag(char *fnamep, FILE *fp)
608{
609 lexer_tok_t tok;
610
611 init_lexer(fnamep, fp, NULL);
612
613 while ((tok = lex_get_token()) != T_EOF) {
614 dag_node_t *dnp;
615
616#if ENABLE_PROTO /* FIXME: delete enourage CPP macros { */
617 if ((tok != T_KW_node) &&
618 (tok != T_KW_proto))
619 lex_fatal("node definition expected");
620 dnp = new_dag_node();
621 if (tok == T_KW_proto) {
622 dnp->is_proto = true;
623 }
624#else /* } { */
625 if (tok != T_KW_node)
626 lex_fatal("node definition expected");
627 dnp = new_dag_node();
628#endif /* } */
629
630 lex_get(T_Token);
631 dnp->typep = Xstrdup(lex.strp);
632
633 lex_get(T_Token);
634 dnp->namep = Xstrdup(lex.strp);
635
636 lex_get(T_L_Brace);
637
638 while ((tok = lex_get_token()) != T_R_Brace) {
639 pair_entry_t *pep;
640
641 switch (tok) {
642#if ENABLE_SETPROP /* FIXME: TBD delete in favour of variables { */
643 case T_KW_setprop:
644 parse_setprop();
645 lex_get(T_S_Colon);
646 break;
647
648#endif /* } */
649#if ENABLE_PROTO /* FIXME: use CPP macros instead */
650 case T_KW_include:
651 parse_include(dnp);
652 break;
653#endif /* } */
654
655 case T_Token:
656 pep = add_pair_entry(&dnp->properties);
657 pep->namep = Xstrdup(lex.strp);
658
659 tok = lex_get_token();
660 switch (tok) {
661 case T_Equals:
662 do_assignment(pep, false);
663 break;
664
665 case T_KW_arc:
666 lex_get(T_Token);
667 pep->utype = PE_noderef;
668 pep->u.strp = Xstrdup(lex.strp);
669 lex_get(T_S_Colon);
670 break;
671
672 default:
673 goto expect;
674 }
675 break;
676
677 default:
678expect:;
679 lex_fatal("property expected");
680 }
681 }
682 }
683}