missing NULL terminator in set_config_x
[geda-gaf.git] / contrib / gmk_sym / gmk_sym.c
blobd0ebb9fc6a06be77d59e91d22f58b91558e74563
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 */
6 /* */
7 /* History: */
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 */
13 /* */
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 */
24 /* Puon) */
25 /* */
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. */
36 /* */
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. */
41 /* */
42 /*-----------------------------------------------------------------------*/
43 /* GMK_SYM typical use: */
44 /* gk_sym 7474.txt >7474-3.sym */
45 /* To build: */
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 /*************************************************************************/
71 #if 0
72 /****************************************************/
73 ;; Filename: 7474.txt
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
78 7474,74HC74,tr,3,5
80 ;; pin name,pin number,shape(line,clock,dot),side(r,l,t,b),pin position
81 D,2,line,L,1
82 CLK,3,clock,L,4
84 Q,5,line,R,1
85 /Q,6,dot,R,4
87 CLR,4,dot,T,1
88 PRE,1,dot,B,1
89 /****************************************************/
90 #endif
92 #ifdef HAVE_CONFIG_H
93 #include "config.h"
94 #endif
96 #include <stdio.h>
97 #include <unistd.h>
98 #include <stdlib.h>
99 #include <string.h>
100 #include <ctype.h>
101 #include <sys/time.h>
102 #include <time.h>
103 #include <errno.h>
105 #define BLACK 0
106 #define WHITE 1
107 #define RED 2
108 #define GREEN 3
109 #define BLUE 4
110 #define YELLOW 5
111 #define CYAN 6
112 #define GREY 7
114 #define MAX_FIELDS 10
116 #define L_SIDE 0
117 #define R_SIDE 1
118 #define B_SIDE 2
119 #define T_SIDE 3
121 #define LINE_SHAPE 0
122 #define DOT_SHAPE 1
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"
136 extern char *optarg;
137 extern int optind,opterr,optopt;
139 /* externals */
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
151 #endif
152 #if !defined(HAVE_STRNCASECMP) && defined(HAVE_STRNICMP) && !defined(strnicmp)
153 #define strncasecmp strnicmp
154 #endif
156 int pin_len=300;
157 int pin_spacing=300;
158 int pin_0_x,pin_0_y;
159 int BoxHeight,BoxWidth;
160 int net_pin=0;
162 char pin_used[300][5]; /* keep track of pin number used. Assume 300 pins max */
163 int pin_counter=0;
165 /***************************************************/
166 /***************************************************/
167 int main(int argc,char **argv)
169 FILE *stream;
170 char LineBuf[256];
171 int fldcnt,i,c,Debug=0;
172 char *pFields[MAX_FIELDS];
173 int line_nub=0;
175 while ((c = getopt(argc, argv, "?hd:")) != EOF)
177 switch (c)
179 case 'd': Debug = 1;
180 break;
181 case '?':
182 case 'h':
183 fprintf(stderr,"usage: %s -dh?\n",argv[0]);
184 exit(0);
185 break;
189 if (Debug)
190 fprintf(stderr, "note: debug flag is currently ignored\n");
192 for(i=0;i<MAX_FIELDS;i++)
193 pFields[i]=NULL;
195 stream=stdin;
196 if (argc > 1)
198 if ((stream = fopen(argv[1],"r")) == NULL)
200 fprintf(stderr, "Cannot open file: %s\n",argv[1]);
201 exit(-1);
204 line_nub=-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)
211 continue;
212 if ((fldcnt = line2fields(LineBuf,10,pFields)) > 0)
214 line_nub++;
215 if (line_nub == 0)
216 make_box(fldcnt,pFields);
217 else
218 if (make_pin(fldcnt,pFields)< 0) {
219 fields_free(pFields);
220 break; /* error processing the pin, get out */
222 fields_free(pFields);
225 fclose(stream);
226 return 0;
229 /***************************************************/
230 /***************************************************/
231 int fields_free(char *pField[])
232 { int i;
233 for (i=0; (i<MAX_FIELDS) && (pField[i] != NULL) ;i++)
235 free(pField[i]);
236 pField[i] = NULL;
238 return 0;
241 /***************************************************/
242 /***************************************************/
243 int line2fields(char *pBuf,int max_fields,char *pField[])
244 { char *p,temp[100];
245 int fld_cnt=0;
247 if ((p = strchr(pBuf,'\n')) != NULL)
248 *p = 0;
249 if ((p = strchr(pBuf,'\r')) != NULL)
250 *p = 0;
251 p = pBuf;
252 do {
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);
257 } while (*p != 0);
258 return fld_cnt;
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)
272 { int x,y;
273 int xdir=0,ydir=0,font_size=8;
275 switch (dir)
277 case L_SIDE: xdir = 1; ydir = 0;
278 break;
279 case R_SIDE: xdir = -1; ydir = 0;
280 break;
281 case B_SIDE: xdir = 0; ydir = 1;
282 break;
283 case T_SIDE: xdir = 0; ydir = -1;
284 break;
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,
292 WHITE);
293 printf("{\n");
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,
301 WHITE);
302 printf("{\n");
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,
312 WHITE);
313 printf("{\n");
315 x = pos_x;
316 y = pos_y;
318 /* pin_xy(dir,pin,font_size,&x,&y); */
319 /* output pinseq */
320 switch (dir)
322 case L_SIDE:
323 printf("T %d %d %d %d 0 1 0 6\n",x-50,y+50,YELLOW,font_size);
324 break;
325 case R_SIDE:
326 printf("T %d %d %d %d 0 1 0 0\n",x+50,y+50,YELLOW,font_size);
327 break;
328 case B_SIDE:
329 printf("T %d %d %d %d 0 1 90 6\n",x-50,y-50,YELLOW,font_size);
330 break;
331 case T_SIDE:
332 printf("T %d %d %d %d 0 1 90 0\n",x-50,y+50,YELLOW,font_size);
333 break;
335 printf("pinseq=%d\n",++net_pin);
337 /* output pinnumber */
338 switch (dir)
340 case L_SIDE:
341 printf("T %d %d %d %d 1 1 0 6\n",x-50,y+50,YELLOW,font_size);
342 break;
343 case R_SIDE:
344 printf("T %d %d %d %d 1 1 0 0\n",x+50,y+50,YELLOW,font_size);
345 break;
346 case B_SIDE:
347 printf("T %d %d %d %d 1 1 90 6\n",x-50,y-50,YELLOW,font_size);
348 break;
349 case T_SIDE:
350 printf("T %d %d %d %d 1 1 90 0\n",x-50,y+50,YELLOW,font_size);
351 break;
353 printf("pinnumber=%s\n",pin);
356 if (type)
358 switch (dir)
360 case L_SIDE:
361 printf("T %d %d %d %d 0 0 0 7\n",pos_x-400,pos_y,YELLOW,font_size);
362 break;
363 case R_SIDE:
364 printf("T %d %d %d %d 0 0 0 1\n",pos_x+400,pos_y,YELLOW,font_size);
365 break;
366 case B_SIDE:
367 printf("T %d %d %d %d 0 0 90 7\n",pos_x,pos_y-400,YELLOW,font_size);
368 break;
369 case T_SIDE:
370 printf("T %d %d %d %d 0 0 90 1\n",pos_x,pos_y+400,YELLOW,font_size);
371 break;
373 printf("pintype=%s\n",type);
376 if (strlen(name))
378 switch (dir)
380 case L_SIDE:
381 printf("T %d %d %d %d 1 1 0 1\n",pos_x+100,pos_y,GREEN,font_size);
382 break;
383 case R_SIDE:
384 printf("T %d %d %d %d 1 1 0 7\n",pos_x-100,pos_y,GREEN,font_size);
385 break;
386 case B_SIDE:
387 printf("T %d %d %d %d 1 1 90 1\n",pos_x,pos_y+100,GREEN,font_size);
388 break;
389 case T_SIDE:
390 printf("T %d %d %d %d 1 1 90 7\n",pos_x,pos_y-100,GREEN,font_size);
391 break;
393 printf("pinlabel=%s\n",name);
397 printf("}\n");
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;
410 int name_size=0;
411 int pincount;
412 char footprint[100];
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;
425 if(fldcnt >=8)
427 strcpy(uref,pFields[5]);
428 strcat(uref,"?");
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
433 * with this tool */
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);
441 else
443 strcpy(class,"IC");
444 strcpy(uref,"U?");
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);
458 #if 0
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);
467 #endif
468 if (strlen(name))
470 name_size = GetStringDisplayLength(name,font_size);
471 /* Vaild positions: tl,tc,tr, bl,bc,br cc */
472 if (!strcasecmp(name_pos,"tl"))
474 pos_x = pin_0_x;
475 pos_y = pin_0_y+50;
477 else if (!strcasecmp(name_pos,"tc"))
479 pos_x = pin_0_x+BoxWidth/2-name_size/2;
480 pos_y = pin_0_y+50;
482 else if (!strcasecmp(name_pos,"tr"))
484 pos_x = pin_0_x+BoxWidth-name_size/2;
485 pos_y = pin_0_y+50;
487 else if (!strcasecmp(name_pos,"bl"))
489 pos_x = pin_0_x;
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;
502 /* puon: begin */
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;
508 /* puon: end */
509 else
511 pos_x = pin_0_x;
512 pos_y = pin_0_y+50;
514 printf("T %d %d %d %d 1 0 0 0\n",pos_x,pos_y,GREEN,font_size);
515 printf("%s\n",name);
517 return 0;
520 /***************************************************/
521 /***************************************************/
522 int make_pin(int fldcnt,char *pFields[]) {
523 int pos_x=0,pos_y=0,shape,side=0,i;
524 char pin_name[40];
525 char pin[40];
526 int pin_pos;
527 char *type;
529 if (fldcnt < 5) {
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");
532 return -1;
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);
541 return -1;
543 strncpy(pin_used[pin_counter++],pin,5); /* save the current pin, the first 5 char */
545 shape = LINE_SHAPE;
546 if (!strcasecmp(pFields[2],"dot")) /* get shape */
547 shape = DOT_SHAPE;
548 if (!strcasecmp(pFields[2],"clock")) /* get shape */
549 shape = CLOCK_SHAPE;
550 if (!strcasecmp(pFields[3],"L")) side = L_SIDE;
551 else
552 if (!strcasecmp(pFields[3],"R")) side = R_SIDE;
553 else
554 if (!strcasecmp(pFields[3],"B")) side = B_SIDE;
555 else
556 if (!strcasecmp(pFields[3],"T")) side = T_SIDE;
557 else {
558 fprintf (stderr,"\nError, %s not a valid position, should be l,t,b or r.\n",pFields[3]);
559 return -1;
562 pin_pos = atoi(pFields[4]);
564 type = NULL;
565 if (pFields[5])
567 if (!strcasecmp(pFields[5],"in"))
568 type = PINTYPE_IN;
569 else if ( !strcasecmp(pFields[5],"out"))
570 type = PINTYPE_OUT;
571 else if ( !strcasecmp(pFields[5],"io"))
572 type = PINTYPE_IO;
573 else if ( !strcasecmp(pFields[5],"oc"))
574 type = PINTYPE_OC;
575 else if ( !strcasecmp(pFields[5],"oe"))
576 type = PINTYPE_OE;
577 else if ( !strcasecmp(pFields[5],"pas"))
578 type = PINTYPE_PAS;
579 else if ( !strcasecmp(pFields[5],"tp"))
580 type = PINTYPE_TP;
581 else if ( !strcasecmp(pFields[5],"tri"))
582 type = PINTYPE_TRI;
583 else if ( !strcasecmp(pFields[5],"clk"))
584 type = PINTYPE_CLK;
585 else if ( !strcasecmp(pFields[5],"pwr"))
586 type = PINTYPE_PWR;
587 else
588 fprintf( stderr, "WARNING: Invalid pin type attribute for pin %s: %s\n", pin_name, pFields[5] );
591 pos_x = pin_spacing;
592 if (side == L_SIDE)
594 pos_y = pin_0_y - (pin_spacing*pin_pos);
595 pos_x = pin_spacing;
597 if (side == R_SIDE)
599 pos_y = pin_0_y - (pin_spacing*pin_pos);
600 pos_x = pin_spacing + BoxWidth;
602 if (side == B_SIDE)
604 pos_x = pin_0_x + (pin_spacing*pin_pos);
605 pos_y = pin_spacing;
607 if (side == T_SIDE)
609 pos_x = pin_0_x + (pin_spacing*pin_pos);
610 pos_y = pin_0_y;
612 pin_add(pos_x,pos_y,pin,shape,side,pin_name,type);
613 return 0;
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)
622 char *q;
623 *pTemp = 0;
624 if ((p == NULL) || (pTemp == NULL))
625 return NULL;
626 q = pTemp;
627 while ((*p == ' ') || (*p == '\t'))
628 p++;
629 while (isprint((int) *p) && (*p != ',')) /* copy string to pTemp */
630 *q++ = *p++;
631 *q = 0; /* terminate the string */
632 strtrail(pTemp); /* drop any trailing spaces */
633 if (*p == ',')
634 p++;
635 return p;
638 /************************************************/
639 /* Clear white spaces from the end of a string */
640 /************************************************/
641 void strtrail(char *wrk)
643 char *p;
644 if (wrk == NULL)
645 return;
646 if ((p = strchr(wrk,'\n')) != NULL)
647 *p = 0;
648 if ((p = strchr(wrk,'\r')) != NULL)
649 *p = 0;
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)
659 char *p;
660 if (pBuf == NULL)
661 return -1;
662 if ((p = strchr(pBuf,'\n')) != NULL)
663 *p = 0;
664 if ((p = strchr(pBuf,'\r')) != NULL)
665 *p = 0;
666 while (isspace((int) *(pBuf + strlen(pBuf) - 1))) /* Clear any trailing spaces */
667 *(pBuf + strlen(pBuf) - 1) = 0;
668 if (*pBuf == ';')
669 return -1;
670 if (strchr(pBuf,',') == NULL)
671 return -1;
672 return 0;