Root/obj.c

Source at commit a9ed5b30aa457704a4c0c912367bfe8c57db8d03 created 3 years 8 months ago.
By Werner Almesberger, fped.1: update for new options; fix typo; bump date
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
38char *pkg_name = NULL;
39struct frame *frames = NULL;
40struct frame *active_frame = NULL;
41void *instantiation_error = NULL;
42enum allow_overlap allow_overlap = ao_none;
43int holes_linked = 1;
44
45
46static 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
57static int found = 0;
58static int search_suspended = 0;
59static const struct vec *find_vec = NULL;
60static const struct obj *find_obj = NULL;
61static struct coord find_pos;
62
63
64static void suspend_search(void)
65{
66    search_suspended++;
67}
68
69static void resume_search(void)
70{
71    assert(search_suspended > 0);
72    search_suspended--;
73}
74
75
76static struct coord get_pos(const struct inst *inst)
77{
78    return inst->obj ? inst->base : inst->u.vec.end;
79}
80
81
82void 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
99void 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
110int 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
146static int generate_frame(struct frame *frame, struct coord base,
147    const struct frame *parent, struct obj *frame_ref, int active);
148
149
150struct 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
163static 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
173static 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
189static 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
209static 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
233error:
234    instantiation_error = vec;
235    return 0;
236}
237
238
239static 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
330error:
331    instantiation_error = obj;
332    return 0;
333}
334
335
336static 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
354static 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
378static 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
446fail:
447    loop->initialized = 0;
448    return 0;
449}
450
451
452static 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
477static 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
498static 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
509static 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
530static 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
549static 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
560int 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
598void obj_cleanup(void)
599{
600    free(pkg_name);
601    while (frames) {
602        delete_frame(frames);
603        destroy();
604    }
605}
606

Archive Download this file

Branches:
master



interactive