This is the mail archive of the cygwin-patches@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Mask mnemonics and expressions, help, getopts_long() for strace


Copyright assignment form is finally in the mail (yesterday).  This is
diffed against the cvs as of this writing, which does not yet contain
Egor's -w patch.


2001-11-04  Gary R. Van Sickle <g.r.vansickle@worldnet.att.net>

	* strace.cc (main): Change getopt() to getopt_long().
	Add support for help and version info.
      Use new parse_mask() function for -m/--mask option.
	(longopts): Add long options structure.
	(opts): Move options string from getopts call to static var.
	(usage): Print usage information.
	(version): Stub for eventually displaying version info.
      (parse_mask): New function supporting parsing of mnemonics,
      hex, and basic expressions in masks.
      (mnemonic2ul): New mnemonic parsing function.
      (tag_mask_mnemonic): New type.
      (mnemonic_table): New table of mnemonics for mnemonic2ul() to
      search through.


Index: winsup/utils/strace.cc
===================================================================
RCS file: /cvs/src/src/winsup/utils/strace.cc,v
retrieving revision 1.11
diff -p -u -b -r1.11 strace.cc
--- strace.cc	2001/03/05 17:55:23	1.11
+++ strace.cc	2001/11/04 06:05:57
@@ -588,6 +588,189 @@ dostrace (unsigned mask, FILE *ofile, ch
   return;
 }

+typedef struct tag_mask_mnemonic
+{
+	unsigned long val;
+	const char *text;
+} mask_mnemonic;
+
+static const mask_mnemonic mnemonic_table[] =
+{
+  { _STRACE_ALL,      "all" },
+  { _STRACE_FLUSH,    "flush" },
+  { _STRACE_INHERIT,  "inherit" },
+  { _STRACE_UHOH,     "uhoh" },
+  { _STRACE_SYSCALL,  "syscall" },
+  { _STRACE_STARTUP,  "startup" },
+  { _STRACE_DEBUG,    "debug" },
+  { _STRACE_PARANOID, "paranoid" },
+  { _STRACE_TERMIOS,  "termios" },
+  { _STRACE_SELECT,   "select" },
+  { _STRACE_WM,       "wm" },
+  { _STRACE_SIGP,     "sigp" },
+  { _STRACE_MINIMAL,  "minimal" },
+  { _STRACE_EXITDUMP, "exitdump" },
+  { _STRACE_SYSTEM,   "system" },
+  { _STRACE_NOMUTEX,  "nomutex" },
+  { _STRACE_MALLOC,   "malloc" },
+  { _STRACE_THREAD,   "thread" },
+  { 0, NULL }
+};
+
+static unsigned long mnemonic2ul (const char *nptr, char **endptr)
+{
+  // Look up mnemonic in table, return value.
+  // *endptr = ptr to char that breaks match.
+  const mask_mnemonic *mnp = mnemonic_table;
+
+  while(mnp->text != NULL)
+  {
+	if(strcmp(mnp->text, nptr) == 0)
+	{
+	  // Found a match.
+	  if(endptr != NULL)
+	  {
+	    *endptr = ((char*)nptr) + strlen(mnp->text);
+	  }
+	  return mnp->val;
+    }
+    mnp++;
+  }
+
+  // Didn't find it.
+  if(endptr != NULL)
+  {
+    *endptr = (char*)nptr;
+  }
+  return 0;
+}
+
+static unsigned long parse_mask (const char *ms, char **endptr)
+{
+  const char *p = ms;
+  char *newp;
+  unsigned long retval = 0, thisval;
+  const size_t bufsize = 16;
+  char buffer[bufsize];
+  size_t len;
+
+  while(*p != '\0')
+  {
+    // First extract the term, terminate it, and lowercase it.
+    strncpy(buffer, p, bufsize);
+    buffer[bufsize-1] = '\0';
+    len = strcspn(buffer, "+,\0");
+    buffer[len] = '\0';
+    strlwr(buffer);
+
+	// Check if this is a mnemonic.  We have to do this first or strtoul()
+	// will false-trigger on anything starting with "a" through "f".
+    thisval = mnemonic2ul(buffer, &newp);
+    if(buffer == newp)
+    {
+      // This term isn't mnemonic, check if it's hex.
+	  thisval = strtoul(buffer, &newp, 16);
+      if(newp != buffer+len)
+      {
+        // Not hex either, syntax error.
+        *endptr = (char*)p;
+        return 0;
+      }
+    }
+
+    p += len;
+    retval += thisval;
+
+    // Handle operators
+    if(*p == '\0') break;
+	if((*p == '+') || (*p == ','))
+	{
+	  // For now these both equate to addition/ORing.  Until we get
+	  // fancy and add things like "all-<something>", all we need do is
+	  // continue the looping.
+	  p++;
+	  continue;
+	}
+	else
+	{
+		// Syntax error
+        *endptr = (char*)p;
+        return 0;
+	}
+  }
+
+  *endptr = (char*)p;
+  return retval;
+}
+
+static void usage ()
+{
+  fprintf (stderr,
+"\
+Usage: strace [OPTIONS] <command-line>\n\
+  -b, --buffer-size=SIZE        Set size of output file buffer.\n\
+  -m, --mask=MASK               Set message filter mask.\n\
+\n\
+    MASK can be any combination of the following mnemonics and/or hex
values\n\
+    (0x is optional).  Combine masks with '+' or ',' like so:\n\
+\n\
+                      --mask=wm+system,malloc+0x00800\n\
+\n\
+    Mnemonic Hex     Corresponding Def  Description\n\
+
=========================================================================\n\
+    all      0x00001 (_STRACE_ALL)      All strace messages.\n\
+    flush    0x00002 (_STRACE_FLUSH)    Flush output buffer after each
message.\n\
+    inherit  0x00004 (_STRACE_INHERIT)  Children inherit mask from
parent.\n\
+    uhoh     0x00008 (_STRACE_UHOH)     Unusual or weird phenomenon.\n\
+    syscall  0x00010 (_STRACE_SYSCALL)  System calls.\n\
+    startup  0x00020 (_STRACE_STARTUP)  argc/envp printout at startup.\n\
+    debug    0x00040 (_STRACE_DEBUG)    Info to help debugging. \n\
+    paranoid 0x00080 (_STRACE_PARANOID) Paranoid info.\n\
+    termios  0x00100 (_STRACE_TERMIOS)  Info for debugging termios
stuff.\n\
+    select   0x00200 (_STRACE_SELECT)   Info on ugly select internals.\n\
+    wm       0x00400 (_STRACE_WM)       Trace Windows msgs (enable
_strace_wm).\n\
+    sigp     0x00800 (_STRACE_SIGP)     Trace signal and process
handling.\n\
+    minimal  0x01000 (_STRACE_MINIMAL)  Very minimal strace output.\n\
+    exitdump 0x04000 (_STRACE_EXITDUMP) Dump strace cache on exit.\n\
+    system   0x08000 (_STRACE_SYSTEM)   Cache strace messages.\n\
+    nomutex  0x10000 (_STRACE_NOMUTEX)  Don't use mutex for
synchronization.\n\
+    malloc   0x20000 (_STRACE_MALLOC)   Trace malloc calls.\n\
+    thread   0x40000 (_STRACE_THREAD)   Thread-locking calls.\n\
+\n\
+  -o, --output=FILENAME         Set output file to FILENAME.\n\
+  -f, --fork-debug              ???\n\
+  -n, --error-number            Also output associated Windows error
number.\n\
+  -d, --delta                   Add a delta-t timestamp to each output
line.\n\
+  -u, --usecs                   Add a microsecond-resolution timestamp to
each
+                                output line.\n\
+  -t, --timestamp               Add an hhmmss timestamp to each output
line.\n\
+  -v, --version                 Display version info.\n\
+  -h, --help                    Display this help info.\n\
+");
+}
+
+static void version ()
+{
+	fprintf (stderr, "Not yet implemented.");
+}
+
+struct option longopts[] =
+{
+  {"help", no_argument, NULL, 'h' },
+  {"version", no_argument, NULL, 'v' },
+  {"buffer-size", required_argument, NULL, 'b'},
+  {"mask", required_argument, NULL, 'm'},
+  {"output", required_argument, NULL, 'o'},
+  {"fork-debug", no_argument, NULL, 'f'},
+  {"error-number", no_argument, NULL, 'n'},
+  {"delta", no_argument, NULL, 'd'},
+  {"usecs", no_argument, NULL, 'u'},
+  {"timestamp", no_argument, NULL, 't'},
+  {NULL, 0, NULL, 0}
+};
+
+static const char *const opts = "hvb:m:o:fndut";
+
 int
 main (int argc, char **argv)
 {
@@ -600,9 +783,19 @@ main (int argc, char **argv)
   else
     pgm++;

-  while ((opt = getopt (argc, argv, "b:m:o:fndut")) != EOF)
+  while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
     switch (opt)
       {
+      case 'h':
+    // Print help and exit
+    usage ();
+    return 1;
+    break;
+      case 'v':
+    // Print version info and exit
+    version ();
+    return 1;
+    break;
       case 'f':
 	forkdebug ^= 1;
 	break;
@@ -610,8 +803,17 @@ main (int argc, char **argv)
 	bufsize = atoi (optarg);
 	break;
       case 'm':
-	mask = strtoul (optarg, NULL, 16);
+      {
+	    char *endptr;
+	    mask = parse_mask (optarg, &endptr);
+	    if(*endptr != '\0')
+	    {
+	      // Bad mask expression.
+	      error(0, "syntax error in mask expression \"%s\" near \
+character #%d.\n", optarg, (int)(endptr-optarg), endptr);
+	    }
 	break;
+	  }
       case 'o':
 	if ((ofile = fopen (optarg, "w")) == NULL)
 	  error (1, "can't open %s", optarg);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]