Root/dump.c

Source at commit ad2c07f49c326140a0839e6453fb68bb48745781 created 4 years 6 months ago.
By Werner Almesberger, dump.c (order_vecs): don't trip over vectors with deferred resolution
1/*
2 * dump.c - Dump objects in the native FPD format
3 *
4 * Written 2009-2012, 2014-2015 by Werner Almesberger
5 * Copyright 2009-2012, 2014-2015 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 <stdio.h>
16#include <string.h>
17#include <assert.h>
18#include <sys/types.h>
19
20#include "util.h"
21#include "unparse.h"
22#include "obj.h"
23#include "gui_status.h"
24#include "dump.h"
25
26
27/* ----- order items ------------------------------------------------------- */
28
29
30static void add_item(struct order **curr, struct vec *vec, struct obj *obj)
31{
32    (*curr)->vec = vec;
33    (*curr)->obj = obj;
34    (*curr)++;
35}
36
37
38static int n_vec_refs(const struct vec *vec)
39{
40    const struct vec *walk;
41    int n;
42
43    n = 0;
44    for (walk = vec->frame->vecs; walk; walk = walk->next)
45        if (walk->base == vec)
46            n++;
47    return n;
48}
49
50
51/*
52 * If "prev" is non-NULL, we're looking for objects that need to be put after
53 * the current vector (in "prev"). Only those objects need to be put there
54 * that have at least one base that isn't the frame's origin.
55 *
56 * We could also make an exception for manually named vectors, but we get
57 * better clustering without.
58 */
59
60static int need(const struct vec *base, const struct vec *prev)
61{
62    if (!base)
63        return 0;
64#if 0
65    if (base->name && *base->name != '_')
66        return 0;
67#endif
68    if (prev)
69        return base == prev;
70    return 1;
71}
72
73
74/*
75 * If we need a vector that's defined later, we have to defer dumping the
76 * object.
77 */
78
79static int later(const struct vec *base, const struct vec *prev)
80{
81    return base && !base->dumped;
82#if 0
83    while (1) {
84        prev = prev->next;
85        if (!prev)
86            break;
87        if (base == prev)
88            return 1;
89    }
90    return 0;
91#endif
92}
93
94
95static int may_put_obj_now(const struct obj *obj, const struct vec *prev)
96{
97    int n, l;
98
99    n = need(obj->base, prev);
100    l = later(obj->base, prev);
101
102    switch (obj->type) {
103    case ot_frame:
104        break;
105    case ot_line:
106        n |= need(obj->u.line.other, prev);
107        l |= later(obj->u.line.other, prev);
108        break;
109    case ot_rect:
110        n |= need(obj->u.rect.other, prev);
111        l |= later(obj->u.rect.other, prev);
112        break;
113    case ot_pad:
114        n |= need(obj->u.pad.other, prev);
115        l |= later(obj->u.pad.other, prev);
116        break;
117    case ot_hole:
118        n |= need(obj->u.hole.other, prev);
119        l |= later(obj->u.hole.other, prev);
120        break;
121    case ot_arc:
122        n |= need(obj->u.arc.start, prev);
123        n |= need(obj->u.arc.end, prev);
124        l |= later(obj->u.arc.start, prev);
125        l |= later(obj->u.arc.end, prev);
126        break;
127    case ot_meas:
128        return 0;
129    default:
130        abort();
131    }
132
133    return n && !l;
134}
135
136
137static void put_obj(struct order **curr, struct obj *obj,
138    struct vec *prev)
139{
140    if (obj->dumped)
141        return;
142    obj->dumped = 1;
143    add_item(curr, prev, obj);
144}
145
146/*
147 * Tricky logic ahead: when dumping a vector, we search for a vector that
148 * depends on that vector for ".". If we find one, we dump it immediately after
149 * this vector.
150 */
151
152static void recurse_vec(struct order **curr, struct vec *vec)
153{
154    struct vec *next;
155    struct obj *obj;
156
157    vec->dumped = 1;
158    add_item(curr, vec, NULL);
159    for (obj = vec->frame->objs; obj; obj = obj->next)
160        if (may_put_obj_now(obj, vec))
161            put_obj(curr, obj, vec);
162    if (n_vec_refs(vec) == 1) {
163        for (next = vec->next; next->base != vec; next = next->next);
164        recurse_vec(curr, next);
165    }
166}
167
168
169static void order_vecs(struct order **curr, struct vec *vecs)
170{
171    struct vec *vec;
172
173    for (vec = vecs; vec; vec = vec->next) {
174        const char *name = (const char *) vec->base;
175
176        if (!vec->base || *name || n_vec_refs(vec->base) != 1)
177            recurse_vec(curr, vec);
178    }
179}
180
181
182struct order *order_frame(const struct frame *frame)
183{
184    struct order *order, *curr;
185    struct vec *vec;
186    struct obj *obj;
187    int n = 0;
188
189    for (vec = frame->vecs; vec; vec = vec->next)
190        n++;
191    for (obj = frame->objs; obj; obj = obj->next)
192        if (obj->type != ot_meas)
193            n++;
194
195    for (vec = frame->vecs; vec; vec = vec->next)
196        vec->dumped = 0;
197    for (obj = frame->objs; obj; obj = obj->next)
198        obj->dumped = 0;
199
200    order = alloc_size(sizeof(*order)*(n+1));
201    curr = order;
202
203    order_vecs(&curr, frame->vecs);
204
205    /* frames based on @ (anything else ?) */
206    for (obj = frame->objs; obj; obj = obj->next)
207        if (obj->type != ot_meas)
208            put_obj(&curr, obj, NULL);
209
210    assert(curr == order+n);
211    add_item(&curr, NULL, NULL);
212
213    return order;
214}
215
216
217/* ----- variables --------------------------------------------------------- */
218
219
220static void dump_var(FILE *file, const struct table *table,
221    const char *indent)
222{
223    char *s;
224
225    s = unparse(table->rows->values->expr);
226    fprintf(file, "%sset %s%s = %s\n\n", indent,
227        table->vars->key ? "?" : "", table->vars->name, s);
228    free(s);
229}
230
231
232static void dump_table(FILE *file, const struct table *table,
233    const char *indent)
234{
235    const struct var *var;
236    const struct row *row;
237    const struct value *value;
238    char *s;
239
240    if (table->vars && !table->vars->next &&
241        table->rows && !table->rows->next) {
242        dump_var(file, table, indent);
243        return;
244    }
245    fprintf(file, "%stable\n%s {", indent, indent);
246    for (var = table->vars; var; var = var->next)
247        fprintf(file, "%s %s%s", var == table->vars ? "" : ",",
248            var->key ? "?" : "", var->name);
249    fprintf(file, " }\n");
250    for (row = table->rows; row; row = row->next) {
251        fprintf(file, "%s {", indent);
252        for (value = row->values; value; value = value->next) {
253            s = unparse(value->expr);
254            fprintf(file, "%s %s",
255                value == row->values? "" : ",", s);
256            free(s);
257        }
258        fprintf(file, " }\n");
259    }
260    fprintf(file, "\n");
261}
262
263
264static void dump_loop(FILE *file, const struct loop *loop, const char *indent)
265{
266    char *from, *to;
267
268    from = unparse(loop->from.expr);
269    to = unparse(loop->to.expr);
270    fprintf(file, "%sloop %s = %s, %s\n\n",
271        indent, loop->var.name, from, to);
272    free(from);
273    free(to);
274}
275
276
277/* ----- vectors and objects ----------------------------------------------- */
278
279
280static void generate_name(struct vec *base)
281{
282    char tmp[10]; /* plenty */
283    const char *s;
284    struct vec *walk;
285    int n = 0;
286
287    while (1) {
288        sprintf(tmp, "__%d", n);
289        s = unique(tmp);
290        for (walk = base->frame->vecs; walk; walk = walk->next)
291            if (walk->name == s)
292                break;
293        if (!walk)
294            break;
295        n++;
296    }
297    base->name = s;
298}
299
300
301static const char *base_name(struct vec *base, const struct vec *next)
302{
303    const char *name = (const char *) base;
304
305    if (!base)
306        return "@";
307    if (*name)
308        return name;
309    if (next && base->next == next)
310        return ".";
311    if (!base->name)
312        generate_name(base);
313    return base->name;
314}
315
316
317static const char *obj_base_name(struct vec *base, const struct vec *prev)
318{
319    if (base && base == prev)
320        return ".";
321    return base_name(base, NULL);
322}
323
324
325char *print_obj(const struct obj *obj, const struct vec *prev)
326{
327    const char *base, *s1, *s3;
328    char *s, *s2;
329
330    base = obj_base_name(obj->base, prev);
331    switch (obj->type) {
332    case ot_frame:
333        s = stralloc_printf("frame %s %s",
334            obj->u.frame.ref->name, base);
335        break;
336    case ot_line:
337        s1 = obj_base_name(obj->u.line.other, prev);
338        s2 = unparse(obj->u.line.width);
339        s = stralloc_printf("line %s %s %s", base, s1, s2);
340        free(s2);
341        break;
342    case ot_rect:
343        s1 = obj_base_name(obj->u.rect.other, prev);
344        s2 = unparse(obj->u.rect.width);
345        s = stralloc_printf("rect %s %s %s", base, s1, s2);
346        free(s2);
347        break;
348    case ot_pad:
349        s1 = obj_base_name(obj->u.pad.other, prev);
350        switch (obj->u.pad.type) {
351        case pt_normal:
352            s2 = "";
353            break;
354        case pt_bare:
355            s2 = " bare";
356            break;
357        case pt_trace:
358            s2 = " trace";
359            break;
360        case pt_paste:
361            s2 = " paste";
362            break;
363        case pt_mask:
364            s2 = " mask";
365            break;
366        default:
367            abort();
368        }
369        s = stralloc_printf("%spad \"%s\" %s %s%s",
370            obj->u.pad.rounded ? "r" : "",
371            obj->u.pad.name, base, s1, s2);
372        break;
373    case ot_hole:
374        s1 = obj_base_name(obj->u.hole.other, prev);
375        s = stralloc_printf("hole %s %s", base, s1);
376        break;
377    case ot_arc:
378        s1 = obj_base_name(obj->u.arc.start, prev);
379        s2 = unparse(obj->u.arc.width);
380        if (obj->u.arc.start == obj->u.arc.end) {
381            s = stralloc_printf("circ %s %s %s", base, s1, s2);
382        } else {
383            s3 = obj_base_name(obj->u.arc.end, prev);
384            s = stralloc_printf("arc %s %s %s %s",
385                base, s1, s3, s2);
386        }
387        free(s2);
388        break;
389    case ot_iprint:
390        s2 = unparse(obj->u.iprint.expr);
391        s = stralloc_printf("%%iprint %s", s2);
392        free(s2);
393        break;
394    default:
395        abort();
396    }
397    return s;
398}
399
400
401/* ----- print measurement ------------------------------------------------- */
402
403
404static const char *meas_type_name[mt_n] = {
405    "meas", "measx", "measy",
406    "meas", "measx", "measy",
407};
408
409
410
411static char *print_meas_base(struct vec *base, const struct frame_qual *qual)
412{
413    const char *name;
414    size_t n;
415    const struct frame_qual *walk;
416    char *s, *p;
417
418    name = base_name(base, NULL);
419    n = strlen(name)+1; /* vec\0 */
420    for (walk = qual; walk; walk = walk->next)
421        n += strlen(walk->frame->name)+1; /* frame/ */
422    if (base->frame != frames)
423        n += strlen(base->frame->name)+1; /* frame. */
424
425    s = p = alloc_size(n);
426    for (walk = qual; walk; walk = walk->next) {
427        n = strlen(walk->frame->name);
428        memcpy(p, walk->frame->name, n);
429        p[n] = '/';
430        p += n+1;
431    }
432    if (base->frame != frames) {
433        n = strlen(base->frame->name);
434        memcpy(p, base->frame->name, n);
435        p[n] = '.';
436        p += n+1;
437    }
438    strcpy(p, name);
439    return s;
440}
441
442
443char *print_meas(const struct obj *obj)
444{
445    char *s, *t;
446    char *s1, *s2, *s3;
447
448    assert(obj->type == ot_meas);
449
450    s = stralloc_printf("%s ", meas_type_name[obj->u.meas.type]);
451    if (obj->u.meas.label) {
452        t = stralloc_printf("%s\"%s\" ", s, obj->u.meas.label);
453        free(s);
454        s = t;
455    }
456    s1 = print_meas_base(obj->base, obj->u.meas.low_qual);
457    s2 = stralloc_printf(" %s ",
458            obj->u.meas.type < 3 ? obj->u.meas.inverted ? "<-" : "->" :
459            obj->u.meas.inverted ? "<<" : ">>");
460    s3 = print_meas_base(obj->u.meas.high, obj->u.meas.high_qual);
461    t = stralloc_printf("%s%s%s%s", s, s1, s2, s3);
462    free(s);
463    free(s1);
464    free(s2);
465    free(s3);
466    s = t;
467
468    if (!obj->u.meas.offset)
469        return s;
470
471    s1 = unparse(obj->u.meas.offset);
472    t = stralloc_printf("%s %s", s, s1);
473    free(s);
474    free(s1);
475    return t;
476}
477
478
479/* ----- print vector ------------------------------------------------------ */
480
481
482const char *print_label(struct vec *vec)
483{
484    if (!vec->name)
485        generate_name(vec);
486    return vec->name;
487}
488
489
490char *print_vec(const struct vec *vec)
491{
492    const char *base;
493    char *x, *y, *s;
494
495    base = base_name(vec->base, vec);
496    x = unparse(vec->x);
497    y = unparse(vec->y);
498    if (vec->name)
499        s = stralloc_printf("vec %s(%s, %s)", base, x, y);
500    else
501        s = stralloc_printf("vec %s(%s, %s)", base, x, y);
502    free(x);
503    free(y);
504    return s;
505}
506
507
508/* ----- frames ------------------------------------------------------------ */
509
510
511static void dump_frame(FILE *file, struct frame *frame, const char *indent)
512{
513    const struct table *table;
514    const struct loop *loop;
515    struct obj *obj;
516    struct order *order;
517    const struct order *item;
518    char *s;
519    const char *s1;
520
521    if (frame->dumped)
522        return;
523    frame->dumped = 1;
524
525    for (obj = frame->objs; obj; obj = obj->next)
526        if (obj->type == ot_frame)
527            dump_frame(file, obj->u.frame.ref, "\t");
528
529    if (frame->name)
530        fprintf(file, "frame %s {\n", frame->name);
531
532    for (table = frame->tables; table; table = table->next)
533        dump_table(file, table, indent);
534    for (loop = frame->loops; loop; loop = loop->next)
535        dump_loop(file, loop, indent);
536
537    order = order_frame(frame);
538    for (item = order; item->vec || item->obj; item++) {
539        if (item->obj) {
540            fprintf(file, "%s", indent);
541            if (item->obj->name)
542                fprintf(file, "%s: ", item->obj->name);
543            s = print_obj(item->obj, item->vec);
544            fprintf(file, "%s\n", s);
545        } else {
546            s1 = print_label(item->vec);
547            s = print_vec(item->vec);
548            fprintf(file, "%s%s: %s\n", indent, s1, s);
549        }
550        free(s);
551    }
552    free(order);
553
554    for (obj = frame->objs; obj; obj = obj->next) {
555        if (obj->dumped)
556            continue;
557        s = print_meas(obj);
558        fprintf(file, "%s%s\n", indent, s);
559        free(s);
560    }
561
562    if (frame->name)
563        fprintf(file, "}\n\n");
564}
565
566
567/* ----- file -------------------------------------------------------------- */
568
569
570static void dump_unit(FILE *file)
571{
572    switch (curr_unit) {
573    case curr_unit_mm:
574        fprintf(file, "unit mm\n");
575        break;
576    case curr_unit_mil:
577        fprintf(file, "unit mil\n");
578        break;
579    case curr_unit_auto:
580        fprintf(file, "unit auto\n");
581        break;
582    default:
583        abort();
584    }
585}
586
587
588static void dump_allow(FILE *file)
589{
590    switch (allow_overlap) {
591    case ao_none:
592        break;
593    case ao_touch:
594        fprintf(file, "allow touch\n");
595        break;
596    case ao_any:
597        fprintf(file, "allow overlap\n");
598        break;
599    default:
600        abort();
601    }
602    if (!holes_linked)
603        fprintf(file, "allow holes\n");
604}
605
606
607static void reverse_frames(FILE *file, struct frame *last)
608{
609    if (last) {
610        reverse_frames(file, last->next);
611        dump_frame(file, last, "\t");
612    }
613}
614
615
616int dump(FILE *file, const char *one)
617{
618    struct frame *frame;
619
620    assert(!one);
621
622    fprintf(file, "%s\n", MACHINE_GENERATED);
623    for (frame = frames; frame; frame = frame->next)
624        frame->dumped = 0;
625
626    reverse_frames(file, frames->next);
627    fprintf(file, "package \"%s\"\n", pkg_name);
628    dump_unit(file);
629    dump_allow(file);
630    fprintf(file, "\n");
631    dump_frame(file, frames, "");
632
633    fflush(file);
634    return !ferror(file);
635}
636

Archive Download this file

Branches:
master



interactive