2 * gEDA - GNU Electronic Design Automation
3 * This files is a part of gerbv.
5 * Copyright (C) 2000-2002 Stefan Petersen (spe@stacken.kth.se)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
25 \brief Aperture macro parsing functions
34 #include "gerb_file.h"
38 * Allocates a new instruction structure
40 static gerbv_instruction_t
*
43 gerbv_instruction_t
*instruction
;
45 instruction
= (gerbv_instruction_t
*)malloc(sizeof(gerbv_instruction_t
));
46 if (instruction
== NULL
) {
51 memset(instruction
, 0, sizeof(gerbv_instruction_t
));
54 } /* new_instruction */
58 * Allocates a new amacro structure
60 static gerbv_amacro_t
*
63 gerbv_amacro_t
*amacro
;
65 amacro
= (gerbv_amacro_t
*)malloc(sizeof(gerbv_amacro_t
));
71 memset(amacro
, 0, sizeof(gerbv_amacro_t
));
78 * Parses the definition of an aperture macro
81 parse_aperture_macro(gerb_file_t
*fd
)
83 gerbv_amacro_t
*amacro
;
84 gerbv_instruction_t
*ip
= NULL
;
85 int primitive
= 0, c
, found_primitive
= 0;
86 gerbv_opcodes_t math_op
= GERBV_OPCODE_NOP
;
87 int comma
= 0; /* Just read an operator (one of '*+X/) */
88 int neg
= 0; /* negative numbers succeding , */
89 unsigned char continueLoop
= 1;
92 amacro
= new_amacro();
97 amacro
->name
= gerb_fgetstring(fd
, '*');
98 c
= gerb_fgetc(fd
); /* skip '*' */
104 * Since I'm lazy I have a dummy head. Therefore the first
105 * instruction in all programs will be NOP.
107 amacro
->program
= new_instruction();
108 ip
= amacro
->program
;
110 while(continueLoop
) {
115 if (found_primitive
) {
116 ip
->next
= new_instruction(); /* XXX Check return value */
118 ip
->opcode
= GERBV_OPCODE_PPUSH
;
120 ip
->data
.ival
= gerb_fgetint(fd
, NULL
);
123 equate
= gerb_fgetint(fd
, NULL
);
127 if (math_op
!= GERBV_OPCODE_NOP
) {
128 ip
->next
= new_instruction(); /* XXX Check return value */
130 ip
->opcode
= math_op
;
131 math_op
= GERBV_OPCODE_NOP
;
134 * Check is due to some gerber files has spurious empty lines.
135 * (EagleCad of course).
137 if (found_primitive
) {
138 ip
->next
= new_instruction(); /* XXX Check return value */
141 ip
->opcode
= GERBV_OPCODE_PPOP
;
142 ip
->data
.ival
= equate
;
144 ip
->opcode
= GERBV_OPCODE_PRIM
;
145 ip
->data
.ival
= primitive
;
158 if (!found_primitive
) {
162 if (math_op
!= GERBV_OPCODE_NOP
) {
163 ip
->next
= new_instruction(); /* XXX Check return value */
165 ip
->opcode
= math_op
;
166 math_op
= GERBV_OPCODE_NOP
;
171 if (math_op
!= GERBV_OPCODE_NOP
) {
172 ip
->next
= new_instruction(); /* XXX Check return value */
174 ip
->opcode
= math_op
;
176 math_op
= GERBV_OPCODE_ADD
;
185 if (math_op
!= GERBV_OPCODE_NOP
) {
186 ip
->next
= new_instruction(); /* XXX Check return value */
188 ip
->opcode
= math_op
;
190 math_op
= GERBV_OPCODE_SUB
;
193 if (math_op
!= GERBV_OPCODE_NOP
) {
194 ip
->next
= new_instruction(); /* XXX Check return value */
196 ip
->opcode
= math_op
;
198 math_op
= GERBV_OPCODE_DIV
;
203 if (math_op
!= GERBV_OPCODE_NOP
) {
204 ip
->next
= new_instruction(); /* XXX Check return value */
206 ip
->opcode
= math_op
;
208 math_op
= GERBV_OPCODE_MUL
;
213 * Comments in aperture macros are a definition starting with
214 * zero and ends with a '*'
216 if (!found_primitive
&& (primitive
== 0)) {
217 /* Comment continues 'til next *, just throw it away */
218 gerb_fgetstring(fd
, '*');
219 c
= gerb_fgetc(fd
); /* Read the '*' */
232 * First number in an aperture macro describes the primitive
233 * as a numerical value
235 if (!found_primitive
) {
236 primitive
= (primitive
* 10) + (c
- '0');
239 (void)gerb_ungetc(fd
);
240 ip
->next
= new_instruction(); /* XXX Check return value */
242 ip
->opcode
= GERBV_OPCODE_PUSH
;
244 ip
->data
.fval
= gerb_fgetdouble(fd
);
246 ip
->data
.fval
= -ip
->data
.fval
;
251 gerb_ungetc(fd
); /* Must return with % first in string
252 since the main parser needs it */
268 free_amacro(gerbv_amacro_t
*amacro
)
270 gerbv_amacro_t
*am1
, *am2
;
271 gerbv_instruction_t
*instr1
, *instr2
;
274 while (am1
!= NULL
) {
278 instr1
= am1
->program
;
279 while (instr1
!= NULL
) {
281 instr1
= instr1
->next
;
297 print_program(gerbv_amacro_t
*amacro
)
299 gerbv_instruction_t
*ip
;
301 printf("Macroname [%s] :\n", amacro
->name
);
302 for (ip
= amacro
->program
; ip
!= NULL
; ip
= ip
->next
) {
304 case GERBV_OPCODE_NOP
:
307 case GERBV_OPCODE_PUSH
:
308 printf(" PUSH %f\n", ip
->data
.fval
);
310 case GERBV_OPCODE_PPOP
:
311 printf(" PPOP %d\n", ip
->data
.ival
);
313 case GERBV_OPCODE_PPUSH
:
314 printf(" PPUSH %d\n", ip
->data
.ival
);
316 case GERBV_OPCODE_ADD
:
319 case GERBV_OPCODE_SUB
:
322 case GERBV_OPCODE_MUL
:
325 case GERBV_OPCODE_DIV
:
328 case GERBV_OPCODE_PRIM
:
329 printf(" PRIM %d\n", ip
->data
.ival
);
337 } /* print_program */