static int badPath(char_t* path, char_t* badPath, int badLen) { int retval = 0; int len = gstrlen(path); int i = 0; if (len <= badLen +1) { for (i = 0; i < badLen; ++i) { if (badPath[i] != gtolower(path[i])) { return 0; } } /* if we get here, the first 'badLen' characters match. * If 'path' is 1 character larger than 'badPath' and that extra * character is NOT a letter or a number, we have a bad path. */ retval = 1; if (badLen + 1 == len) { /* e.g. path == "aux:" */ if (gisalnum(path[len-1])) { /* the last character is alphanumeric, so we let this path go * through. */ retval = 0; } } } return retval; }
void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)) { bStatsFileType *fp, *files; bStatsBlkType *blkp; bType *bp; char_t *cp; int q, count, mem, total, len; static int recurseProtect = 0; if (recurseProtect++ > 0) { recurseProtect--; return; } if (writefn == NULL) { writefn = bstatsWrite; } /* * Print stats for each memory block */ (*writefn)(handle, T("\nMemory Stats\n")); /* * The following tabular format is now used for the output. * Q Size Free Bytes Inuse Bytes Allocs * dd ddddd ddd ddddd dddd ddddd dddd */ (*writefn)(handle, " Q Size Free Bytes Inuse Bytes Allocs\n"); total = 0; for (q = 0; q < B_MAX_CLASS; q++) { count = 0; for (bp = bQhead[q]; bp; bp = bp->u.next) { count++; } mem = count * (1 << (q + B_SHIFT)); total += mem; (*writefn)(handle, T("%2d %5d %4d %6d %4d %5d %4d\n"), q, 1 << (q + B_SHIFT), count, mem, bStats[q].inuse, bStats[q].inuse * (1 << (q + B_SHIFT)), bStats[q].alloc); } (*writefn)(handle, T("\n")); /* * Print summary stats * * bFreeSize Initial memory reserved with bopen call * bStatsMemMalloc memory from calls to system MALLOC * bStatsMemMax * bStatsBallocMax largest amount of memory from balloc calls * bStatsMemInUse * bStatsBallocInUse present balloced memory being used * bStatsBlksMax); * bStackStart * bStackMin); * total); * bFreeLeft); * */ (*writefn)(handle, T("Initial free list size %7d\n"), bFreeSize); (*writefn)(handle, T("Max memory malloced %7d\n"), bStatsMemMalloc); (*writefn)(handle, T("Max memory ever used %7d\n"), bStatsMemMax); (*writefn)(handle, T("Max memory ever balloced %7d\n"), bStatsBallocMax); (*writefn)(handle, T("Memory currently in use %7d\n"), bStatsMemInUse); (*writefn)(handle, T("Memory currently balloced %7d\n"), bStatsBallocInUse); (*writefn)(handle, T("Max blocks allocated %7d\n"), bStatsBlksMax); (*writefn)(handle, T("Maximum stack used %7d\n"), (int) bStackStart - (int) bStackMin); (*writefn)(handle, T("Free memory on all queues %7d\n"), total); (*writefn)(handle, T("Free list buffer left %7d\n"), bFreeLeft); (*writefn)(handle, T("Total free memory %7d\n"), bFreeLeft + total); /* * Print per file allocation stats. Sort the copied table. */ len = sizeof(bStatsFileType) * B_MAX_FILES; files = malloc(len); if (files == NULL) { (*writefn)(handle, T("Can't allocate stats memory\n")); recurseProtect--; return; } memcpy(files, bStatsFiles, len); qsort(files, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort); (*writefn)(handle, T("\nMemory Currently Allocated\n")); total = 0; (*writefn)(handle, T(" bytes, blocks in use, total times,") T("largest, q\n")); for (fp = files; fp < &files[bStatsFilesMax]; fp++) { if (fp->file[0]) { (*writefn)(handle, T("%18s, %7d, %5d, %6d, %7d,%4d\n"), fp->file, fp->allocated, fp->count, fp->times, fp->largest, fp->q); total += fp->allocated; } } (*writefn)(handle, T("\nTotal allocated %7d\n\n"), total); /* * Dump the actual strings */ (*writefn)(handle, T("\nStrings\n")); for (blkp = &bStatsBlks[bStatsBlksMax - 1]; blkp >= bStatsBlks; blkp--) { if (blkp->ptr) { cp = (char_t*) ((char*) blkp->ptr + sizeof(bType)); fp = blkp->who; if (gisalnum(*cp)) { (*writefn)(handle, T("%-50s allocated by %s\n"), cp, fp->file); } } } free(files); recurseProtect--; }
static int getLexicalToken(ej_t* ep, int state) { ringq_t *inq, *tokq; ejinput_t* ip; int done, tid, c, quote, style; a_assert(ep); ip = ep->input; a_assert(ip); inq = &ip->script; tokq = &ip->tokbuf; ep->tid = -1; tid = -1; ep->token = T(""); ringqFlush(tokq); if (ip->putBackTokenId > 0) { ringqPutStr(tokq, ip->putBackToken); tid = ip->putBackTokenId; ip->putBackTokenId = 0; ep->token = (char_t*) tokq->servp; return tid; } if ((c = inputGetc(ep)) < 0) { return TOK_EOF; } for (done = 0; !done; ) { switch (c) { case -1: return TOK_EOF; case ' ': case '\t': case '\r': do { if ((c = inputGetc(ep)) < 0) break; } while (c == ' ' || c == '\t' || c == '\r'); break; case '\n': return TOK_NEWLINE; case '(': tokenAddChar(ep, c); return TOK_LPAREN; case ')': tokenAddChar(ep, c); return TOK_RPAREN; case '{': tokenAddChar(ep, c); return TOK_LBRACE; case '}': tokenAddChar(ep, c); return TOK_RBRACE; case '+': if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c != '+' ) { inputPutback(ep, c); tokenAddChar(ep, EXPR_PLUS); return TOK_EXPR; } tokenAddChar(ep, EXPR_INC); return TOK_INC_DEC; case '-': if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c != '-' ) { inputPutback(ep, c); tokenAddChar(ep, EXPR_MINUS); return TOK_EXPR; } tokenAddChar(ep, EXPR_DEC); return TOK_INC_DEC; case '*': tokenAddChar(ep, EXPR_MUL); return TOK_EXPR; case '%': tokenAddChar(ep, EXPR_MOD); return TOK_EXPR; case '/': /* * Handle the division operator and comments */ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c != '*' && c != '/') { inputPutback(ep, c); tokenAddChar(ep, EXPR_DIV); return TOK_EXPR; } style = c; /* * Eat comments. Both C and C++ comment styles are supported. */ while (1) { if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '\n' && style == '/') { break; } else if (c == '*') { c = inputGetc(ep); if (style == '/') { if (c == '\n') { break; } } else { if (c == '/') { break; } } } } /* * Continue looking for a token, so get the next character */ if ((c = inputGetc(ep)) < 0) { return TOK_EOF; } break; case '<': /* < and <= */ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '<') { tokenAddChar(ep, EXPR_LSHIFT); return TOK_EXPR; } else if (c == '=') { tokenAddChar(ep, EXPR_LESSEQ); return TOK_EXPR; } tokenAddChar(ep, EXPR_LESS); inputPutback(ep, c); return TOK_EXPR; case '>': /* > and >= */ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '>') { tokenAddChar(ep, EXPR_RSHIFT); return TOK_EXPR; } else if (c == '=') { tokenAddChar(ep, EXPR_GREATEREQ); return TOK_EXPR; } tokenAddChar(ep, EXPR_GREATER); inputPutback(ep, c); return TOK_EXPR; case '=': /* "==" */ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '=') { tokenAddChar(ep, EXPR_EQ); return TOK_EXPR; } inputPutback(ep, c); return TOK_ASSIGNMENT; case '!': /* "!=" or "!"*/ if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } if (c == '=') { tokenAddChar(ep, EXPR_NOTEQ); return TOK_EXPR; } inputPutback(ep, c); tokenAddChar(ep, EXPR_BOOL_COMP); return TOK_EXPR; case ';': tokenAddChar(ep, c); return TOK_SEMI; case ',': tokenAddChar(ep, c); return TOK_COMMA; case '|': /* "||" */ if ((c = inputGetc(ep)) < 0 || c != '|') { ejError(ep, T("Syntax Error")); return TOK_ERR; } tokenAddChar(ep, COND_OR); return TOK_LOGICAL; case '&': /* "&&" */ if ((c = inputGetc(ep)) < 0 || c != '&') { ejError(ep, T("Syntax Error")); return TOK_ERR; } tokenAddChar(ep, COND_AND); return TOK_LOGICAL; case '\"': /* String quote */ case '\'': quote = c; if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Syntax Error")); return TOK_ERR; } while (c != quote) { /* * check for escape sequence characters */ if (c == '\\') { c = inputGetc(ep); if (gisdigit(c)) { /* * octal support, \101 maps to 65 = 'A'. put first char * back so converter will work properly. */ inputPutback(ep, c); c = charConvert(ep, OCTAL, 3); } else { switch (c) { case 'n': c = '\n'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'x': /* * hex support, \x41 maps to 65 = 'A' */ c = charConvert(ep, HEX, 2); break; case 'u': /* * unicode support, \x0401 maps to 65 = 'A' */ c = charConvert(ep, HEX, 2); c = c*16 + charConvert(ep, HEX, 2); break; case '\'': case '\"': case '\\': break; default: ejError(ep, T("Invalid Escape Sequence")); return TOK_ERR; } } if (tokenAddChar(ep, c) < 0) { return TOK_ERR; } } else { if (tokenAddChar(ep, c) < 0) { return TOK_ERR; } } if ((c = inputGetc(ep)) < 0) { ejError(ep, T("Unmatched Quote")); return TOK_ERR; } } return TOK_LITERAL; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': do { if (tokenAddChar(ep, c) < 0) { return TOK_ERR; } if ((c = inputGetc(ep)) < 0) break; } while (gisdigit(c)); inputPutback(ep, c); return TOK_LITERAL; default: /* * Identifiers or a function names */ while (1) { if (c == '\\') { /* * just ignore any \ characters. */ } else if (tokenAddChar(ep, c) < 0) { break; } if ((c = inputGetc(ep)) < 0) { break; } if (!gisalnum(c) && c != '$' && c != '_' && c != '\\') { break; } } if (! gisalpha(*tokq->servp) && *tokq->servp != '$' && *tokq->servp != '_') { ejError(ep, T("Invalid identifier %s"), tokq->servp); return TOK_ERR; } /* * Check for reserved words (only "if", "else", "var", "for" * and "return" at the moment) */ if (state == STATE_STMT) { if (gstrcmp(ep->token, T("if")) == 0) { return TOK_IF; } else if (gstrcmp(ep->token, T("else")) == 0) { return TOK_ELSE; } else if (gstrcmp(ep->token, T("var")) == 0) { return TOK_VAR; } else if (gstrcmp(ep->token, T("for")) == 0) { return TOK_FOR; } else if (gstrcmp(ep->token, T("return")) == 0) { if ((c == ';') || (c == '(')) { inputPutback(ep, c); } return TOK_RETURN; } } /* * Skip white space after token to find out whether this is * a function or not. */ while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { if ((c = inputGetc(ep)) < 0) break; } tid = (c == '(') ? TOK_FUNCTION : TOK_ID; done++; } } /* * Putback the last extra character for next time */ inputPutback(ep, c); return tid; }