evlog.c
来自「spice中支持多层次元件模型仿真的可单独运行的插件源码」· C语言 代码 · 共 388 行
C
388 行
/* $Header: /home/harrison/c/tcgmsg/ipcv4.0/RCS/evlog.c,v 1.1 91/12/06 17:26:28 harrison Exp Locker: harrison $ *//* Event logging routine with key driven varargs interface */#include <stdio.h>#include <varargs.h>#ifdef SEQUENT#include <strings.h>#else#include <string.h>#endif#if defined(ALLIANT) || defined(ENCORE) || defined(SEQUENT) || \ defined(CONVEX) || defined(ARDENT) || defined(ULTRIX) || \ defined(AIX) || defined(IPSC) || defined(NEXT)extern char *strdup();#endif#if defined(ULTRIX) || defined(SGI) || defined(NEXT) || defined(KSR)extern void *malloc();#elseextern char *malloc();#endif#include "evlog.h"static double walltime();/* If sprintf returns an integer instead of a character pointer then define the flag INTSPRINTF */#if defined(SGI) || defined(AIX) || defined(IPSC) || defined(CRAY) || \ defined(HPUX) || defined(ALLIANT) || defined(CONVEX) || defined(NEXT) || \ defined(KSR)#define INTSPRINTF#endifvoid evlog(va_alist) va_dcl/* The format of the argument list is as follows: evlog([(int) key, [values, ...]], ..., EVKEY_LAST_ARG) Arguments are read as keys with corresponding values. Recognised keys are defined in evlog.h and are described in detail below. Logging is enabled/disabled by calling evlog with one of EVKEY_ENABLE or EVKEY_DISABLE specified. Note that EVKEY_ENABLE must be the first key specified for it to be recognized and that all keys in the argument list after EVKEY_DISABLE are ignored. By default events are logged in the file events. This can be overridden with the key EVKEY_FILENAME, which takes the filename as its value. The model for logging events assumed by the post-analysis routines assumes that upon logging an event: a) no state chage occurs (EVKEY_EVENT). The event is just recorded. b) the process changes state by pushing the event onto the state stack (EVKEY_BEGIN). c) the process changes state by popping an event off the state stack (EVKEY_END). If the event or state popped off the stack does not match the specified event then the post-analysis may get confused but this does not interfere with the actual logging. EVKEY_EVENT, EVKEY_BEGIN or EVKEY_END must be the first key specified other than a possible EVKEY_ENABLE. Internally an event is stored as a large character string to simplify post-analysis. Users specify data for storage in addition to that which is automatically stored (only the time and process) with key, value combinations (EVKEY_STR_INT, EVKEY_STR_DBL, EVKEY_STR). Many such key-value combinations as required may be specified. Since the internal data format uses colons ':', double quotation marks '"' and carriage returns users should avoid these in their string data. ---------------------------- Sample calling sequence: evlog(EVKEY_ENABLE, EVKEY_FILENAME, "events.log", EVKEY_LAST_ARG); evlog(EVKEY_EVENT, "Finished startup code", EVKEY_STR, "Now do some real work", EVKEY_LAST_ARG); evlog(EVKEY_BEGIN, "Get Matrix", EVKEY_LAST_ARG); evlog(EVKEY_END, "Get matrix", EVKEY_STR_INT, "Size of matrix", (int) N, EVKEY_STR_DBL, "Norm of matrix", (double) matrix_norm, EVKEY_LAST_ARG); evlog(EVKEY_BEGIN, "Transform matrix", EVKEY_STR_DBL, "Recomputed norm", (double) matrix_norm, EVKEY_LAST_ARG); evlog(EVKEY_END, "Transform matrix", EVKEY_STR_INT, "No. of iterations", (int) niters, EVKEY_LAST_ARG); evlog(EVKEY_DUMP, EVKEY_DISABLE, EVKEY_LAST_ARG); evlog(EVKEY_EVENT, "Logging is disabled ... this should not print", EVKEY_DUMP, EVKEY_LAST_ARG); ---------------------------- EVKEY_LAST_ARG Terminates list ... takes no value and must be present EVKEY_EVENT, (char *) event Simply log occurence of the event EVKEY_BEGIN, (char *) event Push event onto process state stack EVKEY_END, (char *) event Pop event off process state stack EVKEY_MSG_LEN, (int) length Value is (int) mesage length SND/RCV only EVKEY_MSG_TO, (int) to Value is (int) to process id SND/RCV only EVKEY_MSG_FROM, (int) from Value is (int) from process SND/RCV only EVKEY_MSG_TYPE, (int) type Value is (int) message type SND/RCV only EVKEY_STR_INT, (char *) string, (int) data User data value pair EVKEY_STR_DBL, (char *) string, (double) data User data value pair (char *), (double) EVKEY_STR, (char *) string User data value (char *) EVKEY_ENABLE Enable logging EVKEY_DISABLE Disable logging EVKEY_DUMP Dump out the current buffer to disk EVKEY_FILE, (char *) filename Use specified file to capture events. Default is "events".*/{ static int logging=0; /* Boolean flag for login enabled/disabled */ static int error=0; /* Boolean flag for error detected */ static int ncall=0; /* Need to do stuff on first entry */ static char *buffer; /* Logging buffer ... null terminated */ static char *bufpt; /* Pointer to next free char in buffer */ static int left; /* Amount of free space in buffer */#define BUFLEN 262144 /* Size allocated for buffer ... biggish */#define MAX_EV_LEN 1000 /* Assumed maximum size of single event record */ static FILE *EVfile; /* File where events will be dumped */ static char *EVfilename = "events"; /* Default name of events file */ va_list ap; /* For variable argument list */ int key; /* Hold key being processed */ int nchars; /* No. of chars printed by sprintf call */ char *temp; /* Temporary copy of bufpt */ char *string; /* Temporary */ int integer; /* Temporary */ double dbl; /* Temporary */ int valid; /* Temporary */ #define ERROR_RETURN if (!error) fputs("Event Log Error\n", stderr); \ error = 1; return; \#define DUMPBUF (void) fputs(buffer, EVfile); \ (void) fflush(EVfile);\ if(ferror(EVfile)) {ERROR_RETURN} \ bufpt = buffer; left = BUFLEN;/* sprintf is a disaster area!!!!#ifdef INTSPRINTF#define RECORD(A) nchars = (A); bufpt += nchars; left -= nchars#else#define RECORD(A) nchars = strlen(A); bufpt += nchars; left -= nchars#endif*/#define RECORD(A) A; nchars = strlen(bufpt); bufpt += nchars; left -= nchars /* If an error was detected on a previous call don't even try to do anything */ if (error) {ERROR_RETURN} /* First time in need to allocate the buffer, open the file etc */ if (ncall == 0) { ncall = 1; if (!(bufpt = buffer = malloc((unsigned) BUFLEN))) {ERROR_RETURN} left = BUFLEN; if (!(EVfile = fopen(EVfilename, "w"))) {ERROR_RETURN} } /* Parse the arguments */ temp = bufpt; /* Save to check if anything has been logged */ valid = 0; /* One of BEGIN, END or EVENT must preceed most keys */ va_start(ap); while ( (key = va_arg(ap, int)) != EVKEY_LAST_ARG) { if ( (!logging) && (key != EVKEY_ENABLE) ) return; switch (key) { case EVKEY_ENABLE: logging = 1; break; case EVKEY_DISABLE: logging = 0; goto done;/* break; */ case EVKEY_FILENAME: EVfilename = strdup(va_arg(ap, char *)); if (!(EVfile = freopen(EVfilename, "w", EVfile))) {ERROR_RETURN} break; case EVKEY_BEGIN: valid = 1; RECORD(sprintf(bufpt, ":BEGIN:%s", va_arg(ap, int))); RECORD(sprintf(bufpt, ":TIME:%.2f", walltime())); break; case EVKEY_END: valid = 1; RECORD(sprintf(bufpt, ":END:%s", va_arg(ap, int))); RECORD(sprintf(bufpt, ":TIME:%.2f", walltime())); break; case EVKEY_EVENT: valid = 1; RECORD(sprintf(bufpt, ":EVENT:%s", va_arg(ap, int))); RECORD(sprintf(bufpt, ":TIME:%.2f", walltime())); break; case EVKEY_MSG_LEN: if (!valid) {ERROR_RETURN} RECORD(sprintf(bufpt, ":MSG_LEN:%d", va_arg(ap, int))); break; case EVKEY_MSG_TO: if (!valid) {ERROR_RETURN} RECORD(sprintf(bufpt, ":MSG_TO:%d", va_arg(ap, int))); break; case EVKEY_MSG_FROM: if (!valid) {ERROR_RETURN} RECORD(sprintf(bufpt, ":MSG_FROM:%d", va_arg(ap, int))); break; case EVKEY_MSG_TYPE: if (!valid) {ERROR_RETURN} RECORD(sprintf(bufpt, ":MSG_TYPE:%d", va_arg(ap, int))); break; case EVKEY_MSG_SYNC: if (!valid) {ERROR_RETURN} RECORD(sprintf(bufpt, ":MSG_SYNC:%d", va_arg(ap, int))); break; case EVKEY_STR_INT: if (!valid) {ERROR_RETURN} string = va_arg(ap, char *); integer = va_arg(ap, int); RECORD(sprintf(bufpt, ":STR_INT:%s:%d", string, integer)); break; case EVKEY_STR_DBL: if (!valid) {ERROR_RETURN} string = va_arg(ap, char *); dbl = va_arg(ap, double); RECORD(sprintf(bufpt, ":STR_DBL:%s:%g", string, dbl)); break; case EVKEY_STR: if (!valid) {ERROR_RETURN} RECORD(sprintf(bufpt, ":STR:%s", va_arg(ap, char *))); break; case EVKEY_DUMP: {DUMPBUF} if (temp != bufpt) { RECORD(sprintf(bufpt, "\n")); temp = bufpt; } break; default: {DUMPBUF} {ERROR_RETURN} } } done: va_end(ap); /* Put a linefeed on the end of the record if something is written */ if (temp != bufpt) { RECORD(sprintf(bufpt, "\n")); temp = bufpt; } /* Should really check on every access to the buffer that there is enough space ... however just assume a very large maximum size for a single event log entry and check here */ if (left <= 0) {ERROR_RETURN} if (left < MAX_EV_LEN) {DUMPBUF}}#include "sndrcv.h"static double walltime()/* return the wall time in seconds as a double*/{ return ((double) MTIME_()) * 0.01;}/*int main(){ int N = 19; double matrix_norm = 99.1; int niters = 5; evlog(EVKEY_ENABLE, EVKEY_FILENAME, "events.log", EVKEY_LAST_ARG); evlog(EVKEY_EVENT, "Finished startup code", EVKEY_STR, "Now do some real work", EVKEY_LAST_ARG); evlog(EVKEY_BEGIN, "Get Matrix", EVKEY_LAST_ARG); evlog(EVKEY_END, "Get matrix", EVKEY_STR_INT, "Size of matrix", (int) N, EVKEY_STR_DBL, "Norm of matrix", (double) matrix_norm, EVKEY_LAST_ARG); evlog(EVKEY_BEGIN, "Transform matrix", EVKEY_STR_DBL, "Recomputed norm", (double) matrix_norm, EVKEY_LAST_ARG); evlog(EVKEY_END, "Transform matrix", EVKEY_STR_INT, "No. of iterations", (int) niters, EVKEY_LAST_ARG); evlog(EVKEY_DUMP, EVKEY_LAST_ARG); evlog(EVKEY_EVENT, "Logging is disabled ... this should not print", EVKEY_DUMP, EVKEY_LAST_ARG); return 0;}*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?