Commit 9406549c by Francois-Xavier Coudert Committed by François-Xavier Coudert

re PR fortran/29711 ([4.2 only] error_print does not support %N$X)

	PR fortran/29711
	* error.c (error_print): Handle printf-style position specifiers,
	of the form "%3$d".

From-SVN: r119203
parent 786f159e
2006-11-25 Francois-Xavier Coudert <coudert@clipper.ens.fr>
PR fortran/29711
* error.c (error_print): Handle printf-style position specifiers,
of the form "%3$d".
2006-11-24 Paul Thomas <pault@gcc.gnu.org>
PR fortran/20880
......
......@@ -378,69 +378,150 @@ show_loci (locus * l1, locus * l2)
static void ATTRIBUTE_GCC_GFC(2,0)
error_print (const char *type, const char *format0, va_list argp)
{
char c, c_arg[MAX_ARGS], *cp_arg[MAX_ARGS];
int n, have_l1, i_arg[MAX_ARGS];
enum { TYPE_CURRENTLOC, TYPE_LOCUS, TYPE_INTEGER, TYPE_CHAR, TYPE_STRING,
NOTYPE };
struct
{
int type;
int pos;
union
{
int intval;
char charval;
const char * stringval;
} u;
} arg[MAX_ARGS], spec[MAX_ARGS];
/* spec is the array of specifiers, in the same order as they
appear in the format string. arg is the array of arguments,
in the same order as they appear in the va_list. */
char c;
int i, n, have_l1, pos, maxpos;
locus *l1, *l2, *loc;
const char *format;
l1 = l2 = loc = NULL;
l1 = l2 = NULL;
have_l1 = 0;
pos = -1;
maxpos = -1;
n = 0;
format = format0;
for (i = 0; i < MAX_ARGS; i++)
{
arg[i].type = NOTYPE;
spec[i].pos = -1;
}
/* First parse the format string for position specifiers. */
while (*format)
{
c = *format++;
if (c == '%')
if (c != '%')
continue;
if (*format == '%')
continue;
if (ISDIGIT (*format))
{
c = *format++;
/* This is a position specifier. For example, the number
12 in the format string "%12$d", which specifies the third
argument of the va_list, formatted in %d format.
For details, see "man 3 printf". */
pos = atoi(format) - 1;
gcc_assert (pos >= 0);
while (ISDIGIT(*format))
format++;
gcc_assert (*format++ == '$');
}
else
pos++;
switch (c)
{
case '%':
break;
c = *format++;
if (pos > maxpos)
maxpos = pos;
switch (c)
{
case 'C':
arg[pos].type = TYPE_CURRENTLOC;
break;
case 'L':
arg[pos].type = TYPE_LOCUS;
break;
case 'd':
case 'i':
arg[pos].type = TYPE_INTEGER;
break;
case 'c':
arg[pos].type = TYPE_CHAR;
break;
case 's':
arg[pos].type = TYPE_STRING;
break;
default:
gcc_unreachable ();
}
spec[n++].pos = pos;
}
/* Then convert the values for each %-style argument. */
for (pos = 0; pos <= maxpos; pos++)
{
gcc_assert (arg[pos].type != NOTYPE);
switch (arg[pos].type)
{
case TYPE_CURRENTLOC:
loc = &gfc_current_locus;
/* Fall through. */
case 'L':
case TYPE_LOCUS:
if (arg[pos].type == TYPE_LOCUS)
loc = va_arg (argp, locus *);
/* Fall through */
case 'C':
if (c == 'C')
loc = &gfc_current_locus;
if (have_l1)
{
l2 = loc;
}
else
{
l1 = loc;
have_l1 = 1;
}
break;
case 'd':
case 'i':
i_arg[n++] = va_arg (argp, int);
break;
case 'c':
c_arg[n++] = va_arg (argp, int);
break;
case 's':
cp_arg[n++] = va_arg (argp, char *);
break;
case '\0':
format--;
break;
}
if (have_l1)
{
l2 = loc;
arg[pos].u.stringval = "(2)";
}
else
{
l1 = loc;
have_l1 = 1;
arg[pos].u.stringval = "(1)";
}
break;
case TYPE_INTEGER:
arg[pos].u.intval = va_arg (argp, int);
break;
case TYPE_CHAR:
arg[pos].u.charval = (char) va_arg (argp, int);
break;
case TYPE_STRING:
arg[pos].u.stringval = (const char *) va_arg (argp, char *);
break;
default:
gcc_unreachable ();
}
}
for (n = 0; spec[n].pos >= 0; n++)
spec[n].u = arg[spec[n].pos].u;
/* Show the current loci if we have to. */
if (have_l1)
show_loci (l1, l2);
......@@ -464,6 +545,15 @@ error_print (const char *type, const char *format0, va_list argp)
}
format++;
if (ISDIGIT(*format))
{
/* This is a position specifier. See comment above. */
while (ISDIGIT(*format))
/* Skip over the dollar sign. */
format++;
}
switch (*format)
{
case '%':
......@@ -471,26 +561,18 @@ error_print (const char *type, const char *format0, va_list argp)
break;
case 'c':
error_char (c_arg[n++]);
error_char (spec[n++].u.charval);
break;
case 's':
error_string (cp_arg[n++]);
break;
case 'd':
case 'i':
error_integer (i_arg[n++]);
break;
case 'C': /* Current locus */
case 'L': /* Specified locus */
error_string (have_l1 ? "(2)" : "(1)");
have_l1 = 1;
error_string (spec[n++].u.stringval);
break;
case '\0':
format--;
case 'd':
case 'i':
error_integer (spec[n++].u.intval);
break;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment