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