1:
2: // Compiler implementation of the D programming language
3: // Copyright (c) 1999-2009 by Digital Mars
4: // All Rights Reserved
5: // written by Walter Bright
6: // http://www.digitalmars.com
7: // License for redistribution is by either the Artistic License
8: // in artistic.txt, or the GNU General Public License in gnu.txt.
9: // See the included readme.txt for details.
10:
11: // This implements the JSON capability.
12:
13: #include <stdio.h>
14: #include <string.h>
15: #include <time.h>
16: #include <ctype.h>
17: static char __file__[] = __FILE__; /* for tassert.h */
18: #include "tassert.h"
19:
20: #include "rmem.h"
21: #include "root.h"
22:
23: #include "mars.h"
24: #include "dsymbol.h"
25: #include "macro.h"
26: #include "template.h"
27: #include "lexer.h"
28: #include "aggregate.h"
29: #include "declaration.h"
30: #include "enum.h"
31: #include "id.h"
32: #include "module.h"
33: #include "scope.h"
34: #include "hdrgen.h"
35: #include "json.h"
36: #include "mtype.h"
37: #include "attrib.h"
38: #include "cond.h"
39:
40: const char Pname[] = "name";
41: const char Pkind[] = "kind";
42: const char Pfile[] = "file";
43: const char Pline[] = "line";
44: const char Ptype[] = "type";
45: const char Pcomment[] = "comment";
46: const char Pmembers[] = "members";
47: const char Pprotection[] = "protection";
48: const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"};
49:
50: void JsonRemoveComma(OutBuffer *buf);
51:
52: void json_generate(Modules *modules)
53: { OutBuffer buf;
54:
55: buf.writestring("[\n");
56: for (int i = 0; i < modules->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
57: { Module *m = modules->tdata()[i];
58: if (global.params.verbose)
59: printf("json gen %s\n", m->toChars());
60: m->toJsonBuffer(&buf);
61: buf.writestring(",\n");
62: }
63: JsonRemoveComma(&buf);
64: buf.writestring("]\n");
65:
66: // Write buf to file
67: char *arg = global.params.xfilename;
68: if (!arg || !*arg)
69: { // Generate lib file name from first obj name
70: char *n = global.params.objfiles->tdata()[0];
71:
72: n = FileName::name(n);
73: FileName *fn = FileName::forceExt(n, global.json_ext);
74: arg = fn->toChars();
75: }
76: else if (arg[0] == '-' && arg[1] == 0)
77: { // Write to stdout; assume it succeeds
78: int n = fwrite(buf.data, 1, buf.offset, stdout);
79: assert(n == buf.offset); // keep gcc happy about return values
80: return;
81: }
82: // if (!FileName::absolute(arg))
83: // arg = FileName::combine(dir, arg);
84: FileName *jsonfilename = FileName::defaultExt(arg, global.json_ext);
85: File *jsonfile = new File(jsonfilename);
86: assert(jsonfile);
87: jsonfile->setbuffer(buf.data, buf.offset);
88: jsonfile->ref = 1;
89: char *pt = FileName::path(jsonfile->toChars());
90: if (*pt)
91: FileName::ensurePathExists(pt);
92: mem.free(pt);
93: jsonfile->writev();
94: }
95:
96:
97: /*********************************
98: * Encode string into buf, and wrap it in double quotes.
99: */
100: void JsonString(OutBuffer *buf, const char *s)
101: {
102: buf->writeByte('\"');
103: for (; *s; s++)
104: {
105: unsigned char c = (unsigned char) *s;
106: switch (c)
107: {
108: case '\n':
109: buf->writestring("\\n");
110: break;
111:
112: case '\r':
113: buf->writestring("\\r");
114: break;
115:
116: case '\t':
117: buf->writestring("\\t");
118: break;
119:
120: case '\"':
121: buf->writestring("\\\"");
122: break;
123:
124: case '\\':
125: buf->writestring("\\\\");
126: break;
127:
128: case '/':
129: buf->writestring("\\/");
130: break;
131:
132: case '\b':
133: buf->writestring("\\b");
134: break;
135:
136: case '\f':
137: buf->writestring("\\f");
138: break;
139:
140: default:
141: if (c < 0x20)
142: buf->printf("\\u%04x", c);
143: else
144: // Note that UTF-8 chars pass through here just fine
145: buf->writeByte(c);
146: break;
147: }
148: }
149: buf->writeByte('\"');
150: }
151:
152: void JsonProperty(OutBuffer *buf, const char *name, const char *value)
153: {
154: JsonString(buf, name);
155: buf->writestring(" : ");
156: JsonString(buf, value);
157: buf->writestring(",\n");
158: }
159:
160: void JsonProperty(OutBuffer *buf, const char *name, int value)
161: {
162: JsonString(buf, name);
163: buf->writestring(" : ");
164: buf->printf("%d", value);
165: buf->writestring(",\n");
166: }
167:
168: void JsonRemoveComma(OutBuffer *buf)
169: {
170: if (buf->offset >= 2 &&
171: buf->data[buf->offset - 2] == ',' &&
172: buf->data[buf->offset - 1] == '\n')
173: buf->offset -= 2;
174: }
175:
176: void Dsymbol::toJsonBuffer(OutBuffer *buf)
177: {
178: }
179:
180: void Module::toJsonBuffer(OutBuffer *buf)
181: {
182: buf->writestring("{\n");
183:
184: if (md)
185: JsonProperty(buf, Pname, md->toChars());
186:
187: JsonProperty(buf, Pkind, kind());
188:
189: JsonProperty(buf, Pfile, srcfile->toChars());
190:
191: if (comment)
192: JsonProperty(buf, Pcomment, (const char *)comment);
193:
194: JsonString(buf, Pmembers);
195: buf->writestring(" : [\n");
196:
197: size_t offset = buf->offset;
198: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
199: { Dsymbol *s = members->tdata()[i];
200: if (offset != buf->offset)
201: { buf->writestring(",\n");
202: offset = buf->offset;
203: }
204: s->toJsonBuffer(buf);
205: }
206:
207: JsonRemoveComma(buf);
208: buf->writestring("]\n");
209:
210: buf->writestring("}\n");
211: }
212:
213: void AttribDeclaration::toJsonBuffer(OutBuffer *buf)
214: {
215: //printf("AttribDeclaration::toJsonBuffer()\n");
216:
217: Dsymbols *d = include(NULL, NULL);
218:
219: if (d)
220: {
221: size_t offset = buf->offset;
222: for (unsigned i = 0; i < d->dim; i++)
223: { Dsymbol *s = d->tdata()[i];
224: //printf("AttribDeclaration::toJsonBuffer %s\n", s->toChars());
225: if (offset != buf->offset)
226: { buf->writestring(",\n");
227: offset = buf->offset;
228: }
229: s->toJsonBuffer(buf);
230: }
231: JsonRemoveComma(buf);
232: }
233: }
234:
235:
236: void ConditionalDeclaration::toJsonBuffer(OutBuffer *buf)
237: {
238: //printf("ConditionalDeclaration::toJsonBuffer()\n");
239: if (condition->inc)
240: {
241: AttribDeclaration::toJsonBuffer(buf);
242: }
243: }
244:
245:
246: void InvariantDeclaration::toJsonBuffer(OutBuffer *buf) { }
247: void DtorDeclaration::toJsonBuffer(OutBuffer *buf) { }
248: void StaticCtorDeclaration::toJsonBuffer(OutBuffer *buf) { }
249: void StaticDtorDeclaration::toJsonBuffer(OutBuffer *buf) { }
250: void ClassInfoDeclaration::toJsonBuffer(OutBuffer *buf) { }
251: void ModuleInfoDeclaration::toJsonBuffer(OutBuffer *buf) { }
252: void TypeInfoDeclaration::toJsonBuffer(OutBuffer *buf) { }
253: void UnitTestDeclaration::toJsonBuffer(OutBuffer *buf) { }
254: #if DMDV2
255: void PostBlitDeclaration::toJsonBuffer(OutBuffer *buf) { }
256: #endif
257:
258: void Declaration::toJsonBuffer(OutBuffer *buf)
259: {
260: //printf("Declaration::toJsonBuffer()\n");
261: buf->writestring("{\n");
262:
263: JsonProperty(buf, Pname, toChars());
264: JsonProperty(buf, Pkind, kind());
265:
266: if (prot())
267: JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
268:
269: if (type)
270: JsonProperty(buf, Ptype, type->toChars());
271:
272: if (comment)
273: JsonProperty(buf, Pcomment, (const char *)comment);
274:
275: if (loc.linnum)
276: JsonProperty(buf, Pline, loc.linnum);
277:
278: TypedefDeclaration *td = isTypedefDeclaration();
279: if (td)
280: {
281: JsonProperty(buf, "base", td->basetype->toChars());
282: }
283:
284: JsonRemoveComma(buf);
285: buf->writestring("}\n");
286: }
287:
288: void AggregateDeclaration::toJsonBuffer(OutBuffer *buf)
289: {
290: //printf("AggregateDeclaration::toJsonBuffer()\n");
291: buf->writestring("{\n");
292:
293: JsonProperty(buf, Pname, toChars());
294: JsonProperty(buf, Pkind, kind());
295:
296: if (prot())
297: JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
298:
299: if (comment)
300: JsonProperty(buf, Pcomment, (const char *)comment);
301:
302: if (loc.linnum)
303: JsonProperty(buf, Pline, loc.linnum);
304:
305: ClassDeclaration *cd = isClassDeclaration();
306: if (cd)
307: {
308: if (cd->baseClass)
309: {
310: JsonProperty(buf, "base", cd->baseClass->toChars());
311: }
312: if (cd->interfaces_dim)
313: {
314: JsonString(buf, "interfaces");
315: buf->writestring(" : [\n");
316: size_t offset = buf->offset;
317: for (int i = 0; i < cd->interfaces_dim; i++)
318: { BaseClass *b = cd->interfaces[i];
319: if (offset != buf->offset)
320: { buf->writestring(",\n");
321: offset = buf->offset;
322: }
323: JsonString(buf, b->base->toChars());
324: }
325: JsonRemoveComma(buf);
326: buf->writestring("],\n");
327: }
328: }
329:
330: if (members)
331: {
332: JsonString(buf, Pmembers);
333: buf->writestring(" : [\n");
334: size_t offset = buf->offset;
335: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
336: { Dsymbol *s = members->tdata()[i];
337: if (offset != buf->offset)
338: { buf->writestring(",\n");
339: offset = buf->offset;
340: }
341: s->toJsonBuffer(buf);
342: }
343: JsonRemoveComma(buf);
344: buf->writestring("]\n");
345: }
346: JsonRemoveComma(buf);
347:
348: buf->writestring("}\n");
349: }
350:
351: void TemplateDeclaration::toJsonBuffer(OutBuffer *buf)
352: {
353: //printf("TemplateDeclaration::toJsonBuffer()\n");
354:
355: buf->writestring("{\n");
356:
357: JsonProperty(buf, Pname, toChars());
358: JsonProperty(buf, Pkind, kind());
359:
360: if (prot())
361: JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
362:
363: if (comment)
364: JsonProperty(buf, Pcomment, (const char *)comment);
365:
366: if (loc.linnum)
367: JsonProperty(buf, Pline, loc.linnum);
368:
369: JsonString(buf, Pmembers);
370: buf->writestring(" : [\n");
371: size_t offset = buf->offset;
372: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
373: { Dsymbol *s = members->tdata()[i];
374: if (offset != buf->offset)
375: { buf->writestring(",\n");
376: offset = buf->offset;
377: }
378: s->toJsonBuffer(buf);
379: }
380: JsonRemoveComma(buf);
381: buf->writestring("]\n");
382:
383: buf->writestring("}\n");
384: }
385:
386: void EnumDeclaration::toJsonBuffer(OutBuffer *buf)
387: {
388: //printf("EnumDeclaration::toJsonBuffer()\n");
389: if (isAnonymous())
390: {
391: if (members)
392: {
393: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
394: {
395: Dsymbol *s = members->tdata()[i];
396: s->toJsonBuffer(buf);
397: buf->writestring(",\n");
398: }
399: JsonRemoveComma(buf);
400: }
401: return;
402: }
403:
404: buf->writestring("{\n");
405:
406: JsonProperty(buf, Pname, toChars());
407: JsonProperty(buf, Pkind, kind());
408:
409: if (prot())
410: JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
411:
412: if (comment)
413: JsonProperty(buf, Pcomment, (const char *)comment);
414:
415: if (loc.linnum)
416: JsonProperty(buf, Pline, loc.linnum);
417:
418: if (memtype)
419: JsonProperty(buf, "base", memtype->toChars());
420:
421: if (members)
422: {
423: JsonString(buf, Pmembers);
424: buf->writestring(" : [\n");
425: size_t offset = buf->offset;
426: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
427: { Dsymbol *s = members->tdata()[i];
428: if (offset != buf->offset)
429: { buf->writestring(",\n");
430: offset = buf->offset;
431: }
432: s->toJsonBuffer(buf);
433: }
434: JsonRemoveComma(buf);
435: buf->writestring("]\n");
436: }
437: JsonRemoveComma(buf);
438:
439: buf->writestring("}\n");
440: }
441:
442: void EnumMember::toJsonBuffer(OutBuffer *buf)
443: {
444: //printf("EnumMember::toJsonBuffer()\n");
445: buf->writestring("{\n");
446:
447: JsonProperty(buf, Pname, toChars());
448: JsonProperty(buf, Pkind, kind());
449:
450: if (prot())
451: JsonProperty(buf, Pprotection, Pprotectionnames[prot()]);
452:
453: if (comment)
454: JsonProperty(buf, Pcomment, (const char *)comment);
455:
456: if (loc.linnum)
457: JsonProperty(buf, Pline, loc.linnum);
458:
459: JsonRemoveComma(buf);
460: buf->writestring("}\n");
461: }
462:
463:
464: