Index: gcc/fortran/error.c =================================================================== --- gcc/fortran/error.c (revision 118930) +++ gcc/fortran/error.c (working copy) @@ -378,69 +378,151 @@ 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]; - locus *l1, *l2, *loc; + enum { TYPE_CURRENTLOC, TYPE_LOCUS, TYPE_INTEGER, TYPE_CHAR, TYPE_STRING, + NOTYPE }; + struct + { + int type; + int pos; + union + { + locus * locval; + int intval; + char charval; + char * stringval; + } u; + } percent[MAX_ARGS], arg[MAX_ARGS]; + + char c; + int i, n, have_l1, use_dollars, pos, maxpos; + locus *l1, *l2; const char *format; - l1 = l2 = loc = NULL; + l1 = l2 = NULL; have_l1 = 0; + use_dollars = -1; + pos = -1; + maxpos = -1; n = 0; format = format0; + for (i = 0; i < MAX_ARGS; i++) + { + percent[i].type = NOTYPE; + arg[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. */ + gcc_assert (use_dollars != 0); + use_dollars = 1; - switch (c) - { - case '%': - break; + pos = atoi(format) - 1; + gcc_assert (pos >= 0); + while (ISDIGIT(*format)) + format++; + gcc_assert (*format++ == '$'); + } + c = *format++; - case 'L': - loc = va_arg (argp, locus *); - /* Fall through */ + if (use_dollars == -1) + use_dollars = 0; + if (!use_dollars) + pos++; - case 'C': - if (c == 'C') - loc = &gfc_current_locus; + if (pos > maxpos) + maxpos = pos; - if (have_l1) - { - l2 = loc; - } - else - { - l1 = loc; - have_l1 = 1; - } - break; + switch (c) + { + case 'C': + percent[pos].type = TYPE_CURRENTLOC; + break; - case 'd': - case 'i': - i_arg[n++] = va_arg (argp, int); - break; + case 'L': + percent[pos].type = TYPE_LOCUS; + break; - case 'c': - c_arg[n++] = va_arg (argp, int); - break; + case 'd': + case 'i': + percent[pos].type = TYPE_INTEGER; + break; - case 's': - cp_arg[n++] = va_arg (argp, char *); - break; + case 'c': + percent[pos].type = TYPE_CHAR; + break; - case '\0': - format--; - break; + case 's': + percent[pos].type = TYPE_STRING; + break; + + default: + gcc_unreachable (); + } + + arg[n++].pos = pos; + } + + /* The convert the values for each %-style argument. */ + for (pos = 0; pos <= maxpos; pos++) + { + gcc_assert (percent[pos].type != NOTYPE); + switch (percent[pos].type) + { + case TYPE_CURRENTLOC: + percent[pos].u.locval = &gfc_current_locus; + break; + + case TYPE_LOCUS: + percent[pos].u.locval = va_arg (argp, locus *); + break; + + case TYPE_INTEGER: + percent[pos].u.intval = va_arg (argp, int); + break; + + case TYPE_CHAR: + percent[pos].u.charval = (char) va_arg (argp, int); + break; + + case TYPE_STRING: + percent[pos].u.stringval = va_arg (argp, char *); + break; + + default: + gcc_unreachable (); + } + + if (percent[pos].type == TYPE_CURRENTLOC + || percent[pos].type == TYPE_LOCUS) + { + if (have_l1) + l2 = percent[pos].u.locval; + else + { + l1 = percent[pos].u.locval; + have_l1 = 1; } } + } + for (n = 0; arg[n].pos >= 0; n++) + arg[n].u = percent[arg[n].pos].u; + /* Show the current loci if we have to. */ if (have_l1) show_loci (l1, l2); @@ -464,6 +546,13 @@ } format++; + if (ISDIGIT(*format)) + { + while (ISDIGIT(*format)) + format++; + format++; + } + switch (*format) { case '%': @@ -471,22 +560,23 @@ break; case 'c': - error_char (c_arg[n++]); + error_char (arg[n++].u.charval); break; case 's': - error_string (cp_arg[n++]); + error_string (arg[n++].u.stringval); break; case 'd': case 'i': - error_integer (i_arg[n++]); + error_integer (arg[n++].u.intval); break; case 'C': /* Current locus */ case 'L': /* Specified locus */ error_string (have_l1 ? "(2)" : "(1)"); have_l1 = 1; + n++; break; case '\0':