mariadb/dbug/dbug_analyze.c
unknown 16115af97c Changed to use my_global.h
Fixed problem with LIKE with latin1_de
Added parsing support of UNSIGNED LONG LONG


Docs/manual.texi:
  Changelog
client/client_priv.h:
  Changed to use my_global.h
client/completion_hash.cc:
  Changed to use my_global.h
client/errmsg.c:
  Changed to use my_global.h
client/get_password.c:
  Changed to use my_global.h
client/mysqldump.c:
  Changed to use my_global.h
client/mysqlshow.c:
  Changed to use my_global.h
client/mysqltest.c:
  Changed to use my_global.h
client/password.c:
  Changed to use my_global.h
client/readline.cc:
  Changed to use my_global.h
client/sql_string.cc:
  Changed to use my_global.h
client/thimble.cc:
  Changed to use my_global.h
client/thread_test.c:
  Changed to use my_global.h
dbug/dbug.c:
  Changed to use my_global.h
dbug/dbug_analyze.c:
  Changed to use my_global.h
dbug/example1.c:
  Changed to use my_global.h
dbug/example2.c:
  Changed to use my_global.h
dbug/example3.c:
  Changed to use my_global.h
dbug/factorial.c:
  Changed to use my_global.h
dbug/main.c:
  Changed to use my_global.h
dbug/sanity.c:
  Changed to use my_global.h
extra/comp_err.c:
  Changed to use my_global.h
extra/my_print_defaults.c:
  Changed to use my_global.h
extra/perror.c:
  Changed to use my_global.h
extra/replace.c:
  Changed to use my_global.h
extra/resolve_stack_dump.c:
  Changed to use my_global.h
extra/resolveip.c:
  Changed to use my_global.h
fs/libmysqlfs.h:
  Changed to use my_global.h
fs/mysqlcorbafs.h:
  Changed to use my_global.h
heap/hp_test1.c:
  Changed to use my_global.h
include/Makefile.am:
  Changed to use my_global.h
include/m_ctype.h:
  Changed to use my_global.h
include/my_base.h:
  Changed to use my_global.h
innobase/include/univ.i:
  Changed to use my_global.h
libmysql/dll.c:
  Changed to use my_global.h
libmysql/errmsg.c:
  Changed to use my_global.h
libmysql/get_password.c:
  Changed to use my_global.h
libmysql/libmysql.c:
  Changed to use my_global.h
libmysql/net.c:
  Changed to use my_global.h
libmysql/password.c:
  Changed to use my_global.h
libmysqld/lib_sql.cc:
  Changed to use my_global.h
libmysqld/lib_vio.c:
  Changed to use my_global.h
libmysqld/libmysqld.c:
  Changed to use my_global.h
mysql-test/mysql-test-run.sh:
  Changed to use latin1 as default character set
mysql-test/r/ctype_latin1_de.result:
  Changed to use my_global.h
mysql-test/r/func_like.result:
  New test
mysql-test/t/ctype_latin1_de.test:
  Added test of part keys
mysql-test/t/func_like.test:
  New test
mysys/checksum.c:
  Changed to use my_global.h
mysys/getopt.c:
  Changed to use my_global.h
mysys/getopt1.c:
  Changed to use my_global.h
mysys/make-conf.c:
  Changed to use my_global.h
mysys/my_alloc.c:
  Changed to use my_global.h
mysys/my_clock.c:
  Changed to use my_global.h
mysys/my_compress.c:
  Changed to use my_global.h
mysys/mysys_priv.h:
  Changed to use my_global.h
mysys/test_charset.c:
  Changed to use my_global.h
mysys/testhash.c:
  Changed to use my_global.h
mysys/thr_alarm.c:
  Changed to use my_global.h
mysys/thr_mutex.c:
  Changed to use my_global.h
regex/debug.c:
  Changed to use my_global.h
regex/main.c:
  Changed to use my_global.h
regex/regcomp.c:
  Changed to use my_global.h
regex/regerror.c:
  Changed to use my_global.h
regex/regexec.c:
  Changed to use my_global.h
regex/regexp.c:
  Changed to use my_global.h
regex/regfree.c:
  Changed to use my_global.h
regex/reginit.c:
  Changed to use my_global.h
sql/cache_manager.cc:
  Changed to use my_global.h
sql/gen_lex_hash.cc:
  Changed to use my_global.h
sql/ha_berkeley.cc:
  Fixed problem with UNIQUE keys that could contain NULL
sql/ha_gemini.h:
  Changed to use my_global.h
sql/handler.cc:
  Fixed problem after merge
sql/item.cc:
  Added Item_unit
sql/item.h:
  Added Item_uint
sql/matherr.c:
  Changed to use my_global.h
sql/md5.c:
  Changed to use my_global.h
sql/mini_client.cc:
  Changed to use my_global.h
sql/my_lock.c:
  Changed to use my_global.h
sql/mysql_priv.h:
  Changed to use my_global.h
sql/net_serv.cc:
  Changed to use my_global.h
sql/password.c:
  Changed to use my_global.h
sql/sql_lex.cc:
  Added parsing support of UNSIGNED LONG LONG
sql/sql_show.cc:
  Changed to use my_global.h
sql/sql_string.cc:
  Changed to use my_global.h
sql/sql_yacc.yy:
  Added usage of Int_uint
sql/stacktrace.c:
  Changed to use my_global.h
sql/udf_example.cc:
  Changed to use my_global.h
strings/atof.c:
  Changed to use my_global.h
strings/bchange.c:
  Changed to use my_global.h
strings/bcmp.c:
  Changed to use my_global.h
strings/bfill.c:
  Changed to use my_global.h
strings/bmove.c:
  Changed to use my_global.h
strings/bmove512.c:
  Changed to use my_global.h
strings/bmove_upp.c:
  Changed to use my_global.h
strings/ctype-big5.c:
  Changed to use my_global.h
strings/ctype-czech.c:
  Changed to use my_global.h
strings/ctype-euc_kr.c:
  Changed to use my_global.h
strings/ctype-gb2312.c:
  Changed to use my_global.h
strings/ctype-gbk.c:
  Changed to use my_global.h
strings/ctype-latin1_de.c:
  Fixed problem with LIKE
strings/ctype-sjis.c:
  Changed to use my_global.h
strings/ctype-tis620.c:
  Changed to use my_global.h
strings/ctype-ujis.c:
  Changed to use my_global.h
strings/ctype.c:
  Changed to use my_global.h
strings/do_ctype.c:
  Changed to use my_global.h
strings/int2str.c:
  Changed to use my_global.h
strings/is_prefix.c:
  Changed to use my_global.h
strings/llstr.c:
  Changed to use my_global.h
strings/longlong2str.c:
  Changed to use my_global.h
strings/r_strinstr.c:
  Changed to use my_global.h
strings/str2int.c:
  Changed to use my_global.h
strings/str_test.c:
  Changed to use my_global.h
strings/strappend.c:
  Changed to use my_global.h
strings/strcend.c:
  Changed to use my_global.h
strings/strcont.c:
  Changed to use my_global.h
strings/strend.c:
  Changed to use my_global.h
strings/strfill.c:
  Changed to use my_global.h
strings/strings-not-used.h:
  Changed to use my_global.h
strings/strinstr.c:
  Changed to use my_global.h
strings/strmake.c:
  Changed to use my_global.h
strings/strmov.c:
  Changed to use my_global.h
strings/strnlen.c:
  Changed to use my_global.h
strings/strnmov.c:
  Changed to use my_global.h
strings/strstr.c:
  Changed to use my_global.h
strings/strto.c:
  Changed to use my_global.h
strings/strtol.c:
  Changed to use my_global.h
strings/strtoll.c:
  Changed to use my_global.h
strings/strtoul.c:
  Changed to use my_global.h
strings/strtoull.c:
  Changed to use my_global.h
strings/strxmov.c:
  Changed to use my_global.h
strings/strxnmov.c:
  Changed to use my_global.h
strings/udiv.c:
  Changed to use my_global.h
tools/mysqlmanager.c:
  Changed to use my_global.h
vio/test-ssl.c:
  Changed to use my_global.h
vio/test-sslclient.c:
  Changed to use my_global.h
vio/test-sslserver.c:
  Changed to use my_global.h
vio/test-ssl:
  Changed to use my_global.h
vio/vio.c:
  Changed to use my_global.h
vio/viosocket.c:
  Changed to use my_global.h
vio/viossl.c:
  Changed to use my_global.h
vio/viosslfactories.c:
  Changed to use my_global.h
vio/viotest-ssl.c:
  Changed to use my_global.h
2001-09-14 02:54:33 +03:00

716 lines
19 KiB
C

/*
* Analyze the profile file (cmon.out) written out by the dbug
* routines with profiling enabled.
*
* Copyright June 1987, Binayak Banerjee
* All rights reserved.
*
* This program may be freely distributed under the same terms and
* conditions as Fred Fish's Dbug package.
*
* Compile with -- cc -O -s -o %s analyze.c
*
* Analyze will read an trace file created by the dbug package
* (when run with traceing enabled). It will then produce a
* summary on standard output listing the name of each traced
* function, the number of times it was called, the percentage
* of total calls, the time spent executing the function, the
* proportion of the total time and the 'importance'. The last
* is a metric which is obtained by multiplying the proportions
* of calls and the proportions of time for each function. The
* greater the importance, the more likely it is that a speedup
* could be obtained by reducing the time taken by that function.
*
* Note that the timing values that you obtain are only rough
* measures. The overhead of the dbug package is included
* within. However, there is no need to link in special profiled
* libraries and the like.
*
* CHANGES:
*
* 2-Mar-89: fnf
* Changes to support tracking of stack usage. This required
* reordering the fields in the profile log file to make
* parsing of different record types easier. Corresponding
* changes made in dbug runtime library. Also used this
* opportunity to reformat the code more to my liking (my
* apologies to Binayak Banerjee for "uglifying" his code).
*
* 24-Jul-87: fnf
* Because I tend to use functions names like
* "ExternalFunctionDoingSomething", I've rearranged the
* printout to put the function name last in each line, so
* long names don't screw up the formatting unless they are
* *very* long and wrap around the screen width...
*
* 24-Jul-87: fnf
* Modified to put out table very similar to Unix profiler
* by default, but also puts out original verbose table
* if invoked with -v flag.
*/
#include <my_global.h>
#include <m_string.h>
static char *my_name;
static int verbose;
/*
* Structure of the stack.
*/
#define PRO_FILE "dbugmon.out" /* Default output file name */
#define STACKSIZ 100 /* Maximum function nesting */
#define MAXPROCS 10000 /* Maximum number of function calls */
# ifdef BSD
# include <sysexits.h>
# else
# define EX_SOFTWARE 1
# define EX_DATAERR 1
# define EX_USAGE 1
# define EX_OSERR 1
# define EX_IOERR 1
#ifndef EX_OK
# define EX_OK 0
#endif
# endif
#define __MERF_OO_ "%s: Malloc Failed in %s: %d\n"
#define MALLOC(Ptr,Num,Typ) do /* Malloc w/error checking & exit */ \
if (!(Ptr = (Typ *)malloc((Num)*(sizeof(Typ))))) \
{fprintf(stderr,__MERF_OO_,my_name,__FILE__,__LINE__);\
exit(EX_OSERR);} while(0)
#define Malloc(Ptr,Num,Typ) do /* Weaker version of above */\
if (!(Ptr = (Typ *)malloc((Num)*(sizeof(Typ))))) \
fprintf(stderr,__MERF_OO_,my_name,__FILE__,__LINE__);\
while(0)
#define FILEOPEN(Fp,Fn,Mod) do /* File open with error exit */ \
if (!(Fp = fopen(Fn,Mod)))\
{fprintf(stderr,"%s: Couldn't open %s\n",my_name,Fn);\
exit(EX_IOERR);} while(0)
#define Fileopen(Fp,Fn,Mod) do /* Weaker version of above */ \
if(!(Fp = fopen(Fn,Mod))) \
fprintf(stderr,"%s: Couldn't open %s\n",my_name,Fn);\
while(0)
struct stack_t {
unsigned int pos; /* which function? */
unsigned long time; /* Time that this was entered */
unsigned long children; /* Time spent in called funcs */
};
static struct stack_t fn_stack[STACKSIZ+1];
static unsigned int stacktop = 0; /* Lowest stack position is a dummy */
static unsigned long tot_time = 0;
static unsigned long tot_calls = 0;
static unsigned long highstack = 0;
static unsigned long lowstack = (ulong) ~0;
/*
* top() returns a pointer to the top item on the stack.
* (was a function, now a macro)
*/
#define top() &fn_stack[stacktop]
/*
* Push - Push the given record on the stack.
*/
void push (name_pos, time_entered)
register unsigned int name_pos;
register unsigned long time_entered;
{
register struct stack_t *t;
DBUG_ENTER("push");
if (++stacktop > STACKSIZ) {
fprintf (DBUG_FILE,"%s: stack overflow (%s:%d)\n",
my_name, __FILE__, __LINE__);
exit (EX_SOFTWARE);
}
DBUG_PRINT ("push", ("%d %ld",name_pos,time_entered));
t = &fn_stack[stacktop];
t -> pos = name_pos;
t -> time = time_entered;
t -> children = 0;
DBUG_VOID_RETURN;
}
/*
* Pop - pop the top item off the stack, assigning the field values
* to the arguments. Returns 0 on stack underflow, or on popping first
* item off stack.
*/
unsigned int pop (name_pos, time_entered, child_time)
register unsigned int *name_pos;
register unsigned long *time_entered;
register unsigned long *child_time;
{
register struct stack_t *temp;
register unsigned int rtnval;
DBUG_ENTER ("pop");
if (stacktop < 1) {
rtnval = 0;
} else {
temp = &fn_stack[stacktop];
*name_pos = temp->pos;
*time_entered = temp->time;
*child_time = temp->children;
DBUG_PRINT ("pop", ("%d %d %d",*name_pos,*time_entered,*child_time));
rtnval = stacktop--;
}
DBUG_RETURN (rtnval);
}
/*
* We keep the function info in another array (serves as a simple
* symbol table)
*/
struct module_t {
char *name;
unsigned long m_time;
unsigned long m_calls;
unsigned long m_stkuse;
};
static struct module_t modules[MAXPROCS];
/*
* We keep a binary search tree in order to look up function names
* quickly (and sort them at the end.
*/
struct bnode {
unsigned int lchild; /* Index of left subtree */
unsigned int rchild; /* Index of right subtree */
unsigned int pos; /* Index of module_name entry */
};
static struct bnode s_table[MAXPROCS];
static unsigned int n_items = 0; /* No. of items in the array so far */
/*
* Need a function to allocate space for a string and squirrel it away.
*/
char *strsave (s)
char *s;
{
register char *retval;
register unsigned int len;
DBUG_ENTER ("strsave");
DBUG_PRINT ("strsave", ("%s",s));
if (!s || (len = strlen (s)) == 0) {
DBUG_RETURN (0);
}
MALLOC (retval, ++len, char);
strcpy (retval, s);
DBUG_RETURN (retval);
}
/*
* add() - adds m_name to the table (if not already there), and returns
* the index of its location in the table. Checks s_table (which is a
* binary search tree) to see whether or not it should be added.
*/
unsigned int add (m_name)
char *m_name;
{
register unsigned int ind = 0;
register int cmp;
DBUG_ENTER ("add");
if (n_items == 0) { /* First item to be added */
s_table[0].pos = ind;
s_table[0].lchild = s_table[0].rchild = MAXPROCS;
addit:
modules[n_items].name = strsave (m_name);
modules[n_items].m_time = 0;
modules[n_items].m_calls = 0;
modules[n_items].m_stkuse = 0;
DBUG_RETURN (n_items++);
}
while (cmp = strcmp (m_name,modules[ind].name)) {
if (cmp < 0) { /* In left subtree */
if (s_table[ind].lchild == MAXPROCS) {
/* Add as left child */
if (n_items >= MAXPROCS) {
fprintf (DBUG_FILE,
"%s: Too many functions being profiled\n",
my_name);
exit (EX_SOFTWARE);
}
s_table[n_items].pos = s_table[ind].lchild = n_items;
s_table[n_items].lchild = s_table[n_items].rchild = MAXPROCS;
#ifdef notdef
modules[n_items].name = strsave (m_name);
modules[n_items].m_time = modules[n_items].m_calls = 0;
DBUG_RETURN (n_items++);
#else
goto addit;
#endif
}
ind = s_table[ind].lchild; /* else traverse l-tree */
} else {
if (s_table[ind].rchild == MAXPROCS) {
/* Add as right child */
if (n_items >= MAXPROCS) {
fprintf (DBUG_FILE,
"%s: Too many functions being profiled\n",
my_name);
exit (EX_SOFTWARE);
}
s_table[n_items].pos = s_table[ind].rchild = n_items;
s_table[n_items].lchild = s_table[n_items].rchild = MAXPROCS;
#ifdef notdef
modules[n_items].name = strsave (m_name);
modules[n_items].m_time = modules[n_items].m_calls = 0;
DBUG_RETURN (n_items++);
#else
goto addit;
#endif
}
ind = s_table[ind].rchild; /* else traverse r-tree */
}
}
DBUG_RETURN (ind);
}
/*
* process() - process the input file, filling in the modules table.
*/
void process (inf)
FILE *inf;
{
char buf[BUFSIZ];
char fn_name[64]; /* Max length of fn_name */
unsigned long fn_time;
unsigned long fn_sbot;
unsigned long fn_ssz;
unsigned long lastuse;
unsigned int pos;
unsigned long time;
unsigned int oldpos;
unsigned long oldtime;
unsigned long oldchild;
struct stack_t *t;
DBUG_ENTER ("process");
while (fgets (buf,BUFSIZ,inf) != NULL) {
switch (buf[0]) {
case 'E':
sscanf (buf+2, "%ld %64s", &fn_time, fn_name);
DBUG_PRINT ("erec", ("%ld %s", fn_time, fn_name));
pos = add (fn_name);
push (pos, fn_time);
break;
case 'X':
sscanf (buf+2, "%ld %64s", &fn_time, fn_name);
DBUG_PRINT ("xrec", ("%ld %s", fn_time, fn_name));
pos = add (fn_name);
/*
* An exited function implies that all stacked
* functions are also exited, until the matching
* function is found on the stack.
*/
while (pop (&oldpos, &oldtime, &oldchild)) {
DBUG_PRINT ("popped", ("%d %d", oldtime, oldchild));
time = fn_time - oldtime;
t = top ();
t -> children += time;
DBUG_PRINT ("update", ("%s", modules[t -> pos].name));
DBUG_PRINT ("update", ("%d", t -> children));
time -= oldchild;
modules[oldpos].m_time += time;
modules[oldpos].m_calls++;
tot_time += time;
tot_calls++;
if (pos == oldpos) {
goto next_line; /* Should be a break2 */
}
}
/*
* Assume that item seen started at time 0.
* (True for function main). But initialize
* it so that it works the next time too.
*/
t = top ();
time = fn_time - t -> time - t -> children;
t -> time = fn_time; t -> children = 0;
modules[pos].m_time += time;
modules[pos].m_calls++;
tot_time += time;
tot_calls++;
break;
case 'S':
sscanf (buf+2, "%lx %lx %64s", &fn_sbot, &fn_ssz, fn_name);
DBUG_PRINT ("srec", ("%lx %lx %s", fn_sbot, fn_ssz, fn_name));
pos = add (fn_name);
lastuse = modules[pos].m_stkuse;
#if 0
/*
* Needs further thought. Stack use is determined by
* difference in stack between two functions with DBUG_ENTER
* macros. If A calls B calls C, where A and C have the
* macros, and B doesn't, then B's stack use will be lumped
* in with either A's or C's. If somewhere else A calls
* C directly, the stack use will seem to change. Just
* take the biggest for now...
*/
if (lastuse > 0 && lastuse != fn_ssz) {
fprintf (stderr,
"warning - %s stack use changed (%lx to %lx)\n",
fn_name, lastuse, fn_ssz);
}
#endif
if (fn_ssz > lastuse) {
modules[pos].m_stkuse = fn_ssz;
}
if (fn_sbot > highstack) {
highstack = fn_sbot;
} else if (fn_sbot < lowstack) {
lowstack = fn_sbot;
}
break;
default:
fprintf (stderr, "unknown record type '%s'\n", buf[0]);
break;
}
next_line:;
}
/*
* Now, we've hit eof. If we still have stuff stacked, then we
* assume that the user called exit, so give everything the exited
* time of fn_time.
*/
while (pop (&oldpos,&oldtime,&oldchild)) {
time = fn_time - oldtime;
t = top ();
t -> children += time;
time -= oldchild;
modules[oldpos].m_time += time;
modules[oldpos].m_calls++;
tot_time += time;
tot_calls++;
}
DBUG_VOID_RETURN;
}
/*
* out_header () -- print out the header of the report.
*/
void out_header (outf)
FILE *outf;
{
DBUG_ENTER ("out_header");
if (verbose) {
fprintf (outf, "Profile of Execution\n");
fprintf (outf, "Execution times are in milliseconds\n\n");
fprintf (outf, " Calls\t\t\t Time\n");
fprintf (outf, " -----\t\t\t ----\n");
fprintf (outf, "Times\tPercentage\tTime Spent\tPercentage\n");
fprintf (outf, "Called\tof total\tin Function\tof total Importance\tFunction\n");
fprintf (outf, "======\t==========\t===========\t========== ==========\t========\t\n");
} else {
fprintf (outf, "%ld bytes of stack used, from %lx down to %lx\n\n",
highstack - lowstack, highstack, lowstack);
fprintf (outf,
" %%time sec #call ms/call %%calls weight stack name\n");
}
DBUG_VOID_RETURN;
}
/*
* out_trailer () - writes out the summary line of the report.
*/
void out_trailer (outf,sum_calls,sum_time)
FILE *outf;
unsigned long int sum_calls, sum_time;
{
DBUG_ENTER ("out_trailer");
if (verbose) {
fprintf (outf, "======\t==========\t===========\t==========\t========\n");
fprintf (outf, "%6d\t%10.2f\t%11d\t%10.2f\t\t%-15s\n",
sum_calls, 100.0, sum_time, 100.0, "Totals");
}
DBUG_VOID_RETURN;
}
/*
* out_item () - prints out the output line for a single entry,
* and sets the calls and time fields appropriately.
*/
void out_item (outf, m,called,timed)
FILE *outf;
register struct module_t *m;
unsigned long int *called, *timed;
{
char *name = m -> name;
register unsigned int calls = m -> m_calls;
register unsigned long time = m -> m_time;
register unsigned long stkuse = m -> m_stkuse;
unsigned int import;
double per_time = 0.0;
double per_calls = 0.0;
double ms_per_call, ftime;
DBUG_ENTER ("out_item");
if (tot_time > 0) {
per_time = (double) (time * 100) / (double) tot_time;
}
if (tot_calls > 0) {
per_calls = (double) (calls * 100) / (double) tot_calls;
}
import = (unsigned int) (per_time * per_calls);
if (verbose) {
fprintf (outf, "%6d\t%10.2f\t%11d\t%10.2f %10d\t%-15s\n",
calls, per_calls, time, per_time, import, name);
} else {
ms_per_call = time;
ms_per_call /= calls;
ftime = time;
ftime /= 1000;
fprintf (outf, "%8.2f%8.3f%8u%8.3f%8.2f%8u%8u %-s\n",
per_time, ftime, calls, ms_per_call, per_calls, import,
stkuse, name);
}
*called = calls;
*timed = time;
DBUG_VOID_RETURN;
}
/*
* out_body (outf, root,s_calls,s_time) -- Performs an inorder traversal
* on the binary search tree (root). Calls out_item to actually print
* the item out.
*/
void out_body (outf, root,s_calls,s_time)
FILE *outf;
register unsigned int root;
register unsigned long int *s_calls, *s_time;
{
unsigned long int calls, time;
DBUG_ENTER ("out_body");
DBUG_PRINT ("out_body", ("%d,%d",*s_calls,*s_time));
if (root == MAXPROCS) {
DBUG_PRINT ("out_body", ("%d,%d",*s_calls,*s_time));
} else {
while (root != MAXPROCS) {
out_body (outf, s_table[root].lchild,s_calls,s_time);
out_item (outf, &modules[s_table[root].pos],&calls,&time);
DBUG_PRINT ("out_body", ("-- %d -- %d --", calls, time));
*s_calls += calls;
*s_time += time;
root = s_table[root].rchild;
}
DBUG_PRINT ("out_body", ("%d,%d", *s_calls, *s_time));
}
DBUG_VOID_RETURN;
}
/*
* output () - print out a nice sorted output report on outf.
*/
void output (outf)
FILE *outf;
{
unsigned long int sum_calls = 0;
unsigned long int sum_time = 0;
DBUG_ENTER ("output");
if (n_items == 0) {
fprintf (outf, "%s: No functions to trace\n", my_name);
exit (EX_DATAERR);
}
out_header (outf);
out_body (outf, 0,&sum_calls,&sum_time);
out_trailer (outf, sum_calls,sum_time);
DBUG_VOID_RETURN;
}
#define usage() fprintf (DBUG_FILE,"Usage: %s [-v] [prof-file]\n",my_name)
#ifdef MSDOS
extern int getopt(int argc, char **argv, char *opts);
#endif
extern int optind;
extern char *optarg;
int main (int argc, char **argv)
{
register int c;
int badflg = 0;
FILE *infile;
FILE *outfile = {stdout};
DBUG_ENTER ("main");
DBUG_PROCESS (argv[0]);
my_name = argv[0];
while ((c = getopt (argc,argv,"#:v")) != EOF) {
switch (c) {
case '#': /* Debugging Macro enable */
DBUG_PUSH (optarg);
break;
case 'v': /* Verbose mode */
verbose++;
break;
default:
badflg++;
break;
}
}
if (badflg) {
usage ();
DBUG_RETURN (EX_USAGE);
}
if (optind < argc) {
FILEOPEN (infile, argv[optind], "r");
} else {
FILEOPEN (infile, PRO_FILE, "r");
}
process (infile);
output (outfile);
DBUG_RETURN (EX_OK);
}
#ifdef MSDOS
/*
* From std-unix@ut-sally.UUCP (Moderator, John Quarterman) Sun Nov 3 14:34:15 1985
* Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site gatech.CSNET
* Posting-Version: version B 2.10.2 9/18/84; site ut-sally.UUCP
* Path: gatech!akgua!mhuxv!mhuxt!mhuxr!ulysses!allegra!mit-eddie!genrad!panda!talcott!harvard!seismo!ut-sally!std-unix
* From: std-unix@ut-sally.UUCP (Moderator, John Quarterman)
* Newsgroups: mod.std.unix
* Subject: public domain AT&T getopt source
* Message-ID: <3352@ut-sally.UUCP>
* Date: 3 Nov 85 19:34:15 GMT
* Date-Received: 4 Nov 85 12:25:09 GMT
* Organization: IEEE/P1003 Portable Operating System Environment Committee
* Lines: 91
* Approved: jsq@ut-sally.UUCP
*
* Here's something you've all been waiting for: the AT&T public domain
* source for getopt(3). It is the code which was given out at the 1985
* UNIFORUM conference in Dallas. I obtained it by electronic mail
* directly from AT&T. The people there assure me that it is indeed
* in the public domain.
*
* There is no manual page. That is because the one they gave out at
* UNIFORUM was slightly different from the current System V Release 2
* manual page. The difference apparently involved a note about the
* famous rules 5 and 6, recommending using white space between an option
* and its first argument, and not grouping options that have arguments.
* Getopt itself is currently lenient about both of these things White
* space is allowed, but not mandatory, and the last option in a group can
* have an argument. That particular version of the man page evidently
* has no official existence, and my source at AT&T did not send a copy.
* The current SVR2 man page reflects the actual behavor of this getopt.
* However, I am not about to post a copy of anything licensed by AT&T.
*
* I will submit this source to Berkeley as a bug fix.
*
* I, personally, make no claims or guarantees of any kind about the
* following source. I did compile it to get some confidence that
* it arrived whole, but beyond that you're on your own.
*
*/
/*LINTLIBRARY*/
int opterr = 1;
int optind = 1;
int optopt;
char *optarg;
static void _ERR(s,c,argv)
char *s;
int c;
char *argv[];
{
char errbuf[3];
if (opterr) {
errbuf[0] = c;
errbuf[1] = '\n';
(void) fprintf(stderr, "%s", argv[0]);
(void) fprintf(stderr, "%s", s);
(void) fprintf(stderr, "%s", errbuf);
}
}
int getopt(argc, argv, opts)
int argc;
char **argv, *opts;
{
static int sp = 1;
register int c;
register char *cp;
if(sp == 1)
if(optind >= argc ||
argv[optind][0] != '-' || argv[optind][1] == '\0')
return(EOF);
else if(strcmp(argv[optind], "--") == 0) {
optind++;
return(EOF);
}
optopt = c = argv[optind][sp];
if(c == ':' || (cp=strchr(opts, c)) == NULL) {
_ERR(": illegal option -- ", c, argv);
if(argv[optind][++sp] == '\0') {
optind++;
sp = 1;
}
return('?');
}
if(*++cp == ':') {
if(argv[optind][sp+1] != '\0')
optarg = &argv[optind++][sp+1];
else if(++optind >= argc) {
_ERR(": option requires an argument -- ", c, argv);
sp = 1;
return('?');
} else
optarg = argv[optind++];
sp = 1;
} else {
if(argv[optind][++sp] == '\0') {
sp = 1;
optind++;
}
optarg = NULL;
}
return(c);
}
#endif /* !unix && !xenix */