[patch, fortran] Wide character I/O Part 1.1 Round 2
FX
fxcoudert@gmail.com
Sun Jun 8 23:15:00 GMT 2008
Hi Jerry,
Sorry I took so long to review your patch. Still not fully OK for me,
but we're definitely very close to it. We discussed it on IRC
already, but for the record: I suggest you simplify things by dumping
endian_off completely (it's not needed, and adds loads from memory
and additions) and access things by casting them to the right type.
Here's the detailed review:
> + for (i = j = 0; i < m; i++, j += 4)
> + q[j + endian_off] = dtp->u.p.saved_string[i];
If you do that, you need to be absolutely sure that all bytes in the
saved_string has prevously been zero'ed. Is it so? But I don't
understand why you don't want to do it that way:
for (i = j = 0; i < m; i++, j++)
((gfc_char4_t *) q)[j] = (unsigned char) dtp->u.p.saved_string
[i];
> + for (i = m, j = m * 4; i < (int) size - m; i++, j += 4)
> + q[j + endian_off] = ' ';
Same here, if you do it that way, you need to be sure that q was
previously zero'ed out. (And it may break in the future is someone
decides to not zero this buffer after all.) I think it'd be best
rewritten as:
for (i = j = m; i < (int) size - m; i++, j++)
((gfc_char4_t *) q)[j] = (unsigned char) ' ';
> + for (n = 0; n < m; n++, dest += 4, s++)
> + dest[endian_off] = *s;
> +
> + for (n = 0; n < length - (int) w; n++, dest += 4)
> + dest[endian_off] = ' ';
Same again.
> + /* Handle wide chracters. */
> + if (type == BT_CHARACTER && kind == 4)
> + {
> + sz = (size_t) kind;
> + for (i = 0; i < size * nelems; i++)
> + {
> + read_block_direct (dtp, buffer, &sz);
> + reverse_memcpy (p, buffer, kind);
> + p += kind;
> + }
> + return;
> + }
Couldn't you just do the same thing as for complex, and have it use
the same loop as all others with tweaking the values of nelems and
size? Something like:
if (type == BT_CHARACTER && kind != 1)
{
nelems *= size;
size = kind;
}
> + /* Handle wide chracters. */
> + if (type == BT_CHARACTER && kind == 4)
> + {
> + sz = (size_t) kind;
> + for (i = 0; i < size * nelems; i++)
> + {
> + reverse_memcpy(buffer, p, sz);
> + p += sz;
> + write_buf (dtp, buffer, sz);
> + }
> + return;
> + }
Same thing here: do "nelems *= size" and "size = kind", and I believe
the "standard" a few lines down will do fine (and avoid code
duplication).
> +/* This macro casts a kind=1 character to a kind=4. */
> +#define GFC_CHAR4(x) (*(gfc_char4_t *)&x)
The comment is wrong: it takes an element of an array, and returns
the 4 bytes that start with this element, as an character(kind=4).
But that's a bit convoluted...
> + /* Scan the source string looking for '\n' and convert it if
> found. */
> + for (i = kk = 0; i < wlen; i++, kk += 4)
> + {
> + if (GFC_CHAR4(source[kk]) == '\n')
It's weird to do it that way; I think the code gives the good results
in all cases (so I'm not objecting to it strongly), but I think it's
certainly hard to read. I'd be tempted to have kk go by increments of
1 instead of 4, and do:
if (((gfc_char4_t *)source)[kk] == (unsigned char) '\n')
(I'm not even sure if the "unsigned char" cast is needed, but it
can't hurt.)
> + {
> + /* Write out the previously scanned characters in the
> string. */
> + if (bytes > 0)
> + {
> + p = write_block (dtp, bytes);
> + if (p == NULL)
> + return;
> + for (j = k = 0; j < bytes; j++, k += 4)
The you'd also make k go by increments of 1.
> + p[j] = GFC_CHAR4(source[k]) > 255 ?
> + '?' : source[k + endian_off];
And that would be:
p[j] = (((gfc_char4_t *) source)[k] > 255 ? '?' : (unsigned char)
((gfc_char4_t *) source)[k]);
Once again, remove the need for endian_off and let unsigned
arithmetics wrapping do its job.
> + for (j = k = 0; j < bytes; j++, k += 4)
> + p[j] = GFC_CHAR4(source[k]) > 255 ? '?' : source[k +
> endian_off];
And again, same thing here.
> + for (j = k = 0; j < wlen; j++, k += 4)
> + p[j] = GFC_CHAR4(source[k]) > 255 ?
> + '?' : source[k + endian_off];
And there. (Macro?)
> + p[j] = GFC_CHAR4(source[k]) > 255 ?
> + '?' : source[k + endian_off];
And there. (Macro, for sure!)
> + for (i = j = 0; i < length; i++, j += 4)
> + if (GFC_CHAR4(source[j]) == (gfc_char4_t) d)
> + extra++;
Same here. Actually, I believe you could have a macro that looks up
for a character in a char4 string:
#define CHAR4_AT_POS(string,pos) (((gfc_char4_t *) (string))[pos])
That way, you could use directly CHAR4_AT_POS(source, j)
and same thing everywhere you used GFC_CHAR4. That'd be way clearer
(at least to me, but other opinions are welcome!).
> + for (i = j = 0; i < length; i++, j += 4)
> + p[i] = GFC_CHAR4(source[j]) > 255 ?
> + '?' : source[j + endian_off];
Again.
> + for (i = j = 0; i < length; i++, j += 4)
> + {
> + *p++ = GFC_CHAR4(source[j]) > 255 ?
> + '?' : source[i * kind + endian_off];
> + if (GFC_CHAR4(source[j]) == (gfc_char4_t) d)
> + *p++ = d;
> + }
And again.
FX
--
François-Xavier Coudert
http://www.homepages.ucl.ac.uk/~uccafco/
More information about the Fortran
mailing list