📄 diag.c
字号:
if (s == NULL) s = "%n.%p.trace";#if TARGET == TARGET_UNIX sprintf(p, "%s/%s", d, s);#elif TARGET == TARGET_AMIGA if ((d[strlen(d) - 1] == ':') || (d[strlen(d) - 1] == '/')) sprintf(p, "%s%s", d, s); else sprintf(p, "%s/%s", d, s);#else /* TARGET */ sprintf(p, "%s\\%s", d, s);#endif /* TARGET */ processfile(m, p, b, sizeof(b)); } else { if (s == NULL) s = MP_TRACEFILE; processfile(m, s, b, sizeof(b)); } return b;}/* Attempt to open the log file. */MP_GLOBALint__mp_openlogfile(char *s){ /* The log file name can also be named as stderr and stdout which will go * to the standard error and standard output streams respectively. */ if ((s == NULL) || (strcmp(s, "stderr") == 0)) logfile = stderr; else if (strcmp(s, "stdout") == 0) logfile = stdout; else if ((logfile = fopen(s, "w")) == NULL) { /* Because logfile is NULL, the __mp_error() function will open the log * file as stderr, which should always work. */ logfile = stderr; __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot open file\n", s); return 0; } /* Attempt to set the stream buffer for the log file. This is done here so * that we won't get recursive memory allocations if the standard library * tries to allocate space for the stream buffer. */ if ((logfile == stderr) ||#if defined(HAVE_CONFIG_H) && defined(SETVBUF_REVERSED) setvbuf(logfile, _IOLBF, buffer, sizeof(buffer)))#else /* HAVE_CONFIG_H && SETVBUF_REVERSED */ setvbuf(logfile, buffer, _IOLBF, sizeof(buffer)))#endif /* HAVE_CONFIG_H && SETVBUF_REVERSED */ /* If that failed, or the log file is stderr, then we set the buffering * mode for the log file to none. The standard error stream is not * guaranteed to be unbuffered by default on all systems. */#if defined(HAVE_CONFIG_H) && defined(SETVBUF_REVERSED) setvbuf(logfile, _IONBF, NULL, 0);#else /* HAVE_CONFIG_H && SETVBUF_REVERSED */ setvbuf(logfile, NULL, _IONBF, 0);#endif /* HAVE_CONFIG_H && SETVBUF_REVERSED */ if ((__mp_diagflags & FLG_HTMLNEXT) && (s != NULL)) { __mp_diagflags |= FLG_HTML; __mp_diagtag("<HTML>\n"); __mp_diagtag("<HEAD>\n"); __mp_diagtag("<META NAME=\"GENERATOR\" CONTENT=\"" MP_VERSION "\">\n"); __mp_diagtag("<TITLE>"); __mp_diag("mpatrol log"); __mp_diagtag("</TITLE>\n"); __mp_diagtag("</HEAD>\n"); __mp_diagtag("<BODY>\n"); __mp_diagtag("<H3>"); __mp_diag("mpatrol log"); __mp_diagtag("</H3>\n"); __mp_diagtag("<P>\n"); } else __mp_diagflags &= ~FLG_HTML; return 1;}/* Attempt to close the log file. */MP_GLOBALint__mp_closelogfile(void){ int r; r = 1; if (__mp_diagflags & FLG_HTML) { __mp_diagtag("</BODY>\n"); __mp_diagtag("</HTML>\n"); } if ((logfile == NULL) || (logfile == stderr) || (logfile == stdout)) { /* We don't want to close the stderr or stdout file streams so * we just flush them instead. If the log file hasn't been set, * this will just flush all open output files. */ if (fflush(logfile)) r = 0; } else if (fclose(logfile)) r = 0; logfile = NULL; return r;}/* Sends a diagnostic message to the log file. */MP_GLOBALvoid__mp_diag(char *s, ...){ char b[2048]; char *t; va_list v; char c; if (logfile == NULL) __mp_openlogfile(NULL); va_start(v, s); if (__mp_diagflags & FLG_HTML) vsprintf(b, s, v); else vfprintf(logfile, s, v); va_end(v); /* If we are outputting HTML then we must filter the diagnostics to ensure * that we replace <, >, & and " with <, >, & and " respectively. */ if (__mp_diagflags & FLG_HTML) for (s = t = b; t != NULL; s = t + 1) { if (t = strpbrk(s, "<>&\"")) { c = *t; *t = '\0'; } if (*s != '\0') fputs(s, logfile); if (t != NULL) switch (c) { case '<': fputs("<", logfile); break; case '>': fputs(">", logfile); break; case '&': fputs("&", logfile); break; case '"': fputs(""", logfile); break; default: break; } }}/* Sends an HTML tag to the log file. */MP_GLOBALvoid__mp_diagtag(char *s){ if (logfile == NULL) __mp_openlogfile(NULL); fputs(s, logfile);}/* Sends a warning message to the log file. */MP_GLOBALvoid__mp_warn(errortype e, alloctype f, char *n, unsigned long l, char *s, ...){ va_list v; if (logfile == NULL) __mp_openlogfile(NULL); __mp_diag("WARNING: "); if (e != ET_MAX) __mp_diag("[%s]: ", __mp_errordetails[e].code); if (f != AT_MAX) __mp_diag("%s: ", __mp_functionnames[f]); va_start(v, s); if ((s == NULL) && (__mp_errordetails[e].format != NULL)) vfprintf(logfile, __mp_errordetails[e].format, v); else vfprintf(logfile, s, v); va_end(v); __mp_diag("\n"); if (((__mp_diagflags & FLG_EDIT) || (__mp_diagflags & FLG_LIST)) && (n != NULL)) { if (logfile != stderr) { fputs("WARNING: ", stderr); if (e != ET_MAX) fprintf(stderr, "[%s]: ", __mp_errordetails[e].code); if (f != AT_MAX) fprintf(stderr, "%s: ", __mp_functionnames[f]); va_start(v, s); if ((s == NULL) && (__mp_errordetails[e].format != NULL)) vfprintf(stderr, __mp_errordetails[e].format, v); else vfprintf(stderr, s, v); va_end(v); fputc('\n', stderr); } if (__mp_editfile(n, l, ((__mp_diagflags & FLG_LIST) != 0)) == -1) fprintf(stderr, "ERROR: problems %sing file `%s'\n", (__mp_diagflags & FLG_LIST) ? "list" : "edit", n); } __mp_errno = e; warnings++;}/* Sends an error message to the log file. */MP_GLOBALvoid__mp_error(errortype e, alloctype f, char *n, unsigned long l, char *s, ...){ va_list v; if (logfile == NULL) __mp_openlogfile(NULL); __mp_diag("ERROR: "); if (e != ET_MAX) __mp_diag("[%s]: ", __mp_errordetails[e].code); if (f != AT_MAX) __mp_diag("%s: ", __mp_functionnames[f]); va_start(v, s); if ((s == NULL) && (__mp_errordetails[e].format != NULL)) vfprintf(logfile, __mp_errordetails[e].format, v); else vfprintf(logfile, s, v); va_end(v); __mp_diag("\n"); if (((__mp_diagflags & FLG_EDIT) || (__mp_diagflags & FLG_LIST)) && (n != NULL)) { if (logfile != stderr) { fputs("ERROR: ", stderr); if (e != ET_MAX) fprintf(stderr, "[%s]: ", __mp_errordetails[e].code); if (f != AT_MAX) fprintf(stderr, "%s: ", __mp_functionnames[f]); va_start(v, s); if ((s == NULL) && (__mp_errordetails[e].format != NULL)) vfprintf(stderr, __mp_errordetails[e].format, v); else vfprintf(stderr, s, v); va_end(v); fputc('\n', stderr); } if (__mp_editfile(n, l, ((__mp_diagflags & FLG_LIST) != 0)) == -1) fprintf(stderr, "ERROR: problems %sing file `%s'\n", (__mp_diagflags & FLG_LIST) ? "list" : "edit", n); } __mp_errno = e; errors++;}/* Invoke a text editor on a given source file at a specific line. */MP_GLOBALint__mp_editfile(char *f, unsigned long l, int d){#if TARGET == TARGET_UNIX#if MP_PRELOAD_SUPPORT char s[256];#endif /* MP_PRELOAD_SUPPORT */ char t[32]; char *v[5]; pid_t p; int r;#endif /* TARGET */#if TARGET == TARGET_UNIX#if MP_PRELOAD_SUPPORT sprintf(s, "%s=", MP_PRELOAD_NAME);#endif /* MP_PRELOAD_SUPPORT */ sprintf(t, "%lu", l); if ((p = fork()) < 0) return -1; if (p == 0) {#if MP_PRELOAD_SUPPORT /* We have to ensure that we don't end up debugging the editor and its * child processes as well! Hopefully, if we ensure that the relevant * environment variable is set then putenv() will not use malloc() to * expand the environment. */ if (getenv(MP_PRELOAD_NAME)) putenv(s);#endif /* MP_PRELOAD_SUPPORT */ v[0] = MP_EDITOR; if (d == 0) { v[1] = f; v[2] = t; v[3] = NULL; } else { v[1] = "--listing"; v[2] = f; v[3] = t; v[4] = NULL; } execvp(v[0], v); _exit(EXIT_FAILURE); } while (waitpid(p, &r, 0) < 0) if (errno != EINTR) return -1; if (!WIFEXITED(r) || (WEXITSTATUS(r) != 0)) return -1; return 1;#else /* TARGET */ return 0;#endif /* TARGET */}/* Calculate the filename to use for an allocation contents file. */staticchar *allocfile(char *s, unsigned long n){ static char b[1024]; if (s == NULL) s = MP_CONTENTSFILE; sprintf(b, "%s.%lu", s, n); return b;}/* Read in an allocation contents file. */MP_GLOBALint__mp_readalloc(char *s, unsigned long n, void *a, size_t l){ FILE *f; int r; r = 0; if (f = fopen(allocfile(s, n), "rb")) { if (fread(a, sizeof(char), l, f) == l) r = 1; fclose(f); } return r;}/* Write out an allocation contents file. */MP_GLOBALint__mp_writealloc(char *s, unsigned long n, void *a, size_t l){ FILE *f; char *t; int r; r = 0; t = allocfile(s, n); if (f = fopen(t, "wb")) { if (fwrite(a, sizeof(char), l, f) == l) r = 1; fclose(f); if (r == 0) remove(t); } return r;}/* Compare an allocation contents file with the contents currently in memory. */MP_GLOBALlong__mp_cmpalloc(char *s, unsigned long n, void *a, size_t l){ FILE *f; char *p; long r; int c; r = -1; if (f = fopen(allocfile(s, n), "rb")) { r = 0; p = (char *) a; while (((c = fgetc(f)) != EOF) && (l != 0)) { if ((unsigned char) *p != (unsigned char) c) { if (r == 0) __mp_diag("allocation %lu (" MP_POINTER ") differences:\n", n, a); __mp_diag("\t" MP_POINTER " %02X -> %02X (offset %lu)\n", p, (unsigned char) c, (unsigned char) *p, (unsigned long) (p - (char *) a)); r++; } p++; l--; } if (c != EOF) { __mp_diag("allocation %lu (" MP_POINTER ") has decreased in size\n", n, a); r++; } else if (l != 0) { __mp_diag("allocation %lu (" MP_POINTER ") has increased in size\n", n, a); r++; } if (r != 0) __mp_diag("\n"); fclose(f); } return r;}/* Remove an allocation contents file. */MP_GLOBAL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -