comparison ueda/libuschem/rdschem_parse.c @ 0:cd92449fdb51

initial import of ueda and ifctf-part-lib from ifctfvax CVS
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 20 Jul 2015 00:24:37 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:cd92449fdb51
1 /*
2 * uschem schematic parser
3 */
4
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include <strings.h>
8 #include "schemstruct.h"
9 #include "parserint.h"
10
11 extern char *copystr();
12
13 extern struct schem_parse_state schem_parse_state;
14
15 extern struct schemobj *parser_alloc_obj();
16 extern struct decoration *parser_alloc_decor();
17 extern struct netpoint *parser_alloc_netpoint();
18 extern struct xypair parse_drawing_size_spec();
19 extern struct graphblock *rdschem_graphblock();
20
21 rdschem_parse_schemline()
22 {
23 register int t;
24 struct xypair drawing_size;
25
26 t = rdschem_token();
27 if (t != STRING || strcmp(schem_parse_state.string, "Schem")) {
28 fprintf(stderr,
29 "%s is not a uschem schematic (doesn't begin with Schem)\n",
30 schem_parse_state.schem->orig_filename);
31 exit(1);
32 }
33
34 t = rdschem_token();
35 if (t != STRING)
36 inv: rdschem_error("Schem line: syntax error");
37 if (!strcmp(schem_parse_state.string, "graph")) {
38 schem_parse_state.schem->is_graph = 1;
39 t = rdschem_token();
40 if (t != STRING && t != QSTRING)
41 goto inv;
42 drawing_size =
43 parse_drawing_size_spec(schem_parse_state.string);
44 schem_parse_state.schem->graph_xsize = drawing_size.x;
45 schem_parse_state.schem->graph_ysize = drawing_size.y;
46 } else if (!strcmp(schem_parse_state.string, "nograph"))
47 schem_parse_state.schem->is_graph = 0;
48 else
49 goto inv;
50
51 t = rdschem_token();
52 if (t != ';')
53 goto inv;
54 }
55
56 static struct decoration *
57 parse_decor_attr()
58 {
59 register struct decoration *decor;
60 register int t;
61
62 decor = parser_alloc_decor(DECOR_TYPE_ATTR);
63 t = rdschem_token();
64 if (t != STRING && t != QSTRING)
65 syntaxerr: rdschem_error("(attribute definition decoration) syntax error");
66 if (!schem_parse_state.string[0])
67 rdschem_error("attribute name may not be a null string");
68 decor->decorattr_name = copystr(schem_parse_state.string);
69 t = rdschem_token();
70 if (t != '=')
71 goto syntaxerr;
72 t = rdschem_token();
73 if (t != STRING && t != QSTRING)
74 goto syntaxerr;
75 if (!schem_parse_state.string[0])
76 rdschem_error("attribute value may not be a null string");
77 decor->decorattr_value = copystr(schem_parse_state.string);
78 t = rdschem_token();
79 if (t != ')')
80 goto syntaxerr;
81 return(decor);
82 }
83
84 static struct decoration *
85 parse_decor_displayattr()
86 {
87 register struct decoration *decor;
88 register int t;
89
90 decor = parser_alloc_decor(DECOR_TYPE_DISPLAYATTR);
91 t = rdschem_token();
92 if (t != STRING && t != QSTRING)
93 syntaxerr: rdschem_error("(DisplayAttr decoration) syntax error");
94 if (!schem_parse_state.string[0])
95 rdschem_error("attribute name may not be a null string");
96 decor->decordisp_attr = copystr(schem_parse_state.string);
97 decor->decordisp_x = parse_number();
98 decor->decordisp_y = parse_number();
99 decor->decordisp_ptsize = parse_number();
100 decor->decordisp_rotate = parse_number();
101 decor->decordisp_alignment = parse_number();
102 t = rdschem_token();
103 if (t != ';')
104 goto syntaxerr;
105 return(decor);
106 }
107
108 static struct decoration *
109 parse_decor_displaynetname()
110 {
111 register struct decoration *decor;
112 register int t;
113
114 decor = parser_alloc_decor(DECOR_TYPE_DISPLAYNETNAME);
115 decor->decordisp_x = parse_number();
116 decor->decordisp_y = parse_number();
117 decor->decordisp_ptsize = parse_number();
118 decor->decordisp_rotate = parse_number();
119 decor->decordisp_alignment = parse_number();
120 t = rdschem_token();
121 if (t != ';')
122 rdschem_error("(DisplayNetName decoration) syntax error");
123 return(decor);
124 }
125
126 static struct decoration *
127 parse_decor_pintonet()
128 {
129 register struct decoration *decor;
130 register int t;
131
132 decor = parser_alloc_decor(DECOR_TYPE_PINTONET);
133 t = rdschem_token();
134 if (t != STRING && t != QSTRING)
135 syntaxerr: rdschem_error("(PinToNet decoration) syntax error");
136 if (!schem_parse_state.string[0])
137 rdschem_error("pin ID may not be a null string");
138 if (!strcmp(schem_parse_state.string, "#"))
139 rdschem_error("pin ID \"#\" is invalid");
140 decor->decorpincon_pin = copystr(schem_parse_state.string);
141 t = rdschem_token();
142 if (t != STRING && t != QSTRING)
143 goto syntaxerr;
144 if (!schem_parse_state.string[0])
145 rdschem_error("net name may not be a null string");
146 decor->decorpincon_netname = copystr(schem_parse_state.string);
147 t = rdschem_token();
148 if (t != ';')
149 goto syntaxerr;
150 return(decor);
151 }
152
153 static struct decoration *
154 parse_decor_noconnect()
155 {
156 register struct decoration *decor;
157 register int t;
158
159 decor = parser_alloc_decor(DECOR_TYPE_NOCONNECT);
160 t = rdschem_token();
161 if (t != STRING && t != QSTRING)
162 syntaxerr: rdschem_error("(NoConnect decoration) syntax error");
163 if (!schem_parse_state.string[0])
164 rdschem_error("pin ID may not be a null string");
165 if (!strcmp(schem_parse_state.string, "#"))
166 rdschem_error("pin ID \"#\" is invalid");
167 decor->decorpincon_pin = copystr(schem_parse_state.string);
168 t = rdschem_token();
169 if (t != ';')
170 goto syntaxerr;
171 return(decor);
172 }
173
174 static struct decoration *
175 parse_decor_symonpin()
176 {
177 register struct decoration *decor;
178 register int t;
179
180 decor = parser_alloc_decor(DECOR_TYPE_SYMONPIN);
181 t = rdschem_token();
182 if (t != STRING && t != QSTRING)
183 syntaxerr: rdschem_error("(SymOnPin decoration) syntax error");
184 if (!schem_parse_state.string[0])
185 rdschem_error("pin ID may not be a null string");
186 if (!strcmp(schem_parse_state.string, "#"))
187 rdschem_error("pin ID \"#\" is invalid");
188 decor->decorpinsym_pin = copystr(schem_parse_state.string);
189 t = rdschem_token();
190 if (t != STRING && t != QSTRING)
191 goto syntaxerr;
192 if (!schem_parse_state.string[0])
193 rdschem_error("graphical symbol name may not be a null string");
194 decor->decorpinsym_symname = copystr(schem_parse_state.string);
195 t = rdschem_token();
196 if (t == STRING && !strcmp(schem_parse_state.string, "mirror")) {
197 decor->decorpinsym_mirror = 1;
198 t = rdschem_token();
199 }
200 if (t != ';')
201 goto syntaxerr;
202 return(decor);
203 }
204
205 static struct decoration *
206 parse_decor_graphblock(type)
207 {
208 register int t;
209 register struct decoration *decor;
210 register struct graphblock *blk;
211
212 t = rdschem_token();
213 if (t != '{')
214 rdschem_error("GraphBlockG/GraphBlockPS must be followed by '{'");
215 blk = rdschem_graphblock(type);
216 decor = parser_alloc_decor(DECOR_TYPE_GRAPHBLOCK);
217 decor->decorgraph_body = blk;
218 schem_parse_state.schem->has_graphblocks = 1;
219 return(decor);
220 }
221
222 static struct decoration *
223 parse_decor_comment()
224 {
225 register int t;
226 register struct decoration *decor;
227
228 t = rdschem_token();
229 if (t != STRING && t != QSTRING)
230 syntaxerr: rdschem_error("(Comment decoration) syntax error");
231 if (!schem_parse_state.string[0])
232 rdschem_error("schematic comment may not be a null string");
233 decor = parser_alloc_decor(DECOR_TYPE_COMMENT);
234 decor->decorcomment_text = copystr(schem_parse_state.string);
235 t = rdschem_token();
236 if (t != ';')
237 goto syntaxerr;
238 return(decor);
239 }
240
241 struct decoration *
242 rdschem_parse_decor_block()
243 {
244 struct decoration *decor, *head, **tailp;
245 register int t;
246 char errbuf[256];
247
248 for (head = NULL, tailp = &head; ; ) {
249 t = rdschem_token();
250 switch (t) {
251 case 0:
252 rdschem_error("EOF in a decoration block");
253 case '(':
254 decor = parse_decor_attr();
255 goto addit;
256 case ';':
257 /* "null statement" */
258 continue;
259 case '}':
260 return(head);
261 }
262 if (t != STRING)
263 rdschem_error("syntax error: decoration keyword expected");
264 if (!strcmp(schem_parse_state.string, "DisplayAttr"))
265 decor = parse_decor_displayattr();
266 else if (!strcmp(schem_parse_state.string, "DisplayNetName"))
267 decor = parse_decor_displaynetname();
268 else if (!strcmp(schem_parse_state.string, "PinToNet"))
269 decor = parse_decor_pintonet();
270 else if (!strcmp(schem_parse_state.string, "NoConnect"))
271 decor = parse_decor_noconnect();
272 else if (!strcmp(schem_parse_state.string, "SymOnPin"))
273 decor = parse_decor_symonpin();
274 else if (!strcmp(schem_parse_state.string, "GraphBlockG"))
275 decor = parse_decor_graphblock(GRAPHBLOCK_TYPE_GSCHEM);
276 else if (!strcmp(schem_parse_state.string, "GraphBlockPS"))
277 decor = parse_decor_graphblock(GRAPHBLOCK_TYPE_PS);
278 else if (!strcmp(schem_parse_state.string, "Comment"))
279 decor = parse_decor_comment();
280 else {
281 sprintf(errbuf,
282 "%s is not a recognized decoration keyword",
283 schem_parse_state.string);
284 rdschem_error(errbuf);
285 }
286 addit: *tailp = decor;
287 tailp = &decor->decor_next;
288 }
289 }
290
291 rdschem_parse_object()
292 {
293 register int t;
294 char errbuf[256];
295
296 t = rdschem_token();
297 if (!t) /* EOF aka end of schematic */
298 return(1);
299 if (t == ';') /* "null statement" */
300 return(0);
301 if (t != STRING)
302 rdschem_error("syntax error: object keyword expected");
303
304 if (!strcmp(schem_parse_state.string, "Component"))
305 return(rdschem_parse_compinst());
306 if (!strcmp(schem_parse_state.string, "GraphSym"))
307 return(rdschem_parse_graphsym());
308 if (!strcmp(schem_parse_state.string, "Net"))
309 return(rdschem_parse_net());
310 if (!strcmp(schem_parse_state.string, "GraphNet"))
311 return(rdschem_parse_graphnet());
312 if (!strcmp(schem_parse_state.string, "NetLine"))
313 return(rdschem_parse_netline());
314 if (!strcmp(schem_parse_state.string, "BusSeg"))
315 return(rdschem_parse_busseg());
316 if (!strcmp(schem_parse_state.string, "GraphBlockG"))
317 return(rdschem_parse_graphblock_obj(GRAPHBLOCK_TYPE_GSCHEM));
318 if (!strcmp(schem_parse_state.string, "GraphBlockPS"))
319 return(rdschem_parse_graphblock_obj(GRAPHBLOCK_TYPE_PS));
320 if (!strcmp(schem_parse_state.string, "Comment"))
321 return(rdschem_parse_comment_obj());
322
323 sprintf(errbuf, "%s is not a recognized object keyword",
324 schem_parse_state.string);
325 rdschem_error(errbuf);
326 }
327
328 rdschem_parse_compinst()
329 {
330 register int t;
331 register struct schemobj *obj;
332
333 obj = parser_alloc_obj(OBJTYPE_COMPINST);
334 t = rdschem_token();
335 if (t != STRING && t != QSTRING)
336 syntaxerr: rdschem_error("(Component object) syntax error");
337 if (!schem_parse_state.string[0])
338 rdschem_error("component instance name may not be a null string");
339 obj->compobj_instname = copystr(schem_parse_state.string);
340
341 t = rdschem_token();
342 if (t == STRING && !strcmp(schem_parse_state.string, "graph")) {
343 obj->compobj_isgraph = 1;
344 t = rdschem_token();
345 if (t != STRING && t != QSTRING)
346 goto syntaxerr;
347 if (!schem_parse_state.string[0])
348 rdschem_error("graphical symbol name may not be a null string");
349 obj->compobj_graph_symname = copystr(schem_parse_state.string);
350 obj->compobj_x = parse_number();
351 obj->compobj_y = parse_number();
352 t = rdschem_token();
353 if (t == STRING && !strcmp(schem_parse_state.string, "rot")) {
354 obj->compobj_rotate = parse_number();
355 t = rdschem_token();
356 }
357 if (t == STRING && !strcmp(schem_parse_state.string, "mirror")){
358 obj->compobj_mirror = 1;
359 t = rdschem_token();
360 }
361 }
362
363 if (t == '{') {
364 obj->obj_decorations = rdschem_parse_decor_block();
365 t = rdschem_token();
366 }
367
368 if (t != ';')
369 goto syntaxerr;
370 parser_add_object(obj);
371 return(0);
372 }
373
374 rdschem_parse_graphsym()
375 {
376 register int t;
377 register struct schemobj *obj;
378
379 obj = parser_alloc_obj(OBJTYPE_GRAPHSYM);
380 t = rdschem_token();
381 if (t != STRING && t != QSTRING)
382 syntaxerr: rdschem_error("(GraphSym object) syntax error");
383 if (!schem_parse_state.string[0])
384 rdschem_error("graphical symbol name may not be a null string");
385 obj->compobj_graph_symname = copystr(schem_parse_state.string);
386
387 obj->compobj_x = parse_number();
388 obj->compobj_y = parse_number();
389 t = rdschem_token();
390 if (t == STRING && !strcmp(schem_parse_state.string, "rot")) {
391 obj->compobj_rotate = parse_number();
392 t = rdschem_token();
393 }
394 if (t == STRING && !strcmp(schem_parse_state.string, "mirror")) {
395 obj->compobj_mirror = 1;
396 t = rdschem_token();
397 }
398 if (t == '{') {
399 obj->obj_decorations = rdschem_parse_decor_block();
400 t = rdschem_token();
401 }
402
403 if (t != ';')
404 goto syntaxerr;
405 parser_add_object(obj);
406 return(0);
407 }
408
409 rdschem_parse_net()
410 {
411 register int t;
412 register struct schemobj *obj;
413 register struct netpoint *netpt;
414 struct netpoint *head, **tailp;
415
416 obj = parser_alloc_obj(OBJTYPE_NET);
417 t = rdschem_token();
418 if (t != STRING && t != QSTRING)
419 syntaxerr: rdschem_error("(Net object) syntax error");
420 if (schem_parse_state.string[0])
421 obj->netobj_netname = copystr(schem_parse_state.string);
422
423 head = NULL;
424 tailp = &head;
425 for (;;) {
426 t = rdschem_token();
427 if (t == ';' || t == '{')
428 break;
429 if (t != STRING && t != QSTRING)
430 goto syntaxerr;
431 if (!schem_parse_state.string[0])
432 goto syntaxerr;
433 netpt = parser_alloc_netpoint(NETPT_TYPE_PIN);
434 netpt->netpt_pin_nameref = copystr(schem_parse_state.string);
435 *tailp = netpt;
436 tailp = &netpt->netpt_next;
437 }
438 obj->netobj_points = head;
439
440 if (t == '{') {
441 obj->obj_decorations = rdschem_parse_decor_block();
442 t = rdschem_token();
443 }
444 if (t != ';')
445 goto syntaxerr;
446
447 if (obj->netobj_points)
448 parser_add_object(obj);
449 else {
450 fprintf(stderr, "%s: line %d: null Net object ignored\n",
451 schem_parse_state.schem->orig_filename,
452 schem_parse_state.lineno);
453 free(obj);
454 }
455 return(0);
456 }
457
458 static struct xypair
459 parse_coord_pair()
460 {
461 register int t;
462 struct xypair retval;
463
464 retval.x = parse_number();
465 t = rdschem_token();
466 if (t != ',')
467 syntaxerr: rdschem_error("syntax error in coordinate pair");
468 retval.y = parse_number();
469 t = rdschem_token();
470 if (t != ')')
471 goto syntaxerr;
472 return(retval);
473 }
474
475 static struct netpoint *
476 parse_graphnet_point()
477 {
478 register int t;
479 register struct netpoint *netpt;
480 struct xypair coord_pair;
481
482 t = rdschem_token();
483 if (t == '(') {
484 netpt = parser_alloc_netpoint(NETPT_TYPE_POINT);
485 coord_pair = parse_coord_pair();
486 netpt->netpt_x = coord_pair.x;
487 netpt->netpt_y = coord_pair.y;
488 netpt->netpt_coord_valid = 1;
489 return(netpt);
490 } else if (t == STRING && !strcmp(schem_parse_state.string, "Pin")) {
491 netpt = parser_alloc_netpoint(NETPT_TYPE_PIN);
492 t = rdschem_token();
493 if (t == '(') {
494 coord_pair = parse_coord_pair();
495 netpt->netpt_x = coord_pair.x;
496 netpt->netpt_y = coord_pair.y;
497 netpt->netpt_coord_valid = 1;
498 t = rdschem_token();
499 }
500 if (t == '=') {
501 t = rdschem_token();
502 if (t != STRING && t != QSTRING ||
503 !schem_parse_state.string[0])
504 rdschem_error("syntax error: pin name reference expected");
505 netpt->netpt_pin_nameref =
506 copystr(schem_parse_state.string);
507 } else if (netpt->netpt_coord_valid)
508 schem_parse_state.pushback_token = t;
509 else
510 rdschem_error("syntax error: Pin must be followed by coordinates or name reference");
511 return(netpt);
512 } else if (t == STRING && !strcmp(schem_parse_state.string, "Tjoin")) {
513 netpt = parser_alloc_netpoint(NETPT_TYPE_TJOIN);
514 t = rdschem_token();
515 if (t != '(')
516 rdschem_error("syntax error: Tjoin must be followed by coordinates");
517 coord_pair = parse_coord_pair();
518 netpt->netpt_x = coord_pair.x;
519 netpt->netpt_y = coord_pair.y;
520 netpt->netpt_coord_valid = 1;
521 return(netpt);
522 } else if (t == STRING && !strcmp(schem_parse_state.string, "Pseudo")) {
523 netpt = parser_alloc_netpoint(NETPT_TYPE_PSEUDO);
524 t = rdschem_token();
525 if (t != '(')
526 rdschem_error("syntax error: Pseudo must be followed by coordinates");
527 coord_pair = parse_coord_pair();
528 netpt->netpt_x = coord_pair.x;
529 netpt->netpt_y = coord_pair.y;
530 netpt->netpt_coord_valid = 1;
531 return(netpt);
532 }
533 schem_parse_state.pushback_token = t;
534 return(NULL);
535 }
536
537 rdschem_parse_graphnet()
538 {
539 register int t;
540 register struct schemobj *obj;
541 register struct netpoint *netpt;
542 struct netpoint *head, **tailp;
543
544 obj = parser_alloc_obj(OBJTYPE_GRAPHNET);
545 t = rdschem_token();
546 if (t != STRING && t != QSTRING)
547 syntaxerr: rdschem_error("(GraphNet object) syntax error");
548 if (schem_parse_state.string[0])
549 obj->netobj_netname = copystr(schem_parse_state.string);
550
551 head = NULL;
552 tailp = &head;
553 for (;;) {
554 netpt = parse_graphnet_point();
555 if (!netpt)
556 break;
557 *tailp = netpt;
558 tailp = &netpt->netpt_next;
559 }
560 obj->netobj_points = head;
561
562 t = rdschem_token();
563 if (t == '{') {
564 obj->obj_decorations = rdschem_parse_decor_block();
565 t = rdschem_token();
566 }
567 if (t != ';')
568 goto syntaxerr;
569
570 if (obj->netobj_points)
571 parser_add_object(obj);
572 else {
573 fprintf(stderr, "%s: line %d: null GraphNet object ignored\n",
574 schem_parse_state.schem->orig_filename,
575 schem_parse_state.lineno);
576 free(obj);
577 }
578 return(0);
579 }
580
581 rdschem_parse_netline()
582 {
583 register int t;
584 register struct schemobj *obj;
585 struct xypair coord_pair;
586
587 obj = parser_alloc_obj(OBJTYPE_NETLINE);
588
589 t = rdschem_token();
590 if (t != '(')
591 syntaxerr: rdschem_error("(NetLine object) syntax error");
592 coord_pair = parse_coord_pair();
593 obj->lineobj_x1 = coord_pair.x;
594 obj->lineobj_y1 = coord_pair.y;
595 t = rdschem_token();
596 if (t != '(')
597 goto syntaxerr;
598 coord_pair = parse_coord_pair();
599 obj->lineobj_x2 = coord_pair.x;
600 obj->lineobj_y2 = coord_pair.y;
601
602 t = rdschem_token();
603 if (t == '{') {
604 obj->obj_decorations = rdschem_parse_decor_block();
605 t = rdschem_token();
606 }
607 if (t != ';')
608 goto syntaxerr;
609 parser_add_object(obj);
610 return(0);
611 }
612
613 rdschem_parse_busseg()
614 {
615 register int t;
616 register struct schemobj *obj;
617 struct xypair coord_pair;
618
619 obj = parser_alloc_obj(OBJTYPE_BUSSEG);
620
621 t = rdschem_token();
622 if (t != '(')
623 syntaxerr: rdschem_error("(BusSeg object) syntax error");
624 coord_pair = parse_coord_pair();
625 obj->lineobj_x1 = coord_pair.x;
626 obj->lineobj_y1 = coord_pair.y;
627 t = rdschem_token();
628 if (t != '(')
629 goto syntaxerr;
630 coord_pair = parse_coord_pair();
631 obj->lineobj_x2 = coord_pair.x;
632 obj->lineobj_y2 = coord_pair.y;
633
634 t = rdschem_token();
635 if (t == '{') {
636 obj->obj_decorations = rdschem_parse_decor_block();
637 t = rdschem_token();
638 }
639 if (t != ';')
640 goto syntaxerr;
641 parser_add_object(obj);
642 return(0);
643 }
644
645 rdschem_parse_graphblock_obj(type)
646 {
647 register int t;
648 register struct schemobj *obj;
649 register struct graphblock *blk;
650
651 t = rdschem_token();
652 if (t != '{')
653 rdschem_error("GraphBlockG/GraphBlockPS must be followed by '{'");
654 blk = rdschem_graphblock(type);
655 obj = parser_alloc_obj(OBJTYPE_GRAPHBLOCK);
656 obj->graphblockobj_body = blk;
657 parser_add_object(obj);
658 schem_parse_state.schem->has_graphblocks = 1;
659 return(0);
660 }
661
662 rdschem_parse_comment_obj()
663 {
664 register int t;
665 register struct schemobj *obj;
666
667 t = rdschem_token();
668 if (t != STRING && t != QSTRING)
669 syntaxerr: rdschem_error("(Comment object) syntax error");
670 if (!schem_parse_state.string[0])
671 rdschem_error("schematic comment may not be a null string");
672 obj = parser_alloc_obj(OBJTYPE_COMMENT);
673 obj->commentobj_text = copystr(schem_parse_state.string);
674 t = rdschem_token();
675 if (t != ';')
676 goto syntaxerr;
677 parser_add_object(obj);
678 return(0);
679 }
680
681 static int
682 parse_number()
683 {
684 register int t;
685 char errbuf[256];
686
687 t = rdschem_token();
688 if (t != STRING)
689 rdschem_error("syntax error (number expected)");
690 if (!string_is_valid_decnum(schem_parse_state.string)) {
691 sprintf(errbuf, "\"%s\" is not a valid decimal number",
692 schem_parse_state.string);
693 rdschem_error(errbuf);
694 }
695 return(atoi(schem_parse_state.string));
696 }