7 * PCB, interactive printed circuit board design
8 * Copyright (C) 1994,1995,1996,2006 Thomas Nau
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.
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.
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.
24 * Contact addresses for paper mail and Email:
25 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
26 * Thomas.Nau@rz.uni-ulm.de
30 /* lexical definitions to parse ASCII input of PCB and Element description
41 #if defined(_POSIX_SOURCE) || defined(_HPUX_SOURCE)
47 #ifdef HAVE_LIBDMALLOC
48 # include <dmalloc.h> /* see http://dmalloc.com */
55 #include "crosshair.h"
68 /* ---------------------------------------------------------------------------
69 * some shared parser identifiers
72 int yylineno; /* linenumber */
73 #define yyunput ATTRIBUTE_UNUSED yyunput
76 char *yyfilename; /* in this file */
77 PCBTypePtr yyPCB; /* used by parser */
79 ElementTypePtr yyElement;
82 static int parse_number (double);
84 /* ---------------------------------------------------------------------------
85 * an external prototypes
89 /* ---------------------------------------------------------------------------
90 * some local prototypes
92 static int Parse(char *, char *, char *, char *);
97 DECIMAL -?[1-9][0-9]*|0
98 FLOATING [+-]?[0-9]*("."[0-9]*)?
99 FLOATINGMM {FLOATING}[mM][mM]
100 FLOATINGUM {FLOATING}[uU][mM]
101 FLOATINGIN {FLOATING}[iI][nN]
102 FLOATINGMIL {FLOATING}[mM][iI][lL]
103 CARDINAL [1-9][0-9]*|0
104 STRINGCHAR ([^"\n\r\\]|\\.)
110 FileVersion { return(T_FILEVERSION); }
111 PCB { return(T_PCB); }
112 Grid { return(T_GRID); }
113 Cursor { return(T_CURSOR); }
114 Thermal { return(T_THERMAL); }
115 PolyArea { return(T_AREA); }
116 DRC { return(T_DRC); }
117 Flags { return(T_FLAGS); }
118 Layer { return(T_LAYER); }
119 Pin { return(T_PIN); }
120 Pad { return(T_PAD); }
121 Via { return(T_VIA); }
122 Line { return(T_LINE); }
123 Rat { return(T_RAT); }
124 Rectangle { return(T_RECTANGLE); }
125 Text { return(T_TEXT); }
126 ElementLine { return(T_ELEMENTLINE); }
127 ElementArc { return(T_ELEMENTARC); }
128 Element { return(T_ELEMENT); }
129 SymbolLine { return(T_SYMBOLLINE); }
130 Symbol { return(T_SYMBOL); }
131 Mark { return(T_MARK); }
132 Groups { return(T_GROUPS); }
133 Styles { return(T_STYLES); }
134 Polygon { return(T_POLYGON); }
135 Hole { return(T_POLYGON_HOLE); }
136 Arc { return(T_ARC); }
137 NetList { return(T_NETLIST); }
138 Net { return(T_NET); }
139 Connect { return(T_CONN); }
140 Attribute { return(T_ATTRIBUTE); }
143 yylval.number = (unsigned) *(yytext+1);
146 {FLOATINGMM} { return parse_number(3937.0079); }
147 {FLOATINGUM} { return parse_number(3.9370079); }
148 {FLOATINGIN} { return parse_number(100000.0); }
149 {FLOATINGMIL} { return parse_number(100.0); }
150 {DECIMAL} { return parse_number(1.0); }
153 sscanf((char *) yytext, "%x", &yylval.number);
157 yylval.floating = c_strtod (yytext);
163 /* return NULL on empty string */
166 yylval.string = NULL;
170 /* allocate memory and copy string;
171 * stringlength is counted and copied without
172 * leading and trailing '"'
175 yylval.string = calloc (yyleng+1, sizeof (char));
176 p1 = (char *) (yytext +1);
180 /* check for special character */
200 . { return(*yytext); }
204 /* ---------------------------------------------------------------------------
205 * sets up the preprocessor command
207 static int Parse(char *Executable, char *Path, char *Filename, char *Parameter)
209 static char *command = NULL;
215 static bool firsttime = true;
218 if (EMPTY_STRING_P (Executable))
224 l += strlen (Filename);
226 if ( (tmps = (char *) malloc ( l * sizeof (char))) == NULL)
228 fprintf (stderr, "Parse(): malloc failed\n");
232 if ( Path != NULL && *Path != '\0')
233 sprintf (tmps, "%s%s%s", Path, PCB_DIR_SEPARATOR_S, Filename);
235 sprintf (tmps, "%s", Filename);
237 yyin = fopen (tmps, "r");
240 /* Special case this one, we get it all the time... */
241 if (strcmp (tmps, "./default_font"))
242 Message("Can't open %s for reading\n", tmps);
250 /* release old command and create new from template */
252 command = EvaluateFilename(Executable, Path, Filename, Parameter);
254 /* open pipe to stdout of command */
255 if (*command == '\0' || (yyin = popen(command, "r")) == NULL)
257 PopenErrorMessage(command);
263 /* reset parser if not called the first time */
269 /* init linenumber and filename for yyerror() */
271 yyfilename = Filename;
273 /* We need to save the data temporarily because lex-yacc are able
274 * to break the application if the input file has an illegal format.
275 * It's not necessary if the system supports the call of functions
279 CreateBeLenient (true);
281 #if !defined(HAS_ATEXIT) && !defined(HAS_ON_EXIT)
284 returncode = yyparse();
287 returncode = yyparse();
289 /* clean up parse buffer */
290 yy_delete_buffer(YY_CURRENT_BUFFER);
292 CreateBeLenient (false);
295 return(pclose(yyin) ? 1 : returncode);
296 return(fclose(yyin) ? 1 : returncode);
299 /* ---------------------------------------------------------------------------
300 * initializes LEX and calls parser for a single element file
302 int ParseElementFile(DataTypePtr Ptr, char *Filename)
308 return(Parse(NULL,NULL,Filename,NULL));
311 /* ---------------------------------------------------------------------------
312 * initializes LEX and calls parser for a single library entry
314 int ParseLibraryEntry(DataTypePtr Ptr, char *Template)
320 return(Parse(Settings.LibraryCommand, Settings.LibraryPath,
321 Settings.LibraryFilename, Template));
324 /* ---------------------------------------------------------------------------
325 * initializes LEX and calls parser for a complete board
327 int ParsePCB(PCBTypePtr Ptr, char *Filename)
333 return(Parse(Settings.FileCommand, Settings.FilePath, Filename, NULL));
336 /* ---------------------------------------------------------------------------
337 * initializes LEX and calls parser for a font
339 int ParseFont(FontTypePtr Ptr, char *Filename)
347 path = strdup (Settings.FontPath);
349 /* search through the font path for a font file */
350 for (p = strtok (path, PCB_PATH_DELIMETER); p && *p;
351 p = strtok (NULL, PCB_PATH_DELIMETER))
354 Message ("Looking for %s in %s\n", Filename, p);
356 r = Parse(Settings.FontCommand, p, Filename, NULL);
360 Message ("Found %s in %s\n", Filename, p);
371 parse_number (double scale)
374 sscanf ((char *) yytext, "%lf", &val);
376 /* Round towards nearest means we have to check the sign first. */
381 yylval.number = (int)(val);