contrib/gmk_sym: Fix missing break
[geda-gaf.git] / contrib / gmk_sym / convert_sym.c
blob3a1514eecd98d9624ab8944dc93c447d9c97f084
1 /* convert_sym.c:
3 * Convert a Viewlogic symbol/schematic to gEDA gschem format
5 * accept one argument, the name of the file to
6 * convert, converted output is displayed on stdout.
8 * Copyright (C) 1999-2010 Mike Jarabek
10 * CHANGE HISTORY:
12 * Updated 8/16/2005 by Jeff McLamb (mclamb AT bustech.com)
13 * - Updated to support gEDA file format version 1
14 * - Added capability to import more graphic styles from ViewDraw
15 * - Corrected bug associated with absense of library reference in
16 * local ViewDraw symbols
17 * - Removed command-line option -s; no longer necessary
18 * - Mapped ViewDraw "SIGNAL" attribute to gEDA "net" attribute
19 * - Mapped ViewDraw "HETERO" attribute to a new "split" attribute
20 * - Mapped ViewDraw "PINTYPE" attributes to correct gEDA pintypes
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version 2
25 * of the License, or (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
36 * $Id$
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44 #include <math.h>
46 #include <config.h>
47 #include <libgeda/colors.h>
50 * make it so we can use __attribute__((unused)) on gcc without
51 * breaking non-gcc
53 #ifndef GCC_VERSION
54 #define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
55 #endif /* GCC_VERSION */
57 #if GCC_VERSION > 2007
58 #define ATTRIBUTE_UNUSED __attribute__((unused))
59 #else
60 #define ATTRIBUTE_UNUSED
61 #endif
63 #ifndef lint
64 static char vcid[] ATTRIBUTE_UNUSED = "$Id$";
65 #endif /* lint */
67 #ifndef OPTARG_IN_UNISTD
68 extern char *optarg;
69 extern int optind;
70 #endif
72 /* local defines */
73 #define MAX_TEXTLEN 1024
74 #define MAX_NODES 1024
75 #define MAX_POINTS 1024
77 /* gEDA style enumerators */
78 typedef enum {END_NONE, END_SQUARE, END_ROUND} OBJECT_END;
79 typedef enum {TYPE_SOLID, TYPE_DOTTED, TYPE_DASHED, TYPE_CENTER,
80 TYPE_PHANTOM, TYPE_ERASE} OBJECT_TYPE;
81 typedef enum {FILLING_HOLLOW, FILLING_FILL, FILLING_MESH, FILLING_HATCH,
82 FILLING_VOID} OBJECT_FILLING;
83 typedef enum {NORMAL_PIN, BUS_PIN} OBJECT_PINTYPE;
85 /* Viewdraw Colours
87 * 0 Black | 4 Red | 8 Gray | 12 Lt. Red
88 * 1 Blue | 5 Magenta | 9 Lt. Blue | 13 Lt. Magenta
89 * 2 Green | 6 Brown | 10 Lt. Green | 14 Yellow
90 * 3 Cyan | 7 Lt. Gray | 11 Lt. Cyan | 15 White
92 * Geda Colours:
94 * 0 BLACK | 1 WHITE | 2 RED | 3 GREEN
95 * 4 BLUE | 5 YELLOW | 6 CYAN | 7 GREY
99 /* ViewDraw fill styles:
100 * 0 = Hollow, no fill
101 * 1 = Solid, full fill
102 * 2 = Grey92, mostly fill, thick array of empty space
103 * 4 = Grey50, 50% dot fill
104 * 6 = Grey08, thicker array of dots
105 * 7 = Grey04, thin array of dots
106 * 8 = Diagdn2, widely-spaced diagonals from top left to bottom right
107 * 11 = Diagdn1, narrowly-spaced diagonals from top left to bottom right
108 * 13 = Diagup2, widely-spaced diagonals from bottom left to top right
109 * 16 = Diagup1, narrowly-spaced diagonals from bottom left to top right
110 * 19 = Horiz, narrowly-spaced horizontal lines
111 * 21 = Vert, narrowly-spaced vertical lines
112 * 22 = Grid2, widely-spaced square grid
113 * 23 = Grid1, narrowly-spaced square grid
114 * 24 = X2, widely-spaced diagonal crosshatch
115 * 25 = X1, narrowly-spaced diagonal crosshatch
118 /* ViewDraw line styles:
119 * 0 = Solid
120 * 1 = Dash
121 * 2 = Center, alternating short and long dashes
122 * 3 = Phantom, alternating dash and two dots
123 * 4 = Big dash
124 * 5 = Dot
125 * 6 = Dash-dot, alternating dashes and dots
126 * 7 = Medium dash
129 /* tables */
130 int colormap[16] = /* index is viewlogic colour, entry is geda color */
132 0, /* 0 */
133 4, /* 1 */
134 3, /* 2 */
135 6, /* 3 */
136 2, /* 4 */
137 2, /* 5 */
138 7, /* 6 */
139 7, /* 7 */
140 7, /* 8 */
141 4, /* 9 */
142 3, /* 10 */
143 6, /* 11 */
144 2, /* 12 */
145 2, /* 13 */
146 5, /* 14 */
147 1, /* 15 */
150 /* Fill style structure */
151 struct FillStyle {
152 OBJECT_FILLING fill_type; /* gEDA object fill type */
153 int fill_width; /* width of the fill lines */
154 int fill_angle1; /* first angle of fill lines */
155 int fill_pitch1; /* first pitch/spacing of fill lines */
156 int fill_angle2; /* second angle of fill lines */
157 int fill_pitch2; /* second pitch/spacing of fill lines */
160 /* index is ViewDraw fill style, entry is above gEDA FillStyle struct */
161 struct FillStyle fillmap[26] =
163 /* 0 = Hollow, no fill */
164 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
165 /* 1 = Solid, full fill */
166 {FILLING_FILL, -1, -1, -1, -1, -1},
167 /* 2 = Grey92, mostly fill, thick array of empty space */
168 {FILLING_MESH, 20, 45, 30, 135, 30},
169 /* 3 = Undefined; assume hollow, no fill */
170 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
171 /* 4 = Grey50, 50% dot fill */
172 {FILLING_MESH, 10, 45, 20, 135, 20},
173 /* 5 = Undefined; assume hollow, no fill */
174 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
175 /* 6 = Grey08, thicker array of dots */
176 {FILLING_MESH, 0, 45, 40, 135, 40}, /* Can't do dots; use mesh */
177 /* 7 = Grey04, sparse array of dots */
178 {FILLING_MESH, 0, 45, 80, 135, 80}, /* Can't do dots; use mesh */
179 /* 8 = Diagdn2, widely-spaced diagonals from top left to bottom right */
180 {FILLING_HATCH, 0, 135, 80, -1, -1},
181 /* 9 = Undefined; assume hollow, no fill */
182 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
183 /* 10 = Undefined; assume hollow, no fill */
184 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
185 /* 11 = Diagdn1, narrowly-spaced diagonals from top left to bottom right */
186 {FILLING_HATCH, 0, 135, 40, -1, -1},
187 /* 12 = Undefined; assume hollow, no fill */
188 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
189 /* 13 = Diagup2, widely-spaced diagonals from bottom left to top right */
190 {FILLING_HATCH, 0, 45, 80, -1, -1},
191 /* 14 = Undefined; assume hollow, no fill */
192 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
193 /* 15 = Undefined; assume hollow, no fill */
194 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
195 /* 16 = Diagup1, narrowly-spaced diagonals from bottom left to top right */
196 {FILLING_HATCH, 0, 45, 40, -1, -1},
197 /* 17 = Undefined; assume hollow, no fill */
198 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
199 /* 18 = Undefined; assume hollow, no fill */
200 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
201 /* 19 = Horiz, narrowly-spaced horizontal lines */
202 {FILLING_HATCH, 10, 0, 40, -1, -1},
203 /* 20 = Undefined; assume hollow, no fill */
204 {FILLING_HOLLOW, -1, -1, -1, -1, -1},
205 /* 21 = Vert, narrowly-spaced vertical lines */
206 {FILLING_HATCH, 10, 90, 40, -1, -1},
207 /* 22 = Grid2, widely-spaced square grid */
208 {FILLING_MESH, 0, 0, 80, 90, 80},
209 /* 23 = Grid1, narrowly-spaced square grid */
210 {FILLING_MESH, 0, 0, 40, 90, 40},
211 /* 24 = X2, widely-spaced diagonal crosshatch */
212 {FILLING_MESH, 0, 45, 80, 135, 80},
213 /* 25 = X1, narrowly-spaced diagonal crosshatch */
214 {FILLING_MESH, 0, 45, 40, 135, 40},
215 }; /* fillmap */
217 #define FILL_DEFAULT (struct FillStyle){FILLING_HOLLOW, -1, -1, -1, -1, -1}
219 /* Line style structure */
220 struct LineStyle {
221 int line_width; /* width of line */
222 OBJECT_END line_capstyle; /* gEDA line cap style (end style) */
223 OBJECT_TYPE line_dashstyle; /* gEDA line dash style */
224 int line_dashlength; /* length of line dashes */
225 int line_dashspace; /* space between line dashes */
228 struct LineStyle linemap[8] =
230 /* 0 = Solid */
231 {0, END_NONE, TYPE_SOLID, -1, -1},
232 /* 1 = Dash */
233 {0, END_NONE, TYPE_DASHED, 100, 100},
234 /* 2 = Center, alternating short and long dashes */
235 {0, END_NONE, TYPE_CENTER, 100, 100},
236 /* 3 = Phantom, alternating dash and two dots */
237 {0, END_NONE, TYPE_PHANTOM, 100, 100},
238 /* 4 = Big dash */
239 {0, END_NONE, TYPE_DASHED, 400, 100},
240 /* 5 = Dot */
241 {0, END_NONE, TYPE_DOTTED, -1, 100},
242 /* 6 = Dash-dot, alternating dashes and dots */
243 {0, END_NONE, TYPE_CENTER, 100, 100},
244 /* 7 = Medium dash */
245 {0, END_NONE, TYPE_DASHED, 200, 100},
246 }; /* linemap */
248 #define LINE_DEFAULT (struct LineStyle){0, END_NONE, TYPE_SOLID, -1, -1}
250 /* attribute translation table */
251 struct Translation {
252 char *origName; /* name as it appears on a viewlogic schematic */
253 char *newName; /* name as it should appear in gEDA */
254 unsigned int action; /* what to do with this name */
257 /* action codes for translation action */
258 #define REPLACE_NAME 1
259 #define KILL 2
260 #define WARN_USER 3
262 struct Translation translations[] =
264 {"PKG_TYPE", "footprint", REPLACE_NAME},
265 {"LEVEL", "", KILL},
266 /* {"NC", "", KILL}, */
267 {"NAME", "", KILL},
268 {"LABEL", "", KILL},
269 {"SIGNAL", "net", REPLACE_NAME},
270 {"HETERO", "split", REPLACE_NAME},
273 unsigned int nTranslations = sizeof(translations)/sizeof(struct Translation);
275 /* local function prototypes */
276 int convert_file(FILE *fp);
277 unsigned int strindex(char *s, char c);
278 unsigned int strrindex(char *s, char c);
279 void strtolower(char *s);
280 int get_continued_string(char *buf, size_t buffer_size, FILE *fp);
281 int get_style(FILE *fp, unsigned int *colour,
282 struct LineStyle *linestyle,
283 struct FillStyle *fillstyle);
284 void set_orientation(int *angle, int *mirror, int orientation);
286 /* conversion readers */
287 void do_nop(FILE *fp);
288 void do_bounding_box(FILE *fp);
289 void do_unattached_attribute(FILE *fp);
290 void do_attached_attribute(FILE *fp);
291 void do_text(FILE *fp);
292 void do_line(FILE *fp);
293 void do_pin(FILE *fp);
294 void do_box(FILE *fp);
295 void do_circle(FILE *fp);
296 void do_arc(FILE *fp);
297 void do_label(FILE *fp);
298 void do_net_start(FILE *fp);
299 void do_net_node(FILE *fp);
300 void do_net_segment(FILE *fp);
301 void do_net_segment_bus(FILE *fp);
302 void do_instance(FILE *fp);
304 /* output objects */
305 void text_object(int x, int y, unsigned int color, unsigned int size,
306 unsigned int visibility, unsigned int show_name_value,
307 int angle, char *text, unsigned int origin);
308 void attribute_object(int x, int y, unsigned int color, unsigned int size,
309 unsigned int visibility, unsigned int show_name_value,
310 int angle, char *name, char *value, unsigned int origin);
311 void line_object(int x1, int y1, int x2, int y2, unsigned int color,
312 struct LineStyle *linestyle);
313 void circle_object(int bx, int by, unsigned int radius, unsigned int bcolor,
314 struct LineStyle *linestyle, struct FillStyle *fillstyle);
315 void pin_object(int x1, int y1, int x2, int y2, unsigned int color,
316 OBJECT_PINTYPE pintype, unsigned int whichend);
317 void box_object(int x1, int y1, unsigned int width, unsigned int height,
318 unsigned int color, struct LineStyle *linestyle,
319 struct FillStyle *fillstyle);
320 void arc_object(int x1, int y1, unsigned int radius,
321 int start_angle, int sweep_angle, unsigned int color,
322 struct LineStyle *linestyle);
323 void net_segment(int x1, int y1, int x2, int y2, unsigned int color);
324 void bus_segment(int x1, int y1, int x2, int y2, unsigned int color,
325 int ripperdir);
326 void complex_object(int x, int y, unsigned int selectable,
327 int angle, unsigned int mirror, char *name);
328 void begin_attach(void);
329 void end_attach(void);
330 void reset_attributes(void);
332 /* externals */
333 int GetStringDisplayLength(char *str,int font_size);
337 /* globals */
338 int attach_pending = 0; /* keep track of whether the last object */
339 /* read may have attachments pending. */
340 int add_attributes = 0; /* keep track of whether we are adding attributes */
341 /* to some previous object */
342 int pin_attributes = 0; /* when true, we are adding attributes to a pin */
343 int net_attributes = 0; /* when true, we are adding atrributes to a net */
344 int complex_attributes = 0;/* when true, we are adding attibutes to a complex*/
345 int pin_count = 0; /* to keep track of the number of pins */
346 int reading_net = 0; /* used to keep track of when we are reading a net*/
347 int segment_count = 0; /* the number of net segments read for a net */
348 int net_nodes_x[MAX_NODES];
349 int net_nodes_y[MAX_NODES];
350 int scale = 10; /* scale factor for viewlogic-geda conversion */
351 /* int symbol_mode = 0; */
352 int records_processed = 0; /* used to keep track of the number of viewlogic
353 * records processed for diagnostics
356 int minx = 0; /* bounding box for symbol */
357 int miny = 0;
358 int maxx = 0;
359 int maxy = 0;
361 void
362 usage(char *cmd)
364 fprintf(stderr,
365 "Usage:\n\t%s <viewlogic_filename>\n"
366 " Where:\n"
367 "\t<viewlogic_filename> is the name of the file you\n"
368 "\t\t\t want to convert to gEDA format\n", cmd);
369 exit(1);
373 main(int argc, char **argv)
376 FILE *infile;
377 char *infileName;
379 int ch;
381 while ((ch = getopt (argc, argv, "?h")) != -1) {
382 switch (ch) {
384 case 's':
385 symbol_mode = 1;
386 break;
388 case '?':
389 case 'h':
390 default:
391 usage(argv[0]);
392 break;
396 if (optind == argc)
397 usage(argv[0]);
400 /* 'parse' arguments */
401 infileName = argv[optind];
403 infile=fopen(infileName,"r");
404 if(infile == NULL)
406 fprintf(stderr,"Error: Unable to open file `%s' in %s()\n",
407 infileName,__func__);
408 return 1;
411 convert_file(infile);
413 fclose(infile);
415 return 0;
418 /* convert the given file to geda */
420 convert_file(FILE *fp)
422 int c;
423 int text_len;
425 char buf[MAX_TEXTLEN];
427 /* output pre-amble */
428 printf("v 20050313 1\n"); /* Version timestamp 20050313, file version 1 */
429 reset_attributes();
432 while((c =fgetc(fp)) != EOF) /* fetch record type */
434 switch(c) /* branch to appropriate handler */
436 case 'D':
437 do_bounding_box(fp);
438 break;
440 case 'U':
441 do_unattached_attribute(fp);
442 break;
444 case 'A':
445 do_attached_attribute(fp);
446 break;
448 case 'T':
449 do_text(fp);
450 break;
452 case 'l':
453 do_line(fp);
454 break;
456 case 'P':
457 do_pin(fp);
458 break;
460 case 'b':
461 do_box(fp);
462 break;
464 case 'c':
465 do_circle(fp);
466 break;
468 case 'a':
469 do_arc(fp);
470 break;
472 case 'L':
473 do_label(fp);
474 break;
476 /* net stuff */
477 case 'N':
478 do_net_start(fp);
479 break;
480 case 'J':
481 do_net_node(fp);
482 break;
483 case 'S':
484 do_net_segment(fp);
485 break;
486 case 'B':
487 do_net_segment_bus(fp);
488 break;
490 case 'I':
491 do_instance(fp);
492 break;
493 /* ZZZZ */
495 case 'V': case 'K': case 'Y': case 'i': case 'E':
496 case 'Z':
497 do_nop(fp);
498 break;
500 case 'Q':
501 fprintf(stderr,"Warning 'Q' record found and not handled at"
502 "record %d, contact maintainer\n",records_processed);
503 do_nop(fp);
504 break;
506 case 'C': /* connected pin record */
507 do_nop(fp);
508 break;
510 case 'X': /* unconnected pin record */
511 do_nop(fp);
512 break;
513 case '|': /* some kind of timestamp */
514 do_nop(fp);
515 break;
516 default: /* just read in the record and trash it */
517 fgets(buf, MAX_TEXTLEN, fp);
518 /* nuke trailing CR, if there */
519 text_len=strlen(buf);
520 if(buf[text_len-1] == '\n')
522 buf[text_len-1] = 0;
524 fprintf(stderr,"Warning: Unrecognized record #%d:\n'%c%s'\n",
525 records_processed, c, buf);
527 records_processed++;
530 /* output post-amble */
531 reset_attributes();
534 return 0;
537 void
538 do_nop(FILE *fp)
540 char text[MAX_TEXTLEN];
542 fgets(text,MAX_TEXTLEN,fp);
545 void
546 do_bounding_box(FILE *fp)
548 #if 0
549 unsigned int color;
550 struct LineStyle linestyle;
551 struct FillStyle fillstyle;
552 #endif
554 /* just fetch the values and store */
555 if(fscanf(fp,"%d %d %d %d\n", &minx, &miny, &maxx, &maxy) != 4)
557 fprintf(stderr,"Error: Invalid bounding box record #%d in %s()\n",
558 records_processed, __func__);
559 exit(1);
562 minx *= scale;
563 miny *= scale;
564 maxx *= scale;
565 maxy *= scale;
567 /* Do not draw the bounding box, only retrieve the min and max values */
568 #if 0
569 if (symbol_mode == 0)
571 color = GRAPHIC_COLOR;
572 linestyle = LINE_DEFAULT;
573 fillstyle = FILL_DEFAULT;
574 box_object(minx, miny, maxx-minx, maxy-miny, color, &linestyle,
575 &fillstyle);
577 #endif
581 void
582 do_unattached_attribute(FILE *fp)
584 int x,y,angle;
585 unsigned int dummy, color, size, origin, viewvis;
586 unsigned int index;
587 unsigned int visibility, show_name_value;
588 char text[MAX_TEXTLEN], *name, *value;
589 struct LineStyle linestyle;
590 struct FillStyle fillstyle;
592 /* if we are inside of a pin definition, terminate */
593 reset_attributes();
595 /* for the moment just represent as text */
597 /* viewlogic unnatached attributes have this format:
598 * U #X #Y #SIZE #ROTATION #origin #Visibility ATTR_TEXT
600 if(fscanf(fp,"%d %d %u %d %u %u", &x, &y, &size, &angle, &origin,
601 &viewvis) != 6)
603 fprintf(stderr,"Error: Invalid Unattached attribute record #%d "
604 "in %s()\n",
605 records_processed, __func__);
606 exit(1);
609 /* read in the text */
610 get_continued_string(text, MAX_TEXTLEN, fp);
613 x *= scale; /* correct coordinates */
614 y *= scale;
615 color = DETACHED_ATTRIBUTE_COLOR;
617 linestyle = LINE_DEFAULT;
618 fillstyle = FILL_DEFAULT;
619 get_style(fp, &dummy, &linestyle, &fillstyle);
621 /* evaluate visibility for attributes */
622 switch(viewvis)
624 case 0: /* not at all visibile */
625 visibility = 0;
626 show_name_value = 0;
627 break;
629 case 1: /* attribute and name visible */
630 visibility = 1;
631 show_name_value = 0;
632 break;
634 case 2: /* only name visible */
635 visibility = 2;
636 show_name_value = 1;
637 break;
639 case 3: /* only value visible */
640 visibility = 1;
641 show_name_value = 1;
642 break;
644 default:
645 fprintf(stderr,"Error: Invalid visibility value %d in "
646 "viewlogic file at record #%d in function %s()\n",
647 viewvis, records_processed, __func__);
648 return;
651 /* find name and value pair */
652 name = text;
653 index = strindex(text,'=');
654 if (text[index] == '=')
656 text[index] = 0;
657 value = &text[index+1];
659 else
661 value = NULL;
664 attribute_object( x, y, color, size, visibility, show_name_value, angle,
665 name, value, origin );
669 void
670 do_attached_attribute(FILE *fp)
672 int x,y,angle;
673 unsigned int color, dummy, size, origin, viewvis;
674 unsigned int visibility, show_name_value;
675 unsigned int index;
676 char text[MAX_TEXTLEN],text2[MAX_TEXTLEN],*name,*value;
677 struct LineStyle linestyle;
678 struct FillStyle fillstyle;
680 /* for the moment just represent as text */
682 /* attached attributes have the following format:
683 * A #X #Y #SIZE #ROTATION #ORIGIN #VISIBILITY ATTR_TEXT
685 if(fscanf(fp,"%d %d %u %d %u %u", &x, &y, &size, &angle, &origin,
686 &viewvis) != 6)
688 fprintf(stderr,"Error: Invalid attached attribute record #%d"
689 " in %s()\n", records_processed, __func__);
690 exit(1);
693 x *= scale; /* correct coordinates */
694 y *= scale;
696 /* read in the text */
697 get_continued_string(text, MAX_TEXTLEN, fp);
699 color = ATTRIBUTE_COLOR;
700 linestyle = LINE_DEFAULT;
701 fillstyle = FILL_DEFAULT;
702 get_style(fp, &dummy, &linestyle, &fillstyle);
704 /* evaluate visibility for attributes */
705 switch(viewvis)
707 case 0: /* not at all visibile */
708 visibility = 0;
709 show_name_value = 0;
710 break;
712 case 1: /* attribute and name visible */
713 visibility = 1;
714 show_name_value = 0;
715 break;
717 case 2: /* only name visible */
718 visibility = 1;
719 show_name_value = 2;
720 break;
722 case 3: /* only value visible */
723 visibility = 1;
724 show_name_value = 1;
725 break;
727 default:
728 fprintf(stderr,"Error: Invalid visibility value %d in "
729 "viewlogic file at record #%d, in function %s()\n",
730 viewvis, records_processed, __func__);
731 return;
734 begin_attach();
735 if(pin_attributes) /* are we adding to a pin ? */
737 /* translate pintype attribute */
738 if (strncmp(text, "PINTYPE=", 8) == 0)
740 value = &text[strindex(text,'=')+1];
741 if (strcmp(value, "ANALOG") == 0)
743 #ifdef HAVE_SNPRINTF
744 snprintf(text, MAX_TEXTLEN, "pintype=pas");
745 #else
746 sprintf(text, "pintype=pas");
747 #endif
749 else if (strcmp(value, "BI") == 0)
751 #ifdef HAVE_SNPRINTF
752 snprintf(text, MAX_TEXTLEN, "pintype=io");
753 #else
754 sprintf(text, "pintype=io");
755 #endif
757 else if (strcmp(value, "IN") == 0)
759 #ifdef HAVE_SNPRINTF
760 snprintf(text, MAX_TEXTLEN, "pintype=in");
761 #else
762 sprintf(text, "pintype=in");
763 #endif
765 else if (strcmp(value, "OCL") == 0)
767 #ifdef HAVE_SNPRINTF
768 snprintf(text, MAX_TEXTLEN, "pintype=oc");
769 #else
770 sprintf(text, "pintype=oc");
771 #endif
773 else if (strcmp(value, "OEM") == 0)
775 #ifdef HAVE_SNPRINTF
776 snprintf(text, MAX_TEXTLEN, "pintype=oe");
777 #else
778 sprintf(text, "pintype=oe");
779 #endif
781 else if (strcmp(value, "OUT") == 0)
783 #ifdef HAVE_SNPRINTF
784 snprintf(text, MAX_TEXTLEN, "pintype=out");
785 #else
786 sprintf(text, "pintype=out");
787 #endif
789 else if (strcmp(value, "TRI") == 0)
791 #ifdef HAVE_SNPRINTF
792 snprintf(text, MAX_TEXTLEN, "pintype=tri");
793 #else
794 sprintf(text, "pintype=tri");
795 #endif
797 else if (strcmp(value, "PWR") == 0)
799 #ifdef HAVE_SNPRINTF
800 snprintf(text, MAX_TEXTLEN, "pintype=pwr");
801 #else
802 sprintf(text, "pintype=pwr");
803 #endif
805 else
807 fprintf(stderr,"Error: Invalid or unknown pin type \"%s\" for record "
808 "#%d in %s()\n", value, records_processed, __func__);
809 exit(1);
812 /* find name and value pair */
813 name = text;
814 index = strindex(text,'=');
815 text[index] = 0;
816 value = &text[index+1];
817 attribute_object( x, y, color, size, visibility, show_name_value,
818 angle, name, value, origin );
820 /* done attaching pin attributes */
821 return;
823 /* attach the pinseq and pinnumber attributes */
824 if(text[0] == '#')
826 strncpy(text2, text, MAX_TEXTLEN);
827 #ifdef HAVE_SNPRINTF
828 snprintf(text, MAX_TEXTLEN, "pinseq=%d",pin_count);
829 #else
830 sprintf(text, "pinseq=%d",pin_count);
831 #endif
832 /* pinseq is invisible */
833 visibility = 0; /* overide any previous settings */
834 show_name_value = 1;
836 /* find name and value pair */
837 name = text;
838 index = strindex(text,'=');
839 text[index] = 0;
840 value = &text[index+1];
841 attribute_object( x, y, color, size, visibility, show_name_value,
842 angle, name, value, origin );
844 #ifdef HAVE_SNPRINTF
845 snprintf(text, MAX_TEXTLEN, "pinnumber=%s", &text2[2]);
846 #else
847 sprintf(text, "pinnumber=%s", &text2[2]);
848 #endif
849 /* pinnumber is visible */
850 visibility = 1; /* overide any previous settings */
851 show_name_value = 1;
853 name = text;
854 index = strindex(text,'=');
855 text[index] = 0;
856 value = &text[index+1];
857 attribute_object( x, y, color, size, visibility, show_name_value,
858 angle, name, value, origin );
860 /* done attaching pin attributes */
861 return;
865 name = text;
866 index = strindex(text,'=');
867 if (text[index] == '=')
869 text[index] = 0;
870 value = &text[index+1];
872 else
874 value = NULL;
877 attribute_object( x, y, color, size, visibility, show_name_value, angle,
878 name, value, origin );
881 void
882 do_text(FILE *fp)
884 int x,y,angle;
885 unsigned int size, origin;
886 unsigned int color, show_name_value;
887 unsigned int visibility;
888 char text[MAX_TEXTLEN];
889 struct LineStyle linestyle;
890 struct FillStyle fillstyle;
893 /* if we are inside of a pin definition, terminate */
894 reset_attributes();
896 /* viewlogic text have the following format:
897 * T #X #Y #SIZE #ROTATION #ORIGIN TEXT
899 if(fscanf(fp,"%d %d %u %d %u",&x, &y, &size, &angle,
900 &origin) != 5)
902 fprintf(stderr,"Error: Invalid text record #%d in %s()\n",
903 records_processed, __func__);
904 exit(1);
908 /* read in the text */
909 get_continued_string(text, MAX_TEXTLEN, fp);
911 x *= scale; /* correct coordinates */
912 y *= scale;
913 color = TEXT_COLOR;
914 visibility = 1;
915 show_name_value = 0;
917 /* get possible colour change */
918 linestyle = LINE_DEFAULT;
919 fillstyle = FILL_DEFAULT;
920 get_style(fp, &color, &linestyle, &fillstyle);
922 text_object(x, y, color, size, visibility, show_name_value, angle, text, \
923 origin);
927 void
928 do_line(FILE *fp)
930 int x[MAX_POINTS],y[MAX_POINTS];
931 unsigned int pairs,color,i;
932 struct LineStyle linestyle;
933 struct FillStyle fillstyle;
936 /* if we are inside of a pin definition, terminate */
937 reset_attributes();
940 /* the viewlogic line primitive is composed of
941 * l #PAIRS #X1 #Y1 #X2 #Y2 ... - Line
944 if(fscanf(fp,"%d",&pairs) != 1)
946 fprintf(stderr,"Error: Unable to read number of line pairs "
947 "for record #%d, in %s()\n",
948 records_processed, __func__);
949 exit(1);
952 /* scan in all the co-ordinate pairs and pop them into our array */
953 for (i=0; i < pairs; i++)
955 if(fscanf(fp,"%d %d", &x[i], &y[i]) != 2)
957 fprintf(stderr,"Error: unable to read %dth coodinate pair "
958 "for record #%d, in %s()\n",
959 i+1, records_processed, __func__);
960 exit(1);
963 x[i] *= scale;
964 y[i] *= scale;
967 /* slurp up trailing CR/NL */
968 if (getc(fp) == '\r')
969 getc(fp);
971 color = GRAPHIC_COLOR;
972 linestyle = LINE_DEFAULT;
973 fillstyle = FILL_DEFAULT;
974 /* now check for an optional style record */
975 get_style(fp, &color, &linestyle, &fillstyle);
977 /* now, output the line as a series of geda lines */
978 for(i=1; i<pairs; i++)
979 line_object(x[i-1],y[i-1],x[i],y[i],color,&linestyle);
984 void
985 do_pin(FILE *fp)
987 unsigned int pindir, pinsense, color;
988 unsigned int bradius = 25;
989 unsigned int bdiameter = 2*bradius;
990 unsigned int bcolor = LOGIC_BUBBLE_COLOR;
991 int x1, y1, x2, y2, bx, by, bx1, by1, bx2, by2;
992 OBJECT_PINTYPE pintype;
993 unsigned int whichend;
994 struct LineStyle linestyle;
995 struct FillStyle fillstyle;
997 /* if we are inside of a pin definition, terminate */
998 reset_attributes();
1000 /* viewlogic pin primitives have the following format:
1001 * P #PININSTANCE #X1 #Y1 #X2 #Y2 # #PINDIRECTION #PINSENSE
1004 if(fscanf(fp,"%*d %d %d %d %d %*d %u %u\n",&x1, &y1, &x2, &y2,
1005 &pindir, &pinsense) != 6)
1007 fprintf(stderr,"Error:Invalid pin record #%d in %s()\n",
1008 records_processed, __func__);
1009 exit(1);
1012 x1 *= scale;
1013 y1 *= scale;
1014 x2 *= scale;
1015 y2 *= scale;
1016 bx1 = x1;
1017 by1 = y1;
1018 bx2 = x2;
1019 by2 = y2;
1020 color = PIN_COLOR;
1023 /* Determine the 'whichend' parameter and the coordinates for the "bubble" */
1024 /* if we need to use one. We need a "bubble" when pinsense=1. */
1025 switch (pindir)
1027 case 0: /* Pin on top */
1028 if (y1 > y2)
1030 whichend = 0;
1031 bx = x2;
1032 by = y2+bradius;
1033 by2 += bdiameter;
1035 else
1037 whichend = 1;
1038 bx = x1;
1039 by = y1+bradius;
1040 by1 += bdiameter;
1042 break;
1043 case 1: /* Pin on bottom */
1044 if (y1 < y2)
1046 whichend = 0;
1047 bx = x2;
1048 by = y2-bradius;
1049 by2 -= bdiameter;
1051 else
1053 whichend = 1;
1054 bx = x1;
1055 by = y1-bradius;
1056 by1 -= bdiameter;
1058 break;
1059 case 2: /* Pin on left */
1060 if (x1 < x2)
1062 whichend = 0;
1063 bx = x2-bradius;
1064 by = y2;
1065 bx2 -= bdiameter;
1067 else
1069 whichend = 1;
1070 bx = x1-bradius;
1071 by = y1;
1072 bx1 -= bdiameter;
1074 break;
1075 case 3: /* Pin on right */
1076 if (x1 > x2)
1078 whichend = 0;
1079 bx = x2+bradius;
1080 by = y2;
1081 bx2 += bdiameter;
1083 else
1085 whichend = 1;
1086 bx = x1+bradius;
1087 by = y1;
1088 bx1 += bdiameter;
1090 break;
1091 default:
1092 /* Invalid pin direction */
1093 fprintf(stderr,"Error: Invalid pin direction %d in "
1094 "ViewLogic file at record #%d, in function %s()\n",
1095 pindir, records_processed, __func__);
1096 exit(1);
1099 /* if this pin has to be of negative polarity, add a bitty bubble
1100 * and adjust the size of the pin
1102 if(pinsense == 1)
1104 x1 = bx1;
1105 y1 = by1;
1106 x2 = bx2;
1107 y2 = by2;
1109 linestyle = LINE_DEFAULT;
1110 fillstyle = FILL_DEFAULT;
1112 circle_object(bx,by,bradius,bcolor,&linestyle,&fillstyle);
1115 /* For now, only normal pins are supported */
1116 pintype = NORMAL_PIN;
1118 pin_object(x1,y1,x2,y2,color,pintype,whichend);
1121 add_attributes = 1; /* add attributes */
1122 attach_pending = 1; /* signal that an attachment could be coming */
1123 pin_attributes = 1; /* and that they are pin attributes */
1124 pin_count++; /* bump the number of pins */
1128 void
1129 do_box(FILE *fp)
1131 int x1, y1, x2, y2, width, height;
1132 unsigned int color;
1133 struct LineStyle linestyle;
1134 struct FillStyle fillstyle;
1137 /* if we are inside of a pin definition, terminate */
1138 reset_attributes();
1140 /* a viewlogic box has the following format:
1141 * b #X1 #Y1 #X2 #Y2
1142 * geda view of a box has the corner, width and height
1144 if(fscanf(fp, "%d %d %d %d\n", &x1, &y1, &x2, &y2) != 4)
1146 fprintf(stderr, "Error: Invalid box record #%d in %s()\n",
1147 records_processed, __func__);
1148 exit(1);
1151 x1 *= scale;
1152 y1 *= scale;
1153 x2 *= scale;
1154 y2 *= scale;
1156 width = x2-x1;
1157 height = y2-y1;
1158 color = GRAPHIC_COLOR;
1160 linestyle = LINE_DEFAULT;
1161 fillstyle = FILL_DEFAULT;
1162 get_style(fp, &color, &linestyle, &fillstyle);
1164 box_object(x1,y1,width,height,color,&linestyle,&fillstyle);
1167 void
1168 do_circle(FILE *fp)
1170 int x, y;
1171 unsigned int radius, color;
1172 struct LineStyle linestyle;
1173 struct FillStyle fillstyle;
1175 /* if we are inside of a pin definition, terminate */
1176 reset_attributes();
1178 /* a circle has the following format:
1179 * c #x #y #radius
1181 if(fscanf(fp,"%d %d %u\n",&x, &y, &radius) != 3)
1183 fprintf(stderr,"Error: Invalid circle record #%d in %s()\n",
1184 records_processed, __func__);
1185 exit(1);
1188 x *= scale;
1189 y *= scale;
1190 radius *= scale;
1191 color = GRAPHIC_COLOR;
1193 linestyle = LINE_DEFAULT;
1194 fillstyle = FILL_DEFAULT;
1195 get_style(fp, &color, &linestyle, &fillstyle);
1197 circle_object(x,y,radius,color,&linestyle,&fillstyle);
1200 void
1201 do_arc(FILE *fp)
1203 int x1, y1, x2, y2, x3, y3;
1204 unsigned int color;
1205 double x2p, y2p, x3p, y3p, yop, xop, xo, yo;
1206 double to_rad;
1207 double gstart, sweep_angle, start_angle, end_angle;
1208 double radius;
1209 struct LineStyle linestyle;
1210 struct FillStyle fillstyle;
1212 /* if we are inside of a pin definition, terminate */
1213 reset_attributes();
1215 /* arcs have the following format:
1216 * a #X1 #Y1 #X2 #Y2 #X3 #Y3
1217 * we need to transform this into the geda convention of
1218 * center, radius, start angle, stop angle.
1221 if(fscanf(fp,"%d %d %d %d %d %d\n",
1222 &x1, &y1, &x2, &y2, &x3, &y3) != 6)
1224 fprintf(stderr,"Error: Invalid arc record #%d, in %s()\n",
1225 records_processed, __func__);
1226 exit(1);
1229 x1 *= scale;
1230 y1 *= scale;
1231 x2 *= scale;
1232 y2 *= scale;
1233 x3 *= scale;
1234 y3 *= scale;
1235 color = GRAPHIC_COLOR;
1236 linestyle = LINE_DEFAULT;
1237 fillstyle = FILL_DEFAULT;
1238 get_style(fp, &color, &linestyle, &fillstyle);
1240 x2p = x2 - x1;
1241 y2p = y2 - y1;
1243 x3p = x3 - x1;
1244 y3p = y3 - y1;
1246 /* printf("Buffer: `%s'\n",buf);
1247 * printf("Values: x2p: %f, y2p: %f, x3p: %f, y3p: %f\n",x2p, y2p, x3p, y3p);
1249 if(fabs(x2p * y3p - y2p * x3p) < 0.00001)
1251 /* some miscreant entered a degenerate arc, just output lines */
1252 line_object(x1,y1,x2,y2,color,&linestyle);
1253 line_object(x2,y2,x3,y3,color,&linestyle);
1254 return;
1257 yop = ((x2p * ( x3p*x3p + y3p*y3p ) - x3p * ( x2p*x2p + y2p*y2p )) /
1258 (2 * (x2p * y3p - y2p * x3p)));
1260 xop = (x2p*x2p - 2*y2p*yop) / (2 * x2p);
1262 xo = xop + x1;
1263 yo = yop + y1;
1266 radius = hypot(xop, yop);
1268 /* calculate start and end angles */
1269 to_rad = 180.0/atan2(0,-1);
1270 start_angle = atan2(y1-yo, x1-xo) * to_rad;
1271 end_angle = atan2(y3-yo, x3-xo) * to_rad;
1273 if(start_angle > end_angle)
1275 gstart = end_angle;
1276 sweep_angle = start_angle - end_angle;
1278 else
1280 gstart = start_angle;
1281 sweep_angle = end_angle - start_angle;
1284 /* end_angle =
1285 * end_angle = int(atan2(y1-yo, x1-xo) * to_rad) % 360;
1286 * start_angle = int(atan2(y3-yo, x3-xo) * to_rad) % 360;
1290 arc_object((int)xo,(int)yo, (unsigned int)radius,
1291 (int)gstart,(int)sweep_angle, color, &linestyle);
1295 void
1296 do_label(FILE *fp)
1298 int x, y, angle, global, overbar;
1299 unsigned int color, size, origin, visibility, show_name_value;
1300 char text[MAX_TEXTLEN];
1301 char text2[MAX_TEXTLEN];
1302 struct LineStyle linestyle;
1303 struct FillStyle fillstyle;
1304 int i, length;
1306 /* labels have the following format:
1307 * L #X #Y #SIZE #ROTATION #ORIGIN #GLOBAL #VISIBILITY #OVERBAR TEXT
1310 /* reproduce as simple text, unless it is a label for an object */
1312 if(fscanf(fp, "%d %d %u %d %d %d %d %d", &x, &y, &size, &angle, &origin,
1313 &global, &visibility, &overbar) != 8)
1315 fprintf(stderr,"Error: Invalid label record #%d in %s()\n",
1316 records_processed, __func__);
1317 exit(1);
1320 x *= scale;
1321 y *= scale;
1322 color = ATTRIBUTE_COLOR;
1323 show_name_value = 0;
1325 /* read in the text */
1326 get_continued_string(text2, MAX_TEXTLEN, fp);
1328 /* if ViewDraw showed the label with an overbar, append a '~' to the */
1329 /* beginning of the name. gEDA does not support overbars, so the '~' lets */
1330 /* the designer know he's dealing with an active low signal */
1331 if (overbar)
1333 length = strlen(text2);
1334 text2[length + 1] = 0;
1335 for (i = length; i > 0; i--)
1336 text2[i] = text2[i - 1];
1337 text2[0] = '~';
1340 linestyle = LINE_DEFAULT;
1341 fillstyle = FILL_DEFAULT;
1342 get_style(fp, &color, &linestyle, &fillstyle);
1344 /* if we are inside a pin definition, mangle the pin name */
1345 if(net_attributes == 1) /* a netname on a net is its netname */
1347 #ifdef HAVE_SNPRINTF
1348 snprintf(text, MAX_TEXTLEN, "netname=%s", text2);
1349 #else
1350 sprintf(text, "netname=%s", text2);
1351 #endif
1352 show_name_value = 1;
1355 else if(complex_attributes == 1) /* a label on a complex is its designator */
1357 #ifdef HAVE_SNPRINTF
1358 snprintf(text, MAX_TEXTLEN, "refdes=%s", text2);
1359 #else
1360 sprintf(text, "refdes=%s", text2);
1361 #endif
1362 show_name_value = 1;
1364 else if(pin_attributes == 1) /* a label on a pin is it's pinname */
1366 #ifdef HAVE_SNPRINTF
1367 snprintf(text, MAX_TEXTLEN, "pinlabel=%s", text2);
1368 #else
1369 sprintf(text, "pinlabel=%s", text2);
1370 #endif
1371 show_name_value = 1;
1373 else
1374 strcpy(text,text2); /* don't need to do anything, just copy */
1376 begin_attach();
1377 text_object(x, y, color, size, visibility, show_name_value, angle, text, \
1378 origin);
1381 /* four functions for doing net stuff */
1382 void
1383 do_net_start(FILE *fp)
1385 reset_attributes();
1387 fscanf(fp,"%*d\n"); /* just dispose of the net instance number */
1389 reading_net = 1;
1390 segment_count = 1;
1393 void
1394 do_net_node(FILE *fp)
1396 int x,y,type;
1398 /* in geda nets are composed of a number of segments, gschem connects
1399 * them together on the screen, since viewlogic stores a net as a series
1400 * of nodes we need to tabulate them and only output segments when we
1401 * get connectivity information
1403 * net segments have the following format:
1404 * J #X #Y #SEGNUM - Net segment
1407 if(segment_count > MAX_NODES)
1409 fprintf(stderr,"Error: too many nodes on a net at record #%d, "
1410 "in %s(), try increasing\n"
1411 "\tMAX_NODES\n", records_processed, __func__);
1412 exit(1); /* this is fatal */
1415 /* get the current info */
1416 if(fscanf(fp,"%d %d %d\n",&x, &y, &type) < 2)
1418 fprintf(stderr,"Error: Invalid net node record #%d in %s()\n",
1419 records_processed, __func__);
1420 exit(1);
1423 x *= scale;
1424 y *= scale;
1426 net_nodes_x[segment_count] = x;
1427 net_nodes_y[segment_count] = y;
1429 segment_count++;
1433 void
1434 do_net_segment(FILE *fp)
1436 unsigned int n1, n2, color;
1438 reset_attributes();
1440 /* net segment connectivity records have the following format:
1441 * S #N1 #N2 - Net connectivity, Node N1 is connected to N2
1444 if(fscanf(fp,"%u %u\n",&n1, &n2) != 2)
1446 fprintf(stderr,"Error: Invalid net segment record #%d in %s()\n",
1447 records_processed, __func__);
1448 exit(1);
1451 color = NET_COLOR;
1453 /* output a geda net segment */
1454 net_segment(net_nodes_x[n1], net_nodes_y[n1],
1455 net_nodes_x[n2], net_nodes_y[n2], color);
1457 /* there could be attributes to follow */
1458 add_attributes = 1; /* add attributes */
1459 attach_pending = 1; /* signal that an attachment could be coming */
1460 net_attributes = 1; /* and that they are net attributes */
1463 void
1464 do_net_segment_bus(FILE *fp)
1466 unsigned int n1, n2, color;
1467 int ripperdir;
1469 reset_attributes();
1471 /* bus net segment connectivity records have the following format:
1472 * B #N1 #N2 - Net connectivity, Node N1 is bussed to N2
1475 if(fscanf(fp,"%u %u\n",&n1, &n2) != 2)
1477 fprintf(stderr,"Error: Invalid bus segment record #%d in %s()\n",
1478 records_processed, __func__);
1479 exit(1);
1482 color = BUS_COLOR;
1484 /* For now, we'll use ripperdir=0 (no nets connected to bus yet) */
1485 ripperdir = 0;
1487 /* output a geda bus segment */
1488 bus_segment(net_nodes_x[n1], net_nodes_y[n1],
1489 net_nodes_x[n2], net_nodes_y[n2], color, ripperdir);
1491 /* there could be attributes to follow */
1492 add_attributes = 1; /* add attributes */
1493 attach_pending = 1; /* signal that an attachment could be coming */
1494 net_attributes = 1; /* and that they are net attributes */
1497 void
1498 do_instance(FILE *fp)
1500 char text[MAX_TEXTLEN];
1501 char lib[MAX_TEXTLEN], name[MAX_TEXTLEN], symName[MAX_TEXTLEN];
1502 unsigned int extension, selectable;
1503 int x, y, angle, orientation, mirror;
1504 float scale_factor;
1505 int result, index, i;
1507 reset_attributes();
1509 /* a component instance has the following format
1510 * I #instance LIB:NAME #PAGE #X #Y #ROTATION #MAGNIFICATION '
1513 text[0] = 0;
1514 lib[0] = 0;
1515 name[0] = 0;
1516 extension = 9999;
1517 x = 0;
1518 y = 0;
1519 orientation = 0;
1520 angle = 0;
1521 mirror = 0;
1523 /* Instance doesn't necessarily have to have the LIB:NAME convention, so */
1524 /* read this in as a full string and parse later */
1525 /* if(fscanf(fp,"%*d %[a-zA-Z0-9]:%[a-zA-Z0-9] %u %d %d %d %g %*s\n", */
1526 result = fscanf(fp,"%*d %s %u %d %d %d %g %*s\n",
1527 text, &extension, &x, &y, &orientation, &scale_factor);
1528 /* find library and symbol name */
1529 index = strindex(text, ':');
1530 if (index > 0 || text[0] == ':')
1532 text[index] = 0;
1533 strcpy(lib, text);
1534 strcpy(name, &text[index+1]);
1536 else
1537 strcpy(name, text);
1538 /* Check for input errors */
1539 if (result < 6)
1541 fprintf(stderr,"Error: Invalid instance record #%d in %s()\n"
1542 "lib:'%s', name:'%s'\n"
1543 "extension:%d, x:%d, y:%d\n",
1544 records_processed, __func__, lib,name,extension, x, y);
1545 exit(1);
1548 x *= scale;
1549 y *= scale;
1551 /* ViewDraw components are always selectable */
1552 selectable = 1;
1554 /* Correct orientation */
1555 set_orientation(&angle, &mirror, orientation);
1557 /* fix case */
1558 strtolower(name);
1560 /* replace dashes in the name with underscores */
1561 for (i = strlen(name) - 1; i >= 0; i--)
1562 if (name[i] == '-')
1563 name[i] = '_';
1565 /* produce proper file name: */
1566 #ifdef HAVE_SNPRINTF
1567 snprintf(symName, MAX_TEXTLEN, "%s-%d.sym",name,extension);
1568 #else
1569 sprintf(symName, "%s-%d.sym",name,extension);
1570 #endif
1572 complex_object(x, y, selectable, angle, mirror, symName);
1574 /* there could be attributes to follow */
1575 add_attributes = 1; /* add attributes */
1576 attach_pending = 1; /* signal that an attachment could be coming */
1577 complex_attributes = 1; /* and that they are complex attributes */
1581 /* ViewDraw mirrors components over the x-axis, but gSchem mirrors over the */
1582 /* y-axis. */
1583 /* This makes (270, 1) viewlogic -> (90, 1) gschem */
1584 /* and (90, 1) viewlogic -> (270, 1) gschem */
1585 /* and (180, 1) viewlogic -> (0, 1) gschem */
1586 /* and (0, 1) viewlogic -> (180, 1) gschem */
1587 void
1588 set_orientation(int *angle, int *mirror, int orientation)
1590 switch (orientation) {
1591 case 0: /* 0 rotation, 0 mirror */
1592 *angle = 0;
1593 *mirror = 0;
1594 break;
1595 case 1: /* 90 rotation, 0 mirror */
1596 *angle = 90;
1597 *mirror = 0;
1598 break;
1599 case 2: /* 180 rotation, 0 mirror */
1600 *angle = 180;
1601 *mirror = 0;
1602 break;
1603 case 3: /* 270 rotation, 0 mirror */
1604 *angle = 270;
1605 *mirror = 0;
1606 break;
1607 case 4: /* 180 rotation, 1 mirror */
1608 *angle = 0;
1609 *mirror = 1;
1610 break;
1611 case 5: /* 90 rotation, 1 mirror */
1612 *angle = 270;
1613 *mirror = 1;
1614 break;
1615 case 6: /* 0 rotation, 1 mirror */
1616 *angle = 180;
1617 *mirror = 1;
1618 break;
1619 case 7: /* 270 rotation, 1 mirror */
1620 *angle = 90;
1621 *mirror = 1;
1622 break;
1623 default:
1624 fprintf(stderr,"Error: Invalid orientation value %d at record %d\n",
1625 orientation, records_processed);
1629 /* YYYY */
1631 /* output a geda text object */
1632 void
1633 text_object(int x, int y, unsigned int color, unsigned int size,
1634 unsigned int visibility, unsigned int show_name_value,
1635 int angle, char *text, unsigned int origin)
1637 unsigned int text_size;
1638 #if 0
1639 unsigned int textlen;
1640 #endif
1641 unsigned int numlines;
1643 /* fudge the text size, in viewdraw it is actually the height
1644 * in geda it is the point size. The Variable text_size contains
1645 * the height of the text in points, size contains the height of
1646 * the text in viewlogic units.
1648 text_size = (int)(size * 0.72);
1650 /* Translate ViewDraw text origin to gEDA
1651 * ViewDraw's text origin is specified like this:
1652 * 1 4 7
1653 * 2 5 8
1654 * 3 6 9
1655 * where 1 is the top left corner of the text and 9 is the bottom right,
1656 * etc.
1657 * gEDA's text origin is specified like this:
1658 * 2 5 8
1659 * 1 4 7
1660 * 0 3 6
1661 * so, the below conversion is necessary
1663 origin = (((origin - 1) / 3) * 6) + 3 - origin;
1665 /* No longer necessary to emulate ViewDraw text origin, it is now supported */
1666 /* by gEDA */
1667 #if 0
1668 /* emulate the viewdraw text origin by shifting the text around */
1670 /* if the origin is one of the ones that are along the center line,
1671 * adjust y
1673 if ( (origin == 2) || (origin == 5) || (origin == 8) )
1675 y -= (size * scale) / 2;
1678 if( (origin == 1) || (origin == 4) || (origin == 7) )
1680 y -= size * scale;
1683 /* approximate the length of the text */
1685 switch(show_name_value)
1687 case 0: /* measure whole text length */
1688 textlen = GetStringDisplayLength(text,text_size);
1689 break;
1691 case 1: /* measure just the value part */
1692 textlen = GetStringDisplayLength(&text[strindex(text,'=') + 1],
1693 text_size);
1694 break;
1696 case 2: /* measure just the name part */
1697 textlen = GetStringDisplayLength(text, text_size)
1698 - GetStringDisplayLength(&text[strindex(text,'=')],text_size);
1699 break;
1701 default:
1702 fprintf(stderr,"Error: invalid show_name_value: %d at record #%d, "
1703 "in %s()\n",
1704 show_name_value, records_processed, __func__);
1705 return;
1708 /* if the origin is one of the middle ones
1709 * fix the x coordinate
1711 if( (origin == 4) || (origin == 5) || (origin == 6) )
1713 x -= textlen / 2;
1716 if( (origin == 7) || (origin == 8) || (origin == 9) )
1718 x -= textlen;
1720 #endif
1722 /* Translate ViewDraw text rotation to gEDA text angle
1723 * ViewDraw's text rotation is specified like this:
1724 * 0 = 0 degrees, no rotation
1725 * 1 = 90 degrees
1726 * 2 = 180 degrees
1727 * 3 = 270 degrees
1728 * gEDA's text angle is specified in degrees, so the below conversion is
1729 * necessary
1731 angle *= 90;
1733 /* gEDA now supports rotated text, so we no longer need to force angle to */
1734 /* be 0 */
1735 #if 0
1736 /* currently angled/rotated text is not supported, print a
1737 * warning, and force the orientation
1739 if(angle != 0)
1741 angle = 0;
1742 fprintf(stderr,"Warning: Forcing text '%s' into standard alignment "
1743 "at record #%d\n",
1744 text,records_processed);
1746 #endif
1748 /* Since x and y are automatically multiplied by 10 (the scale factor), */
1749 /* the below operation is not necessary */
1750 #if 0
1751 /* force text to start on a 10 unit boundary */
1752 if((x % 10) < 5)
1753 x = x - (x % 10);
1754 else
1755 x = x + (10 - (x % 10));
1757 if((y % 10) < 5)
1758 y = y - (y % 10);
1759 else
1760 y = y + (10 - (x % 10));
1761 #endif
1763 /* Only one line of text per statement allowed in ViewDraw, so this is */
1764 /* always 1 */
1765 numlines = 1;
1767 printf( "T %d %d %u %u %u %u %d %u %u\n%s\n", x, y, color, text_size,
1768 visibility, show_name_value, angle, origin, numlines, text);
1773 void
1774 attribute_object(int x, int y, unsigned int color, unsigned int size,
1775 unsigned int visibility, unsigned int show_name_value,
1776 int angle, char *name, char *value, unsigned int origin)
1779 char text[MAX_TEXTLEN], text2[MAX_TEXTLEN];
1780 char tmpName[MAX_TEXTLEN], tmpValue[MAX_TEXTLEN];
1781 unsigned int i, j, done, length;
1783 /* make a copy of the attribute to work with */
1784 strncpy(tmpName, name, MAX_TEXTLEN-1);
1785 tmpName[MAX_TEXTLEN-1] = 0; /* terminate in case strncpy doesnt */
1786 if (value == NULL)
1787 tmpValue[0] = 0; /* no value with ViewDraw attribute */
1788 else
1790 strncpy(tmpValue, value, MAX_TEXTLEN-1);
1791 tmpValue[MAX_TEXTLEN-1] = 0; /* terminate in case strncpy doesnt */
1794 /* look up attribute name in translation attribute list
1795 * and translate or print approprate message
1797 done = 0;
1798 for(i=0; (i<nTranslations) && !done; i++)
1801 #ifdef DEBUG
1802 printf("Comparing `%s' to `%s' in %s()\n",tmpName,
1803 translations[i].origName,__func__);
1804 #endif
1806 if(strcmp(tmpName,translations[i].origName) == 0) /* match? */
1807 switch(translations[i].action)
1809 case REPLACE_NAME:
1810 strncpy(tmpName, translations[i].newName, MAX_TEXTLEN-1);
1811 done = 1;
1812 break;
1814 case KILL:
1815 fprintf(stderr,"Warning: Killing attribute `%s=%s' at (%d,%d)"
1816 " from record #%d\n",
1817 tmpName, tmpValue,x,y,records_processed);
1818 done = 1;
1819 return;
1821 case WARN_USER:
1822 fprintf(stderr,"Warning: attribute name `%s=%s' at (%d,%d) "
1823 "at record #%d, found during conversion\n"
1824 "\tpassing it through unchanged\n",
1825 tmpName,tmpValue,x,y,records_processed);
1826 done = 1;
1827 break;
1828 default:
1829 fprintf(stderr,"Error: Unknown action code for attribute\n"
1830 "`%s=%s' at record #%d in %s()\n",
1831 tmpName,tmpValue,records_processed,__func__);
1832 exit(1);
1836 /* if attribute name was not replaced/dropped, convert to lowercase */
1837 /* and pass on */
1838 if (!done)
1839 strtolower(tmpName);
1841 /* If we are changing a ViewDraw SIGNAL attribute to a net attribute, */
1842 /* replace the ';' delimiter with a ':' */
1843 if (strcmp(tmpName, "net") == 0)
1844 tmpValue[strindex(tmpValue, ';')] = ':';
1846 /* If we are changing a ViewDraw HETERO attribute to a split attribute, */
1847 /* format the new value correctly */
1848 if (strcmp(tmpName, "split") == 0)
1850 strcpy(text2, tmpValue);
1851 strtolower(text2);
1852 j = 0;
1853 length = strlen(text2);
1854 for (i = 0; i < length; i++)
1856 /* Drop parentheses */
1857 if (text2[i] != '(' && text2[i] != ')')
1859 /* Convert dashes to underscores */
1860 if (text2[i] == '-')
1861 tmpValue[j++] = '_';
1862 /* insert gEDA symbol file extension before comma */
1863 else if (text2[i] == ',')
1865 #ifdef HAVE_SNPRINTF
1866 snprintf(&tmpValue[j], MAX_TEXTLEN, "-1.sch,");
1867 #else
1868 sprintf(&tmpValue[j], "-1.sch,");
1869 #endif
1870 j += 7;
1872 else
1873 tmpValue[j++] = text2[i];
1876 /* append gEDA symbol file extension to the end */
1877 #ifdef HAVE_SNPRINTF
1878 snprintf(&tmpValue[j], MAX_TEXTLEN, "-1.sch");
1879 #else
1880 sprintf(&tmpValue[j], "-1.sch");
1881 #endif
1884 /* If we have an NC attribute with no value, convert to netname=NC */
1885 if (strcmp(tmpName, "nc") == 0 && tmpValue[0] == 0)
1887 #ifdef HAVE_SNPRINTF
1888 snprintf(tmpName, MAX_TEXTLEN, "netname");
1889 snprintf(tmpValue, MAX_TEXTLEN, "NC");
1890 #else
1891 sprintf(tmpName, "netname");
1892 sprintf(tmpValue, "NC");
1893 #endif
1894 show_name_value = 1;
1897 /* just add an = into the middle */
1898 #ifdef HAVE_SNPRINTF
1899 snprintf(text, MAX_TEXTLEN, "%s=%s", tmpName, tmpValue);
1900 #else
1901 sprintf(text, "%s=%s", tmpName, tmpValue);
1902 #endif
1904 text_object( x, y, color, size, visibility, show_name_value, \
1905 angle, text, origin);
1910 void
1911 line_object(int x1, int y1, int x2, int y2, unsigned int color,
1912 struct LineStyle *linestyle)
1914 printf("L %d %d %d %d %u %i %i %i %i %i\n", x1, y1, x2, y2, color,
1915 linestyle->line_width, linestyle->line_capstyle,
1916 linestyle->line_dashstyle,linestyle->line_dashlength,
1917 linestyle->line_dashspace);
1920 void
1921 circle_object(int bx, int by, unsigned int radius, unsigned int bcolor,
1922 struct LineStyle *linestyle, struct FillStyle *fillstyle)
1924 printf("V %d %d %u %u %i %i %i %i %i %i %i %i %i %i %i\n",
1925 bx, by, radius, bcolor,
1926 linestyle->line_width, linestyle->line_capstyle,
1927 linestyle->line_dashstyle,linestyle->line_dashlength,
1928 linestyle->line_dashspace,
1929 fillstyle->fill_type, fillstyle->fill_width,
1930 fillstyle->fill_angle1, fillstyle->fill_pitch1,
1931 fillstyle->fill_angle2, fillstyle->fill_pitch2);
1934 void
1935 pin_object(int x1, int y1, int x2, int y2, unsigned int color,
1936 OBJECT_PINTYPE pintype, unsigned int whichend)
1938 printf("P %d %d %d %d %u %u %u\n", x1, y1, x2, y2, color,
1939 pintype, whichend);
1942 void
1943 box_object(int x1, int y1, unsigned int width, unsigned int height,
1944 unsigned int color, struct LineStyle *linestyle,
1945 struct FillStyle *fillstyle)
1947 printf("B %d %d %u %u %u %i %i %i %i %i %i %i %i %i %i %i\n", x1, y1,
1948 width, height, color,
1949 linestyle->line_width, linestyle->line_capstyle,
1950 linestyle->line_dashstyle,linestyle->line_dashlength,
1951 linestyle->line_dashspace,
1952 fillstyle->fill_type, fillstyle->fill_width,
1953 fillstyle->fill_angle1, fillstyle->fill_pitch1,
1954 fillstyle->fill_angle2, fillstyle->fill_pitch2);
1957 void
1958 arc_object(int x1, int y1, unsigned int radius,
1959 int start_angle, int sweep_angle, unsigned int color,
1960 struct LineStyle *linestyle)
1962 printf("A %d %d %u %d %d %u %i %i %i %i %i\n", x1, y1, radius,
1963 start_angle, sweep_angle, color,
1964 linestyle->line_width, linestyle->line_capstyle,
1965 linestyle->line_dashstyle, linestyle->line_dashlength,
1966 linestyle->line_dashspace);
1969 void
1970 net_segment(int x1, int y1, int x2, int y2, unsigned int color )
1972 printf("N %d %d %d %d %u\n", x1, y1, x2, y2, color);
1975 void
1976 bus_segment(int x1, int y1, int x2, int y2, unsigned int color, int ripperdir)
1978 printf("U %d %d %d %d %u %i\n", x1, y1, x2, y2, color, ripperdir);
1981 void
1982 complex_object(int x, int y, unsigned int selectable,
1983 int angle, unsigned int mirror, char *name)
1985 printf("C %d %d %u %d %u %s\n", x, y, selectable, angle, mirror, name);
1989 void
1990 begin_attach(void)
1992 if(attach_pending == 1) /* begin an attachment if one is pending*/
1994 printf("{\n");
1995 attach_pending = 0;
1999 void
2000 end_attach(void)
2002 printf("}\n");
2005 void
2006 reset_attributes(void)
2009 /* if we are inside of some kind of attribute attachment
2010 * terminate it, but only if we output the begin_attach.
2012 if((add_attributes == 1) && (attach_pending == 0))
2014 end_attach();
2017 attach_pending = 0; /* keep track of whether the last object */
2018 /* read may have attachments pending. */
2020 add_attributes = 0; /* keep track of whether we are adding attributes */
2021 /* to some previous object */
2022 pin_attributes = 0; /* when true, we are adding attributes to a pin */
2023 net_attributes = 0; /* when true, we are adding atrributes to a net */
2024 complex_attributes = 0;/* when true, we are addint attibutes to a complex */
2027 /* read a string possibly containing continuation characters
2028 * from the given stream
2030 int
2031 get_continued_string(char *buf, size_t buffer_size, FILE *fp)
2033 int c;
2034 size_t text_len;
2036 /* skip leading whitespace */
2037 while(isspace((c=fgetc(fp))));
2038 ungetc(c,fp); /* push back last char, cause it's not whitespace */
2040 /* read in the text */
2041 fgets(buf, buffer_size, fp);
2042 records_processed++;
2043 /* nuke trailing CR/NL, if there */
2044 text_len=strlen(buf);
2045 while (buf[text_len-1] == '\n' || buf[text_len-1] == '\r')
2047 buf[text_len-1] = 0;
2048 text_len--;
2051 /* check for continuation chars */
2052 while((c = getc(fp)) == '+')
2054 c = getc(fp); /* suck in space */
2055 fgets(&buf[text_len], MAX_TEXTLEN-text_len,fp); /* read in next chunk */
2056 records_processed++;
2057 text_len=strlen(buf); /* update text length */
2058 /* nuke trailing CR/NL, if there */
2059 while (buf[text_len-1] == '\n' || buf[text_len-1] == '\r')
2061 buf[text_len-1] = 0;
2062 text_len--;
2065 ungetc(c,fp); /* push back last char, obviously wasn't a + */
2067 #ifdef DEBUG
2068 printf("Buffer:'%s' in %s()\n",buf,__func__);
2069 #endif
2071 return 0;
2074 /* read in a possible style record to modify the current style */
2075 int get_style(FILE *fp, unsigned int *colour,
2076 struct LineStyle *linestyle,
2077 struct FillStyle *fillstyle)
2079 int c;
2080 unsigned int vdfillstyle, vdlinestyle;
2082 c = getc(fp);
2083 if(c == 'Q') /* do we have a modifier? */
2085 if(fscanf(fp,"%u %u %u\n", colour, &vdfillstyle, &vdlinestyle) != 3)
2087 fprintf(stderr,"Error: Invalid modifier record #%d in %s()\n",
2088 records_processed, __func__);
2089 exit(1);
2092 /* re-map colour into a geda colour */
2093 if(*colour > 15)
2095 fprintf(stderr,"Error: Invalid colour number %u in record #%d, "
2096 "in %s()\n",
2097 *colour,records_processed, __func__);
2098 exit(1);
2100 *colour = colormap[*colour];
2102 /* re-map vdfillstyle to gEDA FillStyle */
2103 if (vdfillstyle > 25)
2105 fprintf(stderr,"Warning: Invalid fill style %u in record #%d, "
2106 "in %s(). Assuming \"Hollow\" fill style.\n",
2107 vdfillstyle,records_processed, __func__);
2108 vdfillstyle = 0;
2110 memcpy(fillstyle, &fillmap[vdfillstyle], sizeof(struct FillStyle));
2112 /* re-map vdlinestyle to gEDA LineStyle */
2113 if (vdlinestyle > 7)
2115 fprintf(stderr,"Warning: Invalid line style %u in record #%d, "
2116 "in %s(). Assuming \"Solid\" line style.\n",
2117 vdlinestyle,records_processed, __func__);
2118 vdlinestyle = 0;
2120 memcpy(linestyle, &linemap[vdlinestyle], sizeof(struct LineStyle));
2122 records_processed++;
2124 else
2125 ungetc(c,fp); /* false alarm */
2127 return 0;
2132 /* return the index of character c in the string pointed to by s
2134 unsigned int
2135 strindex(char *s, char c)
2137 char *p;
2138 unsigned int i;
2140 for(p=s, i=0; *p; p++,i++)
2141 if(*p == c)
2142 return i;
2144 return 0;
2147 /* return the index of the last occurance of character c in
2148 * the string pointed to by s
2150 unsigned int
2151 strrindex(char *s, char c)
2153 char *p;
2154 unsigned int i, loc;
2156 loc = 0;
2157 for(p=s, i=0; *p; p++, i++)
2158 if(*p == c)
2159 loc = i;
2161 return loc;
2164 /* convert a string to lower case */
2165 void
2166 strtolower(char *s)
2168 char *p;
2170 for(p=s; *p; p++)
2171 *p = tolower((int) *p);