Root/dump.c

1/*
2 * dump.c - Dump objects in the native FPD format
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 <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    default:
387        abort();
388    }
389    return s;
390}
391
392
393/* ----- print measurement ------------------------------------------------- */
394
395
396static const char *meas_type_name[mt_n] = {
397    "meas", "measx", "measy",
398    "meas", "measx", "measy",
399};
400
401
402
403static char *print_meas_base(struct vec *base, const struct frame_qual *qual)
404{
405    const char *name;
406    size_t n;
407    const struct frame_qual *walk;
408    char *s, *p;
409
410    name = base_name(base, NULL);
411    n = strlen(name)+1; /* vec\0 */
412    for (walk = qual; walk; walk = walk->next)
413        n += strlen(walk->frame->name)+1; /* frame/ */
414    if (base->frame != frames)
415        n += strlen(base->frame->name)+1; /* frame. */
416
417    s = p = alloc_size(n);
418    for (walk = qual; walk; walk = walk->next) {
419        n = strlen(walk->frame->name);
420        memcpy(p, walk->frame->name, n);
421        p[n] = '/';
422        p += n+1;
423    }
424    if (base->frame != frames) {
425        n = strlen(base->frame->name);
426        memcpy(p, base->frame->name, n);
427        p[n] = '.';
428        p += n+1;
429    }
430    strcpy(p, name);
431    return s;
432}
433
434
435char *print_meas(const struct obj *obj)
436{
437    char *s, *t;
438    char *s1, *s2, *s3;
439
440    assert(obj->type == ot_meas);
441
442    s = stralloc_printf("%s ", meas_type_name[obj->u.meas.type]);
443    if (obj->u.meas.label) {
444        t = stralloc_printf("%s\"%s\" ", s, obj->u.meas.label);
445        free(s);
446        s = t;
447    }
448    s1 = print_meas_base(obj->base, obj->u.meas.low_qual);
449    s2 = stralloc_printf(" %s ",
450            obj->u.meas.type < 3 ? obj->u.meas.inverted ? "<-" : "->" :
451            obj->u.meas.inverted ? "<<" : ">>");
452    s3 = print_meas_base(obj->u.meas.high, obj->u.meas.high_qual);
453    t = stralloc_printf("%s%s%s%s", s, s1, s2, s3);
454    free(s);
455    free(s1);
456    free(s2);
457    free(s3);
458    s = t;
459
460    if (!obj->u.meas.offset)
461        return s;
462
463    s1 = unparse(obj->u.meas.offset);
464    t = stralloc_printf("%s %s", s, s1);
465    free(s);
466    free(s1);
467    return t;
468}
469
470
471/* ----- print vector ------------------------------------------------------ */
472
473
474const char *print_label(struct vec *vec)
475{
476    if (!vec->name)
477        generate_name(vec);
478    return vec->name;
479}
480
481
482char *print_vec(const struct vec *vec)
483{
484    const char *base;
485    char *x, *y, *s;
486
487    base = base_name(vec->base, vec);
488    x = unparse(vec->x);
489    y = unparse(vec->y);
490    if (vec->name)
491        s = stralloc_printf("vec %s(%s, %s)", base, x, y);
492    else
493        s = stralloc_printf("vec %s(%s, %s)", base, x, y);
494    free(x);
495    free(y);
496    return s;
497}
498
499
500/* ----- frames ------------------------------------------------------------ */
501
502
503static void dump_frame(FILE *file, struct frame *frame, const char *indent)
504{
505    const struct table *table;
506    const struct loop *loop;
507    struct obj *obj;
508    struct order *order;
509    const struct order *item;
510    char *s;
511    const char *s1;
512
513    if (frame->dumped)
514        return;
515    frame->dumped = 1;
516
517    for (obj = frame->objs; obj; obj = obj->next)
518        if (obj->type == ot_frame)
519            dump_frame(file, obj->u.frame.ref, "\t");
520
521    if (frame->name)
522        fprintf(file, "frame %s {\n", frame->name);
523
524    for (table = frame->tables; table; table = table->next)
525        dump_table(file, table, indent);
526    for (loop = frame->loops; loop; loop = loop->next)
527        dump_loop(file, loop, indent);
528
529    order = order_frame(frame);
530    for (item = order; item->vec || item->obj; item++) {
531        if (item->obj) {
532            fprintf(file, "%s", indent);
533            if (item->obj->name)
534                fprintf(file, "%s: ", item->obj->name);
535            s = print_obj(item->obj, item->vec);
536            fprintf(file, "%s\n", s);
537        } else {
538            s1 = print_label(item->vec);
539            s = print_vec(item->vec);
540            fprintf(file, "%s%s: %s\n", indent, s1, s);
541        }
542        free(s);
543    }
544    free(order);
545
546    for (obj = frame->objs; obj; obj = obj->next) {
547        if (obj->dumped)
548            continue;
549        s = print_meas(obj);
550        fprintf(file, "%s%s\n", indent, s);
551        free(s);
552    }
553
554    if (frame->name)
555        fprintf(file, "}\n\n");
556}
557
558
559/* ----- file -------------------------------------------------------------- */
560
561
562static void dump_unit(FILE *file)
563{
564    switch (curr_unit) {
565    case curr_unit_mm:
566        fprintf(file, "unit mm\n");
567        break;
568    case curr_unit_mil:
569        fprintf(file, "unit mil\n");
570        break;
571    case curr_unit_auto:
572        fprintf(file, "unit auto\n");
573        break;
574    default:
575        abort();
576    }
577}
578
579
580static void dump_allow(FILE *file)
581{
582    switch (allow_overlap) {
583    case ao_none:
584        break;
585    case ao_touch:
586        fprintf(file, "allow touch\n");
587        break;
588    case ao_any:
589        fprintf(file, "allow overlap\n");
590        break;
591    default:
592        abort();
593    }
594    if (!holes_linked)
595        fprintf(file, "allow holes\n");
596}
597
598
599static void reverse_frames(FILE *file, struct frame *last)
600{
601    if (last) {
602        reverse_frames(file, last->next);
603        dump_frame(file, last, "\t");
604    }
605}
606
607
608int dump(FILE *file, const char *one)
609{
610    struct frame *frame;
611
612    assert(!one);
613
614    fprintf(file, "%s\n", MACHINE_GENERATED);
615    for (frame = frames; frame; frame = frame->next)
616        frame->dumped = 0;
617
618    reverse_frames(file, frames->next);
619    fprintf(file, "package \"%s\"\n", pkg_name);
620    dump_unit(file);
621    dump_allow(file);
622    fprintf(file, "\n");
623    dump_frame(file, frames, "");
624
625    fflush(file);
626    return !ferror(file);
627}
628

Archive Download this file

Branches:
master



interactive