1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4  * written by Walter Bright
5  * http://www.digitalmars.com
6  * Distributed under the Boost Software License, Version 1.0.
7  * http://www.boost.org/LICENSE_1_0.txt
8  * https://github.com/D-Programming-Language/dmd/blob/master/src/version.c
9  */
10 
11 #include "root/dsystem.h"
12 #include "root/root.h"
13 
14 #include "identifier.h"
15 #include "dsymbol.h"
16 #include "cond.h"
17 #include "version.h"
18 #include "module.h"
19 
20 void checkReserved(Loc loc, const char *ident);
21 
22 /* ================================================== */
23 
24 /* DebugSymbol's happen for statements like:
25  *      debug = identifier;
26  *      debug = integer;
27  */
28 
DebugSymbol(Loc loc,Identifier * ident)29 DebugSymbol::DebugSymbol(Loc loc, Identifier *ident)
30     : Dsymbol(ident)
31 {
32     this->loc = loc;
33 }
34 
DebugSymbol(Loc loc,unsigned level)35 DebugSymbol::DebugSymbol(Loc loc, unsigned level)
36     : Dsymbol()
37 {
38     this->level = level;
39     this->loc = loc;
40 }
41 
toChars()42 const char *DebugSymbol::toChars()
43 {
44     if (ident)
45         return ident->toChars();
46     else
47     {
48         OutBuffer buf;
49         buf.printf("%d", level);
50         return buf.extractString();
51     }
52 }
53 
syntaxCopy(Dsymbol * s)54 Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s)
55 {
56     assert(!s);
57     DebugSymbol *ds = new DebugSymbol(loc, ident);
58     ds->level = level;
59     return ds;
60 }
61 
addMember(Scope *,ScopeDsymbol * sds)62 void DebugSymbol::addMember(Scope *, ScopeDsymbol *sds)
63 {
64     //printf("DebugSymbol::addMember('%s') %s\n", sds->toChars(), toChars());
65     Module *m = sds->isModule();
66 
67     // Do not add the member to the symbol table,
68     // just make sure subsequent debug declarations work.
69     if (ident)
70     {
71         if (!m)
72         {
73             error("declaration must be at module level");
74             errors = true;
75         }
76         else
77         {
78             if (findCondition(m->debugidsNot, ident))
79             {
80                 error("defined after use");
81                 errors = true;
82             }
83             if (!m->debugids)
84                 m->debugids = new Strings();
85             m->debugids->push(ident->toChars());
86         }
87     }
88     else
89     {
90         if (!m)
91         {
92             error("level declaration must be at module level");
93             errors = true;
94         }
95         else
96             m->debuglevel = level;
97     }
98 }
99 
semantic(Scope *)100 void DebugSymbol::semantic(Scope *)
101 {
102     //printf("DebugSymbol::semantic() %s\n", toChars());
103     if (semanticRun < PASSsemanticdone)
104         semanticRun = PASSsemanticdone;
105 }
106 
kind()107 const char *DebugSymbol::kind() const
108 {
109     return "debug";
110 }
111 
112 /* ================================================== */
113 
114 /* VersionSymbol's happen for statements like:
115  *      version = identifier;
116  *      version = integer;
117  */
118 
VersionSymbol(Loc loc,Identifier * ident)119 VersionSymbol::VersionSymbol(Loc loc, Identifier *ident)
120     : Dsymbol(ident)
121 {
122     this->loc = loc;
123 }
124 
VersionSymbol(Loc loc,unsigned level)125 VersionSymbol::VersionSymbol(Loc loc, unsigned level)
126     : Dsymbol()
127 {
128     this->level = level;
129     this->loc = loc;
130 }
131 
toChars()132 const char *VersionSymbol::toChars()
133 {
134     if (ident)
135         return ident->toChars();
136     else
137     {
138         OutBuffer buf;
139         buf.printf("%d", level);
140         return buf.extractString();
141     }
142 }
143 
syntaxCopy(Dsymbol * s)144 Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s)
145 {
146     assert(!s);
147     VersionSymbol *ds = ident ? new VersionSymbol(loc, ident)
148                               : new VersionSymbol(loc, level);
149     return ds;
150 }
151 
addMember(Scope *,ScopeDsymbol * sds)152 void VersionSymbol::addMember(Scope *, ScopeDsymbol *sds)
153 {
154     //printf("VersionSymbol::addMember('%s') %s\n", sds->toChars(), toChars());
155     Module *m = sds->isModule();
156 
157     // Do not add the member to the symbol table,
158     // just make sure subsequent debug declarations work.
159     if (ident)
160     {
161         checkReserved(loc, ident->toChars());
162         if (!m)
163         {
164             error("declaration must be at module level");
165             errors = true;
166         }
167         else
168         {
169             if (findCondition(m->versionidsNot, ident))
170             {
171                 error("defined after use");
172                 errors = true;
173             }
174             if (!m->versionids)
175                 m->versionids = new Strings();
176             m->versionids->push(ident->toChars());
177         }
178     }
179     else
180     {
181         if (!m)
182         {
183             error("level declaration must be at module level");
184             errors = true;
185         }
186         else
187             m->versionlevel = level;
188     }
189 }
190 
semantic(Scope *)191 void VersionSymbol::semantic(Scope *)
192 {
193     if (semanticRun < PASSsemanticdone)
194         semanticRun = PASSsemanticdone;
195 }
196 
kind()197 const char *VersionSymbol::kind() const
198 {
199     return "version";
200 }
201