[GRASS-dev] [GRASS GIS] #32: r.what: shouldn't use static buffers for the inputs

Ivan Shmakov ivan at theory.asu.ru
Sun Feb 24 14:12:09 EST 2008


>>>>> Ivan Shmakov <ivan at theory.asu.ru> writes:
>>>>> Hamish  <hamish_b at yahoo.com> writes:

[...]

 >> +    /* see v.in.ascii for a better solution */
 >> +    if (opt_fs->answer != NULL) {
 >> +        if (strcmp(opt_fs->answer, "space") == 0)
 >> +            fs = ' ';
 >> +        else if (strcmp(opt_fs->answer, "tab") == 0)
 >> +            fs = '\t';
 >> +        else if (strcmp(opt_fs->answer, "\\t") == 0)
 >> +            fs = '\t';
 >> +        else
 >> +            fs = opt_fs->answer[0];
 >> +    }
 >> +

 > Oh, the piece of code like this is a sure candidate for a library
 > function! (taking into account the number of times it appears in
 > the GRASS source.)

	The base for this function may be like the following:

void
backslash (char *d, const char *s)
{
  /* http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap05.html
   */
  char *dp;
  const char *sp;

  for (dp = d, sp = s; *sp != '\0'; dp++, sp++) {
    if (*sp != '\\') {
      /* not an escape, just copy */
      *dp = *sp;
      continue;
    }

    /* advance to the next character */
    ++sp;

    switch (*sp) {
    case '\\': *dp = '\\'; break;
    case  'a': *dp = '\a'; break;
    case  'b': *dp = '\b'; break;
    case  'f': *dp = '\f'; break;
    case  'n': *dp = '\n'; break;
    case  'r': *dp = '\r'; break;
    case  't': *dp = '\t'; break;
    case  'v': *dp = '\v'; break;
    /* check if it's \O, \OO, \OOO or \xHH */
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7':
    case 'x': case 'X':
      {
        const int hex_p = ((*sp) == 'x' || (*sp) == 'X');
        char buf[4], *tail;
        long r;

        if (hex_p) {
          strncpy (buf, sp + 1, 2);
          buf[2] = '\0';
        } else {
          strncpy (buf, sp,     sizeof (buf) - 1);
          buf[sizeof (buf) - 1] = '\0';
        }

        /* 1 .. 3 octal or exactly two hexadecimal digits are expected
         */
        if ((hex_p && (buf[0] == '\0' || buf[1] == '\0')
            || ((r = strtol (buf, &tail, hex_p ? 16 : 8)),
                tail == buf))) {
          /* NB: skips over unhandled escapes */
          *(dp++) = '\\';
          *(dp)   = *(sp);
          continue;
        }

        *dp = r;
        sp += -1 + (hex_p ? 1 : 0) + (tail - buf);
      }
      break;
    default:
      /* NB: skips over unhandled escapes */
      *(dp++) = '\\';
      *(dp)   = *(sp);
      continue;
    }
  }

  /* terminate the destination with NUL */
  *dp = '\0';
}

	Surprisingly enough, coreutils/src/printf.c has its print_esc ()
	function putchar ()-based.  So, I had to write the above.

	Please note that the implementation above has one subtle
	difference from that of the GNU Coreutils `printf' utility.
	Namely, the latter allows for `\xH', while the former only
	accepts `\xHH' (and passes `\xH' untransformed.)  Also, the
	implementation above gives no warning when for a malformed
	escape.

	Note also that the function above doesn't generally allow `d'
	and `s' to overlap, except for the `d == s' case, which is
	allowed.

	May I suggest the function above (as `G_backslash') for
	`lib/gis/strings.c'?

 >> withcats = 0; nfiles = 0;

 >> I did it as %c like r.cats, other modules are more liberal and allow
 >> %s.  Shrug.

 > I have no use for %s just now, but there should probably be a
 > GRASS-wide policy on using either %c or %s for `fs'.  (In order for
 > the user to learn this exactly once.)

	Since the function above allows strings, I'd opt for allowing a
	string for `sep' everywhere.



More information about the grass-dev mailing list