File: recursive.c

package info (click to toggle)
esnacc 1.8.1-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 4,452 kB
  • sloc: ansic: 42,340; cpp: 13,880; yacc: 2,682; tcl: 1,587; lex: 688; sh: 573; makefile: 111
file content (220 lines) | stat: -rw-r--r-- 6,831 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
 * compiler/core/recursive.c - finds and marks the recursive types in a module.
 *
 * ALSO:
 * prints msgs for infinitely recursive types (ie recursive component
 * is not OPTIONAL, nor a CHOICE elmt, nor a SET OF nor a SEQ OF elmt.
 * (OPTIONALs can be left out, CHOICE elements have alternatives (hopefully),
 * and SET OF and SEQUENCE OF values can have zero elements)
 *
 * prints msg for recursive types that hold no real information
 *     Foo ::= SET OF Foo (sets of sets of .... of empty sets)
 *
 * finds bogus recursive types (hold no info) (same as above)
 *  A ::= B
 *  B ::= C
 *  D ::= A
 *
 * MS 92
 *
 * Copyright (C) 1991, 1992 Michael Sample
 *            and the University of British Columbia
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * $Header: /baseline/SNACC/compiler/core/recursive.c,v 1.7 2004/04/06 15:13:41 gronej Exp $
 * $Log: recursive.c,v $
 * Revision 1.7  2004/04/06 15:13:41  gronej
 * *** empty log message ***
 *
 * Revision 1.6  2004/03/25 19:20:17  gronej
 * fixed some linux warnings
 *
 * Revision 1.5  2003/07/07 14:50:14  nicholar
 * Eliminated headers and cleaned up include references
 *
 * Revision 1.4  2002/09/16 16:50:23  mcphersc
 * Fixed warnings
 *
 * Revision 1.3  2002/09/04 18:31:39  vracarl
 * got rid of c++ comments
 *
 * Revision 1.2  2000/10/24 14:54:55  rwc
 * Updated to remove high-level warnings (level 4 on MSVC++) for an easier build.
 * SOME warnings persist due to difficulty in modifying the SNACC compiler to
 * properly build clean source; also some files are built by Lex/Yacc.
 *
 * Revision 1.1.1.1  2000/08/21 20:36:01  leonberp
 * First CVS Version of SNACC.
 *
 * Revision 1.3  1995/07/25 19:41:43  rj
 * changed `_' to `-' in file names.
 *
 * Revision 1.2  1994/09/01  00:43:10  rj
 * snacc_config.h removed; recursive.h includet.
 *
 * Revision 1.1  1994/08/28  09:49:35  rj
 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
 *
 */

#include "asn-incl.h"
#include "asn1module.h"
#include "snacc-util.h"


void MkRecTypeDef PROTO ((Module *m, TypeDef *td));
void MkRecType  PROTO ((Module *m, TypeDef *td,Type *t, int optional, int empty));


extern FILE* errFileG;		// Defined in snacc.c


void
MarkRecursiveTypes PARAMS ((m),
    Module *m)
{
    TypeDef *td;

    /* first set all typedef as un-visited */
    FOR_EACH_LIST_ELMT (td, m->typeDefs)
    {
        td->visited = FALSE;
        td->tmpRefCount = 0;
    }

    FOR_EACH_LIST_ELMT (td, m->typeDefs)
    {
        MkRecTypeDef (m, td);
    }
}  /* MarkRecursiveTypes */



void
MkRecTypeDef PARAMS ((m, td),
    Module *m _AND_
    TypeDef *td)
{
    MkRecType (m, td, td->type, 0, 1);
}  /* MkRecTypeDef */



/*
 * cruise through aggregate types and type refs looking for
 * a type ref to the original type def, td.  If is a ref to
 * the td, then mark the td as recusive.
 *
 * the optional flag is set if the current type branch is
 * optional via an OPTIONAL SET/SEQ elmt, CHOICE elmt, SET OF elmt
 * or SEQ OF elmt.
 *
 * the empty flag is initially TRUE and remains true until a
 * non-type reference type is encountered
 */
void
MkRecType  PARAMS ((m, td, t, optional, empty),
    Module *m _AND_
    TypeDef *td _AND_
    Type *t _AND_
    int optional _AND_
    int empty)
{
    int newOptional;
    NamedType *e;

    switch (t->basicType->choiceId)
    {
        case BASICTYPE_CHOICE:
            if (AsnListCount (t->basicType->a.choice) > 1)
            {
                empty = 0;
                optional = 1;
            }
            FOR_EACH_LIST_ELMT (e, t->basicType->a.choice)
            {
                MkRecType (m, td, e->type, optional, empty);
            }
            break;

        case BASICTYPE_SET:
        case BASICTYPE_SEQUENCE:
            empty = 0;

            FOR_EACH_LIST_ELMT (e, t->basicType->a.set)
            {
                newOptional = optional || (e->type->optional) ||
                              (e->type->defaultVal != NULL);
                MkRecType (m, td, e->type, newOptional, empty);
            }
            break;

        case BASICTYPE_SETOF:
        case BASICTYPE_SEQUENCEOF:
            empty = 0;  /* since an empty set is actual data */
            optional = 1; /* since SET OF and SEQ OF's can be empty */
            MkRecType (m, td, t->basicType->a.setOf, optional, empty);
            break;

        case BASICTYPE_LOCALTYPEREF:
        case BASICTYPE_IMPORTTYPEREF:

            /*
             * check if ref to original type def & mark recursive if so.
             */
/*            if ((strcmp (t->basicType->a.localTypeRef->typeName, td->definedName) == 0) && (t->basicType->a.localTypeRef->module == m))
 easier to just check ptrs!
*/
            if (t->basicType->a.localTypeRef->link == td)
            {
                td->recursive = 1;
                if (empty)
                {
                    PrintErrLoc (m->asn1SrcFileName, (long)td->type->lineNo);
                    fprintf (errFileG, "WARNING: Type \"%s\" appears to be infinitely recursive and can hold no values! (circular type references)\n",
						td->definedName);
                }
                else if (!optional)
                {
                    PrintErrLoc (m->asn1SrcFileName, (long)t->lineNo);
                    fprintf (errFileG, "WARNING: Type \"%s\" appears to be infinitely recursive! (infinitely sized values)\n",
						td->definedName);
                }
            }

            /*
             * else follow this type reference if we aren't in it already
             * (ie another recursive type in td)
             */
            else if (t->basicType->a.localTypeRef->link->tmpRefCount == 0)
            {
                /*
                 * mark this typedef as 'entered' to
                 * detect when looping in a recusive type that is contained
                 * in the original td (use tmpRefCount)
                 */
                 t->basicType->a.localTypeRef->link->tmpRefCount = 1;

                 newOptional = optional || (t->optional) || (t->defaultVal != NULL);
                 MkRecType (m, td, t->basicType->a.localTypeRef->link->type, newOptional, empty);

                /*
                 * un-mark this type since finished with it
                 * for recursive ref's to td
                 */
                 t->basicType->a.localTypeRef->link->tmpRefCount = 0;
            }
            break;

    default:
      break;
        /*
         * default: other types are not aggregate and
         * do not make recursive refs - they can be ignored
         */
    }
} /* MkRecType */