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 + -
显示快捷键?