Root/
Source at commit 5fdea0e99a2e8543a59d508cf28e1f2ff3607f18 created 9 years 2 months ago. By Werner Almesberger, gui_canvas.c (key_press_event): make / rotate through packages as well | |
---|---|
1 | /* |
2 | * obj.c - Object definition model |
3 | * |
4 | * Written 2009-2012 by Werner Almesberger |
5 | * Copyright 2009-2012 by Werner Almesberger |
6 | * |
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. |
11 | */ |
12 | |
13 | |
14 | #include <stdlib.h> |
15 | #include <string.h> |
16 | #include <assert.h> |
17 | |
18 | #include "util.h" |
19 | #include "error.h" |
20 | #include "expr.h" |
21 | #include "bitset.h" |
22 | #include "meas.h" |
23 | #include "inst.h" |
24 | #include "hole.h" |
25 | #include "overlap.h" |
26 | #include "layer.h" |
27 | #include "delete.h" |
28 | #include "fpd.h" |
29 | #include "obj.h" |
30 | |
31 | |
32 | #define DEFAULT_SILK_WIDTH make_mil(15) /* @@@ */ |
33 | #define DEFAULT_OFFSET make_mil(0) /* @@@ */ |
34 | |
35 | #define MAX_ITERATIONS 1000 /* abort "loop"s at this limit */ |
36 | |
37 | |
38 | char *pkg_name = NULL; |
39 | struct frame *frames = NULL; |
40 | struct frame *active_frame = NULL; |
41 | void *instantiation_error = NULL; |
42 | enum allow_overlap allow_overlap = ao_none; |
43 | int holes_linked = 1; |
44 | |
45 | |
46 | static struct bitset *frame_set; /* frames visited in "call chain" */ |
47 | |
48 | |
49 | /* ----- Searching --------------------------------------------------------- */ |
50 | |
51 | |
52 | /* |
53 | * @@@ Known bug: we should compare all parameters of an instance, not just the |
54 | * object's base or the vectors end. |
55 | */ |
56 | |
57 | static int found = 0; |
58 | static int search_suspended = 0; |
59 | static const struct vec *find_vec = NULL; |
60 | static const struct obj *find_obj = NULL; |
61 | static struct coord find_pos; |
62 | |
63 | |
64 | static void suspend_search(void) |
65 | { |
66 | search_suspended++; |
67 | } |
68 | |
69 | static void resume_search(void) |
70 | { |
71 | assert(search_suspended > 0); |
72 | search_suspended--; |
73 | } |
74 | |
75 | |
76 | static struct coord get_pos(const struct inst *inst) |
77 | { |
78 | return inst->obj ? inst->base : inst->u.vec.end; |
79 | } |
80 | |
81 | |
82 | void find_inst(const struct inst *inst) |
83 | { |
84 | struct coord pos; |
85 | |
86 | if (search_suspended) |
87 | return; |
88 | if (find_vec != inst->vec) |
89 | return; |
90 | if (find_obj != inst->obj) |
91 | return; |
92 | pos = get_pos(inst); |
93 | if (pos.x != find_pos.x || pos.y != find_pos.y) |
94 | return; |
95 | found++; |
96 | } |
97 | |
98 | |
99 | void search_inst(const struct inst *inst) |
100 | { |
101 | find_vec = inst->vec; |
102 | find_obj = inst->obj; |
103 | find_pos = get_pos(inst); |
104 | } |
105 | |
106 | |
107 | /* ----- Get the list of anchors of an object ------------------------------ */ |
108 | |
109 | |
110 | int obj_anchors(struct obj *obj, struct vec ***anchors) |
111 | { |
112 | anchors[0] = &obj->base; |
113 | switch (obj->type) { |
114 | case ot_frame: |
115 | return 1; |
116 | case ot_rect: |
117 | case ot_line: |
118 | anchors[1] = &obj->u.rect.other; |
119 | return 2; |
120 | case ot_pad: |
121 | anchors[1] = &obj->u.pad.other; |
122 | return 2; |
123 | case ot_hole: |
124 | anchors[1] = &obj->u.hole.other; |
125 | return 2; |
126 | case ot_meas: |
127 | anchors[1] = &obj->u.meas.high; |
128 | return 2; |
129 | case ot_arc: |
130 | /* |
131 | * Put end point first so that this is what we grab if dragging |
132 | * a circle (thereby turning it into an arc). |
133 | */ |
134 | anchors[1] = &obj->u.arc.end; |
135 | anchors[2] = &obj->u.arc.start; |
136 | return 3; |
137 | default: |
138 | abort(); |
139 | } |
140 | } |
141 | |
142 | |
143 | /* ----- Instantiation ----------------------------------------------------- */ |
144 | |
145 | |
146 | static int generate_frame(struct frame *frame, struct coord base, |
147 | const struct frame *parent, struct obj *frame_ref, int active); |
148 | |
149 | |
150 | struct num eval_unit(const struct expr *expr, const struct frame *frame); |
151 | /*static*/ struct num eval_unit(const struct expr *expr, const struct frame *frame) |
152 | { |
153 | struct num d; |
154 | |
155 | d = eval_num(expr, frame); |
156 | if (!is_undef(d) && to_unit(&d)) |
157 | return d; |
158 | fail_expr(expr); |
159 | return undef; |
160 | } |
161 | |
162 | |
163 | static struct num eval_unit_default(const struct expr *expr, |
164 | const struct frame *frame, struct num def) |
165 | { |
166 | if (expr) |
167 | return eval_unit(expr, frame); |
168 | to_unit(&def); |
169 | return def; |
170 | } |
171 | |
172 | |
173 | static int recurse_vec(const char *name, const struct frame *frame, |
174 | struct coord *res) |
175 | { |
176 | const struct vec *v; |
177 | |
178 | if (!frame) |
179 | return 0; |
180 | for (v = frame->vecs; v; v = v->next) |
181 | if (v->name == name) { |
182 | *res = v->pos; |
183 | return 1; |
184 | } |
185 | return recurse_vec(name, frame->curr_parent, res); |
186 | } |
187 | |
188 | |
189 | static int resolve_vec(const struct vec *vec, struct coord base_pos, |
190 | const struct frame *frame, struct coord *res) |
191 | { |
192 | const char *name = (const char *) vec; |
193 | |
194 | if (!vec) { |
195 | *res = base_pos; |
196 | return 1; |
197 | } |
198 | if (!*name) { |
199 | *res = vec->pos; |
200 | return 1; |
201 | } |
202 | if (recurse_vec(name, frame->curr_parent, res)) |
203 | return 1; |
204 | fail("unknown vector \"%s\"", name); |
205 | return 0; |
206 | } |
207 | |
208 | |
209 | static int generate_vecs(struct frame *frame, struct coord base_pos) |
210 | { |
211 | struct coord vec_base; |
212 | struct vec *vec; |
213 | struct num x, y; |
214 | |
215 | for (vec = frame->vecs; vec; vec = vec->next) { |
216 | x = eval_unit(vec->x, frame); |
217 | if (is_undef(x)) |
218 | goto error; |
219 | y = eval_unit(vec->y, frame); |
220 | if (is_undef(y)) |
221 | goto error; |
222 | if (!resolve_vec(vec->base, base_pos, frame, &vec_base)) |
223 | goto error; |
224 | vec->pos = vec_base; |
225 | vec->pos.x += x.n; |
226 | vec->pos.y += y.n; |
227 | if (!inst_vec(vec, vec_base)) |
228 | goto error; |
229 | meas_post(vec, vec->pos, frame_set); |
230 | } |
231 | return 1; |
232 | |
233 | error: |
234 | instantiation_error = vec; |
235 | return 0; |
236 | } |
237 | |
238 | |
239 | static int generate_objs(struct frame *frame, struct coord base_pos, |
240 | int active) |
241 | { |
242 | struct obj *obj; |
243 | char *name; |
244 | int ok; |
245 | struct num width, offset; |
246 | struct coord base, other, start, end; |
247 | |
248 | for (obj = frame->objs; obj; obj = obj->next) { |
249 | if (obj->type != ot_meas) |
250 | if (!resolve_vec(obj->base, base_pos, frame, &base)) |
251 | goto error; |
252 | switch (obj->type) { |
253 | case ot_frame: |
254 | if (!generate_frame(obj->u.frame.ref, base, frame, obj, |
255 | active && obj->u.frame.ref->active_ref == obj)) |
256 | return 0; |
257 | break; |
258 | case ot_line: |
259 | if (!resolve_vec(obj->u.line.other, base_pos, frame, |
260 | &other)) |
261 | goto error; |
262 | width = eval_unit_default(obj->u.line.width, frame, |
263 | DEFAULT_SILK_WIDTH); |
264 | if (is_undef(width)) |
265 | goto error; |
266 | if (!inst_line(obj, base, other, width.n)) |
267 | goto error; |
268 | break; |
269 | case ot_rect: |
270 | if (!resolve_vec(obj->u.rect.other, base_pos, frame, |
271 | &other)) |
272 | goto error; |
273 | width = eval_unit_default(obj->u.rect.width, frame, |
274 | DEFAULT_SILK_WIDTH); |
275 | if (is_undef(width)) |
276 | goto error; |
277 | if (!inst_rect(obj, base, other, width.n)) |
278 | goto error; |
279 | break; |
280 | case ot_pad: |
281 | if (!resolve_vec(obj->u.pad.other, base_pos, frame, |
282 | &other)) |
283 | goto error; |
284 | name = expand(obj->u.pad.name, frame); |
285 | if (!name) |
286 | goto error; |
287 | ok = inst_pad(obj, name, base, other); |
288 | free(name); |
289 | if (!ok) |
290 | goto error; |
291 | break; |
292 | case ot_hole: |
293 | if (!resolve_vec(obj->u.hole.other, base_pos, frame, |
294 | &other)) |
295 | goto error; |
296 | if (!inst_hole(obj, base, other)) |
297 | goto error; |
298 | break; |
299 | case ot_arc: |
300 | if (!resolve_vec(obj->u.arc.start, base_pos, frame, |
301 | &start)) |
302 | goto error; |
303 | if (!resolve_vec(obj->u.arc.end, base_pos, frame, |
304 | &end)) |
305 | goto error; |
306 | width = eval_unit_default(obj->u.arc.width, frame, |
307 | DEFAULT_SILK_WIDTH); |
308 | if (is_undef(width)) |
309 | goto error; |
310 | if (!inst_arc(obj, base, start, end, width.n)) |
311 | goto error; |
312 | break; |
313 | case ot_meas: |
314 | assert(frame == frames); |
315 | offset = eval_unit_default(obj->u.meas.offset, frame, |
316 | DEFAULT_OFFSET); |
317 | if (is_undef(offset)) |
318 | goto error; |
319 | inst_meas_hint(obj, offset.n); |
320 | break; |
321 | case ot_iprint: |
322 | dbg_print(obj->u.iprint.expr, frame); |
323 | break; |
324 | default: |
325 | abort(); |
326 | } |
327 | } |
328 | return 1; |
329 | |
330 | error: |
331 | instantiation_error = obj; |
332 | return 0; |
333 | } |
334 | |
335 | |
336 | static int generate_items(struct frame *frame, struct coord base, int active) |
337 | { |
338 | char *s; |
339 | int ok; |
340 | |
341 | if (frame == frames) { |
342 | s = expand(pkg_name, frame); |
343 | /* s is NULL if expansion failed */ |
344 | inst_select_pkg(s ? s : "_", active); |
345 | free(s); |
346 | } |
347 | inst_begin_active(active && frame == active_frame); |
348 | ok = generate_vecs(frame, base) && generate_objs(frame, base, active); |
349 | inst_end_active(); |
350 | return ok; |
351 | } |
352 | |
353 | |
354 | static int match_keys(struct frame *frame, struct coord base, int active) |
355 | { |
356 | const struct table *table; |
357 | const struct var *var; |
358 | const struct value *value; |
359 | int res; |
360 | |
361 | for (table = frame->tables; table; table = table->next) { |
362 | value = table->curr_row->values; |
363 | for (var = table->vars; var; var = var->next) { |
364 | if (var->key) { |
365 | res = var_eq(frame, var->name, value->expr); |
366 | if (!res) |
367 | return 1; |
368 | if (res < 0) |
369 | return 0; |
370 | } |
371 | value = value->next; |
372 | } |
373 | } |
374 | return generate_items(frame, base, active); |
375 | } |
376 | |
377 | |
378 | static int run_loops(struct frame *frame, struct loop *loop, |
379 | struct coord base, int active) |
380 | { |
381 | struct num from, to; |
382 | int n; |
383 | int found_before, ok; |
384 | |
385 | if (!loop) |
386 | return match_keys(frame, base, active); |
387 | from = eval_num(loop->from.expr, frame); |
388 | if (is_undef(from)) { |
389 | fail_expr(loop->from.expr); |
390 | instantiation_error = loop; |
391 | return 0; |
392 | } |
393 | if (!is_dimensionless(from)) { |
394 | fail("incompatible type for start value"); |
395 | fail_expr(loop->from.expr); |
396 | instantiation_error = loop; |
397 | return 0; |
398 | } |
399 | |
400 | to = eval_num(loop->to.expr, frame); |
401 | if (is_undef(to)) { |
402 | fail_expr(loop->to.expr); |
403 | instantiation_error = loop; |
404 | return 0; |
405 | } |
406 | if (!is_dimensionless(to)) { |
407 | fail("incompatible type for end value"); |
408 | fail_expr(loop->to.expr); |
409 | instantiation_error = loop; |
410 | return 0; |
411 | } |
412 | |
413 | assert(!loop->initialized); |
414 | loop->curr_value = from.n; |
415 | loop->initialized = 1; |
416 | |
417 | n = 0; |
418 | for (; loop->curr_value <= to.n; loop->curr_value += 1) { |
419 | if (n >= MAX_ITERATIONS) { |
420 | fail("%s: too many iterations (%d)", loop->var.name, |
421 | MAX_ITERATIONS); |
422 | instantiation_error = loop; |
423 | goto fail; |
424 | } |
425 | found_before = found; |
426 | if (loop->found == loop->active) |
427 | suspend_search(); |
428 | ok = run_loops(frame, loop->next, base, |
429 | active && loop->active == n); |
430 | if (loop->found == loop->active) |
431 | resume_search(); |
432 | if (!ok) |
433 | goto fail; |
434 | if (found_before != found) |
435 | loop->found = n; |
436 | n++; |
437 | } |
438 | loop->initialized = 0; |
439 | loop->curr_value = UNDEF; |
440 | if (active) { |
441 | loop->n = from.n; |
442 | loop->iterations = n; |
443 | } |
444 | return 1; |
445 | |
446 | fail: |
447 | loop->initialized = 0; |
448 | return 0; |
449 | } |
450 | |
451 | |
452 | static int iterate_tables(struct frame *frame, struct table *table, |
453 | struct coord base, int active) |
454 | { |
455 | int found_before, ok; |
456 | |
457 | if (!table) |
458 | return run_loops(frame, frame->loops, base, active); |
459 | for (table->curr_row = table->rows; table->curr_row; |
460 | table->curr_row = table->curr_row->next) { |
461 | found_before = found; |
462 | if (table->found_row == table->active_row) |
463 | suspend_search(); |
464 | ok = iterate_tables(frame, table->next, base, |
465 | active && table->active_row == table->curr_row); |
466 | if (table->found_row == table->active_row) |
467 | resume_search(); |
468 | if (!ok) |
469 | return 0; |
470 | if (found_before != found) |
471 | table->found_row = table->curr_row; |
472 | } |
473 | return 1; |
474 | } |
475 | |
476 | |
477 | static int generate_frame(struct frame *frame, struct coord base, |
478 | const struct frame *parent, struct obj *frame_ref, int active) |
479 | { |
480 | int ok; |
481 | |
482 | /* |
483 | * We ensure during construction that frames can never recurse. |
484 | */ |
485 | inst_begin_frame(frame_ref, frame, base, |
486 | active && parent == active_frame, |
487 | active && frame == active_frame); |
488 | bitset_set(frame_set, frame->n); |
489 | frame->curr_parent = parent; |
490 | ok = iterate_tables(frame, frame->tables, base, active); |
491 | inst_end_frame(frame); |
492 | bitset_clear(frame_set, frame->n); |
493 | frame->curr_parent = NULL; |
494 | return ok; |
495 | } |
496 | |
497 | |
498 | static void reset_all_loops(void) |
499 | { |
500 | const struct frame *frame; |
501 | struct loop *loop; |
502 | |
503 | for (frame = frames; frame; frame = frame->next) |
504 | for (loop = frame->loops; loop; loop = loop->next) |
505 | loop->iterations = 0; |
506 | } |
507 | |
508 | |
509 | static void reset_found(void) |
510 | { |
511 | struct frame *frame; |
512 | struct table *table; |
513 | struct loop *loop; |
514 | |
515 | for (frame = frames; frame; frame = frame->next) { |
516 | for (table = frame->tables; table; table = table->next) |
517 | table->found_row = NULL; |
518 | for (loop = frame->loops; loop; loop = loop->next) |
519 | loop->found = -1; |
520 | frame->found_ref = NULL; |
521 | } |
522 | } |
523 | |
524 | |
525 | /* |
526 | * Note: we don't use frame->found_ref yet. Instead, we adjust the frame |
527 | * references with activate_item in inst.c |
528 | */ |
529 | |
530 | static void activate_found(void) |
531 | { |
532 | struct frame *frame; |
533 | struct table *table; |
534 | struct loop *loop; |
535 | |
536 | for (frame = frames; frame; frame = frame->next) { |
537 | for (table = frame->tables; table; table = table->next) |
538 | if (table->found_row) |
539 | table->active_row = table->found_row; |
540 | for (loop = frame->loops; loop; loop = loop->next) |
541 | if (loop->found != -1) |
542 | loop->active = loop->found; |
543 | if (frame->found_ref) |
544 | frame->active_ref = frame->found_ref; |
545 | } |
546 | } |
547 | |
548 | |
549 | static int enumerate_frames(void) |
550 | { |
551 | struct frame *frame; |
552 | int n = 0; |
553 | |
554 | for (frame = frames; frame; frame = frame->next) |
555 | frame->n = n++; |
556 | return n; |
557 | } |
558 | |
559 | |
560 | int instantiate(void) |
561 | { |
562 | struct coord zero = { 0, 0 }; |
563 | int n_frames; |
564 | int ok; |
565 | |
566 | meas_start(); |
567 | inst_start(); |
568 | n_frames = enumerate_frames(); |
569 | frame_set = bitset_new(n_frames); |
570 | instantiation_error = NULL; |
571 | reset_all_loops(); |
572 | reset_found(); |
573 | found = 0; |
574 | search_suspended = 0; |
575 | ok = generate_frame(frames, zero, NULL, NULL, 1); |
576 | if (ok && (find_vec || find_obj) && found) |
577 | activate_found(); |
578 | find_vec = NULL; |
579 | find_obj = NULL; |
580 | if (ok) |
581 | ok = link_holes(holes_linked); |
582 | if (ok) |
583 | ok = refine_layers(allow_overlap); |
584 | if (ok) |
585 | ok = instantiate_meas(n_frames); |
586 | if (ok) |
587 | inst_commit(); |
588 | else |
589 | inst_revert(); |
590 | bitset_free(frame_set); |
591 | return ok; |
592 | } |
593 | |
594 | |
595 | /* ----- deallocation ------------------------------------------------------ */ |
596 | |
597 | |
598 | void obj_cleanup(void) |
599 | { |
600 | free(pkg_name); |
601 | while (frames) { |
602 | delete_frame(frames); |
603 | destroy(); |
604 | } |
605 | } |
606 |
Branches:
master