/* do not edit automatically generated by mc from M2Diagnostic. */ /* M2Diagnotic provides memory and time diagnosics to the user. Copyright (C) 2024 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Modula-2; see the file COPYING3. If not see . */ #include "config.h" #include "system.h" #include # if !defined (PROC_D) # define PROC_D typedef void (*PROC_t) (void); typedef struct { PROC_t proc; } PROC; # endif # if !defined (TRUE) # define TRUE (1==1) # endif # if !defined (FALSE) # define FALSE (1==0) # endif # include "GStorage.h" # include "Gmcrts.h" #if defined(__cplusplus) # undef NULL # define NULL 0 #endif #define _M2Diagnostic_H #define _M2Diagnostic_C # include "GASCII.h" # include "GSelective.h" # include "GStringConvert.h" # include "GStorage.h" # include "GDynamicStrings.h" # include "GM2RTS.h" typedef struct M2Diagnostic_DiagProc_p M2Diagnostic_DiagProc; # define EnableDiagnostics true # define DefaultTimeEnableValue false # define DefaultMemEnableValue false # define MaxParam 4 # define MICROSEC 100000 typedef struct M2Diagnostic_timeDiag_r M2Diagnostic_timeDiag; typedef struct M2Diagnostic_memDiag_r M2Diagnostic_memDiag; typedef struct M2Diagnostic__T1_r M2Diagnostic__T1; typedef struct M2Diagnostic__T2_a M2Diagnostic__T2; typedef enum {M2Diagnostic_timediag, M2Diagnostic_memdiag} M2Diagnostic_DiagType; # define kilo 1024 # define mega (kilo*kilo) # define giga (mega*kilo) typedef M2Diagnostic__T1 *M2Diagnostic_Diagnostic; typedef void (*M2Diagnostic_DiagProc_t) (M2Diagnostic_Diagnostic); struct M2Diagnostic_DiagProc_p { M2Diagnostic_DiagProc_t proc; }; struct M2Diagnostic_timeDiag_r { unsigned int count; Selective_Timeval total; Selective_Timeval enter; Selective_Timeval exit_; }; struct M2Diagnostic__T2_a { long unsigned int array[MaxParam-1+1]; }; struct M2Diagnostic_memDiag_r { M2Diagnostic__T2 param; }; struct M2Diagnostic__T1_r { DynamicStrings_String name; DynamicStrings_String format; bool enable; M2Diagnostic_Diagnostic next; M2Diagnostic_DiagType type; /* case tag */ union { M2Diagnostic_timeDiag tdiag; M2Diagnostic_memDiag mdiag; }; }; static DynamicStrings_String Output; static long unsigned int TotalHeap; static M2Diagnostic_Diagnostic Head; static bool DefaultTimeEnable; static bool DefaultMemEnable; static Selective_Timeval StartTime; static Selective_Timeval TotalTime; /* InitTimeDiagnostic - create and return a time diagnostic. The format string can be free form and may contain {1T}, {1C} or {1P}. {1T} will contain the time and {1C} the count of the number of times the code enters the time diagnostic code region. {1P} generates the time as a percentage. {0T} is the total time for the application. {{ is rendered as a single {. */ extern "C" M2Diagnostic_Diagnostic M2Diagnostic_InitTimeDiagnostic (const char *name_, unsigned int _name_high, const char *format_, unsigned int _format_high); /* EnterDiagnostic - attribute all execution time from now to TimeDiag. */ extern "C" void M2Diagnostic_EnterDiagnostic (M2Diagnostic_Diagnostic TimeDiag); /* ExitDiagnostic - stop attributing execution time to TimeDiag. */ extern "C" void M2Diagnostic_ExitDiagnostic (M2Diagnostic_Diagnostic TimeDiag); /* InitMemDiagnostic - create and return a memory diagnostic. The format string can be free form and may contain {1M} {1d} {1x} {1P}. {1M} is replaced by the value of the first parameter with memory size units. {1d} unsigned decimal. {1x} unsigned hexadecimal. {0M} is the global allocation (Storage.mod:ALLOCATE). {1P} is the percentage of param 1 relative to global memory. */ extern "C" M2Diagnostic_Diagnostic M2Diagnostic_InitMemDiagnostic (const char *name_, unsigned int _name_high, const char *format_, unsigned int _format_high); /* MemIncr - allow the appropriate parameter to be incremented. All parameters are initially set to zero and are stored as LONGCARD. */ extern "C" void M2Diagnostic_MemIncr (M2Diagnostic_Diagnostic MemDiag, unsigned int paramno, unsigned int incr); /* MemDecr - allow the appropriate parameter to be decremented. All parameters are initially set to zero and are stored as LONGCARD. */ extern "C" void M2Diagnostic_MemDecr (M2Diagnostic_Diagnostic MemDiag, unsigned int paramno, unsigned int decr); /* MemSet - allow the appropriate parameter to be set to value. All parameters are initially set to zero. */ extern "C" void M2Diagnostic_MemSet (M2Diagnostic_Diagnostic MemDiag, unsigned int paramno, unsigned int value); /* TotalHeapIncr - increments the total heap used. */ extern "C" void M2Diagnostic_TotalHeapIncr (unsigned int incr); /* TotalHeapDecr - decrements the total heap used. */ extern "C" void M2Diagnostic_TotalHeapDecr (unsigned int incr); /* SetEnable - set the enable flag in Diag to value. */ extern "C" void M2Diagnostic_SetEnable (M2Diagnostic_Diagnostic Diag, bool value); /* Lookup - returns the Diagnostic containing name or NIL if it does not exist. */ extern "C" M2Diagnostic_Diagnostic M2Diagnostic_Lookup (const char *name_, unsigned int _name_high); /* GetName - returns the name of Diag. */ extern "C" DynamicStrings_String M2Diagnostic_GetName (M2Diagnostic_Diagnostic Diag); /* ForeachDiagDo - for diag in global diag list do dp (diag); end */ extern "C" void M2Diagnostic_ForeachDiagDo (M2Diagnostic_DiagProc dp); /* SetDefaultConfig - force the Diag enable flag to the time or mem global default. */ extern "C" void M2Diagnostic_SetDefaultConfig (M2Diagnostic_Diagnostic Diag); /* Configure - will turn on or off all the memory or time instrumentation diagnostics and set the defaults time and mem values. */ extern "C" void M2Diagnostic_Configure (bool time_, bool mem); /* Generate - return a string containing the output from all the diagnostics enabled. */ extern "C" DynamicStrings_String M2Diagnostic_Generate (void); /* Assert - halt if b is false. */ static void Assert (bool b); /* Error - generate a error simple message with indicating the format specifier ch is incorrect. */ static void Error (const char *msg_, unsigned int _msg_high, char ch); /* Accumulate - total := total + exit - enter */ static void Accumulate (Selective_Timeval total, Selective_Timeval enter, Selective_Timeval exit_); /* IncTime - left := left + right. */ static void IncTime (Selective_Timeval left, Selective_Timeval right); /* DecTime - left := left - right. */ static void DecTime (Selective_Timeval left, Selective_Timeval right); /* CheckParam - */ static void CheckParam (unsigned int paramno); /* CreateStartTime - */ static void CreateStartTime (void); /* UpdateTotalTime - */ static void UpdateTotalTime (void); /* GetTimeParam - a paramno of 0 will return the total time so far whereas a paramno > 0 will return the time associated with Diag. */ static Selective_Timeval GetTimeParam (M2Diagnostic_Diagnostic Diag, unsigned int paramno); /* GetMemParam - return the mem paramno from within Diag. A paramno of 0 will return the total heap. */ static long unsigned int GetMemParam (M2Diagnostic_Diagnostic Diag, unsigned int paramno); /* CreateDecimalMem - converts c to a decimal string. */ static DynamicStrings_String CreateDecimalMem (long unsigned int c); /* CreateHexadecimalMem - converts c to a hexadecimal string. */ static DynamicStrings_String CreateHexadecimalMem (long unsigned int c); /* CreateDecimalTime - return timeval as a decimal seconds.usecs string. */ static DynamicStrings_String CreateDecimalTime (Selective_Timeval timeval); /* CreateHexadecimalTime - return timeval as a hexadecimal seconds.usecs string. */ static DynamicStrings_String CreateHexadecimalTime (Selective_Timeval timeval); /* Decimal - convert paramno in Diag to a string. */ static DynamicStrings_String Decimal (M2Diagnostic_Diagnostic Diag, unsigned int paramno); /* Hexadecimal - convert paramno in Diag to a hex string. */ static DynamicStrings_String Hexadecimal (M2Diagnostic_Diagnostic Diag, unsigned int paramno); /* Count - return the count field for a time diag or return the decimal value for a paramno in a mem diag. */ static DynamicStrings_String Count (M2Diagnostic_Diagnostic Diag, unsigned int paramno); /* Microsec - convert timeval into microseconds and return the value as a longcard. */ static long unsigned int Microsec (Selective_Timeval timeval); /* CreateTimePercent - return timeval as a percentage of the TotalTime. */ static DynamicStrings_String CreateTimePercent (Selective_Timeval timeval); /* CreateMemPercent - return memval as a percentage of TotalHeap. */ static DynamicStrings_String CreateMemPercent (long unsigned int memval); /* DescribePercent - call the appropriate mem or time percentage procedure. */ static DynamicStrings_String DescribePercent (M2Diagnostic_Diagnostic Diag, unsigned int paramno); /* DescribeMemory - return the memory diagnostic */ static DynamicStrings_String DescribeMemory (M2Diagnostic_Diagnostic Diag, unsigned int paramno); /* DescribeTime - returns the time diagnostic in seconds. */ static DynamicStrings_String DescribeTime (M2Diagnostic_Diagnostic Diag, unsigned int paramno); /* ParamSpec - ebnf: ( '{' | '0' | '1' | '2' | '3' | '4' ) ( 'd' | 'x' | 'C' | 'T' | 'M' | 'N' | 'P' ) '}' */ static unsigned int ParamSpec (M2Diagnostic_Diagnostic Diag, unsigned int i); /* FormatDiag - ebnf: { ( '{' ParamSpec ) | any } */ static void FormatDiag (M2Diagnostic_Diagnostic Diag); /* Assert - halt if b is false. */ static void Assert (bool b) { if (! b) { M2RTS_HALT (-1); __builtin_unreachable (); } } /* Error - generate a error simple message with indicating the format specifier ch is incorrect. */ static void Error (const char *msg_, unsigned int _msg_high, char ch) { char msg[_msg_high+1]; /* make a local copy of each unbounded array. */ memcpy (msg, msg_, _msg_high+1); M2RTS_HALT (-1); __builtin_unreachable (); } /* Accumulate - total := total + exit - enter */ static void Accumulate (Selective_Timeval total, Selective_Timeval enter, Selective_Timeval exit_) { IncTime (total, exit_); DecTime (total, enter); } /* IncTime - left := left + right. */ static void IncTime (Selective_Timeval left, Selective_Timeval right) { unsigned int lsec; unsigned int lusec; unsigned int rsec; unsigned int rusec; Selective_GetTime (left, &lsec, &lusec); Selective_GetTime (right, &rsec, &rusec); if ((lusec+rusec) < MICROSEC) { /* No carry */ lusec += rusec; lsec += rsec; } else { lusec += rusec; lusec -= MICROSEC; lsec += rsec+1; } Selective_SetTime (left, lsec, lusec); } /* DecTime - left := left - right. */ static void DecTime (Selective_Timeval left, Selective_Timeval right) { unsigned int lsec; unsigned int lusec; unsigned int rsec; unsigned int rusec; Selective_GetTime (left, &lsec, &lusec); Selective_GetTime (right, &rsec, &rusec); if (lusec >= rusec) { /* No borrow. */ lusec -= rusec; if (lsec >= rsec) { lsec -= rsec; } else { lsec = 0; } } else { if (lsec > 0) { lusec += MICROSEC; lusec -= rusec; lsec -= 1; if (lsec >= rsec) { lsec -= rsec; } else { lsec = 0; } } else { lsec = 0; lusec = 0; } } Selective_SetTime (left, lsec, lusec); } /* CheckParam - */ static void CheckParam (unsigned int paramno) { if ((paramno < 1) || (paramno > MaxParam)) { M2RTS_HALT (-1); __builtin_unreachable (); } } /* CreateStartTime - */ static void CreateStartTime (void) { if (EnableDiagnostics) { /* avoid dangling else. */ if (StartTime == NULL) { StartTime = Selective_InitTime (0, 0); if ((Selective_GetTimeOfDay (StartTime)) == 0) {} /* empty. */ } if (TotalTime == NULL) { TotalTime = Selective_InitTime (0, 0); } } else { StartTime = NULL; TotalTime = NULL; } } /* UpdateTotalTime - */ static void UpdateTotalTime (void) { if ((Selective_GetTimeOfDay (TotalTime)) == 0) {} /* empty. */ DecTime (TotalTime, StartTime); } /* GetTimeParam - a paramno of 0 will return the total time so far whereas a paramno > 0 will return the time associated with Diag. */ static Selective_Timeval GetTimeParam (M2Diagnostic_Diagnostic Diag, unsigned int paramno) { unsigned int sec; unsigned int usec; if (paramno == 0) { UpdateTotalTime (); return TotalTime; } else { return Diag->tdiag.total; } /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* GetMemParam - return the mem paramno from within Diag. A paramno of 0 will return the total heap. */ static long unsigned int GetMemParam (M2Diagnostic_Diagnostic Diag, unsigned int paramno) { if (paramno == 0) { return TotalHeap; } else { return Diag->mdiag.param.array[paramno-1]; } /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* CreateDecimalMem - converts c to a decimal string. */ static DynamicStrings_String CreateDecimalMem (long unsigned int c) { return StringConvert_LongCardinalToString (c, 0, ' ', 10, true); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* CreateHexadecimalMem - converts c to a hexadecimal string. */ static DynamicStrings_String CreateHexadecimalMem (long unsigned int c) { return DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "0x", 2), DynamicStrings_Mark (StringConvert_LongCardinalToString (c, 0, ' ', 16, true))); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* CreateDecimalTime - return timeval as a decimal seconds.usecs string. */ static DynamicStrings_String CreateDecimalTime (Selective_Timeval timeval) { unsigned int sec; unsigned int usec; Selective_GetTime (timeval, &sec, &usec); return DynamicStrings_ConCat (DynamicStrings_ConCat (StringConvert_LongCardinalToString (static_cast (sec), 0, ' ', 10, true), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ".", 1))), StringConvert_LongCardinalToString (static_cast (usec), 6, '0', 10, true)); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* CreateHexadecimalTime - return timeval as a hexadecimal seconds.usecs string. */ static DynamicStrings_String CreateHexadecimalTime (Selective_Timeval timeval) { unsigned int sec; unsigned int usec; Selective_GetTime (timeval, &sec, &usec); return DynamicStrings_ConCat (DynamicStrings_ConCat (StringConvert_LongCardinalToString (static_cast (sec), 0, ' ', 16, true), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ".", 1))), StringConvert_LongCardinalToString (static_cast (usec), 5, '0', 16, true)); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* Decimal - convert paramno in Diag to a string. */ static DynamicStrings_String Decimal (M2Diagnostic_Diagnostic Diag, unsigned int paramno) { switch (Diag->type) { case M2Diagnostic_memdiag: return CreateDecimalMem (GetMemParam (Diag, paramno)); break; case M2Diagnostic_timediag: return CreateDecimalTime (GetTimeParam (Diag, paramno)); break; default: CaseException ("../../gcc/m2/gm2-libs/M2Diagnostic.def", 20, 1); __builtin_unreachable (); } return static_cast (NULL); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* Hexadecimal - convert paramno in Diag to a hex string. */ static DynamicStrings_String Hexadecimal (M2Diagnostic_Diagnostic Diag, unsigned int paramno) { switch (Diag->type) { case M2Diagnostic_memdiag: return CreateHexadecimalMem (GetMemParam (Diag, paramno)); break; case M2Diagnostic_timediag: return CreateHexadecimalTime (GetTimeParam (Diag, paramno)); break; default: CaseException ("../../gcc/m2/gm2-libs/M2Diagnostic.def", 20, 1); __builtin_unreachable (); } return static_cast (NULL); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* Count - return the count field for a time diag or return the decimal value for a paramno in a mem diag. */ static DynamicStrings_String Count (M2Diagnostic_Diagnostic Diag, unsigned int paramno) { switch (Diag->type) { case M2Diagnostic_memdiag: return CreateDecimalMem (GetMemParam (Diag, paramno)); break; case M2Diagnostic_timediag: return StringConvert_ctos (Diag->tdiag.count, 0, ' '); break; default: CaseException ("../../gcc/m2/gm2-libs/M2Diagnostic.def", 20, 1); __builtin_unreachable (); } return static_cast (NULL); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* Microsec - convert timeval into microseconds and return the value as a longcard. */ static long unsigned int Microsec (Selective_Timeval timeval) { unsigned int sec; unsigned int usec; long unsigned int microsec; Selective_GetTime (timeval, &sec, &usec); microsec = (((long unsigned int ) (sec))*MICROSEC)+((long unsigned int ) (usec)); return microsec; /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* CreateTimePercent - return timeval as a percentage of the TotalTime. */ static DynamicStrings_String CreateTimePercent (Selective_Timeval timeval) { long unsigned int total; long unsigned int param; if (timeval == TotalTime) { param = 100; } else { UpdateTotalTime (); param = (Microsec (timeval))*100; total = Microsec (TotalTime); if (total == 0) { param = 0; } else { param = param / total; } } return DynamicStrings_ConCatChar (StringConvert_ctos ((unsigned int ) (param), 3, ' '), '%'); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* CreateMemPercent - return memval as a percentage of TotalHeap. */ static DynamicStrings_String CreateMemPercent (long unsigned int memval) { long unsigned int param; if (memval == TotalHeap) { param = 100; } else { param = memval*100; if (TotalHeap == 0) { param = 0; } else { param = param / TotalHeap; } } return DynamicStrings_ConCatChar (StringConvert_ctos ((unsigned int ) (param), 3, ' '), '%'); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* DescribePercent - call the appropriate mem or time percentage procedure. */ static DynamicStrings_String DescribePercent (M2Diagnostic_Diagnostic Diag, unsigned int paramno) { switch (Diag->type) { case M2Diagnostic_memdiag: return CreateMemPercent (GetMemParam (Diag, paramno)); break; case M2Diagnostic_timediag: return CreateTimePercent (GetTimeParam (Diag, paramno)); break; default: CaseException ("../../gcc/m2/gm2-libs/M2Diagnostic.def", 20, 1); __builtin_unreachable (); } return static_cast (NULL); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* DescribeMemory - return the memory diagnostic */ static DynamicStrings_String DescribeMemory (M2Diagnostic_Diagnostic Diag, unsigned int paramno) { long unsigned int param; DynamicStrings_String s; param = GetMemParam (Diag, paramno); if (param < kilo) { s = DynamicStrings_ConCat (StringConvert_LongCardinalToString (param, 0, ' ', 10, false), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) " Bytes", 6))); } else if (param < mega) { /* avoid dangling else. */ param = param / kilo; s = DynamicStrings_ConCat (StringConvert_LongCardinalToString (param, 0, ' ', 10, false), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "KB", 2))); } else { /* avoid dangling else. */ param = param / mega; s = DynamicStrings_ConCat (StringConvert_LongCardinalToString (param, 0, ' ', 10, false), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) "MB", 2))); } return s; /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* DescribeTime - returns the time diagnostic in seconds. */ static DynamicStrings_String DescribeTime (M2Diagnostic_Diagnostic Diag, unsigned int paramno) { unsigned int sec; unsigned int usec; switch (Diag->type) { case M2Diagnostic_memdiag: M2RTS_HALT (-1); __builtin_unreachable (); break; case M2Diagnostic_timediag: Selective_GetTime (GetTimeParam (Diag, paramno), &sec, &usec); return DynamicStrings_ConCat (DynamicStrings_ConCat (StringConvert_LongCardinalToString (static_cast (sec), 0, ' ', 10, true), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) ".", 1))), DynamicStrings_ConCat (StringConvert_LongCardinalToString (static_cast (usec), 6, '0', 10, true), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) " sec", 4)))); break; default: CaseException ("../../gcc/m2/gm2-libs/M2Diagnostic.def", 20, 1); __builtin_unreachable (); } return static_cast (NULL); /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* ParamSpec - ebnf: ( '{' | '0' | '1' | '2' | '3' | '4' ) ( 'd' | 'x' | 'C' | 'T' | 'M' | 'N' | 'P' ) '}' */ static unsigned int ParamSpec (M2Diagnostic_Diagnostic Diag, unsigned int i) { unsigned int paramno; unsigned int length; char ch; length = DynamicStrings_Length (Diag->format); paramno = 0; if (i < length) { ch = DynamicStrings_char (Diag->format, static_cast (i)); switch (ch) { case '{': Output = DynamicStrings_ConCatChar (Output, '{'); return i+1; break; case '0': paramno = 0; break; case '1': paramno = 1; break; case '2': paramno = 2; break; case '3': paramno = 3; break; case '4': paramno = 4; break; default: Error ((const char *) "unexpected character: ", 22, ch); break; } i += 1; if (i < length) { ch = DynamicStrings_char (Diag->format, static_cast (i)); switch (ch) { case 'd': Output = DynamicStrings_ConCat (Output, Decimal (Diag, paramno)); break; case 'x': Output = DynamicStrings_ConCat (Output, Hexadecimal (Diag, paramno)); break; case 'C': Output = DynamicStrings_ConCat (Output, Count (Diag, paramno)); break; case 'M': Output = DynamicStrings_ConCat (Output, DescribeMemory (Diag, paramno)); break; case 'N': Output = DynamicStrings_ConCat (Output, Diag->name); break; case 'P': Output = DynamicStrings_ConCat (Output, DescribePercent (Diag, paramno)); break; case 'T': Output = DynamicStrings_ConCat (Output, DescribeTime (Diag, paramno)); break; default: Error ((const char *) "unexpected character: ", 22, ch); break; } i += 1; if (i < length) { ch = DynamicStrings_char (Diag->format, static_cast (i)); if (ch != '}') { Error ((const char *) "expected } character, seen ", 27, ch); } } } } return i+1; /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* FormatDiag - ebnf: { ( '{' ParamSpec ) | any } */ static void FormatDiag (M2Diagnostic_Diagnostic Diag) { unsigned int i; unsigned int length; char ch; i = 0; length = DynamicStrings_Length (Diag->format); while (i < length) { ch = DynamicStrings_char (Diag->format, static_cast (i)); if (ch == '{') { i += 1; i = ParamSpec (Diag, i); } else { Output = DynamicStrings_ConCatChar (Output, ch); i += 1; } } Output = DynamicStrings_ConCatChar (Output, ASCII_nl); } /* InitTimeDiagnostic - create and return a time diagnostic. The format string can be free form and may contain {1T}, {1C} or {1P}. {1T} will contain the time and {1C} the count of the number of times the code enters the time diagnostic code region. {1P} generates the time as a percentage. {0T} is the total time for the application. {{ is rendered as a single {. */ extern "C" M2Diagnostic_Diagnostic M2Diagnostic_InitTimeDiagnostic (const char *name_, unsigned int _name_high, const char *format_, unsigned int _format_high) { M2Diagnostic_Diagnostic d; char name[_name_high+1]; char format[_format_high+1]; /* make a local copy of each unbounded array. */ memcpy (name, name_, _name_high+1); memcpy (format, format_, _format_high+1); if (EnableDiagnostics) { Storage_ALLOCATE ((void **) &d, sizeof (M2Diagnostic__T1)); d->name = DynamicStrings_InitString ((const char *) name, _name_high); d->format = DynamicStrings_InitString ((const char *) format, _format_high); d->enable = DefaultTimeEnable; d->next = Head; d->type = M2Diagnostic_timediag; switch (d->type) { case M2Diagnostic_timediag: d->tdiag.count = 0; d->tdiag.total = Selective_InitTime (0, 0); d->tdiag.enter = Selective_InitTime (0, 0); d->tdiag.exit_ = Selective_InitTime (0, 0); break; default: M2RTS_HALT (-1); __builtin_unreachable (); break; } Head = d; return d; } else { return NULL; } /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* EnterDiagnostic - attribute all execution time from now to TimeDiag. */ extern "C" void M2Diagnostic_EnterDiagnostic (M2Diagnostic_Diagnostic TimeDiag) { if (EnableDiagnostics && (TimeDiag != NULL)) { Assert (TimeDiag->type == M2Diagnostic_timediag); Assert ((Selective_GetTimeOfDay (TimeDiag->tdiag.enter)) == 0); TimeDiag->tdiag.count += 1; } } /* ExitDiagnostic - stop attributing execution time to TimeDiag. */ extern "C" void M2Diagnostic_ExitDiagnostic (M2Diagnostic_Diagnostic TimeDiag) { if (EnableDiagnostics && (TimeDiag != NULL)) { Assert (TimeDiag->type == M2Diagnostic_timediag); Assert ((Selective_GetTimeOfDay (TimeDiag->tdiag.exit_)) == 0); Accumulate (TimeDiag->tdiag.total, TimeDiag->tdiag.enter, TimeDiag->tdiag.exit_); } } /* InitMemDiagnostic - create and return a memory diagnostic. The format string can be free form and may contain {1M} {1d} {1x} {1P}. {1M} is replaced by the value of the first parameter with memory size units. {1d} unsigned decimal. {1x} unsigned hexadecimal. {0M} is the global allocation (Storage.mod:ALLOCATE). {1P} is the percentage of param 1 relative to global memory. */ extern "C" M2Diagnostic_Diagnostic M2Diagnostic_InitMemDiagnostic (const char *name_, unsigned int _name_high, const char *format_, unsigned int _format_high) { unsigned int i; M2Diagnostic_Diagnostic d; char name[_name_high+1]; char format[_format_high+1]; /* make a local copy of each unbounded array. */ memcpy (name, name_, _name_high+1); memcpy (format, format_, _format_high+1); if (EnableDiagnostics) { Storage_ALLOCATE ((void **) &d, sizeof (M2Diagnostic__T1)); d->name = DynamicStrings_InitString ((const char *) name, _name_high); d->format = DynamicStrings_InitString ((const char *) format, _format_high); d->enable = DefaultMemEnable; d->next = Head; d->type = M2Diagnostic_memdiag; switch (d->type) { case M2Diagnostic_memdiag: for (i=1; i<=MaxParam; i++) { d->mdiag.param.array[i-1] = 0; } break; default: M2RTS_HALT (-1); __builtin_unreachable (); break; } Head = d; return d; } else { return NULL; } /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* MemIncr - allow the appropriate parameter to be incremented. All parameters are initially set to zero and are stored as LONGCARD. */ extern "C" void M2Diagnostic_MemIncr (M2Diagnostic_Diagnostic MemDiag, unsigned int paramno, unsigned int incr) { if (EnableDiagnostics && (MemDiag != NULL)) { CheckParam (paramno); switch (MemDiag->type) { case M2Diagnostic_memdiag: MemDiag->mdiag.param.array[paramno-1] += (long unsigned int ) (incr); break; default: M2RTS_HALT (-1); __builtin_unreachable (); break; } } } /* MemDecr - allow the appropriate parameter to be decremented. All parameters are initially set to zero and are stored as LONGCARD. */ extern "C" void M2Diagnostic_MemDecr (M2Diagnostic_Diagnostic MemDiag, unsigned int paramno, unsigned int decr) { if (EnableDiagnostics && (MemDiag != NULL)) { CheckParam (paramno); switch (MemDiag->type) { case M2Diagnostic_memdiag: MemDiag->mdiag.param.array[paramno-1] -= (long unsigned int ) (decr); break; default: M2RTS_HALT (-1); __builtin_unreachable (); break; } } } /* MemSet - allow the appropriate parameter to be set to value. All parameters are initially set to zero. */ extern "C" void M2Diagnostic_MemSet (M2Diagnostic_Diagnostic MemDiag, unsigned int paramno, unsigned int value) { if (EnableDiagnostics && (MemDiag != NULL)) { CheckParam (paramno); switch (MemDiag->type) { case M2Diagnostic_memdiag: MemDiag->mdiag.param.array[paramno-1] = (long unsigned int ) (value); break; default: M2RTS_HALT (-1); __builtin_unreachable (); break; } } } /* TotalHeapIncr - increments the total heap used. */ extern "C" void M2Diagnostic_TotalHeapIncr (unsigned int incr) { if (EnableDiagnostics) { TotalHeap = TotalHeap+((long unsigned int ) (incr)); } } /* TotalHeapDecr - decrements the total heap used. */ extern "C" void M2Diagnostic_TotalHeapDecr (unsigned int incr) { if (EnableDiagnostics) { TotalHeap = TotalHeap-((long unsigned int ) (incr)); } } /* SetEnable - set the enable flag in Diag to value. */ extern "C" void M2Diagnostic_SetEnable (M2Diagnostic_Diagnostic Diag, bool value) { if (EnableDiagnostics && (Diag != NULL)) { Diag->enable = value; } } /* Lookup - returns the Diagnostic containing name or NIL if it does not exist. */ extern "C" M2Diagnostic_Diagnostic M2Diagnostic_Lookup (const char *name_, unsigned int _name_high) { M2Diagnostic_Diagnostic ptr; DynamicStrings_String s; char name[_name_high+1]; /* make a local copy of each unbounded array. */ memcpy (name, name_, _name_high+1); if (EnableDiagnostics) { s = DynamicStrings_InitString ((const char *) name, _name_high); ptr = Head; while (ptr != NULL) { if (DynamicStrings_Equal (ptr->name, s)) { s = DynamicStrings_KillString (s); return ptr; } ptr = ptr->next; } s = DynamicStrings_KillString (s); return NULL; } else { return NULL; } /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* GetName - returns the name of Diag. */ extern "C" DynamicStrings_String M2Diagnostic_GetName (M2Diagnostic_Diagnostic Diag) { if (EnableDiagnostics && (Diag != NULL)) { return Diag->name; } else { return static_cast (NULL); } /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } /* ForeachDiagDo - for diag in global diag list do dp (diag); end */ extern "C" void M2Diagnostic_ForeachDiagDo (M2Diagnostic_DiagProc dp) { M2Diagnostic_Diagnostic ptr; ptr = Head; while (ptr != NULL) { (*dp.proc) (ptr); ptr = ptr->next; } } /* SetDefaultConfig - force the Diag enable flag to the time or mem global default. */ extern "C" void M2Diagnostic_SetDefaultConfig (M2Diagnostic_Diagnostic Diag) { if (Diag->type == M2Diagnostic_timediag) { Diag->enable = DefaultTimeEnable; } else { Diag->enable = DefaultMemEnable; } } /* Configure - will turn on or off all the memory or time instrumentation diagnostics and set the defaults time and mem values. */ extern "C" void M2Diagnostic_Configure (bool time_, bool mem) { if (EnableDiagnostics) { DefaultTimeEnable = time_; DefaultMemEnable = mem; M2Diagnostic_ForeachDiagDo ((M2Diagnostic_DiagProc) {(M2Diagnostic_DiagProc_t) M2Diagnostic_SetDefaultConfig}); } } /* Generate - return a string containing the output from all the diagnostics enabled. */ extern "C" DynamicStrings_String M2Diagnostic_Generate (void) { if (EnableDiagnostics) { Output = DynamicStrings_KillString (Output); Output = DynamicStrings_InitString ((const char *) "", 0); M2Diagnostic_ForeachDiagDo ((M2Diagnostic_DiagProc) {(M2Diagnostic_DiagProc_t) FormatDiag}); return Output; } else { return static_cast (NULL); } /* static analysis guarentees a RETURN statement will be used before here. */ __builtin_unreachable (); } extern "C" void _M2_M2Diagnostic_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[]) { TotalHeap = 0; StartTime = NULL; TotalTime = NULL; CreateStartTime (); Head = NULL; Output = static_cast (NULL); DefaultTimeEnable = DefaultTimeEnableValue; DefaultMemEnable = DefaultMemEnableValue; } extern "C" void _M2_M2Diagnostic_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[]) { }