This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Slightly more extended example for named diagnostics


"Joseph S. Myers" wrote:

> Of course an actual implementation would need appropriate changes to
> xgettext if messages stop being visible as C strings in the source,

The comment extraction process produces this:

> #line 300 "c-pragma.c"
> diag[108] = {
>     name    = 'align_not_power_of_2';
>     lev = 'warning';
>     group = 'pragma';
>     fmt = 'alignment must be a small power of two, not %d';
>     doc = 'You have your choice of: 0, 1, 2, 4, 8 or 16.';
>     srcfile = 'c-pragma.c';
>     linenum = '300';
> };

Creating a .po file looks like this:

> [= (out-push-new "gcc.po") =]
> # GCC @PACKAGE-VERSION@ Messages in the default language (English)
> # Copyright (C) [=`date +%Y`=] Free Software Foundation, Inc.
> # blah, blah, blah
> # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
> #
> #, fuzzy
> msgid ""
> msgstr ""
> "Project-Id-Version: PACKAGE VERSION\n"
> "POT-Creation-Date: 2002-12-30 18:47+0000\n"
> "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
> "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
> "Language-Team: LANGUAGE <LL@li.org>\n"
> "MIME-Version: 1.0\n"
> "Content-Type: text/plain; charset=CHARSET\n"
> "Content-Transfer-Encoding: 8bit\n"
> [= FOR diag =]
> #: [=srcfile=]:[=linenum=]
> #, c-format
> msgid [=(c-string (get "fmt"))=]
> msgstr ""
> [= ENDFOR =][= (out-pop) =]

All done.  :-)

> functionality to extract message explanations into the main manual

How would you like it structured?  How about putting all the
details in a numericly ordered section and indexed by name
and sections for each named group that also have indexes
into it for each member of each group?  The groupings ought to go
into the full index, but I think I would omit individual
warnings.  Anything else?  It will be very easy, regardless of
how you want it formatted.

> explanations - if wanted in source rather than just using info anchors in
> the manual and giving an info command that will go to the right point -

The full entry would contain file and line number, with the caveat that
it is only accurate if the source and doc precisely match.  In any event,
one can grep for the diagnostic name and find all places where it is
triggered (which may happen in more and different places than where defined).

> would need careful and separate review from the rest of the patch).  I
> don't feel a need for this in the proof-of-concept examples, but I would
> like to see an example of how this implementation method handles more
> complicated cases - warnings which are enabled or disabled, and may or may
> not be errors, depending on multiple flags.  For example, those in
> <http://gcc.gnu.org/ml/gcc/2003-01/msg01158.html> which illustrates what

I looked at that.  It is trivial to add another control string argument
to the diagostic calls, but with a little trickery, I generated a bit
mask to indicate diagnostic group membership, too.  Those bits can be
used at option processing time to change the value of the "diagnostic
state" for each diagnostic:

> typedef struct {
>   const diagnostic_t    diag_type;      /* base diagnostic type    */
>   diagnostic_t          diag_state;     /* current emission type   */
>   diag_id_t             diag_id;        /* diagnostic id number    */
>   int*                  p_state_stack;  /* stacked emission types  */
>   int                   stack_depth;
>   const char* const     diag_name;      /* hyphenated diag name    */
>   const char* const     msg_id;         /* original message format */
>   const char*           localized_msg;  /* localized version       */
>   const char* const     doc;            /* detail about diagnostic */
>   member_mask_t         member_mask;    /* group membership mask   */
> } diag_state_t;

"diag_state" being the field used to determine how to handle a
diagnosed condition.  "diag_type" being how to reset the
handling type and "p_state_stack" being how to handle push/pop.

Attached is the example with a bit mask.  If we have more than
32 groupings, the code is ready to change "member_mask_t" into
an array.

Cheers - Bruce
/*   -*- buffer-read-only: t -*- vi: set ro:
 *  
 *  DO NOT EDIT THIS FILE   (diag-macros.h)
 *  
 *  It has been AutoGen-ed  
 *  From the definitions    diag-macros.def
 *  and the template file   diagnostic.tpl
 *
 *  Copyright (C) 2003 Free Software Foundation, Inc.
 *
 *  GCC is free software.
 *  
 *  You may redistribute it and/or modify it under the terms of the
 *  GNU General Public License, as published by the Free Software
 *  Foundation; either version 2, or (at your option) any later version.
 *  
 *  GCC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with GCC.  See the file "COPYING".  If not,
 *  write to:  The Free Software Foundation, Inc.,
 *             59 Temple Place - Suite 330,
 *             Boston,  MA  02111-1307, USA.
 */
#ifndef GCC_DIAG_MACROS_H_GUARD
#define GCC_DIAG_MACROS_H_GUARD
/*
 *  Enumerate the diagnostic levels
 */
typedef enum {
  DK_FATAL,
  DK_ICE,
  DK_SORRY,
  DK_ERROR,
  DK_WARNING,
  DK_ANACRONISM,
  DK_NOTE,
  DK_DEBUG,
  DK_SUPPRESSED
} diagnostic_t;
#define  DK_LAST_DIAGNOSTIC_KIND 8

/*
 *  Enumerate every diagnostic message in GCC.
 *  The value is the diagnostic number.
 */
typedef enum {
  DIAG_WARNING_UNPUSHED_POP                     = 101,
  DIAG_WARNING_UNPUSHED_POP_ID                  = 102,
  DIAG_WARNING_NO_PRAGMA_PUSH_POP               = 103,
  DIAG_WARNING_PRAGMA_PACK_SYNTAX               = 104,
  DIAG_WARNING_MALFORMED_PRAGMA                 = 105,
  DIAG_WARNING_BAD_PACK_ACTION                  = 106,
  DIAG_WARNING_PRAGMA_JUNK                      = 107,
  DIAG_WARNING_ALIGN_NOT_POWER_OF_2             = 108,
  DIAG_WARNING_WEAK_TOO_LATE                    = 109,
  DIAG_WARNING_REDEFINE_CONFLICT                = 120,
  DIAG_WARNING_RENAME_CONFLICT                  = 121,
  DIAG_DEBUG_ENTER_HANDLE_PRAGMA_PACK           = 122,
  DIAG_ICE_UNSUPPORTED_WIDE_INT                 = 123,
  DIAG_ERROR_PARAM_SIZE_DEPENDENCY              = 124
} diag_id_t;

#define MIN_DIAGNOSTIC_NUM     101
#define MAX_DIAGNOSTIC_NUM     124

/*
 *  Message Emission Macros
 */
#ifdef DEBUG
#  define ACTIVE_DIAG(n) \
 (diag_states[n].diag_state < DK_SUPPRESSED)
#else
#  define ACTIVE_DIAG(n) \
 (diag_states[n].diag_state < DK_DEBUG)
#endif

#define WARNING_UNPUSHED_POP \
	if (ACTIVE_DIAG(DIAG_WARNING_UNPUSHED_POP)) \
	  assemble_diagnostics (DIAG_WARNING_UNPUSHED_POP)

#define WARNING_UNPUSHED_POP_ID(_arg1, _arg2) \
	if (ACTIVE_DIAG(DIAG_WARNING_UNPUSHED_POP_ID)) \
	  assemble_diagnostics (DIAG_WARNING_UNPUSHED_POP_ID, \
		(_arg1), (_arg2))

#define WARNING_NO_PRAGMA_PUSH_POP(_arg1) \
	if (ACTIVE_DIAG(DIAG_WARNING_NO_PRAGMA_PUSH_POP)) \
	  assemble_diagnostics (DIAG_WARNING_NO_PRAGMA_PUSH_POP, \
		(_arg1))

#define WARNING_PRAGMA_PACK_SYNTAX \
	if (ACTIVE_DIAG(DIAG_WARNING_PRAGMA_PACK_SYNTAX)) \
	  assemble_diagnostics (DIAG_WARNING_PRAGMA_PACK_SYNTAX)

#define WARNING_MALFORMED_PRAGMA(_arg1) \
	if (ACTIVE_DIAG(DIAG_WARNING_MALFORMED_PRAGMA)) \
	  assemble_diagnostics (DIAG_WARNING_MALFORMED_PRAGMA, \
		(_arg1))

#define WARNING_BAD_PACK_ACTION(_arg1) \
	if (ACTIVE_DIAG(DIAG_WARNING_BAD_PACK_ACTION)) \
	  assemble_diagnostics (DIAG_WARNING_BAD_PACK_ACTION, \
		(_arg1))

#define WARNING_PRAGMA_JUNK(_arg1) \
	if (ACTIVE_DIAG(DIAG_WARNING_PRAGMA_JUNK)) \
	  assemble_diagnostics (DIAG_WARNING_PRAGMA_JUNK, \
		(_arg1))

#define WARNING_ALIGN_NOT_POWER_OF_2(_arg1) \
	if (ACTIVE_DIAG(DIAG_WARNING_ALIGN_NOT_POWER_OF_2)) \
	  assemble_diagnostics (DIAG_WARNING_ALIGN_NOT_POWER_OF_2, \
		(_arg1))

#define WARNING_WEAK_TOO_LATE(_arg1) \
	if (ACTIVE_DIAG(DIAG_WARNING_WEAK_TOO_LATE)) \
	  assemble_diag_with_decl (DIAG_WARNING_WEAK_TOO_LATE, \
		(_arg1))

#define WARNING_REDEFINE_CONFLICT \
	if (ACTIVE_DIAG(DIAG_WARNING_REDEFINE_CONFLICT)) \
	  assemble_diagnostics (DIAG_WARNING_REDEFINE_CONFLICT)

#define WARNING_RENAME_CONFLICT \
	if (ACTIVE_DIAG(DIAG_WARNING_RENAME_CONFLICT)) \
	  assemble_diagnostics (DIAG_WARNING_RENAME_CONFLICT)

#ifndef DEBUG
#  define DEBUG_ENTER_HANDLE_PRAGMA_PACK(_arg1)
#else
#  define DEBUG_ENTER_HANDLE_PRAGMA_PACK(_arg1) \
	if (ACTIVE_DIAG(DIAG_DEBUG_ENTER_HANDLE_PRAGMA_PACK)) \
	  assemble_diagnostics (DIAG_DEBUG_ENTER_HANDLE_PRAGMA_PACK, __FILE__, __LINE__, \
		(_arg1))
#endif /* DEBUG */

#define ICE_UNSUPPORTED_WIDE_INT \
	  assemble_diagnostics (DIAG_ICE_UNSUPPORTED_WIDE_INT)

#define ERROR_PARAM_SIZE_DEPENDENCY(_arg1) \
	if (ACTIVE_DIAG(DIAG_ERROR_PARAM_SIZE_DEPENDENCY)) \
	  assemble_diag_with_decl (DIAG_ERROR_PARAM_SIZE_DEPENDENCY, \
		(_arg1))

/*
 *  Diagnostic Group Identifiers
 */
#define DGR_HIDDEN_NAME_ID 0
#define DGR_PRAGMA_ID 1
#define DGR_TRACING_ID 2

typedef uint32_t member_mask_t;

typedef struct {
  const diagnostic_t    diag_type;      /* base diagnostic type    */
  diagnostic_t          diag_state;     /* current emission type   */
  diag_id_t             diag_id;        /* diagnostic id number    */
  int*                  p_state_stack;  /* stacked emission types  */
  int                   stack_depth;
  const char* const     diag_name;      /* hyphenated diag name    */
  const char* const     msg_id;         /* original message format */
  const char*           localized_msg;  /* localized version       */
  const char* const     doc;            /* detail about diagnostic */
  member_mask_t         member_mask;    /* group membership mask   */
} diag_state_t;

extern diag_state_t diag_states[ 24 ];

#ifdef DEFINE_DIAGNOSTICS
diag_state_t diag_states[ 24 ] = {
  /*
   *  Warning 101 defined in c-pragma.c on line 106
   *  It is a member of the following groups:
   *    pragma
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_UNPUSHED_POP,
    NULL, 0, "unpushed-pop",
    "#pragma pack (pop) encountered without matching #pragma pack (push, <n>)", NULL,
    "These must match up.  You may find unifdef(1BSD) useful.", 0x00000002 },

  /*
   *  Warning 102 defined in c-pragma.c on line 129
   *  It is a member of the following groups:
   *    pragma
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_UNPUSHED_POP_ID,
    NULL, 0, "unpushed-pop-id",
    "#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)", NULL,
    "These must match up.  You may find unifdef(1BSD) useful.", 0x00000002 },

  /*
   *  Warning 103 defined in c-pragma.c on line 154
   *  It is a member of the following groups:
   *    pragma
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_NO_PRAGMA_PUSH_POP,
    NULL, 0, "no-pragma-push-pop",
    "#pragma pack(%s[, id], <n>) is not supported on this target", NULL,
    "If you have a choice about the data structure, then reorder\n\
the items so they are always aligned consistently.  Otherwise,\n\
you need to study the default layout and make sure that if you\n\
move the data to another machine that it is consistent.", 0x00000002 },

  /*
   *  Warning 104 defined in c-pragma.c on line 192
   *  It is a member of the following groups:
   *    pragma
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_PRAGMA_PACK_SYNTAX,
    NULL, 0, "pragma-pack-syntax",
    "missing '(' after '#pragma pack' - ignored", NULL,
    "The syntax is:  \"#pragma pack (???)\" where \"???\" is:\n\
\"N\", \"push, N\", \"push, ID, N\", \"pop\", or \"pop, ID\".", 0x00000002 },

  /*
   *  Warning 105 defined in c-pragma.c on line 212
   *  It is a member of the following groups:
   *    pragma
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_MALFORMED_PRAGMA,
    NULL, 0, "malformed-pragma",
    "malformed '#pragma %s' - ignored", NULL,
    "The syntax is:  \"#pragma pack (???)\" where \"???\" is:\n\
\"N\", \"push, N\", \"push, ID, N\", \"pop\", or \"pop, ID\".", 0x00000002 },

  /*
   *  Warning 106 defined in c-pragma.c on line 233
   *  It is a member of the following groups:
   *    pragma
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_BAD_PACK_ACTION,
    NULL, 0, "bad-pack-action",
    "unknown action '%s' for '#pragma pack' - ignored", NULL,
    "The syntax is:  \"#pragma pack (???)\" where \"???\" is:\n\
\"N\", \"push, N\", \"push, ID, N\", \"pop\", or \"pop, ID\".", 0x00000002 },

  /*
   *  Warning 107 defined in c-pragma.c on line 278
   *  It is a member of the following groups:
   *    pragma
   */
  { DK_WARNING, DK_SUPPRESSED, DIAG_WARNING_PRAGMA_JUNK,
    NULL, 0, "pragma-junk",
    "junk at end of '#pragma %s'", NULL,
    "No stray characters should appear after the pragma pack closing\n\
parenthesis.", 0x00000002 },

  /*
   *  Warning 108 defined in c-pragma.c on line 300
   *  It is a member of the following groups:
   *    pragma
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_ALIGN_NOT_POWER_OF_2,
    NULL, 0, "align-not-power-of-2",
    "alignment must be a small power of two, not %d", NULL,
    "You have your choice of: 0, 1, 2, 4, 8 or 16.", 0x00000002 },

  /*
   *  Warning 109 defined in c-pragma.c on line 339
   *  It is a member of the following groups:
   *    pragma
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_WEAK_TOO_LATE,
    NULL, 0, "weak-too-late",
    "applying #pragma weak `%s' after first use results in unspecified behavior", NULL,
    "We'll try to do it, but the results may not be what you expect.", 0x00000002 },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 110 */ },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 111 */ },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 112 */ },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 113 */ },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 114 */ },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 115 */ },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 116 */ },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 117 */ },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 118 */ },
  { DK_SUPPRESSED, DK_SUPPRESSED /* no diagnostic 119 */ },

  /*
   *  Warning 120 defined in c-pragma.c on line 449
   *  It is a member of the following groups:
   *    pragma hidden_name
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_REDEFINE_CONFLICT,
    NULL, 0, "redefine-conflict",
    "#pragma redefine_extname conflicts with declaration", NULL,
    "You will likely have unexpected results.  Please change the\n\
name of your local declaration.", 0x00000003 },

  /*
   *  Warning 121 defined in c-pragma.c on line 524
   *  It is a member of the following groups:
   *    pragma hidden-name
   */
  { DK_WARNING, DK_WARNING, DIAG_WARNING_RENAME_CONFLICT,
    NULL, 0, "rename-conflict",
    "asm declaration conficts with previous rename", NULL,
    "You need to disambiguate them.", 0x00000002 },

  /*
   *  Debug 122 defined in c-pragma.c on line 183
   *  It is a member of the following groups:
   *    tracing
   */
  { 
#ifndef DEBUG
    DK_SUPPRESSED, DK_SUPPRESSED /* Debugging diagnostic */
#else
    DK_DEBUG, DK_DEBUG, DIAG_DEBUG_ENTER_HANDLE_PRAGMA_PACK,
    NULL, 0, "enter-handle-pragma-pack",
    "In file %s on line %d:  We've entered the %s procedure", NULL,
    "This is a tracing display.", 0x00000004
#endif /* DEBUG */
    },

  /*
   *  Ice 123 defined in expr.c on line 6201
   *  This diagnostic is not a member of any group.
   */
  { DK_ICE, DK_ICE, DIAG_ICE_UNSUPPORTED_WIDE_INT,
    NULL, 0, "unsupported-wide-int",
    "unsupported wide integer operation", NULL,
    "The defined machine integer operation mode exceeds the\n\
capacity of the compiler.", 0 },

  /*
   *  Error 124 defined in expr.c on line 6599
   *  This diagnostic is not a member of any group.
   */
  { DK_ERROR, DK_ERROR, DIAG_ERROR_PARAM_SIZE_DEPENDENCY,
    NULL, 0, "param-size-dependency",
    "prior parameter's size depends on `%s'", NULL,
    "I'm unsure of what this means.", 0 }
};

/*
 *  Name -> group number mapping (by index of entry):
 */
static const char *const diagnostic_group_name[] = {
  "hidden_name",
  "pragma",
  "tracing" };

/*
 *  Preamble strings for the kinds of diagnostics
 */
static const char *const diagnostic_kind_text[] = {
  "fatal error: ",
  "internal compiler error: ",
  "sorry, unimplemented: ",
  "error: ",
  "warning: ",
  "anacronism: ",
  "note: ",
  "debug: ",
  "must-not-happen: "
};
#endif /* DEFINE_DIAGNOSTICS */
#endif /* GCC_DIAG_MACROS_H_GUARD */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]