#include // <-- for printf() and stdout #include // <-- for atoi() and atol() #include // <-- for strcmp() #include // <-- for time_t, strftime() (used in PBAR demo) #ifndef WIN32 #include // <-- for sleep() (used in demos) #endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - // define certain things that keef likes to code with: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - typedef int BOOL; typedef unsigned int UINT; typedef unsigned long ULONG; #define strmatch(S1,S2) (!strcmp(S1,S2)) #define strmatchI(S1,S2) (!_stricmp(S1,S2)) #define strmatchN(S1,S2) (!strncmp(S1,S2,strlen(S2))) #define strmatchNI(S1,S2) (!_strnicmp(S1,S2,strlen(S2))) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - // constants and prototypes: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - enum { DEFAULT_BARWIDTH = 70, DEFAULT_BLANK = ':', DEFAULT_DONE = '|', KPS_START = 'S', KPS_ADD = 'A', KPS_END = 'E' }; void SynopsisAndExit (const char** pSynopsis, int iExitCode); char* kpbar (char* szBar, UINT iMaxAlloc, ULONG iSoFar, ULONG iTotal, int chBlank=' ', int chDone='%'); void kpslide (int iAction, ULONG iExpected, ULONG iSoFarLast=0, ULONG iSoFarNow=0, FILE* fp=stdout, int iMaxBars=70, int chDone='%'); int DemoPBAR (int argc, char* argv[]); int DemoSLIDER (int argc, char* argv[]); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - // globals: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - const char* g_Synopsis[] = { "", "pbar -- general purpose 'stateless' progress bars for ascii (console) apps", "", "usage: pbar [...args...]", "", "This command-line utility supports two completely different types of", "progress bar: PBAR and SLIDER.", "", "PBAR : is used for progress bars that are intermingled with other", "output, or for when you have the luxury of repositioning the cursor", "to the same location (through libcurses or your own escape sequences).", " [||||||||||||||||||:::::::::::::::]", "", "SLIDER : is used when you can suppress (or redirect) extraneous output", "so that the *only* thing being output is the progress bar itself.", "Because the slider is stateless, it needs to know both the 'current", "progress' *and* the 'last progress' so it can compute the 'progress delta.'", " v_________________________________v", " ||||||||||||||||||||||||||| |", "", "command line help:", " pbar PBAR help -or- pbar SLIDER help", "", "history:", " Apr 2002 : jkuefler created", "", NULL }; const char* g_SynPBAR[] = { "", "usage: pbar PBAR [ [ []]]", "", "where:", " PBAR : tells pbar to produce an entire bar (not a SLIDER)", " : total steps expected (unsigned int up to 2147483647)", " : steps encountered (percent done is SoFar / Expected)", " : total width that the bar is restricted to (defaults to 75)", " : character used to display the 'done' portion of bar", " : character used to display the 'non-done' portion of bar", "", "example command line invocations:", " pbar PBAR 200 50 25 [||||||::::::::::::::::::]", " pbar PBAR 200 120 25 [||||||||||||||::::::::::]", " pbar PBAR 200 150 25 [||||||||||||||||||::::::]", "", "live simulation:", " pbar PBAR DEMO [ []]", "", NULL }; const char* g_SynSLIDER[] = { "", "SLIDER usage:", " pbar START [ []]", " pbar ADD [ []]", " pbar END []", "", "where:", " : is either START, ADD or END (see below)", " START : outputs the leader row: v____...____v and an opening bar", " ADD : outputs zero or more 'ticks,' depending the progress delta", " END : pads out the rest of the slider and closes it with a bar", " : total steps expected (unsigned int up to 2147483647)", " : steps encountered (percent done is SoFar / Expected)", " : total width that the bar is restricted to (defaults to 75)", " : character used to display the 'done' portion of bar", "", "example command line invocations: v_________________________v", " pbar START 200 25 |", " pbar ADD 200 0 50 25 |||||||", " pbar ADD 200 120 150 25 |||||||||||||||||||", " pbar END 200 150 25 ||||||||||||||||||| |", "", "live simulation:", " pbar SLIDER DEMO [ []]", "", NULL }; //----------------------------------------------------------------------------- int main (int argc, char* argv[]) //----------------------------------------------------------------------------- { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // parse command line: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (--argc < 2) SynopsisAndExit (g_Synopsis, 0); if (strmatch (argv[2], "HELP") || strmatch (argv[2], "help")) { if (strmatch (argv[1], "PBAR") || strmatch (argv[1], "pbar")) SynopsisAndExit (g_SynPBAR, 0); else if (strmatch (argv[1], "SLIDER") || strmatch (argv[1], "slider")) SynopsisAndExit (g_SynSLIDER, 0); else { printf ("pbar: unknown help topic '%s'.\n", argv[1]); SynopsisAndExit (g_Synopsis, 1); } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // pbar PBAR [ [ []]] // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - else if (strmatch (argv[1], "PBAR") || strmatch (argv[1], "pbar")) { if (strmatch (argv[2], "DEMO") || strmatch (argv[2], "demo")) return (DemoPBAR (argc, argv)); if ((argc < 3) || (argc > 6)) SynopsisAndExit (g_SynPBAR, 1); enum {MAX = 500}; ULONG iExpected = atol (argv[2]); ULONG iSoFar = atol (argv[3]); int iBarWidth = (argc > 3) ? atoi (argv[4]) : DEFAULT_BARWIDTH; int chDoneChar = (argc > 4) ? *(argv[5]) : DEFAULT_DONE; int chBlankChar = (argc > 5) ? *(argv[6]) : DEFAULT_BLANK; int iMaxWidth = (iBarWidth < MAX) ? iBarWidth : MAX; char szBar[MAX+1]; kpbar (szBar, iMaxWidth, iSoFar, iExpected, chBlankChar, chDoneChar); printf ("[%s]\n", szBar); } else if ( (strmatch (argv[1], "SLIDER") || strmatch (argv[1], "slider")) && (strmatch (argv[2], "DEMO") || strmatch (argv[2], "demo"))) { return (DemoSLIDER (argc, argv)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // pbar START [ []] // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - else if (strmatch (argv[1], "START") || strmatch (argv[1], "start")) { if ((argc < 2) || (argc > 4)) SynopsisAndExit (g_SynSLIDER, 1); ULONG iExpected = atol (argv[2]); int iBarWidth = (argc > 2) ? atoi (argv[3]) : DEFAULT_BARWIDTH; int chDoneChar = (argc > 3) ? *(argv[4]) : DEFAULT_DONE; kpslide (KPS_START, iExpected, 0, 0, stdout, iBarWidth, chDoneChar); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // pbar ADD [ []] // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - else if (strmatch (argv[1], "ADD") || strmatch (argv[1], "add")) { if ((argc < 4) || (argc > 6)) SynopsisAndExit (g_SynSLIDER, 1); ULONG iExpected = atol (argv[2]); ULONG iSoFarLast = atol (argv[3]); ULONG iSoFarNow = atol (argv[4]); int iBarWidth = (argc > 4) ? atoi (argv[5]) : DEFAULT_BARWIDTH; int chDoneChar = (argc > 5) ? *(argv[6]) : DEFAULT_DONE; kpslide (KPS_ADD, iExpected, iSoFarLast, iSoFarNow, stdout, iBarWidth, chDoneChar); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // pbar END [] // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - else if (strmatch (argv[1], "END") || strmatch (argv[1], "end")) { if ((argc < 3) || (argc > 4)) SynopsisAndExit (g_SynSLIDER, 1); ULONG iExpected = atol (argv[2]); ULONG iSoFarLast = atol (argv[3]); int iBarWidth = (argc > 3) ? atoi (argv[4]) : DEFAULT_BARWIDTH; kpslide (KPS_END, iExpected, iSoFarLast, 0, stdout, iBarWidth, ' '); } else { SynopsisAndExit (g_Synopsis, 1); } return (0); } // main_kgi //----------------------------------------------------------------------------- void SynopsisAndExit (const char** pSynopsis, int iExitCode) //----------------------------------------------------------------------------- { for (int ii=0; pSynopsis[ii]; ++ii) printf ("%s\n", pSynopsis[ii]); exit (iExitCode); } // SynopsisAndExit //----------------------------------------------------------------------------- char* kpbar (char* szBar, UINT iMaxAlloc, ULONG iSoFar, ULONG iTotal, int chBlank/*=' '*/, int chDone/*='%'*/) //----------------------------------------------------------------------------- { UINT iMaxBars = iMaxAlloc-1; // initialize bar: for (UINT ii=0; ii 100.0) percent = 100.0; UINT iNumBars = (UINT) (percent * (double)(iMaxBars)); // show progress: for (UINT jj=0; jj 100.0) nPercentLast = 100.0; double nPercentNow = ((double)iSoFarNow / (double)iExpected); if (nPercentNow > 100.0) nPercentNow = 100.0; int iNumBarsLast = (int) (nPercentLast * (double)(iMaxBars)); int iNumBarsNow = (int) (nPercentNow * (double)(iMaxBars)); switch (iAction) { case KPS_START: fprintf (fp, "v"); for (ii=0; ii [ []] // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ((argc < 3) || (argc > 6)) SynopsisAndExit (g_SynPBAR, 1); enum {MAX = 500}; int iExpected = atoi (argv[3]); int iSoFar = 0; int chDoneChar = (argc > 3) ? *(argv[4]) : DEFAULT_DONE; int chBlankChar = (argc > 4) ? *(argv[5]) : DEFAULT_BLANK; int iMaxWidth = 50; char szBar[MAX+1]; if (iExpected <= 0) { printf ("pbar PBAR DEMO: invalid nsecs=%s\n", argv[3]); return (1); // err } int iNumPhrases = 7; const char* Phrases[] = { "something useful is happening", "something very useful is happening", "something really useful is happening", "something useless is happening", "something very useless is happening", "something really useless is happening", "useless, useful -- that's the question", NULL }; printf ("pbar: simulating a %d second run...\n", iExpected); for (iSoFar=0; iSoFar <= iExpected; ++iSoFar) { time_t tTime = time ((time_t *)NULL); struct tm* ptmStruct = localtime (&tTime); char szTimestamp[25]; strftime (szTimestamp, 25, "%Y-%m-%d %H:%M:%S", ptmStruct); printf ("%s: %s...\n", szTimestamp, Phrases[(iSoFar+0) % iNumPhrases]); printf ("%s: %s...\n", szTimestamp, Phrases[(iSoFar+2) % iNumPhrases]); #ifdef WIN32 //? Sleep (1000); // msecs printf ("%s: %s...\n", szTimestamp, "don't know how to sleep on win32..."); #else sleep (1); // secs #endif tTime = time ((time_t *)NULL); ptmStruct = localtime (&tTime); strftime (szTimestamp, 25, "%Y-%m-%d %H:%M:%S", ptmStruct); kpbar (szBar, iMaxWidth, iSoFar, iExpected, chBlankChar, chDoneChar); printf ("%s: [%s]\n", szTimestamp, szBar); } return (0); } // DemoPBAR //----------------------------------------------------------------------------- int DemoSLIDER (int argc, char* argv[]) //----------------------------------------------------------------------------- { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // pbar SLIDER DEMO [ []] // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ((argc < 3) || (argc > 5)) SynopsisAndExit (g_SynSLIDER, 1); int iExpected = atoi (argv[3]); int iSoFar = 0; int iBarWidth = (argc > 3) ? atoi (argv[4]) : DEFAULT_BARWIDTH; int chDoneChar = (argc > 4) ? *(argv[5]) : DEFAULT_DONE; if (iExpected <= 0) { printf ("pbar SLIDER DEMO: invalid nsecs=%s\n", argv[3]); return (1); // err } printf ("pbar: simulating a %d second run...\n", iExpected); kpslide (KPS_START, iExpected, 0, 0, stdout, iBarWidth, chDoneChar); for (iSoFar=0; iSoFar < iExpected; ++iSoFar) { #ifdef WIN32 //? Sleep (1000); // msecs #else sleep (1); // secs #endif kpslide (KPS_ADD, iExpected, iSoFar, iSoFar+1, stdout, iBarWidth, chDoneChar); } kpslide (KPS_END, iExpected, iExpected, 0, stdout, iBarWidth, ' '); return (0); } // DemoSLIDER