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: