char *Initializer::toChars() { OutBuffer buf; HdrGenState hgs; ::toCBuffer(this, &buf, &hgs); return buf.extractString(); }
void visit(Dsymbol *s) { #if 0 printf("Dsymbol::mangle() '%s'", s->toChars()); if (s->parent) printf(" parent = %s %s", s->parent->kind(), s->parent->toChars()); printf("\n"); #endif char *id = s->ident ? s->ident->toChars() : s->toChars(); OutBuffer buf; if (s->parent) { FuncDeclaration *f = s->parent->isFuncDeclaration(); if (f) mangleExact(f); else s->parent->accept(this); if (result[0] == '_' && result[1] == 'D') result += 2; buf.writestring(result); } buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.extractString(); //printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id); result = id; }
void visit(TemplateInstance *ti) { OutBuffer buf; #if 0 printf("TemplateInstance::mangle() %p %s", ti, ti->toChars()); if (ti->parent) printf(" parent = %s %s", ti->parent->kind(), ti->parent->toChars()); printf("\n"); #endif ti->getIdent(); const char *id = ti->ident ? ti->ident->toChars() : ti->toChars(); if (!ti->tempdecl) ti->error("is not defined"); else { Dsymbol *par = ti->isTemplateMixin() ? ti->parent : ti->tempdecl->parent; if (par) { FuncDeclaration *f = par->isFuncDeclaration(); if (f) mangleExact(f); else par->accept(this); if (result[0] == '_' && result[1] == 'D') result += 2; buf.writestring(result); } } buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.extractString(); //printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id); result = id; }
const char *ProtDeclaration::toPrettyChars(bool) { assert(protection.kind > PROTundefined); OutBuffer buf; buf.writeByte('\''); protectionToBuffer(&buf, protection); buf.writeByte('\''); return buf.extractString(); }
void visit(Declaration *d) { //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", // d, d->toChars(), d->parent ? d->parent->toChars() : "null", d->linkage); if (!d->parent || d->parent->isModule() || d->linkage == LINKcpp) // if at global scope { switch (d->linkage) { case LINKd: break; case LINKc: case LINKwindows: case LINKpascal: result = d->ident->toChars(); break; case LINKcpp: result = toCppMangle(d); break; case LINKdefault: d->error("forward declaration"); result = d->ident->toChars(); break; default: fprintf(stderr, "'%s', linkage = %d\n", d->toChars(), d->linkage); assert(0); } } if (!result) { OutBuffer buf; buf.writestring("_D"); mangleDecl(&buf, d); result = buf.extractString(); } #ifdef DEBUG assert(result); size_t len = strlen(result); assert(len > 0); for (size_t i = 0; i < len; i++) { assert(result[i] == '_' || result[i] == '@' || result[i] == '?' || result[i] == '$' || isalnum(result[i]) || result[i] & 0x80); } #endif }
char* mangleOf(Dsymbol *s) { VarDeclaration *vd = s->isVarDeclaration(); FuncDeclaration *fd = s->isFuncDeclaration(); if (vd) { mangle_variable(vd, false); } else { mangle_function(fd); } return buf.extractString(); }
char *ModuleDeclaration::toChars() { OutBuffer buf; if (packages && packages->dim) { for (size_t i = 0; i < packages->dim; i++) { Identifier *pid = (*packages)[i]; buf.writestring(pid->toChars()); buf.writeByte('.'); } } buf.writestring(id->toChars()); return buf.extractString(); }
char *Loc::toChars() { OutBuffer buf; if (filename) { buf.printf("%s", filename); } if (linnum) { buf.printf("(%d", linnum); if (global.params.showColumns && charnum) buf.printf(",%d", charnum); buf.writeByte(')'); } return buf.extractString(); }
/** * Creates the data symbol for a TLS variable for Mach-O. * * Input: * vd the variable declaration for the symbol * s the regular symbol for the variable * * Returns: the newly create symbol */ Symbol *createTLVDataSymbol(VarDeclaration *vd, Symbol *s) { assert(config.objfmt == OBJ_MACH && I64 && (s->ty() & mTYLINK) == mTYthread); OutBuffer buffer; buffer.writestring(s->Sident); buffer.write("$tlv$init", 9); const char *tlvInitName = buffer.extractString(); Symbol *tlvInit = symbol_name(tlvInitName, SCstatic, type_fake(vd->type->ty)); tlvInit->Sdt = NULL; tlvInit->Salignment = type_alignsize(s->Stype); type_setty(&tlvInit->Stype, tlvInit->Stype->Tty | mTYthreadData); type_setmangle(&tlvInit->Stype, mangle(vd, tlvInit)); return tlvInit; }
void visit(Dsymbol *s) { #if 0 printf("Dsymbol::mangle() '%s'", s->toChars()); if (s->parent) printf(" parent = %s %s", s->parent->kind(), s->parent->toChars()); printf("\n"); #endif OutBuffer buf; mangleParent(&buf, s); char *id = s->ident ? s->ident->toChars() : s->toChars(); buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.extractString(); //printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id); result = id; }
void visit(TemplateInstance *ti) { #if 0 printf("TemplateInstance::mangle() %p %s", ti, ti->toChars()); if (ti->parent) printf(" parent = %s %s", ti->parent->kind(), ti->parent->toChars()); printf("\n"); #endif OutBuffer buf; if (!ti->tempdecl) ti->error("is not defined"); else mangleParent(&buf, ti); ti->getIdent(); const char *id = ti->ident ? ti->ident->toChars() : ti->toChars(); buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.extractString(); //printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id); result = id; }
void obj_write_deferred(Library *library) { for (size_t i = 0; i < obj_symbols_towrite.dim; i++) { Dsymbol *s = obj_symbols_towrite[i]; Module *m = s->getModule(); char *mname; if (m) { mname = m->srcfile->toChars(); lastmname = mname; } else { //mname = s->ident->toChars(); mname = lastmname; assert(mname); } obj_start(mname); static int count; count++; // sequence for generating names /* Create a module that's a doppelganger of m, with just * enough to be able to create the moduleinfo. */ OutBuffer idbuf; idbuf.printf("%s.%d", m ? m->ident->toChars() : mname, count); char *idstr = idbuf.peekString(); if (!m) { // it doesn't make sense to make up a module if we don't know where to put the symbol // so output it into it's own object file without ModuleInfo objmod->initfile(idstr, NULL, mname); toObjFile(s, false); objmod->termfile(); } else { idbuf.data = NULL; Identifier *id = Identifier::create(idstr, TOKidentifier); Module *md = Module::create(mname, id, 0, 0); md->members = Dsymbols_create(); md->members->push(s); // its only 'member' is s md->doppelganger = 1; // identify this module as doppelganger md->md = m->md; md->aimports.push(m); // it only 'imports' m md->massert = m->massert; md->munittest = m->munittest; md->marray = m->marray; genObjFile(md, false); } /* Set object file name to be source name with sequence number, * as mangled symbol names get way too long. */ const char *fname = FileName::removeExt(mname); OutBuffer namebuf; unsigned hash = 0; for (char *p = s->toChars(); *p; p++) hash += *p; namebuf.printf("%s_%x_%x.%s", fname, count, hash, global.obj_ext); FileName::free((char *)fname); fname = namebuf.extractString(); //printf("writing '%s'\n", fname); File *objfile = File::create(fname); obj_end(library, objfile); } obj_symbols_towrite.dim = 0; }
int runLINK() { #if _WIN32 if (global.params.is64bit) { OutBuffer cmdbuf; cmdbuf.writestring("/NOLOGO "); for (size_t i = 0; i < global.params.objfiles->dim; i++) { if (i) cmdbuf.writeByte(' '); const char *p = (*global.params.objfiles)[i]; const char *basename = FileName::removeExt(FileName::name(p)); const char *ext = FileName::ext(p); if (ext && !strchr(basename, '.')) { // Write name sans extension (but not if a double extension) writeFilename(&cmdbuf, p, ext - p - 1); } else writeFilename(&cmdbuf, p); FileName::free(basename); } if (global.params.resfile) { cmdbuf.writeByte(' '); writeFilename(&cmdbuf, global.params.resfile); } cmdbuf.writeByte(' '); if (global.params.exefile) { cmdbuf.writestring("/OUT:"); writeFilename(&cmdbuf, global.params.exefile); } else { /* Generate exe file name from first obj name. * No need to add it to cmdbuf because the linker will default to it. */ const char *n = (*global.params.objfiles)[0]; n = FileName::name(n); global.params.exefile = (char *)FileName::forceExt(n, "exe"); } // Make sure path to exe file exists ensurePathToNameExists(Loc(), global.params.exefile); cmdbuf.writeByte(' '); if (global.params.mapfile) { cmdbuf.writestring("/MAP:"); writeFilename(&cmdbuf, global.params.mapfile); } else if (global.params.map) { const char *fn = FileName::forceExt(global.params.exefile, "map"); const char *path = FileName::path(global.params.exefile); const char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn); else p = fn; cmdbuf.writestring("/MAP:"); writeFilename(&cmdbuf, p); } for (size_t i = 0; i < global.params.libfiles->dim; i++) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEFAULTLIB:"); writeFilename(&cmdbuf, (*global.params.libfiles)[i]); } if (global.params.deffile) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEF:"); writeFilename(&cmdbuf, global.params.deffile); } if (global.params.symdebug) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DEBUG"); // in release mode we need to reactivate /OPT:REF after /DEBUG if (global.params.release) cmdbuf.writestring(" /OPT:REF"); } if (global.params.dll) { cmdbuf.writeByte(' '); cmdbuf.writestring("/DLL"); } for (size_t i = 0; i < global.params.linkswitches->dim; i++) { cmdbuf.writeByte(' '); cmdbuf.writestring((*global.params.linkswitches)[i]); } /* Append the path to the VC lib files, and then the SDK lib files */ const char *vcinstalldir = getenv("VCINSTALLDIR"); if (vcinstalldir) { cmdbuf.writestring(" \"/LIBPATH:"); cmdbuf.writestring(vcinstalldir); cmdbuf.writestring("lib\\amd64\""); } const char *windowssdkdir = getenv("WindowsSdkDir"); if (windowssdkdir) { cmdbuf.writestring(" \"/LIBPATH:"); cmdbuf.writestring(windowssdkdir); cmdbuf.writestring("lib\\x64\""); } char *p = cmdbuf.peekString(); const char *lnkfilename = NULL; size_t plen = strlen(p); if (plen > 7000) { lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); File flnk(lnkfilename); flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) error(Loc(), "error writing file %s", lnkfilename); if (strlen(lnkfilename) < plen) sprintf(p, "@%s", lnkfilename); } const char *linkcmd = getenv("LINKCMD64"); if (!linkcmd) linkcmd = getenv("LINKCMD"); // backward compatible if (!linkcmd) { if (vcinstalldir) { OutBuffer linkcmdbuf; linkcmdbuf.writestring(vcinstalldir); linkcmdbuf.writestring("bin\\amd64\\link"); linkcmd = linkcmdbuf.extractString(); } else linkcmd = "link"; } int status = executecmd(linkcmd, p); if (lnkfilename) { remove(lnkfilename); FileName::free(lnkfilename); } return status; } else { OutBuffer cmdbuf; global.params.libfiles->push("user32"); global.params.libfiles->push("kernel32"); for (size_t i = 0; i < global.params.objfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); const char *p = (*global.params.objfiles)[i]; const char *basename = FileName::removeExt(FileName::name(p)); const char *ext = FileName::ext(p); if (ext && !strchr(basename, '.')) { // Write name sans extension (but not if a double extension) writeFilename(&cmdbuf, p, ext - p - 1); } else writeFilename(&cmdbuf, p); FileName::free(basename); } cmdbuf.writeByte(','); if (global.params.exefile) writeFilename(&cmdbuf, global.params.exefile); else { /* Generate exe file name from first obj name. * No need to add it to cmdbuf because the linker will default to it. */ const char *n = (*global.params.objfiles)[0]; n = FileName::name(n); global.params.exefile = (char *)FileName::forceExt(n, "exe"); } // Make sure path to exe file exists ensurePathToNameExists(Loc(), global.params.exefile); cmdbuf.writeByte(','); if (global.params.mapfile) writeFilename(&cmdbuf, global.params.mapfile); else if (global.params.map) { const char *fn = FileName::forceExt(global.params.exefile, "map"); const char *path = FileName::path(global.params.exefile); const char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn); else p = fn; writeFilename(&cmdbuf, p); } else cmdbuf.writestring("nul"); cmdbuf.writeByte(','); for (size_t i = 0; i < global.params.libfiles->dim; i++) { if (i) cmdbuf.writeByte('+'); writeFilename(&cmdbuf, (*global.params.libfiles)[i]); } if (global.params.deffile) { cmdbuf.writeByte(','); writeFilename(&cmdbuf, global.params.deffile); } /* Eliminate unnecessary trailing commas */ while (1) { size_t i = cmdbuf.offset; if (!i || cmdbuf.data[i - 1] != ',') break; cmdbuf.offset--; } if (global.params.resfile) { cmdbuf.writestring("/RC:"); writeFilename(&cmdbuf, global.params.resfile); } if (global.params.map || global.params.mapfile) cmdbuf.writestring("/m"); #if 0 if (debuginfo) cmdbuf.writestring("/li"); if (codeview) { cmdbuf.writestring("/co"); if (codeview3) cmdbuf.writestring(":3"); } #else if (global.params.symdebug) cmdbuf.writestring("/co"); #endif cmdbuf.writestring("/noi"); for (size_t i = 0; i < global.params.linkswitches->dim; i++) { cmdbuf.writestring((*global.params.linkswitches)[i]); } cmdbuf.writeByte(';'); char *p = cmdbuf.peekString(); const char *lnkfilename = NULL; size_t plen = strlen(p); if (plen > 7000) { lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); File flnk(lnkfilename); flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) error(Loc(), "error writing file %s", lnkfilename); if (strlen(lnkfilename) < plen) sprintf(p, "@%s", lnkfilename); } const char *linkcmd = getenv("LINKCMD"); if (!linkcmd) linkcmd = "link"; int status = executecmd(linkcmd, p); if (lnkfilename) { remove(lnkfilename); FileName::free(lnkfilename); } return status; } #elif __linux__ || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun pid_t childpid; int status; // Build argv[] Strings argv; const char *cc = getenv("CC"); if (!cc) cc = "gcc"; argv.push(cc); argv.insert(1, global.params.objfiles); #if __APPLE__ // If we are on Mac OS X and linking a dynamic library, // add the "-dynamiclib" flag if (global.params.dll) argv.push("-dynamiclib"); #elif __linux__ || __FreeBSD__ || __OpenBSD__ || __sun if (global.params.dll) argv.push("-shared"); #endif // None of that a.out stuff. Use explicit exe file name, or // generate one from name of first source file. argv.push("-o"); if (global.params.exefile) { argv.push(global.params.exefile); } else if (global.params.run) { #if 1 char name[L_tmpnam + 14 + 1]; strcpy(name, P_tmpdir); strcat(name, "/dmd_runXXXXXX"); int fd = mkstemp(name); if (fd == -1) { error(Loc(), "error creating temporary file"); return 1; } else close(fd); global.params.exefile = mem.strdup(name); argv.push(global.params.exefile); #else /* The use of tmpnam raises the issue of "is this a security hole"? * The hole is that after tmpnam and before the file is opened, * the attacker modifies the file system to get control of the * file with that name. I do not know if this is an issue in * this context. * We cannot just replace it with mkstemp, because this name is * passed to the linker that actually opens the file and writes to it. */ char s[L_tmpnam + 1]; char *n = tmpnam(s); global.params.exefile = mem.strdup(n); argv.push(global.params.exefile); #endif } else { // Generate exe file name from first obj name const char *n = (*global.params.objfiles)[0]; char *ex; n = FileName::name(n); const char *e = FileName::ext(n); if (e) { e--; // back up over '.' ex = (char *)mem.malloc(e - n + 1); memcpy(ex, n, e - n); ex[e - n] = 0; // If generating dll then force dll extension if (global.params.dll) ex = (char *)FileName::forceExt(ex, global.dll_ext); } else ex = (char *)"a.out"; // no extension, so give up argv.push(ex); global.params.exefile = ex; } // Make sure path to exe file exists ensurePathToNameExists(Loc(), global.params.exefile); if (global.params.symdebug) argv.push("-g"); if (global.params.is64bit) argv.push("-m64"); else argv.push("-m32"); if (global.params.map || global.params.mapfile) { argv.push("-Xlinker"); #if __APPLE__ argv.push("-map"); #else argv.push("-Map"); #endif if (!global.params.mapfile) { const char *fn = FileName::forceExt(global.params.exefile, "map"); const char *path = FileName::path(global.params.exefile); const char *p; if (path[0] == '\0') p = FileName::combine(global.params.objdir, fn); else p = fn; global.params.mapfile = (char *)p; } argv.push("-Xlinker"); argv.push(global.params.mapfile); } if (0 && global.params.exefile) { /* This switch enables what is known as 'smart linking' * in the Windows world, where unreferenced sections * are removed from the executable. It eliminates unreferenced * functions, essentially making a 'library' out of a module. * Although it is documented to work with ld version 2.13, * in practice it does not, but just seems to be ignored. * Thomas Kuehne has verified that it works with ld 2.16.1. * BUG: disabled because it causes exception handling to fail * because EH sections are "unreferenced" and elided */ argv.push("-Xlinker"); argv.push("--gc-sections"); } for (size_t i = 0; i < global.params.linkswitches->dim; i++) { const char *p = (*global.params.linkswitches)[i]; if (!p || !p[0] || !(p[0] == '-' && (p[1] == 'l' || p[1] == 'L'))) // Don't need -Xlinker if switch starts with -l or -L. // Eliding -Xlinker is significant for -L since it allows our paths // to take precedence over gcc defaults. argv.push("-Xlinker"); argv.push(p); } /* Add each library, prefixing it with "-l". * The order of libraries passed is: * 1. any libraries passed with -L command line switch * 2. libraries specified on the command line * 3. libraries specified by pragma(lib), which were appended * to global.params.libfiles. * 4. standard libraries. */ for (size_t i = 0; i < global.params.libfiles->dim; i++) { const char *p = (*global.params.libfiles)[i]; size_t plen = strlen(p); if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a') argv.push(p); else { char *s = (char *)mem.malloc(plen + 3); s[0] = '-'; s[1] = 'l'; memcpy(s + 2, p, plen + 1); argv.push(s); } } for (size_t i = 0; i < global.params.dllfiles->dim; i++) { const char *p = (*global.params.dllfiles)[i]; argv.push(p); } /* Standard libraries must go after user specified libraries * passed with -l. */ const char *libname = (global.params.symdebug) ? global.params.debuglibname : global.params.defaultlibname; size_t slen = strlen(libname); if (slen) { char *buf = (char *)malloc(3 + slen + 1); strcpy(buf, "-l"); /* Use "-l:libname.a" if the library name is complete */ if (slen > 3 + 2 && memcmp(libname, "lib", 3) == 0 && (memcmp(libname + slen - 2, ".a", 2) == 0 || memcmp(libname + slen - 3, ".so", 3) == 0) ) { strcat(buf, ":"); } strcat(buf, libname); argv.push(buf); // turns into /usr/lib/libphobos2.a } #ifdef __sun argv.push("-mt"); #endif // argv.push("-ldruntime"); argv.push("-lpthread"); argv.push("-lm"); #if __linux__ // Changes in ld for Ubuntu 11.10 require this to appear after phobos2 argv.push("-lrt"); #endif if (global.params.verbose) { // Print it for (size_t i = 0; i < argv.dim; i++) fprintf(global.stdmsg, "%s ", argv[i]); fprintf(global.stdmsg, "\n"); } argv.push(NULL); // set up pipes int fds[2]; if (pipe(fds) == -1) { perror("Unable to create pipe to linker"); return -1; } childpid = fork(); if (childpid == 0) { // pipe linker stderr to fds[0] dup2(fds[1], STDERR_FILENO); close(fds[0]); execvp(argv[0], (char **)argv.tdata()); perror(argv[0]); // failed to execute return -1; } else if (childpid == -1) { perror("Unable to fork"); return -1; } close(fds[1]); const int nme = findNoMainError(fds[0]); waitpid(childpid, &status, 0); if (WIFEXITED(status)) { status = WEXITSTATUS(status); if (status) { if (nme == -1) { perror("Error with the linker pipe"); return -1; } else { printf("--- errorlevel %d\n", status); if (nme == 1) error(Loc(), "no main function specified"); } } } else if (WIFSIGNALED(status)) { printf("--- killed by signal %d\n", WTERMSIG(status)); status = 1; } return status; #else printf ("Linking is not yet supported for this version of DMD.\n"); return -1; #endif }
/****************************************************************************** * isv : for the enclosing auto functions of an inner class/struct type. * An aggregate type which defined inside auto function, it might * become Voldemort Type so its object might be returned. * This flag is necessary due to avoid mutual mangling * between return type and enclosing scope. See bugzilla 8847. */ char *mangleDecl(Declaration *sthis, bool isv) { OutBuffer buf; char *id; Dsymbol *s; //printf("::mangleDecl(%s)\n", sthis->toChars()); s = sthis; do { //printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent); if (s->getIdent()) { FuncDeclaration *fd = s->isFuncDeclaration(); if (s != sthis && fd) { id = mangleDecl(fd, isv); buf.prependstring(id); goto L1; } else { id = s->ident->toChars(); size_t len = strlen(id); char tmp[sizeof(len) * 3 + 1]; buf.prependstring(id); sprintf(tmp, "%d", (int)len); buf.prependstring(tmp); } } else buf.prependstring("0"); TemplateInstance *ti = s->isTemplateInstance(); if (ti && !ti->isTemplateMixin()) s = ti->tempdecl->parent; else s = s->parent; } while (s); // buf.prependstring("_D"); L1: //printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null"); //printf("sthis->type = %s\n", sthis->type->toChars()); FuncDeclaration *fd = sthis->isFuncDeclaration(); if (fd && (fd->needThis() || fd->isNested())) buf.writeByte(Type::needThisPrefix()); if (isv && fd && (fd->inferRetType || getFuncTemplateDecl(fd))) { #if DDMD TypeFunction *tfn = (TypeFunction *)sthis->type->copy(); TypeFunction *tfo = (TypeFunction *)sthis->originalType; tfn->purity = tfo->purity; tfn->isnothrow = tfo->isnothrow; tfn->isproperty = tfo->isproperty; tfn->isref = fd->storage_class & STCauto ? false : tfo->isref; tfn->trust = tfo->trust; tfn->next = NULL; // do not mangle return type tfn->toDecoBuffer(&buf, 0); #else TypeFunction tfn = *(TypeFunction *)sthis->type; TypeFunction *tfo = (TypeFunction *)sthis->originalType; tfn.purity = tfo->purity; tfn.isnothrow = tfo->isnothrow; tfn.isproperty = tfo->isproperty; tfn.isref = fd->storage_class & STCauto ? false : tfo->isref; tfn.trust = tfo->trust; tfn.next = NULL; // do not mangle return type tfn.toDecoBuffer(&buf, 0); #endif } else if (sthis->type->deco) buf.writestring(sthis->type->deco); else { #ifdef DEBUG if (!fd->inferRetType) printf("%s\n", fd->toChars()); #endif assert(fd && fd->inferRetType && fd->type->ty == Tfunction); TypeFunction *tf = (TypeFunction *)sthis->type; Type *tn = tf->next; tf->next = NULL; // do not mangle undetermined return type tf->toDecoBuffer(&buf, 0); tf->next = tn; } id = buf.extractString(); return id; }
// Split a path into an Array of paths Strings *FileName::splitPath(const char *path) { char c = 0; // unnecessary initializer is for VC /W4 const char *p; OutBuffer buf; Strings *array; array = new Strings(); if (path) { p = path; do { char instring = 0; while (isspace((utf8_t)*p)) // skip leading whitespace p++; buf.reserve(strlen(p) + 1); // guess size of path for (; ; p++) { c = *p; switch (c) { case '"': instring ^= 1; // toggle inside/outside of string continue; #if MACINTOSH case ',': #endif #if _WIN32 case ';': #endif #if POSIX case ':': #endif p++; break; // note that ; cannot appear as part // of a path, quotes won't protect it case 0x1A: // ^Z means end of file case 0: break; case '\r': continue; // ignore carriage returns #if POSIX case '~': buf.writestring(getenv("HOME")); continue; #endif #if 0 case ' ': case '\t': // tabs in filenames? if (!instring) // if not in string break; // treat as end of path #endif default: buf.writeByte(c); continue; } break; } if (buf.offset) // if path is not empty { array->push(buf.extractString()); } } while (c); } return array; }
char *finish() { return buf.extractString(); }