Root/dump.c

Source at commit 8a1a3103964533b0d517a29312ddeabdab1d6271 created 4 years 11 months ago.
By Werner Almesberger, inst.c (find_point_vec): correct indentation
1/*
2 * dump.c - Dump objects in the native FPD format
3 *
4 * Written 2009-2012, 2014 by Werner Almesberger
5 * Copyright 2009-2012, 2014 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        if (!vec->base || n_vec_refs(vec->base) != 1)
175            recurse_vec(curr, vec);
176}
177
178
179struct order *order_frame(const struct frame *frame)
180{
181    struct order *order, *curr;
182    struct vec *vec;
183    struct obj *obj;
184    int n = 0;
185
186    for (vec = frame->vecs; vec; vec = vec->next)
187        n++;
188    for (obj = frame->objs; obj; obj = obj->next)
189        if (obj->type != ot_meas)
190            n++;
191
192    for (vec = frame->vecs; vec; vec = vec->next)
193        vec->dumped = 0;
194    for (obj = frame->objs; obj; obj = obj->next)
195        obj->dumped = 0;
196
197    order = alloc_size(sizeof(*order)*(n+1));
198    curr = order;
199
200    order_vecs(&curr, frame->vecs);
201
202    /* frames based on @ (anything else ?) */
203    for (obj = frame->objs; obj; obj = obj->next)
204        if (obj->type != ot_meas)
205            put_obj(&curr, obj, NULL);
206
207    assert(curr == order+n);
208    add_item(&curr, NULL, NULL);
209
210    return order;
211}
212
213
214/* ----- variables --------------------------------------------------------- */
215
216
217static void dump_var(FILE *file, const struct table *table,
218    const char *indent)
219{
220    char *s;
221
222    s = unparse(table->rows->values->expr);
223    fprintf(file, "%sset %s%s = %s\n\n", indent,
224        table->vars->key ? "?" : "", table->vars->name, s);
225    free(s);
226}
227
228
229static void dump_table(FILE *file, const struct table *table,
230    const char *indent)
231{
232    const struct var *var;
233    const struct row *row;
234    const struct value *value;
235    char *s;
236
237    if (table->vars && !table->vars->next &&
238        table->rows && !table->rows->next) {
239        dump_var(file, table, indent);
240        return;
241    }
242    fprintf(file, "%stable\n%s {", indent, indent);
243    for (var = table->vars; var; var = var->next)
244        fprintf(file, "%s %s%s", var == table->vars ? "" : ",",
245            var->key ? "?" : "", var->name);
246    fprintf(file, " }\n");
247    for (row = table->rows; row; row = row->next) {
248        fprintf(file, "%s {", indent);
249        for (value = row->values; value; value = value->next) {
250            s = unparse(value->expr);
251            fprintf(file, "%s %s",
252                value == row->values? "" : ",", s);
253            free(s);
254        }
255        fprintf(file, " }\n");
256    }
257    fprintf(file, "\n");
258}
259
260
261static void dump_loop(FILE *file, const struct loop *loop, const char *indent)
262{
263    char *from, *to;
264
265    from = unparse(loop->from.expr);
266    to = unparse(loop->to.expr);
267    fprintf(file, "%sloop %s = %s, %s\n\n",
268        indent, loop->var.name, from, to);
269    free(from);
270    free(to);
271}
272
273
274/* ----- vectors and objects ----------------------------------------------- */
275
276
277static void generate_name(struct vec *base)
278{
279    char tmp[10]; /* plenty */
280    const char *s;
281    struct vec *walk;
282    int n = 0;
283
284    while (1) {
285        sprintf(tmp, "__%d", n);
286        s = unique(tmp);
287        for (walk = base->frame->vecs; walk; walk = walk->next)
288            if (walk->name == s)
289                break;
290        if (!walk)
291            break;
292        n++;
293    }
294    base->name = s;
295}
296
297
298static const char *base_name(struct vec *base, const struct vec *next)
299{
300    const char *name = (const char *) base;
301
302    if (!base)
303        return "@";
304    if (*name)
305        return name;
306    if (next && base->next == next)
307        return ".";
308    if (!base->name)
309        generate_name(base);
310    return base->name;
311}
312
313
314static const char *obj_base_name(struct vec *base, const struct vec *prev)
315{
316    if (base && base == prev)
317        return ".";
318    return base_name(base, NULL);
319}
320
321
322char *print_obj(const struct obj *obj, const struct vec *prev)
323{
324    const char *base, *s1, *s3;
325    char *s, *s2;
326
327    base = obj_base_name(obj->base, prev);
328    switch (obj->type) {
329    case ot_frame:
330        s = stralloc_printf("frame %s %s",
331            obj->u.frame.ref->name, base);
332        break;
333    case ot_line:
334        s1 = obj_base_name(obj->u.line.other, prev);
335        s2 = unparse(obj->u.line.width);
336        s = stralloc_printf("line %s %s %s", base, s1, s2);
337        free(s2);
338        break;
339    case ot_rect:
340        s1 = obj_base_name(obj->u.rect.other, prev);
341        s2 = unparse(obj->u.rect.width);
342        s = stralloc_printf("rect %s %s %s", base, s1, s2);
343        free(s2);
344        break;
345    case ot_pad:
346        s1 = obj_base_name(obj->u.pad.other, prev);
347        switch (obj->u.pad.type) {
348        case pt_normal:
349            s2 = "";
350            break;
351        case pt_bare:
352            s2 = " bare";
353            break;
354        case pt_trace:
355            s2 = " trace";
356            break;
357        case pt_paste:
358            s2 = " paste";
359            break;
360        case pt_mask:
361            s2 = " mask";
362            break;
363        default:
364            abort();
365        }
366        s = stralloc_printf("%spad \"%s\" %s %s%s",
367            obj->u.pad.rounded ? "r" : "",
368            obj->u.pad.name, base, s1, s2);
369        break;
370    case ot_hole:
371        s1 = obj_base_name(obj->u.hole.other, prev);
372        s = stralloc_printf("hole %s %s", base, s1);
373        break;
374    case ot_arc:
375        s1 = obj_base_name(obj->u.arc.start, prev);
376        s2 = unparse(obj->u.arc.width);
377        if (obj->u.arc.start == obj->u.arc.end) {
378            s = stralloc_printf("circ %s %s %s", base, s1, s2);
379        } else {
380            s3 = obj_base_name(obj->u.arc.end, prev);
381            s = stralloc_printf("arc %s %s %s %s",
382                base, s1, s3, s2);
383        }
384        free(s2);
385        break;
386    case ot_iprint:
387        s2 = unparse(obj->u.iprint.expr);
388        s = stralloc_printf("%%iprint %s", s2);
389        free(s2);
390        break;
391    default:
392        abort();
393    }
394    return s;
395}
396
397
398/* ----- print measurement ------------------------------------------------- */
399
400
401static const char *meas_type_name[mt_n] = {
402    "meas", "measx", "measy",
403    "meas", "measx", "measy",
404};
405
406
407
408static char *print_meas_base(struct vec *base, const struct frame_qual *qual)
409{
410    const char *name;
411    size_t n;
412    const struct frame_qual *walk;
413    char *s, *p;
414
415    name = base_name(base, NULL);
416    n = strlen(name)+1; /* vec\0 */
417    for (walk = qual; walk; walk = walk->next)
418        n += strlen(walk->frame->name)+1; /* frame/ */
419    if (base->frame != frames)
420        n += strlen(base->frame->name)+1; /* frame. */
421
422    s = p = alloc_size(n);
423    for (walk = qual; walk; walk = walk->next) {
424        n = strlen(walk->frame->name);
425        memcpy(p, walk->frame->name, n);
426        p[n] = '/';
427        p += n+1;
428    }
429    if (base->frame != frames) {
430        n = strlen(base->frame->name);
431        memcpy(p, base->frame->name, n);
432        p[n] = '.';
433        p += n+1;
434    }
435    strcpy(p, name);
436    return s;
437}
438
439
440char *print_meas(const struct obj *obj)
441{
442    char *s, *t;
443    char *s1, *s2, *s3;
444
445    assert(obj->type == ot_meas);
446
447    s = stralloc_printf("%s ", meas_type_name[obj->u.meas.type]);
448    if (obj->u.meas.label) {
449        t = stralloc_printf("%s\"%s\" ", s, obj->u.meas.label);
450        free(s);
451        s = t;
452    }
453    s1 = print_meas_base(obj->base, obj->u.meas.low_qual);
454    s2 = stralloc_printf(" %s ",
455            obj->u.meas.type < 3 ? obj->u.meas.inverted ? "<-" : "->" :
456            obj->u.meas.inverted ? "<<" : ">>");
457    s3 = print_meas_base(obj->u.meas.high, obj->u.meas.high_qual);
458    t = stralloc_printf("%s%s%s%s", s, s1, s2, s3);
459    free(s);
460    free(s1);
461    free(s2);
462    free(s3);
463    s = t;
464
465    if (!obj->u.meas.offset)
466        return s;
467
468    s1 = unparse(obj->u.meas.offset);
469    t = stralloc_printf("%s %s", s, s1);
470    free(s);
471    free(s1);
472    return t;
473}
474
475
476/* ----- print vector ------------------------------------------------------ */
477
478
479const char *print_label(struct vec *vec)
480{
481    if (!vec->name)
482        generate_name(vec);
483    return vec->name;
484}
485
486
487char *print_vec(const struct vec *vec)
488{
489    const char *base;
490    char *x, *y, *s;
491
492    base = base_name(vec->base, vec);
493    x = unparse(vec->x);
494    y = unparse(vec->y);
495    if (vec->name)
496        s = stralloc_printf("vec %s(%s, %s)", base, x, y);
497    else
498        s = stralloc_printf("vec %s(%s, %s)", base, x, y);
499    free(x);
500    free(y);
501    return s;
502}
503
504
505/* ----- frames ------------------------------------------------------------ */
506
507
508static void dump_frame(FILE *file, struct frame *frame, const char *indent)
509{
510    const struct table *table;
511    const struct loop *loop;
512    struct obj *obj;
513    struct order *order;
514    const struct order *item;
515    char *s;
516    const char *s1;
517
518    if (frame->dumped)
519        return;
520    frame->dumped = 1;
521
522    for (obj = frame->objs; obj; obj = obj->next)
523        if (obj->type == ot_frame)
524            dump_frame(file, obj->u.frame.ref, "\t");
525
526    if (frame->name)
527        fprintf(file, "frame %s {\n", frame->name);
528
529    for (table = frame->tables; table; table = table->next)
530        dump_table(file, table, indent);
531    for (loop = frame->loops; loop; loop = loop->next)
532        dump_loop(file, loop, indent);
533
534    order = order_frame(frame);
535    for (item = order; item->vec || item->obj; item++) {
536        if (item->obj) {
537            fprintf(file, "%s", indent);
538            if (item->obj->name)
539                fprintf(file, "%s: ", item->obj->name);
540            s = print_obj(item->obj, item->vec);
541            fprintf(file, "%s\n", s);
542        } else {
543            s1 = print_label(item->vec);
544            s = print_vec(item->vec);
545            fprintf(file, "%s%s: %s\n", indent, s1, s);
546        }
547        free(s);
548    }
549    free(order);
550
551    for (obj = frame->objs; obj; obj = obj->next) {
552        if (obj->dumped)
553            continue;
554        s = print_meas(obj);
555        fprintf(file, "%s%s\n", indent, s);
556        free(s);
557    }
558
559    if (frame->name)
560        fprintf(file, "}\n\n");
561}
562
563
564/* ----- file -------------------------------------------------------------- */
565
566
567static void dump_unit(FILE *file)
568{
569    switch (curr_unit) {
570    case curr_unit_mm:
571        fprintf(file, "unit mm\n");
572        break;
573    case curr_unit_mil:
574        fprintf(file, "unit mil\n");
575        break;
576    case curr_unit_auto:
577        fprintf(file, "unit auto\n");
578        break;
579    default:
580        abort();
581    }
582}
583
584
585static void dump_allow(FILE *file)
586{
587    switch (allow_overlap) {
588    case ao_none:
589        break;
590    case ao_touch:
591        fprintf(file, "allow touch\n");
592        break;
593    case ao_any:
594        fprintf(file, "allow overlap\n");
595        break;
596    default:
597        abort();
598    }
599    if (!holes_linked)
600        fprintf(file, "allow holes\n");
601}
602
603
604static void reverse_frames(FILE *file, struct frame *last)
605{
606    if (last) {
607        reverse_frames(file, last->next);
608        dump_frame(file, last, "\t");
609    }
610}
611
612
613int dump(FILE *file, const char *one)
614{
615    struct frame *frame;
616
617    assert(!one);
618
619    fprintf(file, "%s\n", MACHINE_GENERATED);
620    for (frame = frames; frame; frame = frame->next)
621        frame->dumped = 0;
622
623    reverse_frames(file, frames->next);
624    fprintf(file, "package \"%s\"\n", pkg_name);
625    dump_unit(file);
626    dump_allow(file);
627    fprintf(file, "\n");
628    dump_frame(file, frames, "");
629
630    fflush(file);
631    return !ferror(file);
632}
633

Archive Download this file

Branches:
master



interactive