Avoid GNUism '\|' by using extended REs.
[geda-gaf.git] / contrib / olib / olib.l
blob22d669e37d4f75a5b940c6e4d202b7b171c68420
1 %{
2 /*  $Id$
4     olib.lex - Orcad to gEDA lib converter
5     Copyright (C) 2002 Mario Pascucci <m.pas@libero.it>
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20     or
21     visit the URL http://www.fsf.org/
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <limits.h>
31 #include <math.h>
33 /* gEDA file version: change NEW version as soon as available */
34 #define EDA_VERSION_OLD   "20020209"
35 #define EDA_VERSION_NEW   "20020825"
38 /* defines for flags and types */
39 #define PIN_DOTFLAG     0x0001
40 #define PIN_SHORTFLAG   0x0002
41 #define PIN_CLKFLAG     0x0004
43 #define PIN_TYPE_IO     1
44 #define PIN_TYPE_IN     2
45 #define PIN_TYPE_OUT    3
46 #define PIN_TYPE_PWR    4
47 #define PIN_TYPE_PAS    5
48 #define PIN_TYPE_OC     6
49 #define PIN_TYPE_HIZ    7
50 #define PIN_TYPE_OE     8
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 static const ATTRIBUTE_UNUSED char *mp_name = "OrCAD to gEDA lib converter";
64 static const ATTRIBUTE_UNUSED char *mp_license = "Copyright (c) 2002 Mario Pascucci <m.pas@libero.it>";
66 static char fnsym[512];     /* gEDA symbol file name */
67 static FILE *fsym;          /* FILE* to gEDA symbol file */
68 static int aliascount = 0;    /* alias count */
69 static char part_aliases[200][50];     /* store for aliases of part */
70 static char sym_prefix[50];     /* prefix for .sym file */
72 /* gEDA symbol file version */
73 static char sym_version[10];
74 static int use_old_version;       /* flag for old format */
76 /* pin name options */
77 static int pin_name_hidden;
79 static char buff[512];
81 static int sizex,sizey,partspp;   /* size and number of part per package */
83 static int pincount;        /* pin definitions found until now */
85 struct pin_def {        /* pin definition struct */
86   char  pos;      /* position: L,T,R,B */
87   short num;      /* number in side, 0 mean virtual pin */
88   short pin;      /* real pin number */
89   short flags;    /* DOT, CLK and SHORT flags */
90   short type;     /* I/O, IN, OUT, PWR, PASS, OC */
91   char  name[50]; /* simbolic name of pin */
95 /* REFERENCE handling */
96 static char ref_str[20];
99 /* VECTOR handling */
100 static int vector_count;        /* number of vector found */
102 struct vector_def {
103   char  type;           /* line, arc, circle, box */
104   float p[12];          /* parameters for element drawing */
105   char *str;            /* string for "TEXT" statement */
108 static int paramcount;  /* vector param number count */
110 static struct vector_def part_vectors[100];   /* draw list */
112 static int vector_found;
115 /* type of pin */
116 static char *pintypestr[] = {
117   "???",
118   "I/O",
119   "IN",
120   "OUT",
121   "PWR",
122   "PAS",
123   "OC",
124   "hiZ",
125   "OE"
129 static char *edapintype[] = {
130   "???",
131   "io",
132   "in",
133   "out",
134   "pwr",
135   "pas",
136   "oc",
137   "tri",
138   "oe"
142  /* pin definition database */
143 static struct pin_def pinlist[200];
146 /* generic counter */
147 static int ii;
151 /* strip filename-aware chars from part name,
152     leave only '.' '-' or '_' and changes space
153     in '_' */
154 char *strip_invalid(char *str)
156   char *p;
158   p = buff;
159   while (*str)
160   {
161     if (isalnum((int) *str) || strchr("-_. ",*str))
162     {
163       if (*str == ' ')
164         *p = '_';
165       else
166         *p = *str;
167       p++;
168     }
169     str++;
170   }
171   *p = 0;
172   return buff;
176 /* trim leading and trailing ' in ident */
177 char *strip_quotes(char *str)
179   char *p;
181   p = buff;
182   str++;
183   while (*str != '\'')
184   {
185     *p = *str;
186     p++;
187     str++;
188   }
189   *p = 0;
190   return buff;
195 /* symbol write function in gEDA .sym format */
196 #include "geda_sym_format.h"
203 /* decimal integer */
204 INTEGER         [+-]?[0-9]+
206 /* floating point decimal, like 123.234 */
207 DECIMAL         [+-]?[0-9]*[\.][0-9]*
209 /* string name, like 'abcd' */
210 IDENT           '[^'\n]+'
212 /* comment, like { comment } */
213 COMMENT         \{[^\n\}]*\}
215 /* pin identifier, example T3 L12 R3 .... */
216 PIN_ID          [TBLR][0-9]{1,4}
220 %s wait_END wait_sizex wait_sizey wait_parts pin_list pinrealnum pindata 
221 %s waitnamestart in_name waitnameend waitpinend vector_list vector_ignore
222 %s param_list convert convert_ignore_pin reference
228   /*******************************************
229   handling of:
230   PREFIX
231   'prefix1'
232   'prefix2'
233   ...
234   ...
235   END
236   *******************************************/
239 {COMMENT} {
240   /* ignore comments */
241   fprintf(stderr,"Ignore comment: %s\n",yytext);
245 <INITIAL>PREFIX {
246   /* shortcuts for parts name: ignored */
247   fprintf(stderr,"Found PREFIX\n");
248   BEGIN(wait_END);
252 <wait_END>^{IDENT}.*\n {
253   fprintf(stderr,"Shorthand found, ignored\n");
254   /* ignore shortcut list */
258 <wait_END>END {
259   /* founds shortcut list end */
260   fprintf(stderr,"Found END for shorthands\n");
261   BEGIN(INITIAL);
266   /*******************************************
267   handling of:
268   'IDENT'
269   'IDENT'
270   ...
271   *******************************************/
274 <INITIAL>^{IDENT} {
275   /* founds first part identifier */
276   strcpy(part_aliases[0],strip_invalid(yytext));
277   snprintf(fnsym,511,"%s-%s-1.sym",sym_prefix,part_aliases[0]);
278   fprintf(stderr,"New part name: %s (%s)\n",part_aliases[0],yytext);
279   fprintf(stderr,"New .sym name: %s\n",fnsym);
280   BEGIN(wait_sizex);
281   aliascount = 1;
282   pincount = 0;
283   vector_found = 0;
284   ref_str[0] = 'U';
285   ref_str[1] = 0;
289 <wait_sizex>^REFERENCE {
290   /* REFERENCE statement found */
291   BEGIN(reference);
295 <reference>{IDENT} {
296   /* get an IDENT, i.e. reference id */
297   strcpy(ref_str,strip_quotes(yytext));
298   fprintf(stderr,"REFERENCE: %s\n",yytext);
299   BEGIN(wait_sizex);
303 <wait_sizex>^{IDENT} {
304   /* found an alias for the part name 
305       store alias for future use */
306   fprintf(stderr,"Found an alias: %s\n",yytext);
307   strcpy(part_aliases[aliascount], strip_invalid(yytext));
308   aliascount++;
313   /*******************************************
314   handling of:
315   {X Size =} x      {Y Size =} y      {Parts per Package =} n
316   *******************************************/
319 <wait_sizex>{INTEGER} {
320   /* trovata la dimansione X */
321   sizex = atoi(yytext);
322   fprintf(stderr,"Found X size: %d (%s)\n",sizex,yytext);
323   BEGIN(wait_sizey);
327 <wait_sizey>{INTEGER} {
328   /* trovata la dimansione y */
329   sizey = atoi(yytext);
330   fprintf(stderr,"Found Y size: %d (%s)\n",sizey,yytext);
331   BEGIN(wait_parts);
335 <wait_parts>GRIDARRAY {
336   /* found a PGA component, unsupported */
337   fprintf(stderr,"Found a GRIDARRAY: unsupported\n");
338   BEGIN(INITIAL);
342 <wait_parts>{INTEGER} {
343   /* trovato il parts-per-package */
344   /* per ora supportato solo 1 part-per-package */
345   partspp = atoi(yytext);
346   if (partspp > 1)
347   {
348     fprintf(stderr,"Found parts per package > 1\n");
349     BEGIN(INITIAL);
350   }
351   else
352   {
353     fprintf(stderr,"Found parts per package: %d (%s)\n",partspp,yytext);
354     BEGIN(pin_list);
355     /* size of symbol body */
356     sizex = sizex * PIN_SPACE;
357     sizey = sizey * PIN_SPACE;
358   }
362 <INITIAL>^{PIN_ID}.+\n |
363 <INITIAL>^VECTOR.*\n |
364 <INITIAL>^CONVERT.*\n |
365 <INITIAL>^TEXT.*\n |
366 <INITIAL>^LINE.*\n |
367 <INITIAL>^ARC.*\n |
368 <INITIAL>^FILL.*\n |
369 <INITIAL>^CIRCLE.*\n |
370 <INITIAL>^END.*\n     {
371   /* ignored */
372   fprintf(stderr,"Ignored: %s",yytext);
377   /*******************************************
378   handling of:
379   VECTOR 'IDENT'  (unsupported)
380   or
381   VECTOR
382   LINE x y x1 y1
383   ARC x y dxs dys dxe dye r
384   CIRCLE x y r
385   FILL x y    (unsupported)
386   TEXT x y size 'text'  (partially supported)
387   END
388   *******************************************/
391 <pin_list>^VECTOR {
392   /* components isn't a simple "box", but it's drawed */
393   BEGIN(vector_list);
394   vector_count = 0;
395   vector_found = -1;
396   fprintf(stderr,"Found: VECTOR\n");
400 <vector_list,vector_ignore>{IDENT} {
401   /* the component shape is identical to a previous one 
402       unsupported at the moment */
403   BEGIN(pin_list);
404   fprintf(stderr,"Found unsupported: VECTOR 'IDENT'\n");
408 <vector_list>LINE {
409   /* found LINE vector statement */
410   part_vectors[vector_count].type = 'L';
411   BEGIN(param_list);
412   paramcount = 0;
413   fprintf(stderr,"Found: LINE params:");
417 <vector_list>CIRCLE {
418   /* found CIRCLE vector statement */
419   part_vectors[vector_count].type = 'V';
420   BEGIN(param_list);
421   paramcount = 0;
422   fprintf(stderr,"Found: CIRCLE params:");
426 <vector_list>ARC {
427   /* found ARC vector statement */
428   part_vectors[vector_count].type = 'A';
429   BEGIN(param_list);
430   paramcount = 0;
431   fprintf(stderr,"Found: ARC params:");
435 <vector_list>FILL {
436   /* found FILL vector statement */
437   /* no counterpart in gEDA */
438   part_vectors[vector_count].type = 'f';
439   BEGIN(param_list);
440   paramcount = 0;
441   fprintf(stderr,"Found unsupported: FILL params:");
445 <vector_list>TEXT {
446   /* found ARC vector statement */
447   part_vectors[vector_count].type = 'T';
448   BEGIN(param_list);
449   paramcount = 0;
450   fprintf(stderr,"Found: TEXT params:");
454 <param_list>{INTEGER} {
455   /* found a param */
456   part_vectors[vector_count].p[paramcount] = (float) atof(yytext);
457   paramcount++;
458   BEGIN(param_list);
459   fprintf(stderr," %s",yytext);
463 <param_list>{DECIMAL} {
464   /* found a param */
465   part_vectors[vector_count].p[paramcount] = (float) atof(yytext);
466   paramcount++;
467   BEGIN(param_list);
468   fprintf(stderr," %s",yytext);
472 <param_list>{IDENT} {
473   /* found a string */
474   if (part_vectors[vector_count].type == 'T')
475     part_vectors[vector_count].str = strdup(strip_quotes(yytext));
476   else
477     fprintf(stderr,"Text param found in non text VECTOR instr: %s\n",yytext);
478   paramcount++;
479   BEGIN(param_list);
480   fprintf(stderr," %s",yytext);
484 <param_list>\n  {
485   /* end of params */
486   fprintf(stderr,"\n");
487   switch (part_vectors[vector_count].type)
488   {
489     case 'L':
490       /* line */
491       if (paramcount != 4)
492       {
493         fprintf(stderr,"LINE: wrong parameters number: %d\n",paramcount);
494         BEGIN(vector_list);
495       }
496       break;
497     case 'V':
498       /* circle */
499       if (paramcount != 3)
500       {
501         fprintf(stderr,"CIRCLE: wrong parameters number: %d\n",paramcount);
502         BEGIN(vector_list);
503       }
504       break;
505     case 'A':
506       /* arc */
507       if (paramcount != 7)
508       {
509         fprintf(stderr,"ARC: wrong parameters number: %d\n",paramcount);
510         BEGIN(vector_list);
511       }
512       break;
513     case 'f':
514       /* fill (ignored) */
515       if (paramcount != 2)
516       {
517         fprintf(stderr,"FILL: wrong parameters number: %d\n",paramcount);
518         BEGIN(vector_list);
519       }
520       break;
521     case 'T':
522       /* text */
523       if (paramcount != 4)
524       {
525         fprintf(stderr,"TEXT: wrong parameters number: %d\n",paramcount);
526         BEGIN(vector_list);
527       }
528       break;
529   }
530   vector_count++;
531   BEGIN(vector_list);
535 <vector_list>^END {
536   /* end of vector list */
537   BEGIN(pin_list);
538   fprintf(stderr,"Found: END of VECTOR list\n");
543   /*******************************************
544   handling of:
545   CONVERT 'IDENT'
546   or
547   CONVERT
548   pin_def
549   pin_def
550   ...
551   *******************************************/
554 <pin_list,convert>^CONVERT {
555   /* alternate part drawing */
556   /* unsupported */
557   BEGIN(convert);
561 <convert>{IDENT} {
562   /* CONVERT 'part' unsupported */
563   BEGIN(pin_list);
567 <convert>^{PIN_ID} {
568   /* ignore PIN list in CONVERT */
569   BEGIN(convert_ignore_pin);
573 <convert_ignore_pin>.*\n {
574   /* ignore line */
575   BEGIN(convert);
579 <convert>^VECTOR {
580   /* found VECTOR list in CONVERT */
581   if (vector_found)
582     BEGIN(vector_ignore);
583   else
584   {
585     BEGIN(vector_list);
586     vector_count = 0;
587     vector_found = -1;
588   }
592 <vector_ignore>^END.*\n {
593   /* end of ignore */
594   BEGIN(pin_list);
596 <vector_ignore>^VECTOR.*\n |
597 <vector_ignore>^CONVERT.*\n |
598 <vector_ignore>^TEXT.*\n |
599 <vector_ignore>^LINE.*\n |
600 <vector_ignore>^ARC.*\n |
601 <vector_ignore>^FILL.*\n |
602 <vector_ignore>^CIRCLE.*\n {
603   /* ignored */
604   fprintf(stderr,"Ignored VECTOR: %s",yytext);
609   /*******************************************
610   handling of:
611   pin_def
612   pin_def
613   ...
614   *******************************************/
617 <pin_list>^{PIN_ID} {
618   /* trovato un pin */
619   pinlist[pincount].pos = yytext[0];    /* pin side */
620   pinlist[pincount].num = atoi(yytext+1);       /* gets pin number */
621   pinlist[pincount].flags = 0;
622   pinlist[pincount].type = 0;
623   fprintf(stderr,"Found pin ID: %c-%d (%s)\n",pinlist[pincount].pos,pinlist[pincount].num,yytext);
624   if (partspp == 0)   /* handling of parts without pin number */
625   {
626     /* assign number to a unnumbered pin from the pin count */
627     pinlist[pincount].pin = pincount + 1;
628     BEGIN(pindata);
629   }
630   else
631     BEGIN(pinrealnum);
635 <pin_list>^{IDENT} {
636   /* found a part name after pinlist, this mean that part definition ends,
637       and starts a new part definition */
638   fprintf(stderr,"Writing down new symbol: %s pin: %d  vectors: %d\n",part_aliases[0],pincount,vector_count);
639   write_sym();      /* write the .sym gEDA symbol definition */
640   /* restore initial condition */
641   ref_str[0] = 'U';
642   ref_str[1] = 0;
643   pincount = 0;
644   aliascount = 1;
645   vector_found = 0;
646   vector_count = 0;
647   strcpy(part_aliases[0],strip_invalid(yytext));
648   snprintf(fnsym,511,"%s-%s-1.sym",sym_prefix,part_aliases[0]);
649   fprintf(stderr,"New part name: %s (%s)\n",part_aliases[0],yytext);
650   fprintf(stderr,"New .sym name: %s\n",fnsym);
651   BEGIN(wait_sizex);
656 <pinrealnum>{INTEGER} {
657   /* reads real pin number */
658   pinlist[pincount].pin = atoi(yytext);
659   fprintf(stderr,"Found pin num: %d (%s)\n",pinlist[pincount].pin,yytext);
660   BEGIN(pindata);
664 <pindata>DOT {
665   /* DOT flag found, boolean negate */
666   pinlist[pincount].flags |= PIN_DOTFLAG;
667   fprintf(stderr,"Found DOT flag\n");
671 <pindata>CLK {
672   /* CLK flag found, clock input */
673   pinlist[pincount].flags |= PIN_CLKFLAG;
674   fprintf(stderr,"Found CLK flag\n");
678 <pindata>SHORT {
679   /* SHORT flag found, short terminal */
680   pinlist[pincount].flags |= PIN_SHORTFLAG;
681   fprintf(stderr,"Found SHORT flag\n");
685 <pindata>IN {
686   /* pin type IN */
687   pinlist[pincount].type = PIN_TYPE_IN;
688   BEGIN(waitnamestart);
689   fprintf(stderr,"Pin type IN\n");
693 <pindata>OUT {
694   /* pin type OUT */
695   pinlist[pincount].type = PIN_TYPE_OUT;
696   BEGIN(waitnamestart);
697   fprintf(stderr,"Pin type OUT\n");
701 <pindata>PWR {
702   /* pin type PWR */
703   pinlist[pincount].type = PIN_TYPE_PWR;
704   BEGIN(waitnamestart);
705   fprintf(stderr,"Pin type PWR\n");
709 <pindata>OC {
710   /* pin type OC */
711   pinlist[pincount].type = PIN_TYPE_OC;
712   BEGIN(waitnamestart);
713   fprintf(stderr,"Pin type OC\n");
717 <pindata>OE {
718   /* pin type OE */
719   pinlist[pincount].type = PIN_TYPE_OE;
720   BEGIN(waitnamestart);
721   fprintf(stderr,"Pin type OE\n");
725 <pindata>PAS {
726   /* pin type PAS */
727   pinlist[pincount].type = PIN_TYPE_PAS;
728   BEGIN(waitnamestart);
729   fprintf(stderr,"Pin type PAS\n");
733 <pindata>hiZ {
734   /* pin type hiZ */
735   pinlist[pincount].type = PIN_TYPE_HIZ;
736   BEGIN(waitnamestart);
737   fprintf(stderr,"Pin type hiZ\n");
741 <pindata>"I/O" {
742   /* pin type I/O */
743   pinlist[pincount].type = PIN_TYPE_IO;
744   BEGIN(waitnamestart);
745   fprintf(stderr,"Pin type I/O\n");
749 <waitnamestart>"'" {
750   /* found initial quote */
751   ii = 0;
752   BEGIN(in_name);
756 <in_name>'' {
757   /* found a ' in pin name */
758   pinlist[pincount].name[ii++] = '\'';
762 <in_name>[^"'"\n] {
763   /* get a char from the pin symbolic name */
764   pinlist[pincount].name[ii++] = *yytext;
768 <in_name>"'" {
769   /* all ok, waiting for new pin definition */
770   pinlist[pincount].name[ii] = 0;
771   fprintf(stderr,"Pin label: %s\n",pinlist[pincount].name);
772   BEGIN(waitpinend);
776 <waitpinend>\n {
777   /* ok, found a newline, pin definition ends */
778   fprintf(stderr,"Pin: %c%d %d %x %s %s\n",pinlist[pincount].pos,pinlist[pincount].num,
779     pinlist[pincount].pin, pinlist[pincount].flags, pintypestr[pinlist[pincount].type],
780     pinlist[pincount].name);
781   pincount++;
782   BEGIN(pin_list);
787   /* 
788    * we don't need to use <*> to match any state, we just don't
789    * specify a state
790    */
793 ^\n     { /* empty lines ignored */ }
796 [ \t\n\r]    { /* ignored, the \r char is for "DOS" ASCII files */ }
805 void usage(void)
807   fprintf(stderr,"Usage:\n");
808   fprintf(stderr,"\tolib [options] libname prefix\n");
809   fprintf(stderr,"\nWhere:\n\tlibname is the path to OrCAD(TM) library to convert\n");
810   fprintf(stderr,"\tprefix is the prefix for the .sym files extracted\n");
811   fprintf(stderr,"Options are:\n\t-h\tprint this help and exit\n");
812   fprintf(stderr,"\t-o\tuse old format (v 20020209) for .sym file\n");
813   fprintf(stderr,"\t\telse use 'v 20020825' as version string in .sym file\n");
814   fprintf(stderr,"\t-n\thides pin name if symbol is VECTOR drawed\n");
817 int yywrap()
819   /* found a part name after pinlist, this mean that part definition ends,
820       and starts a new part definition */
821   fprintf(stderr,"Writing down new symbol: %s pin: %d  vectors: %d\n",part_aliases[0],pincount,vector_count);      
822   write_sym();      /* write the .sym gEDA symbol definition */
823   /* restore initial condition */
824   fprintf(stderr,"End of lib file\n");
826   return 1;
830 int main (int argc, char *argv[])
833   FILE  *flib;
834   char  fnlib[PATH_MAX];
835   int   i;
837   strcpy(sym_version,EDA_VERSION_NEW);    /* handle new gEDA version by default */
838   use_old_version = 0;        /* old version flag */
839   pin_name_hidden = 0;        /* hides pin name on VECTOR drawed symbols */
840   opterr = 0;   /* do NOT print default error message for getopt */
841   do
842   {
843     i = getopt(argc,argv,"hon");
844     switch (i)
845     {
846       case 'h':
847         usage();
848         exit(0);
849       case 'o':
850         strcpy(sym_version,EDA_VERSION_OLD);
851         fprintf(stderr,"Use old (%s) format.\n",sym_version);
852         use_old_version = -1;
853         break;
854       case 'n':
855         pin_name_hidden = -1;
856         break;
857       case '?':
858         fprintf(stderr,"Unknown or illegal option :%c\n",(char)optopt);
859         usage();
860         exit(1);
861       case ':':
862         fprintf(stderr,"Parameter wrong for option: %c\n",(char)optopt);
863         usage();
864         exit(1);
865     }
866   }
867   while (i != -1);
868   if ((argc - optind) != 2)
869   {
870     fprintf(stderr,"Library name and prefix are mandatory.\n");
871     usage();
872     return 1;
873   }
874   strcpy(fnlib,argv[optind]);
875   if (!(flib = fopen(fnlib,"r")))
876   {
877     perror("lib file");
878     return 1;
879   }
880   strcpy(sym_prefix,argv[optind+1]);
881   yyin = flib;
882   yylex();
883   fclose(flib);
884   return 0;