int ejsGrowConstants(Ejs *ejs, EjsModule *mp, ssize len) { EjsConstants *cp; int indexSize; lock(mp); cp = mp->constants; if ((cp->poolLength + len) >= cp->poolSize) { cp->poolSize = ((cp->poolSize + len) + EC_BUFSIZE - 1) / EC_BUFSIZE * EC_BUFSIZE; if ((cp->pool = mprRealloc(cp->pool, cp->poolSize)) == 0) { unlock(mp); return MPR_ERR_MEMORY; } } if (cp->indexCount >= cp->indexSize) { indexSize = ((cp->indexCount + EJS_INDEX_INCR) / EJS_INDEX_INCR) * EJS_INDEX_INCR; if ((cp->index = mprRealloc(cp->index, indexSize * sizeof(EjsString*))) == NULL) { unlock(mp); return MPR_ERR_MEMORY; } cp->indexSize = indexSize; } unlock(mp); return 0; }
static void testBasicAlloc(MprTestGroup *gp) { char *cp; int size; size = 16; cp = (char*) mprAlloc(gp, size); assert(cp != 0); memset(cp, 0x77, size); mprFree(cp); cp = (char*) mprAlloc(gp, size); assert(cp != 0); memset(cp, 0x77, size); cp = (char*) mprRealloc(gp, cp, size * 2); assert(cp != 0); mprFree(cp); cp = mprStrdup(gp, "Hello World"); assert(cp != 0); assert(strcmp(cp, "Hello World") == 0); mprFree(cp); /* * Test special MR allowances */ mprFree(0); cp = mprStrdup(gp, 0); assert(cp != 0); assert(cp[0] == '\0'); mprFree(cp); }
char *srejoinv(char *buf, va_list args) { va_list ap; char *dest, *str, *dp; ssize len, required; va_copy(ap, args); len = slen(buf); required = len + 1; str = va_arg(ap, char*); while (str) { required += slen(str); str = va_arg(ap, char*); } if ((dest = mprRealloc(buf, required)) == 0) { return 0; } dp = &dest[len]; va_copy(ap, args); str = va_arg(ap, char*); while (str) { strcpy(dp, str); dp += slen(str); str = va_arg(ap, char*); } *dp = '\0'; return dest; }
static int growTokenBuf(EspParse *parse, int nchar) { char *newBuf; int extra; mprAssert(parse); mprAssert(parse->tokp); mprAssert(parse->endp); mprAssert(nchar > 0); if (parse->tokp >= &parse->endp[- nchar]) { extra = max(nchar, ESP_TOK_INCR); newBuf = (char*) mprRealloc(parse->token, parse->tokLen + extra); if (newBuf == 0) { return ESP_TOK_ERR; } parse->tokp += (newBuf - parse->token); parse->endp += (newBuf - parse->token); parse->tokLen += extra; parse->endp += extra; parse->token = newBuf; *parse->tokp = '\0'; } return 0; }
/* * Format the stack backtrace */ char *ejsFormatStack(Ejs *ejs) { EjsFrame *frame; EjsType *type; EjsFunction *fun; cchar *typeName, *functionName, *line, *typeSep, *codeSep; char *backtrace, *traceLine; int level, len; mprAssert(ejs); backtrace = 0; len = 0; level = 0; for (frame = ejs->frame; frame; frame = frame->caller) { if (frame->currentLine == 0) { line = ""; } else { for (line = frame->currentLine; *line && isspace((int) *line); line++) { ; } } typeName = ""; functionName = "global"; fun = &frame->function; if (fun) { if (fun->owner) { functionName = ejsGetPropertyName(ejs, fun->owner, fun->slotNum).name; } if (ejsIsType(fun->owner)) { type = (EjsType*) fun->owner; if (type) { typeName = type->qname.name; } } } typeSep = (*typeName) ? "." : ""; codeSep = (*line) ? "->" : ""; if (mprAllocSprintf(ejs, &traceLine, MPR_MAX_STRING, " [%02d] %s, %s%s%s, line %d %s %s\n", level++, frame->fileName ? frame->fileName : "script", typeName, typeSep, functionName, frame->lineNumber, codeSep, line) < 0) { break; } backtrace = (char*) mprRealloc(ejs, backtrace, len + (int) strlen(traceLine) + 1); if (backtrace == 0) { return 0; } memcpy(&backtrace[len], traceLine, strlen(traceLine) + 1); len += (int) strlen(traceLine); mprFree(traceLine); } return backtrace; }
/* Read a line from the file. This will put the file into buffered mode. Return NULL on eof. */ PUBLIC char *mprReadLine(MprFile *file, ssize maxline, ssize *lenp) { MprBuf *bp; MprFileSystem *fs; ssize size, len, nlen, consumed; cchar *eol, *newline, *start; char *result; assert(file); if (file == 0) { return NULL; } if (lenp) { *lenp = 0; } if (maxline <= 0) { maxline = ME_MAX_BUFFER; } fs = file->fileSystem; newline = fs->newline; if (file->buf == 0) { file->buf = mprCreateBuf(maxline, maxline); } bp = file->buf; result = NULL; size = 0; do { if (mprGetBufLength(bp) == 0) { if (fillBuf(file) <= 0) { return result; } } start = mprGetBufStart(bp); len = mprGetBufLength(bp); if ((eol = findNewline(start, newline, len, &nlen)) != 0) { len = eol - start; consumed = len + nlen; } else { consumed = len; } file->pos += (MprOff) consumed; if (lenp) { *lenp += len; } if ((result = mprRealloc(result, size + len + 1)) == 0) { return NULL; } memcpy(&result[size], start, len); size += len; result[size] = '\0'; mprAdjustBufStart(bp, consumed); } while (!eol); return result; }
static int growArray(Ejs *ejs, EjsArray *ap, int len) { EjsObj **dp; ssize size, factor, count; int i; assert(ap); if (len <= 0) { return 0; } if (len <= ap->length) { return 0; } size = mprGetBlockSize(ap->data); size = (int) (mprGetBlockSize(ap->data) / sizeof(EjsObj*)); /* Allocate or grow the data structures. */ if (len > size) { if (size > EJS_LOTSA_PROP) { /* Looks like a big object so grow by a bigger chunk */ factor = max(size / 4, EJS_ROUND_PROP); count = (len + factor) / factor * factor; } else { count = len; } // OPT - this is currently 16 count = EJS_PROP_ROUNDUP(count); if (ap->data == 0) { assert(ap->length == 0); assert(count > 0); if ((ap->data = mprAllocZeroed(sizeof(EjsObj*) * count)) == 0) { return EJS_ERR; } } else { assert(size > 0); if ((ap->data = mprRealloc(ap->data, sizeof(EjsObj*) * count)) == 0) { return EJS_ERR; } } dp = &ap->data[ap->length]; for (i = ap->length; i < count; i++) { *dp++ = ESV(undefined); } } else { mprNop(ITOP(size)); } ap->length = len; return 0; }
static int addCharToToken(EcToken *tp, int c) { if (tp->length >= (tp->size - 1)) { tp->size += EC_TOKEN_INCR; if ((tp->text = mprRealloc(tp->text, tp->size * sizeof(wchar))) == 0) { return MPR_ERR_MEMORY; } } tp->text[tp->length++] = c; tp->text[tp->length] = '\0'; if (tp->loc.lineNumber == 0) { tp->loc = tp->stream->loc; } return 0; }
static int growArray(Ejs *ejs, EjsArray *ap, int len) { int size, count, factor; mprAssert(ap); if (len <= 0) { return 0; } if (len <= ap->length) { return 0; } size = mprGetBlockSize(ap->data) / (int) sizeof(EjsVar*); /* * Allocate or grow the data structures. */ if (len > size) { if (size > EJS_LOTSA_PROP) { /* * Looks like a big object so grow by a bigger chunk */ factor = max(size / 4, EJS_NUM_PROP); count = (len + factor) / factor * factor; } else { count = len; } count = EJS_PROP_ROUNDUP(count); if (ap->data == 0) { mprAssert(ap->length == 0); mprAssert(count > 0); ap->data = (EjsVar**) mprAllocZeroed(ap, (int) sizeof(EjsVar*) * count); if (ap->data == 0) { return EJS_ERR; } } else { mprAssert(size > 0); ap->data = (EjsVar**) mprRealloc(ap, ap->data, (int) sizeof(EjsVar*) * count); if (ap->data == 0) { return EJS_ERR; } ejsZeroSlots(ejs, &ap->data[ap->length], (count - ap->length)); } } ap->length = len; return 0; }
/* * Grow the string buffer for a unicode string */ static int growUs(uni *us, int len) { mprAssert(us); mprAssert(len >= 0); if (len < us->length) { return 0; } us->str = mprRealloc(us, us->str, len); if (us->str == 0) { return MPR_ERR_NO_MEMORY; } us->length = len; return 0; }
PUBLIC char *httpReadString(HttpStream *stream) { HttpRx *rx; ssize sofar, nbytes, remaining; char *content; rx = stream->rx; if (rx->length < 0) { return 0; } remaining = (ssize) min(MAXSSIZE, rx->length); if (remaining > 0) { if ((content = mprAlloc(remaining + 1)) == 0) { return 0; } sofar = 0; while (remaining > 0) { nbytes = httpRead(stream, &content[sofar], remaining); if (nbytes < 0) { return 0; } sofar += nbytes; remaining -= nbytes; } } else { content = NULL; sofar = 0; while (1) { if ((content = mprRealloc(content, sofar + ME_BUFSIZE)) == 0) { return 0; } nbytes = httpRead(stream, &content[sofar], ME_BUFSIZE); if (nbytes < 0) { return 0; } else if (nbytes == 0) { break; } sofar += nbytes; } } content[sofar] = '\0'; return content; }
// TODO OPT static int addCharToToken(EcToken *tp, int c) { if (tp->currentLine == 0) { setTokenCurrentLine(tp); } if (tp->textLen >= (tp->textBufSize - 1)) { // TODO - seem to be reallocing a lot. Are tokens being reused? tp->text = (uchar*) mprRealloc(tp, tp->text, tp->textBufSize += EC_TOKEN_INCR); if (tp->text == 0) { return MPR_ERR_NO_MEMORY; } } tp->text[tp->textLen++] = c; mprAssert(tp->textLen < tp->textBufSize); tp->text[tp->textLen] = '\0'; return 0; }
/* * Grow the list by the requried increment */ static int growList(MprCtx ctx, EjsList *lp, int incr) { int len, memsize, capacity; /* * Need to grow the list */ capacity = CAPACITY(lp->items); mprAssert(capacity >= 0); if (capacity >= lp->maxSize) { if (lp->maxSize == 0) { lp->maxSize = INT_MAX; } else { mprAssert(capacity < lp->maxSize); return MPR_ERR_TOO_MANY; } } /* * If growing by 1, then use the default increment which exponentially grows. * Otherwise, assume the caller knows exactly how the list needs to grow. */ if (incr <= 1) { len = MPR_LIST_INCR + capacity + capacity; } else { len = capacity + incr; } memsize = (int) (len * sizeof(void*)); /* * Grow the list of items. Use the existing context for lp->items if it already exists. Otherwise use the list as the * memory context owner. */ lp->items = (void**) mprRealloc(ctx, lp->items, memsize); /* * Zero the new portion (required for no-compact lists) */ memset(&lp->items[capacity], 0, sizeof(void*) * (len - capacity)); return 0; }
int mprAddToArray(MprArray *array, void *item) { int memsize, idx, len; mprAssert(array); mprAssert(array->max >= 0); mprAssert(array->used >= 0); if (array->used < array->max) { idx = array->used++; mprAssert(idx >= 0 && idx < array->max); mprAssert(array->handles[idx] == 0); array->handles[idx] = item; return idx; } for (idx = array->used; idx < array->max; idx++) { if (array->handles[idx] == 0) { array->used++; mprAssert(array->handles[idx] == 0); array->handles[idx] = item; return idx; } } len = array->max + MPR_ARRAY_INCR; memsize = len * sizeof(void*); array->handles = (void**) mprRealloc((void*) array->handles, memsize); if (array->handles == NULL) { return -1; } memset(&array->handles[array->max], 0, sizeof(void*) * MPR_ARRAY_INCR); array->max = len; array->used++; mprAssert(idx >= 0 && idx < array->max); mprAssert(array->handles[idx] == 0); array->handles[idx] = item; return idx; }
/* Read data as a string */ PUBLIC char *httpReadString(HttpConn *conn) { HttpRx *rx; ssize sofar, nbytes, remaining; char *content; rx = conn->rx; remaining = (ssize) min(MAXSSIZE, rx->length); if (remaining > 0) { if ((content = mprAlloc(remaining + 1)) == 0) { return 0; } sofar = 0; while (remaining > 0) { nbytes = httpRead(conn, &content[sofar], remaining); if (nbytes < 0) { return 0; } sofar += nbytes; remaining -= nbytes; } } else { content = mprAlloc(BIT_MAX_BUFFER); sofar = 0; while (1) { nbytes = httpRead(conn, &content[sofar], BIT_MAX_BUFFER); if (nbytes < 0) { return 0; } else if (nbytes == 0) { break; } sofar += nbytes; content = mprRealloc(content, sofar + BIT_MAX_BUFFER); } } content[sofar] = '\0'; return content; }
static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, const char *delim, const char *src, va_list args) { va_list ap; char *dest, *dp; const char *str; int sepLen, addBytes, required; mprAssert(destp); mprAssert(destMax > 0); mprAssert(src); dest = *destp; sepLen = (delim) ? strlen(delim) : 0; va_copy(ap, args); addBytes = 0; str = src; while (str) { addBytes += strlen(str) + sepLen; str = va_arg(ap, const char*); } va_end(ap); if (existingLen > 0) { addBytes += sepLen; } required = existingLen + addBytes + 1; if (required >= destMax) { mprAssert(0); return MPR_ERR_WONT_FIT; } if (alloc) { if (dest == 0) { dest = (char*) mprMalloc(required); } else { dest = (char*) mprRealloc(dest, required); } } else { dest = (char*) *destp; } dp = &dest[existingLen]; if (delim) { strcpy(dp, delim); dp += sepLen; } if (addBytes > 0) { va_copy(ap, args); str = src; while (str) { strcpy(dp, str); dp += strlen(str); str = va_arg(ap, char*); if (delim && str) { strcpy(dp, delim); dp += sepLen; } } va_end(ap); } else if (dest == 0) {
/* Determine the windows program to invoke. Support UNIX style "#!/program" bang directives on windows. Also supports ".cmd" and ".bat" alternatives. */ static void prepWinProgram(MprCmd *cmd) { #if ME_WIN_LIKE MprFile *file; cchar *bat, *ext, *shell, *cp, *start; char bang[ME_MAX_FNAME + 1], *path, *pp; /* Map separators, convert carriage-returns and newlines to spaces and remove quotes on the command */ path = mprAlloc(slen(cmd->argv[0]) * 2 + 1); strcpy(path, cmd->argv[0]); for (pp = path; *pp; pp++) { if (*pp == '/') { *pp = '\\'; } else if (*pp == '\r' || *pp == '\n') { *pp = ' '; } } if (*path == '\"') { if ((pp = strrchr(++path, '"')) != 0) { *pp = '\0'; } path = sclone(path); } cmd->argv[0] = path; /* Support ".cmd" and ".bat" files that take precedence */ if ((ext = mprGetPathExt(path)) == 0) { if ((bat = mprSearchPath(mprJoinPathExt(path, ".cmd"), MPR_SEARCH_EXE, cmd->searchPath, NULL)) == 0) { bat = mprSearchPath(mprJoinPathExt(path, ".bat"), MPR_SEARCH_EXE, cmd->searchPath, NULL); } if (bat) { if ((shell = getenv("COMSPEC")) == 0) { shell = "cmd.exe"; } cmd->argv = mprRealloc((void*) cmd->argv, (cmd->argc + 4) * sizeof(char*)); memmove((void*) &cmd->argv[3], (void*) cmd->argv, sizeof(char*) * (cmd->argc + 1)); cmd->argv[0] = sclone(shell); cmd->argv[1] = sclone("/Q"); cmd->argv[2] = sclone("/C"); cmd->argv[3] = bat; cmd->argc += 3; cmd->argv[cmd->argc] = 0; return; } } if ((file = mprOpenFile(path, O_RDONLY, 0)) != 0) { if (mprReadFile(file, bang, ME_MAX_FNAME) > 0) { mprCloseFile(file); bang[ME_MAX_FNAME] = '\0'; if (bang[0] == '#' && bang[1] == '!') { cp = start = &bang[2]; shell = ssplit(&bang[2], "\r\n", NULL); if (!mprIsPathAbs(shell)) { /* If we cannot access the command shell and the command is not an absolute path, look in the same directory as the script. */ if (mprPathExists(shell, X_OK)) { shell = mprJoinPath(mprGetPathDir(path), shell); } } /* Get length of argv with NULL and add one */ assert(cmd->argv[cmd->argc] == 0); cmd->argv = mprRealloc((void*) cmd->argv, (cmd->argc + 2) * sizeof(char*)); cmd->argv[cmd->argc + 1] = 0; /* Copy up to make room to insert the shell argument. This copies the original NULL */ memmove((void*) &cmd->argv[1], (void*) cmd->argv, sizeof(char*) * cmd->argc); cmd->argv[0] = sclone(shell); cmd->argv[1] = path; cmd->argc += 1; assert(cmd->argv[cmd->argc] == 0); } } else { mprCloseFile(file); } } #endif }
/* * Format the stack backtrace */ char *ejsFormatStack(Ejs *ejs, EjsError *error) { EjsType *type; EjsFrame *fp; cchar *typeName, *functionName, *line, *typeSep, *codeSep; char *backtrace, *traceLine; int level, len, oldFlags; mprAssert(ejs); backtrace = 0; len = 0; level = 0; /* * Pretend to be the compiler so we can access function frame names */ oldFlags = ejs->flags; ejs->flags |= EJS_FLAG_COMPILER; for (fp = ejs->state->fp; fp; fp = fp->caller) { typeName = ""; functionName = "global"; if (fp->currentLine == 0) { line = ""; } else { for (line = fp->currentLine; *line && isspace((int) *line); line++) { ; } } if (fp) { if (fp->function.owner && fp->function.slotNum >= 0) { functionName = ejsGetPropertyName(ejs, fp->function.owner, fp->function.slotNum).name; } if (ejsIsType(fp->function.owner)) { type = (EjsType*) fp->function.owner; if (type) { typeName = type->qname.name; } } } typeSep = (*typeName) ? "." : ""; codeSep = (*line) ? "->" : ""; if (error && backtrace == 0) { error->filename = mprStrdup(error, fp->filename); error->lineNumber = fp->lineNumber; } if ((traceLine = mprAsprintf(ejs, MPR_MAX_STRING, " [%02d] %s, %s%s%s, line %d %s %s\n", level++, fp->filename ? fp->filename : "script", typeName, typeSep, functionName, fp->lineNumber, codeSep, line)) == NULL) { break; } backtrace = (char*) mprRealloc(ejs, backtrace, len + (int) strlen(traceLine) + 1); if (backtrace == 0) { return 0; } memcpy(&backtrace[len], traceLine, strlen(traceLine) + 1); len += (int) strlen(traceLine); mprFree(traceLine); } ejs->flags = oldFlags; if (error) { error->stack = backtrace; } return backtrace; }