Root/delete.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 * delete.c - Object deletion
3 *
4 * Written 2009, 2010, 2012 by Werner Almesberger
5 * Copyright 2009, 2010, 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 <assert.h>
16
17#include "util.h"
18#include "error.h"
19#include "expr.h"
20#include "obj.h"
21#include "delete.h"
22
23
24static struct deletion {
25    enum del_type {
26        dt_vec,
27        dt_obj,
28        dt_frame,
29        dt_table,
30        dt_row,
31        dt_column,
32        dt_loop,
33    } type;
34    union {
35        struct {
36            struct frame *ref;
37            struct frame *prev;
38        } frame;
39        struct {
40            struct vec *ref;
41            struct vec *prev;
42        } vec;
43        struct {
44            struct obj *ref;
45            struct obj *prev;
46        } obj;
47        struct {
48            struct table *ref;
49            struct table *prev;
50        } table;
51        struct {
52            struct row *ref;
53            struct row *prev;
54        } row;
55        struct column {
56            struct var *var;
57            struct value *values;
58            struct table *table;
59            int n;
60        } col;
61        struct {
62            struct loop *ref;
63            struct loop *prev;
64        } loop;
65    } u;
66    int group;
67    struct deletion *next;
68} *deletions = NULL;
69
70static int groups = 0;
71
72
73static void do_delete_vec(struct vec *vec);
74static void do_delete_obj(struct obj *obj);
75
76
77/* ----- helper functions -------------------------------------------------- */
78
79
80static struct deletion *new_deletion(enum del_type type)
81{
82    struct deletion *del;
83
84    del = alloc_type(struct deletion);
85    del->type = type;
86    del->group = groups;
87    del->next = deletions;
88    deletions = del;
89    return del;
90}
91
92
93static void reset_active_ref(struct frame *ref)
94{
95    const struct frame *frame;
96    struct obj *obj = NULL;
97
98    for (frame = frames; frame; frame = frame->next)
99        for (obj = frame->objs; obj; obj = obj->next)
100            if (obj->type == ot_frame && obj->u.frame.ref == ref)
101                break;
102    ref->active_ref = obj;
103}
104
105
106/* ----- vectors ----------------------------------------------------------- */
107
108
109static void destroy_vec(struct vec *vec)
110{
111    free_expr(vec->x);
112    free_expr(vec->y);
113    free(vec);
114}
115
116
117static void delete_vecs_by_ref(struct vec *vecs, const struct vec *ref)
118{
119    while (vecs) {
120        if (vecs->base == ref)
121            do_delete_vec(vecs);
122        vecs = vecs->next;
123    }
124}
125
126
127static int obj_has_ref(const struct obj *obj, const struct vec *ref)
128{
129    if (obj->base == ref)
130        return 1;
131    switch (obj->type) {
132    case ot_frame:
133        return 0;
134    case ot_line:
135        return obj->u.line.other == ref;
136    case ot_rect:
137        return obj->u.rect.other == ref;
138    case ot_pad:
139        return obj->u.pad.other == ref;
140    case ot_hole:
141        return obj->u.hole.other == ref;
142    case ot_arc:
143        return obj->u.arc.start == ref || obj->u.arc.end == ref;
144    case ot_meas:
145        return obj->u.meas.high == ref;
146    case ot_iprint:
147        return 0;
148    default:
149        abort();
150    }
151}
152
153
154static void delete_objs_by_ref(struct obj **objs, const struct vec *ref)
155{
156    struct obj *obj;
157
158    for (obj = *objs; obj; obj = obj->next)
159        if (obj_has_ref(obj, ref))
160            do_delete_obj(obj);
161}
162
163
164static void do_delete_vec(struct vec *vec)
165{
166    struct vec *walk, *prev;
167    struct deletion *del;
168
169    prev = NULL;
170    for (walk = vec->frame->vecs; walk != vec; walk = walk->next)
171        prev = walk;
172    if (prev)
173        prev->next = vec->next;
174    else
175        vec->frame->vecs = vec->next;
176    del = new_deletion(dt_vec);
177    del->u.vec.ref = vec;
178    del->u.vec.prev = prev;
179
180    delete_vecs_by_ref(vec->frame->vecs, vec);
181    delete_objs_by_ref(&vec->frame->objs, vec);
182    /*
183     * Catch measurements. During final cleanup, we may operate on an empty
184     * list of frames, hence the test.
185     */
186    if (frames)
187        delete_objs_by_ref(&frames->objs, vec);
188}
189
190
191void delete_vec(struct vec *vec)
192{
193    groups++;
194    do_delete_vec(vec);
195}
196
197
198static void undelete_vec(struct vec *vec, struct vec *prev)
199{
200    if (prev) {
201        assert(vec->next == prev->next);
202        prev->next = vec;
203    } else {
204        assert(vec->next == vec->frame->vecs);
205        vec->frame->vecs = vec;
206    }
207}
208
209
210/* ----- objects ----------------------------------------------------------- */
211
212
213static void destroy_obj(struct obj *obj)
214{
215    switch (obj->type) {
216    case ot_frame:
217        if (obj->u.frame.ref->active_ref == obj)
218            reset_active_ref(obj->u.frame.ref);
219        break;
220    case ot_pad:
221        free(obj->u.pad.name);
222        break;
223    case ot_hole:
224        break;
225    case ot_line:
226        if (obj->u.line.width)
227            free_expr(obj->u.line.width);
228        break;
229    case ot_rect:
230        if (obj->u.rect.width)
231            free_expr(obj->u.rect.width);
232        break;
233    case ot_arc:
234        if (obj->u.arc.width)
235            free_expr(obj->u.arc.width);
236        break;
237    case ot_meas:
238        if (obj->u.meas.label)
239            free(obj->u.meas.label);
240        if (obj->u.meas.offset)
241            free_expr(obj->u.meas.offset);
242        break;
243    case ot_iprint:
244        free_expr(obj->u.iprint.expr);
245        break;
246    default:
247        abort();
248    }
249    free(obj);
250}
251
252
253static void do_delete_obj(struct obj *obj)
254{
255    struct obj *walk, *prev;
256    struct deletion *del;
257
258    prev = NULL;
259    for (walk = obj->frame->objs; walk != obj; walk = walk->next)
260        prev = walk;
261    if (prev)
262        prev->next = obj->next;
263    else
264        obj->frame->objs = obj->next;
265    del = new_deletion(dt_obj);
266    del->u.obj.ref = obj;
267    del->u.obj.prev = prev;
268    if (obj->type == ot_frame && obj->u.frame.ref->active_ref == obj)
269        reset_active_ref(obj->u.frame.ref);
270}
271
272
273void delete_obj(struct obj *obj)
274{
275    groups++;
276    do_delete_obj(obj);
277}
278
279
280static void undelete_obj(struct obj *obj, struct obj *prev)
281{
282    if (prev) {
283        assert(obj->next == prev->next);
284        prev->next = obj;
285    } else {
286        assert(obj->next == obj->frame->objs);
287        obj->frame->objs = obj;
288    }
289}
290
291
292
293/* ----- rows -------------------------------------------------------------- */
294
295
296static void destroy_row(struct row *row)
297{
298    struct value *next_value;
299
300    while (row->values) {
301        next_value = row->values->next;
302        free_expr(row->values->expr);
303        free(row->values);
304        row->values = next_value;
305    }
306    free(row);
307}
308
309
310void delete_row(struct row *row)
311{
312    struct deletion *del;
313    struct row *walk, *prev;
314
315    groups++;
316    prev = NULL;
317    for (walk = row->table->rows; walk != row; walk = walk->next)
318        prev = walk;
319    if (prev)
320        prev->next = row->next;
321    else
322        row->table->rows = row->next;
323    del = new_deletion(dt_row);
324    del->u.row.ref = row;
325    del->u.row.prev = prev;
326}
327
328
329static void undelete_row(struct row *row, struct row *prev)
330{
331    if (prev) {
332        assert(row->next == prev->next);
333        prev->next = row;
334    } else {
335        assert(row->next == row->table->rows);
336        row->table->rows = row;
337    }
338}
339
340
341/* ----- columns ----------------------------------------------------------- */
342
343
344void delete_column(struct table *table, int n)
345{
346    struct deletion *del;
347    struct column *col;
348    struct var **var;
349    struct row *row;
350    struct value **next, **value;
351    int i;
352
353    groups++;
354
355    del = new_deletion(dt_column);
356    col = &del->u.col;
357    col->table = table;
358    col->n = n;
359
360    var = &table->vars;
361    for (i = 0; i != n; i++)
362        var = &(*var)->next;
363    col->var = *var;
364    *var = (*var)->next;
365
366    next = &col->values;
367    for (row = table->rows; row; row = row->next) {
368        value = &row->values;
369        for (i = 0; i != n; i++)
370            value = &(*value)->next;
371        *next = *value;
372        *value = (*value)->next;
373        next = &(*next)->next;
374    }
375    *next = NULL;
376}
377
378
379static void undelete_column(const struct column *col)
380{
381    struct var **var;
382    struct row *row;
383    struct value **anchor, *value, *next;
384    int i;
385
386    var = &col->table->vars;
387    for (i = 0; i != col->n; i++)
388        var = &(*var)->next;
389    col->var->next = *var;
390    *var = col->var;
391
392    value = col->values;
393    for (row = col->table->rows; row; row = row->next) {
394        anchor = &row->values;
395        for (i = 0; i != col->n; i++)
396            anchor = &(*anchor)->next;
397        next = value->next;
398        value->next = *anchor;
399        *anchor = value;
400        value = next;
401    }
402}
403
404
405/* ----- tables ------------------------------------------------------------ */
406
407
408static void destroy_table(struct table *table)
409{
410    struct var *next_var;
411
412    while (table->vars) {
413        next_var = table->vars->next;
414        free(table->vars);
415        table->vars = next_var;
416    }
417    while (table->rows) {
418        delete_row(table->rows);
419        destroy();
420    }
421    free(table);
422}
423
424
425void delete_table(struct table *table)
426{
427    struct frame *frame = table->vars->frame;
428    struct deletion *del;
429    struct table *walk, *prev;
430
431    groups++;
432    prev = NULL;
433    for (walk = frame->tables; walk != table; walk = walk->next)
434        prev = walk;
435    if (prev)
436        prev->next = table->next;
437    else
438        frame->tables = table->next;
439    del = new_deletion(dt_table);
440    del->u.table.ref = table;
441    del->u.table.prev = prev;
442}
443
444
445static void undelete_table(struct table *table, struct table *prev)
446{
447    struct frame *frame = table->vars->frame;
448
449    if (prev) {
450        assert(table->next == prev->next);
451        prev->next = table;
452    } else {
453        assert(table->next == frame->tables);
454        frame->tables = table;
455    }
456}
457
458
459/* ----- loops ------------------------------------------------------------- */
460
461
462static void destroy_loop(struct loop *loop)
463{
464    free_expr(loop->from.expr);
465    free_expr(loop->to.expr);
466    free(loop);
467}
468
469
470void delete_loop(struct loop *loop)
471{
472    struct frame *frame = loop->var.frame;
473    struct deletion *del;
474    struct loop *walk, *prev;
475
476    groups++;
477    prev = NULL;
478    for (walk = frame->loops; walk != loop; walk = walk->next)
479        prev = walk;
480    if (prev)
481        prev->next = loop->next;
482    else
483        frame->loops = loop->next;
484    del = new_deletion(dt_loop);
485    del->u.loop.ref = loop;
486    del->u.loop.prev = prev;
487}
488
489
490static void undelete_loop(struct loop *loop, struct loop *prev)
491{
492    struct frame *frame = loop->var.frame;
493
494    if (prev) {
495        assert(loop->next == prev->next);
496        prev->next = loop;
497    } else {
498        assert(loop->next == frame->loops);
499        frame->loops = loop;
500    }
501}
502
503
504/* ----- frames ------------------------------------------------------------ */
505
506
507static void destroy_frame(struct frame *frame)
508{
509    while (frame->tables) {
510        delete_table(frame->tables);
511        destroy();
512    }
513    while (frame->loops) {
514        delete_loop(frame->loops);
515        destroy();
516    }
517    while (frame->vecs) {
518        delete_vec(frame->vecs);
519        destroy();
520    }
521    while (frame->objs) {
522        delete_obj(frame->objs);
523        destroy();
524    }
525    free(frame);
526}
527
528
529static int qual_ref(const struct frame_qual *qual, const struct frame *ref)
530{
531    while (qual) {
532        if (qual->frame == ref)
533            return 1;
534        qual = qual->next;
535    }
536    return 0;
537}
538
539
540static void delete_references(const struct frame *ref)
541{
542    struct frame *frame;
543    struct obj *obj;
544
545    for (frame = frames; frame; frame = frame->next)
546        for (obj = frame->objs; obj; obj = obj->next)
547            switch (obj->type) {
548            case ot_frame:
549                if (obj->u.frame.ref == ref)
550                    do_delete_obj(obj);
551                break;
552            case ot_meas:
553                if (obj->base->frame == ref ||
554                    obj->u.meas.high->frame == ref ||
555                    qual_ref(obj->u.meas.low_qual, ref) ||
556                    qual_ref(obj->u.meas.high_qual, ref))
557                    do_delete_obj(obj);
558                break;
559            default:
560                break;
561            }
562    for (obj = ref->objs; obj; obj = obj->next)
563        if (obj->type == ot_frame)
564            if (obj->u.frame.ref->active_ref == obj)
565                reset_active_ref(obj->u.frame.ref);
566}
567
568
569void delete_frame(struct frame *frame)
570{
571    struct deletion *del;
572    struct frame *walk;
573    groups++;
574
575    del = new_deletion(dt_frame);
576    del->u.frame.ref = frame;
577    del->u.frame.prev = NULL;
578    for (walk = frames; walk != frame; walk = walk->next)
579        del->u.frame.prev = walk;
580    if (del->u.frame.prev)
581        del->u.frame.prev->next = frame->next;
582    else
583        frames = frame->next; /* hmm, deleting the root frame ? */
584
585    delete_references(frame);
586}
587
588
589static void undelete_frame(struct frame *frame, struct frame *prev)
590{
591    if (prev) {
592        assert(frame->next == prev->next);
593        prev->next = frame;
594    } else {
595        assert(frame->next == frames);
596        frames = frame;
597    }
598}
599
600
601/* ----- destroy/undelete interface ---------------------------------------- */
602
603
604static void destroy_one(void)
605{
606    struct deletion *del;
607
608    del = deletions;
609    switch (del->type) {
610    case dt_vec:
611        destroy_vec(del->u.vec.ref);
612        break;
613    case dt_obj:
614        destroy_obj(del->u.obj.ref);
615        break;
616    case dt_frame:
617        destroy_frame(del->u.frame.ref);
618        break;
619    case dt_loop:
620        destroy_loop(del->u.loop.ref);
621        break;
622    case dt_table:
623        destroy_table(del->u.table.ref);
624        break;
625    case dt_row:
626        destroy_row(del->u.row.ref);
627        break;
628    case dt_column:
629        abort(); /* @@@ later */
630        break;
631    default:
632        abort();
633    }
634    deletions = del->next;
635    free(del);
636}
637
638
639void destroy(void)
640{
641    int group;
642
643    assert(deletions);
644    group = deletions->group;
645    while (deletions && deletions->group == group)
646        destroy_one();
647}
648
649
650static int undelete_one(void)
651{
652    struct deletion *del;
653
654    if (!deletions)
655        return 0;
656    del = deletions;
657    switch (del->type) {
658    case dt_vec:
659        undelete_vec(del->u.vec.ref, del->u.vec.prev);
660        break;
661    case dt_obj:
662        undelete_obj(del->u.obj.ref, del->u.obj.prev);
663        break;
664    case dt_frame:
665        undelete_frame(del->u.frame.ref, del->u.frame.prev);
666        break;
667    case dt_loop:
668        undelete_loop(del->u.loop.ref, del->u.loop.prev);
669        break;
670    case dt_table:
671        undelete_table(del->u.table.ref, del->u.table.prev);
672        break;
673    case dt_row:
674        undelete_row(del->u.row.ref, del->u.row.prev);
675        break;
676    case dt_column:
677        undelete_column(&del->u.col);
678        break;
679    default:
680        abort();
681    }
682    deletions = del->next;
683    free(del);
684    return 1;
685}
686
687
688int undelete(void)
689{
690    int group;
691
692    if (!deletions)
693        return 0;
694    group = deletions->group;
695    while (deletions && deletions->group == group)
696        undelete_one();
697    return 1;
698}
699
700
701void purge(void)
702{
703    while (deletions)
704        destroy();
705}
706

Archive Download this file

Branches:
master



interactive