(no commit message)
[geda-pcb/pcjc2.git] / src / parse_l.l
blob4f648807fa2e3a0f5400a620b9d2c0ca7ac0d3b6
1 %{
2 /*
3  *                            COPYRIGHT
4  *
5  *  PCB, interactive printed circuit board design
6  *  Copyright (C) 1994,1995,1996,2006 Thomas Nau
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  *  Contact addresses for paper mail and Email:
23  *  Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
24  *  Thomas.Nau@rz.uni-ulm.de
25  *
26  */
28 /* lexical definitions to parse ASCII input of PCB and Element description
29  */
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <ctype.h>
39 #if defined(_POSIX_SOURCE) || defined(_HPUX_SOURCE)
40 #include <unistd.h>
41 #endif
43 #include "global.h"
45 #ifdef HAVE_LIBDMALLOC
46 # include <dmalloc.h> /* see http://dmalloc.com */
47 #endif
49 #include "global.h"
50 #include "crosshair.h"
51 #include "data.h"
52 #include "error.h"
53 #include "file.h"
54 #include "mymem.h"
55 #include "misc.h"
56 #include "strflags.h"
57 #include "parse_l.h"
58 #include "parse_y.h"
59 #include "create.h"
61 #define YY_NO_INPUT
63 /* ---------------------------------------------------------------------------
64  * some shared parser identifiers
65  */
66 #ifdef FLEX_SCANNER
68 #define yyunput ATTRIBUTE_UNUSED yyunput
69 #endif
71 char                    *yyfilename;    /* in this file */
72 PCBType                 *yyPCB;         /* used by parser */
73 DataType                *yyData;
74 ElementType             *yyElement;
75 FontType                *yyFont;
77 static int parse_number (void);
79 /* ---------------------------------------------------------------------------
80  * an external prototypes
81  */
82 int     yyparse(void);
84 /* ---------------------------------------------------------------------------
85  * some local prototypes
86  */
87 static  int             Parse(char *, char *, char *, char *);
91 HEX                             0x[0-9a-fA-F]+
92 INTEGER                 [+-]?([1-9][0-9]*|0)
93 FLOATING                {INTEGER}?"."[0-9]*
94 STRINGCHAR              ([^"\n\r\\]|\\.)
96 %option yylineno
100 FileVersion     { return(T_FILEVERSION); }
101 PCB                     { return(T_PCB); }
102 Grid            { return(T_GRID); }
103 Cursor          { return(T_CURSOR); }
104 Thermal         { return(T_THERMAL); }
105 PolyArea        { return(T_AREA); }
106 DRC             { return(T_DRC); }
107 Flags           { return(T_FLAGS); }
108 Layer           { return(T_LAYER); }
109 Pin                     { return(T_PIN); }
110 Pad                     { return(T_PAD); }
111 Via                     { return(T_VIA); }
112 Line            { return(T_LINE); }
113 Rat             { return(T_RAT); }
114 Rectangle       { return(T_RECTANGLE); }
115 Text            { return(T_TEXT); }
116 ElementLine     { return(T_ELEMENTLINE); }
117 ElementArc      { return(T_ELEMENTARC); }
118 Element         { return(T_ELEMENT); }
119 SymbolLine      { return(T_SYMBOLLINE); }
120 Symbol          { return(T_SYMBOL); }
121 Mark            { return(T_MARK); }
122 Groups          { return(T_GROUPS); }
123 Styles          { return(T_STYLES); }
124 Polygon         { return(T_POLYGON); }
125 Hole            { return(T_POLYGON_HOLE); }
126 Arc             { return(T_ARC); }
127 NetList         { return(T_NETLIST); }
128 Net             { return(T_NET); }
129 Connect         { return(T_CONN); }
130 Attribute       { return(T_ATTRIBUTE); }
132 nm      { return T_NM; }
133 um      { return T_UM; }
134 mm      { return T_MM; }
135 m       { return T_M; }
136 km      { return T_KM; }
137 umil    { return T_UMIL; }
138 cmil    { return T_CMIL; }
139 mil     { return T_MIL; }
140 in      { return T_IN; }
141 px  { return T_PX; }
143 \'.\'                           {
144                                                 yylval.integer = (unsigned) *(yytext+1);
145                                                 return(CHAR_CONST);
146                                         }
147 {FLOATING}              {       return parse_number(); }
148 {INTEGER}               {       yylval.integer = round (g_ascii_strtod (yytext, NULL)); return INTEGER; }
150 {HEX}                   {       unsigned n;
151                                 sscanf((char *) yytext, "%x", &n);
152                                 yylval.integer = n;
153                                 return INTEGER;
154                                         }
155 \"{STRINGCHAR}*\"       {
156                                                 char    *p1, *p2;
158                                                         /* return NULL on empty string */
159                                                 if (yyleng == 2)
160                                                 {
161                                                         yylval.string = NULL;
162                                                         return(STRING);
163                                                 }
165                                                         /* allocate memory and copy string;
166                                                          * stringlength is counted and copied without
167                                                          * leading and trailing '"'
168                                                          */
169                                                 yyleng -= 2;
170                                                 yylval.string = (char *)calloc (yyleng+1, sizeof (char));
171                                                 p1 = (char *) (yytext +1);
172                                                 p2 = yylval.string;
173                                                 while(yyleng--)
174                                                 {
175                                                                 /* check for special character */
176                                                         if (*p1 == '\\')
177                                                         {
178                                                                 yyleng--;
179                                                                 p1++;
181                                                         }
182                                                         *p2++ = *p1++;
183                                                 }
184                                                 *p2 = '\0';
185                                                 return(STRING);
186                                         }
187 #.*                                     {}
188 [ \t]+                          {}
189 [\n]                            {
190 #ifndef FLEX_SCANNER
191                                                 yylineno++;
192 #endif
193                                         }
194 [\r]                            {}
195 .                                       { return(*yytext); }
199 /* ---------------------------------------------------------------------------
200  * sets up the preprocessor command
201  */
202 static int Parse(char *Executable, char *Path, char *Filename, char *Parameter)
204         static  char    *command = NULL;
205         int             returncode;
206         int             used_popen = 0;
207         char *tmps;
208         size_t l;
209 #ifdef FLEX_SCANNER
210         static  bool    firsttime = true;
211 #endif
213         if (EMPTY_STRING_P (Executable))
214           {
215             l = 2;
216             if ( Path != NULL )
217               l += strlen (Path);
219             l += strlen (Filename);
221             if ( (tmps = (char *) malloc ( l * sizeof (char))) == NULL)
222               {
223                 fprintf (stderr, "Parse():  malloc failed\n");
224                 exit (1);
225               }
227             if ( Path != NULL && *Path != '\0')
228               sprintf (tmps, "%s%s%s", Path, PCB_DIR_SEPARATOR_S, Filename);
229             else
230               sprintf (tmps, "%s", Filename);
232             yyin = fopen (tmps, "r");
233             if (!yyin)
234               {
235                 /* Special case this one, we get it all the time... */
236                 if (strcmp (tmps, "./default_font"))
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             free (command);
247             command = EvaluateFilename(Executable, Path, Filename, Parameter);
249             /* open pipe to stdout of command */
250             if (*command == '\0' || (yyin = popen(command, "r")) == NULL)
251               {
252                 PopenErrorMessage(command);
253                 return(1);
254               }
255           }
257 #ifdef FLEX_SCANNER
258                 /* reset parser if not called the first time */
259         if (!firsttime)
260                 yyrestart(yyin);
261         firsttime = false;
262 #endif
264                 /* init linenumber and filename for yyerror() */
265         yylineno = 1;
266         yyfilename = Filename;
268                 /* We need to save the data temporarily because lex-yacc are able
269                  * to break the application if the input file has an illegal format.
270                  * It's not necessary if the system supports the call of functions
271                  * on termination.
272                  */
274         CreateBeLenient (true);
276 #if !defined(HAS_ATEXIT) && !defined(HAS_ON_EXIT)
277         if (PCB && PCB->Data)
278           SaveTMPData();
279         returncode = yyparse();
280         RemoveTMPData();
281 #else
282         returncode = yyparse();
283 #endif
284         /* clean up parse buffer */
285         yy_delete_buffer(YY_CURRENT_BUFFER);
287         CreateBeLenient (false);
289         if (used_popen)
290           return(pclose(yyin) ? 1 : returncode);
291         return(fclose(yyin) ? 1 : returncode);
294 /* ---------------------------------------------------------------------------
295  * initializes LEX and calls parser for a single element file
296  */
298 ParseElementFile (DataType *Ptr, char *Filename)
300         yyPCB = NULL;
301         yyData = Ptr;
302         yyFont = &PCB->Font;
303         yyElement = NULL;
304         return(Parse(NULL,NULL,Filename,NULL));
307 /* ---------------------------------------------------------------------------
308  * initializes LEX and calls parser for a single library entry
309  */
311 ParseLibraryEntry (DataType *Ptr, char *Template)
313         yyPCB = NULL;
314         yyData = Ptr;
315         yyFont = &PCB->Font;
316         yyElement = NULL;
317         return(Parse(Settings.LibraryCommand, Settings.LibraryPath,
318                 Settings.LibraryFilename, Template));
321 /* ---------------------------------------------------------------------------
322  * initializes LEX and calls parser for a complete board
323  */
325 ParsePCB (PCBType *Ptr, char *Filename)
327         yyPCB = Ptr;
328         yyData = NULL;
329         yyFont = NULL;
330         yyElement = NULL;
331         return(Parse(Settings.FileCommand, Settings.FilePath, Filename, NULL));
334 /* ---------------------------------------------------------------------------
335  * initializes LEX and calls parser for a font
336  */
338 ParseFont (FontType *Ptr, char *Filename)
340         int r = 0;
341         char *path, *p;
342         yyPCB = NULL;
343         yyFont = Ptr;
344         yyElement = NULL;
346         path = strdup (Settings.FontPath);
348         /* search through the font path for a font file */
349         for (p = strtok (path, PCB_PATH_DELIMETER); p && *p;
350                 p = strtok (NULL, PCB_PATH_DELIMETER))
351           {
352 #ifdef DEBUG
353             Message ("Looking for %s in %s\n", Filename, p);
354 #endif
355             r = Parse(Settings.FontCommand, p, Filename, NULL);
356             if (r == 0)
357               {
358 #ifdef DEBUG
359                 Message ("Found %s in %s\n", Filename, p);
360 #endif
361                 break;
362               }
363           }
364         free (path);
366         return r;
369 static int
370 parse_number ()
372   yylval.number = g_ascii_strtod ((gchar *) yytext, NULL);
373   return FLOATING;