1 /*************************************************************************/
2 /* gmk_sym, a program to create rectangular symbols for gschem */
3 /* from a file composed of comma separated lines */
4 /* From: Jerry O'Keefe, jerryok@pacbell.net */
5 /* Version: 0.000005 */
8 /* 99/03/23 Fixed pin#= placeholder as define in Component Symbol Guide */
9 /* 99/04/02 Fixed pin spacing on right side and changed name to gmk_sym */
10 /* 99/04/27 Add Mike Jarabek's updates, alphanumeric pin name support */
11 /* and improved text spacing */
12 /* 99/05/02 Add char_width.c support */
14 /* 00/07/12 Major changes to match new styles for text and attributes */
15 /* 02/01/19 Changed the way pin labels and numbers are anchored to the */
16 /* pins. They make use of the text origin feature so that */
17 /* calculation of the string width is no longer needed. This */
18 /* results in much more uniformly placed pins on the left and */
19 /* bottom side of the device. Also added the ability to */
20 /* place the device name in the center of the symbol, useful */
21 /* for large symbols containing pins on all sides. Top and */
22 /* bottom pin numbers are rotated by 90 degrees to match the */
23 /* pin rotation. Added pin type attribute capability. (Roberto */
26 /* 2002/05/15 Added checks to prevent segfaults on invalid */
27 /* input data (Chris Ellec) */
28 /* 2002/08/14 Check for multiple instances of the same pin number and quit */
29 /* when this happens, give Fatal error messsage. (Chris Ellec) */
30 /* 2002/12/30 Change to new file format (Chris Ellec), version 20021103 */
31 /*-----------------------------------------------------------------------*/
32 /* This program is free software; you can redistribute it and/or modify */
33 /* it under the terms of the GNU General Public License as published by */
34 /* the Free Software Foundation; either version 2 of the License, or */
35 /* (at your option) any later version. */
37 /* This program is distributed in the hope that it will be useful, */
38 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
39 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
40 /* GNU General Public License for more details. */
42 /*-----------------------------------------------------------------------*/
43 /* GMK_SYM typical use: */
44 /* gk_sym 7474.txt >7474-3.sym */
46 /* gcc -O2 -Wall gmk_sym.c -o gmk_sym */
47 /*-----------------------------------------------------------------------*/
48 /*-----------------------------------------------------------------------*/
49 /* The input file format: */
50 /* 1. lines starting with ';' are comment lines, and */
51 /* are not processed. */
52 /* 2. The 1st valid line describes a device */
53 /* 1st value: device name */
54 /* 2nd value: visible name */
55 /* 3rd value: visible name location on package, */
56 /* 4th value: box's hoz size, in pins spacings */
57 /* 5th value: box's ver size, in pins spacings */
58 /* 6th value: uref prefix, like U or J */
59 /* 7th value: Footprint */
60 /* 8th value: Total number of pins on device (including hidden) */
61 /* 3. All other valid lines describes the symbol's pins */
62 /* 1st value: pin name */
63 /* 2nd value: pin number */
64 /* 3rd value: pin shape, choice of: line, clock, dot&line */
65 /* 4th value: side of box to attach the pin,choice of: R, L, T, B */
66 /* 5th value: location of pin on side of box, in pin spacings */
67 /* 6th value: (optional) pin type attribute: in, out, io, oc, oe, */
68 /* pas, tp, tri, clk, pwr */
69 /* See the 7474 sample file below */
70 /*************************************************************************/
72 /****************************************************/
74 ;; An example of a
7474 symbol make file
75 ; This is a comment line
76 /* puon: added "cc" */
77 ;; device name
,name
, name
location(tl
,tc
,tr
,bl
,bc
,br
,cc
),X size in pins
,Y size in pins
80 ;; pin name
,pin number
,shape(line
,clock
,dot
),side(r
,l
,t
,b
),pin position
89 /****************************************************/
101 #include <sys/time.h>
114 #define MAX_FIELDS 10
123 #define CLOCK_SHAPE 2
125 #define PINTYPE_IN "IN"
126 #define PINTYPE_OUT "OUT"
127 #define PINTYPE_IO "IO"
128 #define PINTYPE_OC "OC"
129 #define PINTYPE_OE "OE"
130 #define PINTYPE_PAS "PAS"
131 #define PINTYPE_TP "TP"
132 #define PINTYPE_TRI "TRI"
133 #define PINTYPE_CLK "CLK"
134 #define PINTYPE_PWR "PWR"
137 extern int optind
,opterr
,optopt
;
140 int GetStringDisplayLength(char *str
,int font_size
);
142 int line2fields(char *pBuf
,int field_cnt
,char *pField
[]);
143 int fields_free(char *pField
[]);
144 int make_pin(int fldcnt
,char *pFields
[]);
145 int make_box(int fldcnt
,char *pFields
[]);
146 static char *strLabel(char *p
, char *pTemp
);
147 void strtrail(char *wrk
);
148 int line_chk(char *pBuf
);
149 #if !defined(HAVE_STRCASECMP) && defined(HAVE_STRICMP) && !defined(stricmp)
150 #define strcasecmp stricmp
152 #if !defined(HAVE_STRNCASECMP) && defined(HAVE_STRNICMP) && !defined(strnicmp)
153 #define strncasecmp strnicmp
159 int BoxHeight
,BoxWidth
;
162 char pin_used
[300][5]; /* keep track of pin number used. Assume 300 pins max */
165 /***************************************************/
166 /***************************************************/
167 int main(int argc
,char **argv
)
171 int fldcnt
,i
,c
,Debug
=0;
172 char *pFields
[MAX_FIELDS
];
175 while ((c
= getopt(argc
, argv
, "?hd:")) != EOF
)
183 fprintf(stderr
,"usage: %s -dh?\n",argv
[0]);
190 fprintf(stderr
, "note: debug flag is currently ignored\n");
192 for(i
=0;i
<MAX_FIELDS
;i
++)
198 if ((stream
= fopen(argv
[1],"r")) == NULL
)
200 fprintf(stderr
, "Cannot open file: %s\n",argv
[1]);
206 printf("v 20030525\n"); /* The v character is the version of the file */
208 while (fgets(LineBuf
,sizeof(LineBuf
)-1,stream
) != NULL
)
210 if (line_chk(LineBuf
) < 0)
212 if ((fldcnt
= line2fields(LineBuf
,10,pFields
)) > 0)
216 make_box(fldcnt
,pFields
);
218 if (make_pin(fldcnt
,pFields
)< 0) {
219 fields_free(pFields
);
220 break; /* error processing the pin, get out */
222 fields_free(pFields
);
229 /***************************************************/
230 /***************************************************/
231 int fields_free(char *pField
[])
233 for (i
=0; (i
<MAX_FIELDS
) && (pField
[i
] != NULL
) ;i
++)
241 /***************************************************/
242 /***************************************************/
243 int line2fields(char *pBuf
,int max_fields
,char *pField
[])
247 if ((p
= strchr(pBuf
,'\n')) != NULL
)
249 if ((p
= strchr(pBuf
,'\r')) != NULL
)
253 pField
[fld_cnt
] = NULL
;
254 p
= strLabel(p
, temp
); /* copy the tokens from the string to array */
255 pField
[fld_cnt
] = (char *) malloc(strlen(temp
) + 1);
256 strcpy(pField
[fld_cnt
++], temp
);
261 /***************************************************/
262 /***************************************************/
263 void cross(int pos_x
,int pos_y
,int color
)
265 printf("L %d %d %d %d %d 0 0 0 -1 -1\n",pos_x
+-50,pos_y
,pos_x
+50,pos_y
,color
);
266 printf("L %d %d %d %d %d 0 0 0 -1 -1\n",pos_x
,pos_y
+50,pos_x
,pos_y
-50,color
);
269 /***************************************************/
270 /***************************************************/
271 void pin_add(int pos_x
,int pos_y
,char *pin
,int shape
,int dir
,char *name
, char *type
)
273 int xdir
=0,ydir
=0,font_size
=8;
277 case L_SIDE
: xdir
= 1; ydir
= 0;
279 case R_SIDE
: xdir
= -1; ydir
= 0;
281 case B_SIDE
: xdir
= 0; ydir
= 1;
283 case T_SIDE
: xdir
= 0; ydir
= -1;
287 if (shape
== LINE_SHAPE
)
289 /* Added "0 1" to match the new file format for pins - Chris Ellec */
290 printf("P %d %d %d %d %d 0 1\n",pos_x
,pos_y
,
291 pos_x
-pin_len
*xdir
,pos_y
-pin_len
*ydir
,
295 else if (shape
== DOT_SHAPE
)
297 printf("V %d %d 50 %d 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n",
298 pos_x
-50*xdir
,pos_y
-50*ydir
,CYAN
);
299 printf("P %d %d %d %d %d 0 1\n",pos_x
-100*xdir
,pos_y
-100*ydir
,
300 pos_x
-pin_len
*xdir
,pos_y
-pin_len
*ydir
,
304 else if (shape
== CLOCK_SHAPE
)
306 printf("L %d %d %d %d %d 0 0 0 -1 -1\n",pos_x
-100*ydir
,pos_y
-100*xdir
,
307 pos_x
+100*xdir
,pos_y
+100*ydir
,GREEN
);
308 printf("L %d %d %d %d %d 0 0 0 -1 -1\n",pos_x
+100*ydir
,pos_y
+100*xdir
,
309 pos_x
+100*xdir
,pos_y
+100*ydir
,GREEN
);
310 printf("P %d %d %d %d %d 0 1\n",pos_x
,pos_y
,
311 pos_x
-pin_len
*xdir
,pos_y
-pin_len
*ydir
,
318 /* pin_xy(dir,pin,font_size,&x,&y); */
323 printf("T %d %d %d %d 0 1 0 6\n",x
-50,y
+50,YELLOW
,font_size
);
326 printf("T %d %d %d %d 0 1 0 0\n",x
+50,y
+50,YELLOW
,font_size
);
329 printf("T %d %d %d %d 0 1 90 6\n",x
-50,y
-50,YELLOW
,font_size
);
332 printf("T %d %d %d %d 0 1 90 0\n",x
-50,y
+50,YELLOW
,font_size
);
335 printf("pinseq=%d\n",++net_pin
);
337 /* output pinnumber */
341 printf("T %d %d %d %d 1 1 0 6\n",x
-50,y
+50,YELLOW
,font_size
);
344 printf("T %d %d %d %d 1 1 0 0\n",x
+50,y
+50,YELLOW
,font_size
);
347 printf("T %d %d %d %d 1 1 90 6\n",x
-50,y
-50,YELLOW
,font_size
);
350 printf("T %d %d %d %d 1 1 90 0\n",x
-50,y
+50,YELLOW
,font_size
);
353 printf("pinnumber=%s\n",pin
);
361 printf("T %d %d %d %d 0 0 0 7\n",pos_x
-400,pos_y
,YELLOW
,font_size
);
364 printf("T %d %d %d %d 0 0 0 1\n",pos_x
+400,pos_y
,YELLOW
,font_size
);
367 printf("T %d %d %d %d 0 0 90 7\n",pos_x
,pos_y
-400,YELLOW
,font_size
);
370 printf("T %d %d %d %d 0 0 90 1\n",pos_x
,pos_y
+400,YELLOW
,font_size
);
373 printf("pintype=%s\n",type
);
381 printf("T %d %d %d %d 1 1 0 1\n",pos_x
+100,pos_y
,GREEN
,font_size
);
384 printf("T %d %d %d %d 1 1 0 7\n",pos_x
-100,pos_y
,GREEN
,font_size
);
387 printf("T %d %d %d %d 1 1 90 1\n",pos_x
,pos_y
+100,GREEN
,font_size
);
390 printf("T %d %d %d %d 1 1 90 7\n",pos_x
,pos_y
-100,GREEN
,font_size
);
393 printf("pinlabel=%s\n",name
);
403 /***************************************************/
404 /***************************************************/
405 int make_box(int fldcnt
,char *pFields
[])
406 { int pos_x
=300,pos_y
=300;
407 char name
[100],device
[100],name_pos
[100];
408 char uref
[100],class[100];
409 int pin_width
,pin_height
,font_size
=10;
414 strcpy(device
,pFields
[0]);
415 strcpy(name
,pFields
[1]);
416 strcpy(name_pos
,pFields
[2]);
417 pin_width
= atoi(pFields
[3]);
418 pin_height
= atoi(pFields
[4]);
420 pin_0_x
= pin_spacing
;
421 pin_0_y
= pin_spacing
*(pin_height
+ 1);
422 BoxWidth
= pin_width
* pin_spacing
;
423 BoxHeight
= pin_height
* pin_spacing
;
427 strcpy(uref
,pFields
[5]);
429 if(uref
[0]=='U' || uref
[0]=='u')strcpy(class,"IC");
430 if(uref
[0]=='J' || uref
[0]=='j')strcpy(class,"IO");
431 if(uref
[0]=='C' || uref
[0]=='c')strcpy(class,"IO");
432 /* U is for ICs, J or CONN for IO. We assume no discretes
434 strcpy(footprint
,pFields
[6]);
435 pincount
= atoi(pFields
[7]);
436 printf("T %d %d %d %d 0 0 0 0\n",pos_x
,pos_y
+BoxHeight
+1100,YELLOW
,font_size
);
437 printf("footprint=%s\n",footprint
);
438 printf("T %d %d %d %d 0 0 0 0\n",pos_x
,pos_y
+BoxHeight
+1300,YELLOW
,font_size
);
439 printf("pins=%d\n",pincount
);
448 /* new file format: x y width height color width
449 end type length space filling fillwidth angle1 pitch1 angle2 pitch2 */
450 printf("B %d %d %d %d %d 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n",pos_x
,pos_y
,BoxWidth
,BoxHeight
,GREEN
);
451 printf("T %d %d %d %d 0 0 0 0\n",pos_x
,pos_y
+BoxHeight
+700,YELLOW
,font_size
);
452 printf("device=%s\n",device
);
453 printf("T %d %d %d %d 0 0 0 0\n",pos_x
,pos_y
+BoxHeight
+900,YELLOW
,font_size
);
454 printf("class=%s\n",class);
455 printf("T %d %d %d %d 1 1 0 0\n",pos_x
,pos_y
+BoxHeight
+500,RED
,font_size
);
456 printf("refdes=%s\n",uref
);
459 /* Display pin locations */
460 for (i
=0;i
<= (BoxHeight
/pin_spacing
);i
++)
461 cross(pos_x
,pos_y
+i
*pin_spacing
,BLUE
);
463 for (i
=0;i
<= (BoxWidth
/pin_spacing
);i
++)
464 cross(pos_x
+i
*pin_spacing
,pos_y
,BLUE
);
466 cross(pin_0_x
,pin_0_y
,RED
);
470 name_size
= GetStringDisplayLength(name
,font_size
);
471 /* Vaild positions: tl,tc,tr, bl,bc,br cc */
472 if (!strcasecmp(name_pos
,"tl"))
477 else if (!strcasecmp(name_pos
,"tc"))
479 pos_x
= pin_0_x
+BoxWidth
/2-name_size
/2;
482 else if (!strcasecmp(name_pos
,"tr"))
484 pos_x
= pin_0_x
+BoxWidth
-name_size
/2;
487 else if (!strcasecmp(name_pos
,"bl"))
490 pos_y
= pin_0_y
-BoxHeight
-175;
492 else if (!strcasecmp(name_pos
,"bc"))
494 pos_x
= pin_0_x
+BoxWidth
/2-name_size
/2;
495 pos_y
= pin_0_y
-BoxHeight
-175;
497 else if (!strcasecmp(name_pos
,"br"))
499 pos_x
= pin_0_x
+BoxWidth
-(name_size
)/2;
500 pos_y
= pin_0_y
-BoxHeight
-175;
503 else if (!strcmp(name_pos
,"cc"))
505 pos_x
= pin_0_x
+BoxWidth
/2-(name_size
)/2;
506 pos_y
= pin_0_y
-BoxHeight
/2;
514 printf("T %d %d %d %d 1 0 0 0\n",pos_x
,pos_y
,GREEN
,font_size
);
520 /***************************************************/
521 /***************************************************/
522 int make_pin(int fldcnt
,char *pFields
[]) {
523 int pos_x
=0,pos_y
=0,shape
,side
=0,i
;
530 fprintf (stderr
,"\nError, not enough parameters on input line:%i instead of 5 !\n",fldcnt
);
531 fprintf (stderr
,"\nPlease fix the input file then try again.\n\n");
535 strcpy(pin_name
,pFields
[0]);
536 strcpy(pin
,pFields
[1]); /* get pin number */
538 for (i
=0;i
<pin_counter
;i
++)
539 if (!strcmp(pin
,pin_used
[i
])) {
540 fprintf (stderr
,"\nFatal Error, pin %s is used more that once !\n\n",pin
);
543 strncpy(pin_used
[pin_counter
++],pin
,5); /* save the current pin, the first 5 char */
546 if (!strcasecmp(pFields
[2],"dot")) /* get shape */
548 if (!strcasecmp(pFields
[2],"clock")) /* get shape */
550 if (!strcasecmp(pFields
[3],"L")) side
= L_SIDE
;
552 if (!strcasecmp(pFields
[3],"R")) side
= R_SIDE
;
554 if (!strcasecmp(pFields
[3],"B")) side
= B_SIDE
;
556 if (!strcasecmp(pFields
[3],"T")) side
= T_SIDE
;
558 fprintf (stderr
,"\nError, %s not a valid position, should be l,t,b or r.\n",pFields
[3]);
562 pin_pos
= atoi(pFields
[4]);
567 if (!strcasecmp(pFields
[5],"in"))
569 else if ( !strcasecmp(pFields
[5],"out"))
571 else if ( !strcasecmp(pFields
[5],"io"))
573 else if ( !strcasecmp(pFields
[5],"oc"))
575 else if ( !strcasecmp(pFields
[5],"oe"))
577 else if ( !strcasecmp(pFields
[5],"pas"))
579 else if ( !strcasecmp(pFields
[5],"tp"))
581 else if ( !strcasecmp(pFields
[5],"tri"))
583 else if ( !strcasecmp(pFields
[5],"clk"))
585 else if ( !strcasecmp(pFields
[5],"pwr"))
588 fprintf( stderr
, "WARNING: Invalid pin type attribute for pin %s: %s\n", pin_name
, pFields
[5] );
594 pos_y
= pin_0_y
- (pin_spacing
*pin_pos
);
599 pos_y
= pin_0_y
- (pin_spacing
*pin_pos
);
600 pos_x
= pin_spacing
+ BoxWidth
;
604 pos_x
= pin_0_x
+ (pin_spacing
*pin_pos
);
609 pos_x
= pin_0_x
+ (pin_spacing
*pin_pos
);
612 pin_add(pos_x
,pos_y
,pin
,shape
,side
,pin_name
,type
);
616 /***************************************************/
617 /* Pull a token from a comma separate string */
618 /* delete leading and trailing spaces */
619 /***************************************************/
620 static char *strLabel(char *p
, char *pTemp
)
624 if ((p
== NULL
) || (pTemp
== NULL
))
627 while ((*p
== ' ') || (*p
== '\t'))
629 while (isprint((int) *p
) && (*p
!= ',')) /* copy string to pTemp */
631 *q
= 0; /* terminate the string */
632 strtrail(pTemp
); /* drop any trailing spaces */
638 /************************************************/
639 /* Clear white spaces from the end of a string */
640 /************************************************/
641 void strtrail(char *wrk
)
646 if ((p
= strchr(wrk
,'\n')) != NULL
)
648 if ((p
= strchr(wrk
,'\r')) != NULL
)
650 while (isspace((int) *(wrk
+ strlen(wrk
) - 1))) /* Clear any trailing spaces */
651 *(wrk
+ strlen(wrk
) - 1) = 0;
654 /************************************************/
655 /* Check for empty or comment lines */
656 /************************************************/
657 int line_chk(char *pBuf
)
662 if ((p
= strchr(pBuf
,'\n')) != NULL
)
664 if ((p
= strchr(pBuf
,'\r')) != NULL
)
666 while (isspace((int) *(pBuf
+ strlen(pBuf
) - 1))) /* Clear any trailing spaces */
667 *(pBuf
+ strlen(pBuf
) - 1) = 0;
670 if (strchr(pBuf
,',') == NULL
)