You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by ab...@apache.org on 2008/03/31 22:04:02 UTC
svn commit: r643120 - /stdcxx/trunk/util/output.cpp
Author: ablack
Date: Mon Mar 31 13:03:58 2008
New Revision: 643120
URL: http://svn.apache.org/viewvc?rev=643120&view=rev
Log:
2008-03-31 Andrew Black <ab...@roguewave.com>
STDCXX-426
* util/output.cpp (struct readback): Add convenience data structure
for backwards file reading.
(rbinit): Add method to initialize structure.
(rbbof): Add method to check if structure points to the beginning
of a file.
(rbsync): Add method to synchronize the file handle the structure
is built on to the structure.
(rbgetc): Add method to retrieve a character from the file and
move the structure one position closer to the start
(rbscanf): Add methods to search for a string using the
structure, possibly capturing an unsigned integer in the process.
(check_test, check_compat_test): Alter to use above methods.
Modified:
stdcxx/trunk/util/output.cpp
Modified: stdcxx/trunk/util/output.cpp
URL: http://svn.apache.org/viewvc/stdcxx/trunk/util/output.cpp?rev=643120&r1=643119&r2=643120&view=diff
==============================================================================
--- stdcxx/trunk/util/output.cpp (original)
+++ stdcxx/trunk/util/output.cpp Mon Mar 31 13:03:58 2008
@@ -44,6 +44,239 @@
# define ENOENT 2
#endif /* ENOENT */
+/**
+ Arbitrary constant controling static read buffer size.
+
+ @see check_example ()
+ @see rbread ()
+*/
+#define DELTA_BUF_LEN 64
+
+/**
+ This structure is used to encapsulate the data involved in a backwards
+ file read.
+*/
+struct readback {
+ FILE* src;
+ char buf[DELTA_BUF_LEN];
+ long bpos;
+};
+
+/**
+ Initializes the provided readback structure, with the provided file
+ handle.
+
+ @param rb pointer to readback structure to initialize
+ @param src file handle to initialize rb with.
+ @returns true if successfully initialized, false otherwise.
+*/
+static bool
+rbinit (struct readback* rb, FILE* const src)
+{
+ const size_t buflen = sizeof rb->buf;
+ long fpos;
+ assert (0 != rb);
+ assert (0 != src);
+
+ rb->src = src;
+ if (-1 == fseek (rb->src, 0, SEEK_END))
+ return false;
+ fpos = ftell (rb->src);
+ if (-1 == fpos)
+ return false;
+
+ if (fpos <= buflen)
+ rb->bpos = fpos;
+ else
+ rb->bpos = buflen;
+
+ if (-1 == fseek (rb->src, fpos - rb->bpos, SEEK_SET))
+ return false;
+
+ return rb->bpos == fread (rb->buf, 1, rb->bpos, rb->src);
+}
+
+/**
+ This method is semi-analagous to feof.
+
+ @param rb pointer to readback structure to check begin-of-file state for
+ @returns true if structure points to the begining of the file, false
+ otherwise
+*/
+static bool
+rbbof (const struct readback* const rb)
+{
+ assert (0 != rb);
+ assert (0 != rb->src);
+ return (0 == rb->bpos) && (0 == ftell (rb->src));
+}
+
+/**
+ Syncronizes the file handle underlying a readback structure to the
+ pointer in the structure. This method is called if you wish to start
+ reading forward from the current point in the readback structure.
+
+ @param rb pointer to the readback structure to syncronize.
+ @return true if the structure was successfully syncronized, false
+ otherwise.
+*/
+static bool
+rbsync (struct readback* const rb)
+{
+ assert (0 != rb);
+ assert (0 != rb->src);
+ const size_t buflen = sizeof rb->buf;
+ long fpos = ftell (rb->src) - buflen;
+ if (0 > fpos)
+ fpos=0;
+ fpos += rb->bpos;
+ rb->bpos=0;
+
+ return -1 != fseek (rb->src, fpos, SEEK_SET);
+}
+
+/**
+ Updates the provided readback structure, returning the last unread
+ character in the file. This method is semi-analagous to fgetc.
+
+ @param rb pointer to readback structure to read from.
+ @return EOF if beginning of file or I/O error, read character
+ otherwise.
+*/
+static char
+rbgetc (struct readback* rb)
+{
+ const size_t buflen = sizeof rb->buf;
+ assert (0 != rb);
+ assert (0 != rb->src);
+ if (!rb->bpos) {
+ const size_t bufdelta = buflen << 1;
+ long fpos = ftell (rb->src);
+ long seek;
+
+ if (-1 == fpos)
+ return EOF;
+
+ if (bufdelta <= fpos) {
+ seek = fpos - bufdelta;
+ rb->bpos = buflen;
+ }
+ else if (buflen < fpos) {
+ seek = 0;
+ rb->bpos = fpos - buflen;
+ }
+ else {
+ fseek (rb->src, 0, SEEK_SET);
+ return EOF;
+ }
+
+ if (-1 == fseek (rb->src, seek, SEEK_SET))
+ return EOF;
+
+ if (rb->bpos != fread (rb->buf, 1, rb->bpos, rb->src))
+ return EOF;
+ }
+ assert (0 < rb->bpos && rb->bpos <= buflen);
+
+ return rb->buf [--rb->bpos];
+}
+
+/**
+ This method is semi-analagous to fscanf, with some key differences.
+ First, it opperates on a readback structure. Second, it scans until
+ either the search pattern is matched, or until the begining of the file
+ is reached. Third, it reads backwards from the end of the file.
+
+ Limitations: string to match can't end in a repeated set of characters
+ (ie: 'singing' has the repeated characters 'ing')
+
+ @param rb pointer to readback structure to operate on
+ @param match string to search for
+ @return true if match is found, false if begining of file is reached
+*/
+static bool
+rbscanf (struct readback* rb, const char* const match)
+{
+ char tok;
+ size_t matched;
+ size_t count;
+ assert (0 != rb);
+ assert (0 != match);
+
+ matched = count = strlen (match) - 1;
+
+ for(tok = rbgetc(rb); matched && !rbbof (rb); tok = rbgetc (rb)) {
+ if (tok == match [matched])
+ --matched;
+ else
+ matched = count;
+ }
+ return !matched;
+}
+
+/**
+ This method is semi-analagous to fscanf, reading backwards on a readback
+ structure, starting from the end of the file.
+
+ This method searches backwards for the first (last) number and captures
+ it. It then checks if the match string exists directly after (before)
+ the captured value. If this is the case, a match is considered to have
+ been found, and the captured value is copied to val. Otherwise, the
+ search process is restarted. If the search hits the beginning of the
+ file, matching is considered to have failed, and val is unaltered.
+
+ Limitations: string to match can't end in a repeated set of characters
+ (ie: 'singing' has the repeated characters 'ing'.) or a repeated set
+ of characters, bordering on either side of one or more numbers (ie:
+ 'xyzzy9zzy' has the repeated characters 'zzy')
+
+ @param rb pointer to readback structure to operate on.
+ @param match string to search for.
+ @param val reference to variable to store captured value in.
+ @return true if match is found, false if begining of file is reached.
+*/
+static bool
+rbscanf (struct readback* rb, const char* const match, unsigned& val)
+{
+ size_t count;
+ unsigned tval =0;
+ unsigned radix;
+ assert (0 != rb);
+ assert (0 != match);
+
+ count = strlen (match) - 1;
+
+ while (!rbbof(rb)) {
+ char tok;
+ size_t matched = count;
+
+ tval=0;
+ radix=1;
+
+ /* Search for a numeric digit */
+ for (tok = rbgetc (rb);
+ (tok < '0' || tok > '9') && !rbbof (rb);
+ tok = rbgetc (rb)) /* Do nothing */;
+
+ /* Read in the number. */
+ for ( ; tok >= '0' && tok <= '9' && !rbbof (rb);
+ tok = rbgetc (rb)) {
+ tval += (tok-'0') * radix;
+ radix *= 10;
+ }
+
+ /* Make certain the content prior to the number in the file
+ matches the search pattern. */
+ for( ; matched && tok == match [matched] && !rbbof (rb);
+ tok = rbgetc (rb), --matched) /* Do nothing */;
+
+ if (tok == match [matched]) {
+ val = tval;
+ return true;
+ }
+ }
+ return false;
+}
/**
Parses contents of the open file handle data for test target_name.
@@ -58,6 +291,7 @@
static void
check_test (FILE* data, struct target_status* status)
{
+ struct readback buf;
unsigned r_lvl = 0; /* diagnostic severity level */
unsigned r_active = 0; /* number of active diagnostics */
unsigned r_total = 0; /* total number of diagnostics */
@@ -73,15 +307,28 @@
assert (0 != data);
assert (0 != status);
- tok = fgetc (data);
+ if (!rbinit (&buf, data)) {
+ status->status = ST_SYSTEM_ERROR;
+ return;
+ }
- if (feof (data)) {
+ if (rbbof (&buf)) {
/* target produced no output (regression test?) */
status->status = ST_NO_OUTPUT;
return;
}
- for ( ; fsm < 6 && !feof (data); tok = fgetc (data)) {
+ if (!rbscanf (&buf, "| INACTIVE |\n# +")) {
+ status->status = ST_FORMAT;
+ return;
+ }
+
+ rbsync(&buf);
+
+ /* While it'd probably be (slightly) faster to seek to a fixed position
+ after the file pointer has been synced, this should be more reliable
+ */
+ for (tok = fgetc (data); fsm < 6 && !feof (data); tok = fgetc (data)) {
switch (tok) {
case '\n':
fsm = 1;
@@ -150,58 +397,25 @@
static void
check_compat_test (FILE* data, struct target_status* status)
{
- int read = 0;
- unsigned fsm = 0;
- char tok;
+ struct readback buf;
assert (0 != data);
assert (0 != status);
- tok = fgetc (data);
-
- if (feof (data)) {
+ if (!rbinit (&buf, data)) {
+ status->status = ST_SYSTEM_ERROR;
+ }
+ else if (rbbof (&buf)) {
/* target produced no output (regression test?) */
status->status = ST_NO_OUTPUT;
- return;
- }
-
- for ( ; !feof (data); tok = fgetc (data)) {
- switch (tok) {
- case '\n':
- fsm = 1;
- break;
- case '#':
- if (1 == fsm || 2 == fsm)
- ++fsm;
- else
- fsm = 0;
- break;
- case ' ':
- if (3 == fsm)
- ++fsm;
- else
- fsm = 0;
- break;
- case 'W':
- if (4 == fsm && !feof (data)) /* leading "## W" eaten */
- read = fscanf (data, "arnings = %u\n## Assertions = %u\n"
- "## FailedAssertions = %u",
- &status->t_warn, &status->assert, &status->failed);
- default:
- fsm = 0;
- }
}
- if (3 != read) {
+ else if ( !rbscanf (&buf, "## FailedAssertions = ", status->failed)
+ || !rbscanf (&buf, "## Assertions = ", status->assert)
+ || !rbscanf (&buf, "## Warnings = ", status->t_warn)) {
status->status = ST_FORMAT;
}
}
-/**
- Arbitrary constant controling static read buffer size.
-
- @see check_example ()
-*/
-#define DELTA_BUF_LEN 64
/**
Parses output file out_name for the example target_name.
Re: svn commit: r643120 - /stdcxx/trunk/util/output.cpp
Posted by Martin Sebor <se...@roguewave.com>.
Andrew, we're getting a bunch of new signed/unsigned comparison
warnings after this change. Can you look into silencing them when
you have a minute?
$TOPDIR/util/output.cpp: In function ‘bool rbinit(readback*, FILE*)’:
$TOPDIR/util/output.cpp:88: warning: comparison between signed and
unsigned integer expressions
$TOPDIR/util/output.cpp:96: warning: comparison between signed and
unsigned integer expressions
$TOPDIR/util/output.cpp: In function ‘char rbgetc(readback*)’:
$TOPDIR/util/output.cpp:160: warning: comparison between signed and
unsigned integer expressions
$TOPDIR/util/output.cpp:164: warning: comparison between signed and
unsigned integer expressions
$TOPDIR/util/output.cpp:176: warning: comparison between signed and
unsigned integer expressions
$TOPDIR/util/output.cpp:179: warning: comparison between signed and
unsigned integer expressions
Thanks
Martin
ablack@apache.org wrote:
> Author: ablack
> Date: Mon Mar 31 13:03:58 2008
> New Revision: 643120
>
> URL: http://svn.apache.org/viewvc?rev=643120&view=rev
> Log:
> 2008-03-31 Andrew Black <ab...@roguewave.com>
>
> STDCXX-426
> * util/output.cpp (struct readback): Add convenience data structure
> for backwards file reading.
> (rbinit): Add method to initialize structure.
> (rbbof): Add method to check if structure points to the beginning
> of a file.
> (rbsync): Add method to synchronize the file handle the structure
> is built on to the structure.
> (rbgetc): Add method to retrieve a character from the file and
> move the structure one position closer to the start
> (rbscanf): Add methods to search for a string using the
> structure, possibly capturing an unsigned integer in the process.
> (check_test, check_compat_test): Alter to use above methods.
>
>
> Modified:
> stdcxx/trunk/util/output.cpp
>
> Modified: stdcxx/trunk/util/output.cpp
> URL: http://svn.apache.org/viewvc/stdcxx/trunk/util/output.cpp?rev=643120&r1=643119&r2=643120&view=diff
> ==============================================================================
> --- stdcxx/trunk/util/output.cpp (original)
> +++ stdcxx/trunk/util/output.cpp Mon Mar 31 13:03:58 2008
> @@ -44,6 +44,239 @@
> # define ENOENT 2
> #endif /* ENOENT */
>
> +/**
> + Arbitrary constant controling static read buffer size.
> +
> + @see check_example ()
> + @see rbread ()
> +*/
> +#define DELTA_BUF_LEN 64
> +
> +/**
> + This structure is used to encapsulate the data involved in a backwards
> + file read.
> +*/
> +struct readback {
> + FILE* src;
> + char buf[DELTA_BUF_LEN];
> + long bpos;
> +};
> +
> +/**
> + Initializes the provided readback structure, with the provided file
> + handle.
> +
> + @param rb pointer to readback structure to initialize
> + @param src file handle to initialize rb with.
> + @returns true if successfully initialized, false otherwise.
> +*/
> +static bool
> +rbinit (struct readback* rb, FILE* const src)
> +{
> + const size_t buflen = sizeof rb->buf;
> + long fpos;
> + assert (0 != rb);
> + assert (0 != src);
> +
> + rb->src = src;
> + if (-1 == fseek (rb->src, 0, SEEK_END))
> + return false;
> + fpos = ftell (rb->src);
> + if (-1 == fpos)
> + return false;
> +
> + if (fpos <= buflen)
> + rb->bpos = fpos;
> + else
> + rb->bpos = buflen;
> +
> + if (-1 == fseek (rb->src, fpos - rb->bpos, SEEK_SET))
> + return false;
> +
> + return rb->bpos == fread (rb->buf, 1, rb->bpos, rb->src);
> +}
> +
> +/**
> + This method is semi-analagous to feof.
> +
> + @param rb pointer to readback structure to check begin-of-file state for
> + @returns true if structure points to the begining of the file, false
> + otherwise
> +*/
> +static bool
> +rbbof (const struct readback* const rb)
> +{
> + assert (0 != rb);
> + assert (0 != rb->src);
> + return (0 == rb->bpos) && (0 == ftell (rb->src));
> +}
> +
> +/**
> + Syncronizes the file handle underlying a readback structure to the
> + pointer in the structure. This method is called if you wish to start
> + reading forward from the current point in the readback structure.
> +
> + @param rb pointer to the readback structure to syncronize.
> + @return true if the structure was successfully syncronized, false
> + otherwise.
> +*/
> +static bool
> +rbsync (struct readback* const rb)
> +{
> + assert (0 != rb);
> + assert (0 != rb->src);
> + const size_t buflen = sizeof rb->buf;
> + long fpos = ftell (rb->src) - buflen;
> + if (0 > fpos)
> + fpos=0;
> + fpos += rb->bpos;
> + rb->bpos=0;
> +
> + return -1 != fseek (rb->src, fpos, SEEK_SET);
> +}
> +
> +/**
> + Updates the provided readback structure, returning the last unread
> + character in the file. This method is semi-analagous to fgetc.
> +
> + @param rb pointer to readback structure to read from.
> + @return EOF if beginning of file or I/O error, read character
> + otherwise.
> +*/
> +static char
> +rbgetc (struct readback* rb)
> +{
> + const size_t buflen = sizeof rb->buf;
> + assert (0 != rb);
> + assert (0 != rb->src);
> + if (!rb->bpos) {
> + const size_t bufdelta = buflen << 1;
> + long fpos = ftell (rb->src);
> + long seek;
> +
> + if (-1 == fpos)
> + return EOF;
> +
> + if (bufdelta <= fpos) {
> + seek = fpos - bufdelta;
> + rb->bpos = buflen;
> + }
> + else if (buflen < fpos) {
> + seek = 0;
> + rb->bpos = fpos - buflen;
> + }
> + else {
> + fseek (rb->src, 0, SEEK_SET);
> + return EOF;
> + }
> +
> + if (-1 == fseek (rb->src, seek, SEEK_SET))
> + return EOF;
> +
> + if (rb->bpos != fread (rb->buf, 1, rb->bpos, rb->src))
> + return EOF;
> + }
> + assert (0 < rb->bpos && rb->bpos <= buflen);
> +
> + return rb->buf [--rb->bpos];
> +}
> +
> +/**
> + This method is semi-analagous to fscanf, with some key differences.
> + First, it opperates on a readback structure. Second, it scans until
> + either the search pattern is matched, or until the begining of the file
> + is reached. Third, it reads backwards from the end of the file.
> +
> + Limitations: string to match can't end in a repeated set of characters
> + (ie: 'singing' has the repeated characters 'ing')
> +
> + @param rb pointer to readback structure to operate on
> + @param match string to search for
> + @return true if match is found, false if begining of file is reached
> +*/
> +static bool
> +rbscanf (struct readback* rb, const char* const match)
> +{
> + char tok;
> + size_t matched;
> + size_t count;
> + assert (0 != rb);
> + assert (0 != match);
> +
> + matched = count = strlen (match) - 1;
> +
> + for(tok = rbgetc(rb); matched && !rbbof (rb); tok = rbgetc (rb)) {
> + if (tok == match [matched])
> + --matched;
> + else
> + matched = count;
> + }
> + return !matched;
> +}
> +
> +/**
> + This method is semi-analagous to fscanf, reading backwards on a readback
> + structure, starting from the end of the file.
> +
> + This method searches backwards for the first (last) number and captures
> + it. It then checks if the match string exists directly after (before)
> + the captured value. If this is the case, a match is considered to have
> + been found, and the captured value is copied to val. Otherwise, the
> + search process is restarted. If the search hits the beginning of the
> + file, matching is considered to have failed, and val is unaltered.
> +
> + Limitations: string to match can't end in a repeated set of characters
> + (ie: 'singing' has the repeated characters 'ing'.) or a repeated set
> + of characters, bordering on either side of one or more numbers (ie:
> + 'xyzzy9zzy' has the repeated characters 'zzy')
> +
> + @param rb pointer to readback structure to operate on.
> + @param match string to search for.
> + @param val reference to variable to store captured value in.
> + @return true if match is found, false if begining of file is reached.
> +*/
> +static bool
> +rbscanf (struct readback* rb, const char* const match, unsigned& val)
> +{
> + size_t count;
> + unsigned tval =0;
> + unsigned radix;
> + assert (0 != rb);
> + assert (0 != match);
> +
> + count = strlen (match) - 1;
> +
> + while (!rbbof(rb)) {
> + char tok;
> + size_t matched = count;
> +
> + tval=0;
> + radix=1;
> +
> + /* Search for a numeric digit */
> + for (tok = rbgetc (rb);
> + (tok < '0' || tok > '9') && !rbbof (rb);
> + tok = rbgetc (rb)) /* Do nothing */;
> +
> + /* Read in the number. */
> + for ( ; tok >= '0' && tok <= '9' && !rbbof (rb);
> + tok = rbgetc (rb)) {
> + tval += (tok-'0') * radix;
> + radix *= 10;
> + }
> +
> + /* Make certain the content prior to the number in the file
> + matches the search pattern. */
> + for( ; matched && tok == match [matched] && !rbbof (rb);
> + tok = rbgetc (rb), --matched) /* Do nothing */;
> +
> + if (tok == match [matched]) {
> + val = tval;
> + return true;
> + }
> + }
> + return false;
> +}
>
> /**
> Parses contents of the open file handle data for test target_name.
> @@ -58,6 +291,7 @@
> static void
> check_test (FILE* data, struct target_status* status)
> {
> + struct readback buf;
> unsigned r_lvl = 0; /* diagnostic severity level */
> unsigned r_active = 0; /* number of active diagnostics */
> unsigned r_total = 0; /* total number of diagnostics */
> @@ -73,15 +307,28 @@
> assert (0 != data);
> assert (0 != status);
>
> - tok = fgetc (data);
> + if (!rbinit (&buf, data)) {
> + status->status = ST_SYSTEM_ERROR;
> + return;
> + }
>
> - if (feof (data)) {
> + if (rbbof (&buf)) {
> /* target produced no output (regression test?) */
> status->status = ST_NO_OUTPUT;
> return;
> }
>
> - for ( ; fsm < 6 && !feof (data); tok = fgetc (data)) {
> + if (!rbscanf (&buf, "| INACTIVE |\n# +")) {
> + status->status = ST_FORMAT;
> + return;
> + }
> +
> + rbsync(&buf);
> +
> + /* While it'd probably be (slightly) faster to seek to a fixed position
> + after the file pointer has been synced, this should be more reliable
> + */
> + for (tok = fgetc (data); fsm < 6 && !feof (data); tok = fgetc (data)) {
> switch (tok) {
> case '\n':
> fsm = 1;
> @@ -150,58 +397,25 @@
> static void
> check_compat_test (FILE* data, struct target_status* status)
> {
> - int read = 0;
> - unsigned fsm = 0;
> - char tok;
> + struct readback buf;
>
> assert (0 != data);
> assert (0 != status);
>
> - tok = fgetc (data);
> -
> - if (feof (data)) {
> + if (!rbinit (&buf, data)) {
> + status->status = ST_SYSTEM_ERROR;
> + }
> + else if (rbbof (&buf)) {
> /* target produced no output (regression test?) */
> status->status = ST_NO_OUTPUT;
> - return;
> - }
> -
> - for ( ; !feof (data); tok = fgetc (data)) {
> - switch (tok) {
> - case '\n':
> - fsm = 1;
> - break;
> - case '#':
> - if (1 == fsm || 2 == fsm)
> - ++fsm;
> - else
> - fsm = 0;
> - break;
> - case ' ':
> - if (3 == fsm)
> - ++fsm;
> - else
> - fsm = 0;
> - break;
> - case 'W':
> - if (4 == fsm && !feof (data)) /* leading "## W" eaten */
> - read = fscanf (data, "arnings = %u\n## Assertions = %u\n"
> - "## FailedAssertions = %u",
> - &status->t_warn, &status->assert, &status->failed);
> - default:
> - fsm = 0;
> - }
> }
> - if (3 != read) {
> + else if ( !rbscanf (&buf, "## FailedAssertions = ", status->failed)
> + || !rbscanf (&buf, "## Assertions = ", status->assert)
> + || !rbscanf (&buf, "## Warnings = ", status->t_warn)) {
> status->status = ST_FORMAT;
> }
> }
>
> -/**
> - Arbitrary constant controling static read buffer size.
> -
> - @see check_example ()
> -*/
> -#define DELTA_BUF_LEN 64
>
> /**
> Parses output file out_name for the example target_name.
>
>
>