Introduce POLYGONHOLE_MODE for creating holes in polygons
[geda-pcb/gde.git] / src / parse_l.l
blob8aa754c2951042c9a2246458e9bff03308e92007
1 /* $Id$ */
3 %{
4 /*
5  *                            COPYRIGHT
6  *
7  *  PCB, interactive printed circuit board design
8  *  Copyright (C) 1994,1995,1996,2006 Thomas Nau
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  *  Contact addresses for paper mail and Email:
25  *  Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
26  *  Thomas.Nau@rz.uni-ulm.de
27  *
28  */
30 /* lexical definitions to parse ASCII input of PCB and Element description
31  */
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <ctype.h>
41 #if defined(_POSIX_SOURCE) || defined(_HPUX_SOURCE)
42 #include <unistd.h>
43 #endif
45 #include "global.h"
47 #ifdef HAVE_LIBDMALLOC
48 # include <dmalloc.h> /* see http://dmalloc.com */
49 #endif
51 RCSID("$Id$");
54 #include "global.h"
55 #include "crosshair.h"
56 #include "data.h"
57 #include "error.h"
58 #include "file.h"
59 #include "mymem.h"
60 #include "misc.h"
61 #include "strflags.h"
62 #include "parse_l.h"
63 #include "parse_y.h"
65 /* ---------------------------------------------------------------------------
66  * some shared parser identifiers
67  */
68 #ifdef FLEX_SCANNER
69 int                             yylineno;               /* linenumber */
70 #define yyunput ATTRIBUTE_UNUSED yyunput
71 #endif
73 char                    *yyfilename;    /* in this file */
74 PCBTypePtr              yyPCB;                  /* used by parser */
75 DataTypePtr             yyData;
76 ElementTypePtr          yyElement;
77 FontTypePtr             yyFont;
79 static int parse_number (double);
81 /* ---------------------------------------------------------------------------
82  * an external prototypes
83  */
84 int     yyparse(void);
86 /* ---------------------------------------------------------------------------
87  * some local prototypes
88  */
89 static  int             Parse(char *, char *, char *, char *);
93 HEX                             0x[0-9a-fA-F]+
94 DECIMAL                 -?[1-9][0-9]*|0
95 FLOATING                [+-]?[0-9]*("."[0-9]*)?
96 FLOATINGMM              {FLOATING}[mM][mM]
97 FLOATINGUM              {FLOATING}[uU][mM]
98 FLOATINGIN              {FLOATING}[iI][nN]
99 FLOATINGMIL             {FLOATING}[mM][iI][lL]
100 CARDINAL                [1-9][0-9]*|0
101 STRINGCHAR              ([^"\n\r\\]|\\.)
103 %option yylineno
107 FileVersion     { return(T_FILEVERSION); }
108 PCB                     { return(T_PCB); }
109 Grid            { return(T_GRID); }
110 Cursor          { return(T_CURSOR); }
111 Thermal         { return(T_THERMAL); }
112 PolyArea        { return(T_AREA); }
113 DRC             { return(T_DRC); }
114 Flags           { return(T_FLAGS); }
115 Layer           { return(T_LAYER); }
116 Pin                     { return(T_PIN); }
117 Pad                     { return(T_PAD); }
118 Via                     { return(T_VIA); }
119 Line            { return(T_LINE); }
120 Rat             { return(T_RAT); }
121 Rectangle       { return(T_RECTANGLE); }
122 Text            { return(T_TEXT); }
123 ElementLine     { return(T_ELEMENTLINE); }
124 ElementArc      { return(T_ELEMENTARC); }
125 Element         { return(T_ELEMENT); }
126 SymbolLine      { return(T_SYMBOLLINE); }
127 Symbol          { return(T_SYMBOL); }
128 Mark            { return(T_MARK); }
129 Groups          { return(T_GROUPS); }
130 Styles          { return(T_STYLES); }
131 Polygon         { return(T_POLYGON); }
132 Hole            { return(T_POLYGON_HOLE); }
133 Arc             { return(T_ARC); }
134 NetList         { return(T_NETLIST); }
135 Net             { return(T_NET); }
136 Connect         { return(T_CONN); }
137 Attribute       { return(T_ATTRIBUTE); }
139 \'.\'                           {
140                                                 yylval.number = (unsigned) *(yytext+1);
141                                                 return(CHAR_CONST);
142                                         }
143 {FLOATINGMM}            {       return parse_number(3937.0079); }
144 {FLOATINGUM}            {       return parse_number(3.9370079); }
145 {FLOATINGIN}            {       return parse_number(100000.0); }
146 {FLOATINGMIL}           {       return parse_number(100.0); }
147 {DECIMAL}               {       return parse_number(1.0); }
149 {HEX}                   {
150                                                 sscanf((char *) yytext, "%x", &yylval.number);
151                                                 return(NUMBER);
152                                         }
153 {FLOATING}                      {
154                                                 yylval.floating = c_strtod (yytext);
155                                                 return(FLOAT);
156                                         }
157 \"{STRINGCHAR}*\"       {
158                                                 char    *p1, *p2;
160                                                         /* return NULL on empty string */
161                                                 if (yyleng == 2)
162                                                 {
163                                                         yylval.string = NULL;
164                                                         return(STRING);
165                                                 }
167                                                         /* allocate memory and copy string;
168                                                          * stringlength is counted and copied without
169                                                          * leading and trailing '"'
170                                                          */
171                                                 yyleng -= 2;
172                                                 yylval.string = MyCalloc(yyleng+1, sizeof(char), "LEX");
173                                                 p1 = (char *) (yytext +1);
174                                                 p2 = yylval.string;
175                                                 while(yyleng--)
176                                                 {
177                                                                 /* check for special character */
178                                                         if (*p1 == '\\')
179                                                         {
180                                                                 yyleng--;
181                                                                 p1++;
183                                                         }
184                                                         *p2++ = *p1++;
185                                                 }
186                                                 *p2 = '\0';
187                                                 return(STRING);
188                                         }
189 #.*                                     {}
190 [ \t]+                          {}
191 [\n]                            {
192 #ifndef FLEX_SCANNER
193                                                 yylineno++;
194 #endif
195                                         }
196 [\r]                            {}
197 .                                       { return(*yytext); }
201 /* ---------------------------------------------------------------------------
202  * sets up the preprocessor command
203  */
204 static int Parse(char *Executable, char *Path, char *Filename, char *Parameter)
206         static  char    *command = NULL;
207         int             returncode;
208         int             used_popen = 0;
209         char *tmps;
210         size_t l;
211 #ifdef FLEX_SCANNER
212         static  bool    firsttime = true;
213 #endif
215         if (EMPTY_STRING_P (Executable))
216           {
217             l = 2;
218             if ( Path != NULL )
219               l += strlen (Path);
221             l += strlen (Filename);
223             if ( (tmps = (char *) malloc ( l * sizeof (char))) == NULL)
224               {
225                 fprintf (stderr, "Parse():  malloc failed\n");
226                 exit (1);
227               }
229             if ( Path != NULL && *Path != '\0')
230               sprintf (tmps, "%s%s%s", Path, PCB_DIR_SEPARATOR_S, Filename);
231             else
232               sprintf (tmps, "%s", Filename);
234             yyin = fopen (tmps, "r");
235             if (!yyin)
236               {
237                 Message("Can't open %s for reading\n", tmps);
238                 return(1);
239               }
240             free (tmps);
241           }
242         else
243           {
244             used_popen = 1;
245             /* release old command and create new from template */
246             if (command)
247               MYFREE (command);
248             command = EvaluateFilename(Executable, Path, Filename, Parameter);
250             /* open pipe to stdout of command */
251             if (*command == '\0' || (yyin = popen(command, "r")) == NULL)
252               {
253                 PopenErrorMessage(command);
254                 return(1);
255               }
256           }
258 #ifdef FLEX_SCANNER
259                 /* reset parser if not called the first time */
260         if (!firsttime)
261                 yyrestart(yyin);
262         firsttime = false;
263 #endif
265                 /* init linenumber and filename for yyerror() */
266         yylineno = 1;
267         yyfilename = Filename;
269                 /* We need to save the data temporarily because lex-yacc are able
270                  * to break the application if the input file has an illegal format.
271                  * It's not necessary if the system supports the call of functions
272                  * on termination.
273                  */
275 #if !defined(HAS_ATEXIT) && !defined(HAS_ON_EXIT)
276         if (PCB)
277           SaveTMPData();
278         returncode = yyparse();
279         RemoveTMPData();
280 #else
281         returncode = yyparse();
282 #endif
283         /* clean up parse buffer */
284         yy_delete_buffer(YY_CURRENT_BUFFER);
286         if (used_popen)
287           return(pclose(yyin) ? 1 : returncode);
288         return(fclose(yyin) ? 1 : returncode);
291 /* ---------------------------------------------------------------------------
292  * initializes LEX and calls parser for a single element file
293  */
294 int ParseElementFile(DataTypePtr Ptr, char *Filename)
296         yyPCB = NULL;
297         yyData = Ptr;
298         yyFont = &PCB->Font;
299         yyElement = NULL;
300         return(Parse(NULL,NULL,Filename,NULL));
303 /* ---------------------------------------------------------------------------
304  * initializes LEX and calls parser for a single library entry
305  */
306 int ParseLibraryEntry(DataTypePtr Ptr, char *Template)
308         yyPCB = NULL;
309         yyData = Ptr;
310         yyFont = &PCB->Font;
311         yyElement = NULL;
312         return(Parse(Settings.LibraryCommand, Settings.LibraryPath,
313                 Settings.LibraryFilename, Template));
316 /* ---------------------------------------------------------------------------
317  * initializes LEX and calls parser for a complete board
318  */
319 int ParsePCB(PCBTypePtr Ptr, char *Filename)
321         yyPCB = Ptr;
322         yyData = NULL;
323         yyFont = NULL;
324         yyElement = NULL;
325         return(Parse(Settings.FileCommand, Settings.FilePath, Filename, NULL));
328 /* ---------------------------------------------------------------------------
329  * initializes LEX and calls parser for a font
330  */
331 int ParseFont(FontTypePtr Ptr, char *Filename)
333         int r = 0;
334         char *path, *p;
335         yyPCB = NULL;
336         yyFont = Ptr;
337         yyElement = NULL;
339         path = strdup (Settings.FontPath);
341         /* search through the font path for a font file */
342         for (p = strtok (path, PCB_PATH_DELIMETER); p && *p;
343                 p = strtok (NULL, PCB_PATH_DELIMETER))
344           {
345             Message ("Looking for %s in %s\n", Filename, p);
346             r = Parse(Settings.FontCommand, p, Filename, NULL);
347             if (r == 0)
348               {
349                 Message ("Found %s in %s\n", Filename, p);
350                 break;
351               }
352           }
353         free (path);
355         return r;
358 static int
359 parse_number (double scale)
361   double val;
362   sscanf ((char *) yytext, "%lf", &val);
363   val *= scale;
364   /* Round towards nearest means we have to check the sign first.  */
365   if (val < 0)
366     val -= 0.49;
367   else
368     val += 0.49;
369   yylval.number = (int)(val);
370   return NUMBER;