Assorted improvements to diagnostics.
[pspp] / src / libpspp / message.h
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2010, 2011, 2014 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifndef MESSAGE_H
18 #define MESSAGE_H 1
19
20 #include <stdarg.h>
21 #include <stdbool.h>
22 #include <stddef.h>
23 #include "libpspp/compiler.h"
24
25 struct string;
26 struct substring;
27
28 /* What kind of message is this? */
29 enum msg_category
30   {
31     MSG_C_GENERAL,              /* General info. */
32     MSG_C_SYNTAX,               /* Messages that relate to syntax files. */
33     MSG_C_DATA,                 /* Messages that relate to data files. */
34     MSG_N_CATEGORIES
35   };
36
37 /* How important a condition is it? */
38 enum msg_severity
39   {
40     MSG_S_ERROR,
41     MSG_S_WARNING,
42     MSG_S_NOTE,
43     MSG_N_SEVERITIES
44   };
45
46 const char *msg_severity_to_string (enum msg_severity);
47
48 /* Combination of a category and a severity for convenience. */
49 enum msg_class
50   {
51     ME, MW, MN,                 /* General error/warning/note. */
52     SE, SW, SN,                 /* Script error/warning/note. */
53     DE, DW, DN,                 /* Data-file error/note. */
54     MSG_CLASS_CNT,
55   };
56
57 static inline enum msg_category
58 msg_class_to_category (enum msg_class class)
59 {
60   return class / 3;
61 }
62
63 static inline enum msg_severity
64 msg_class_to_severity (enum msg_class class)
65 {
66   return class % 3;
67 }
68
69 static inline enum msg_class
70 msg_class_from_category_and_severity (enum msg_category category,
71                                       enum msg_severity severity)
72 {
73   return category * 3 + severity;
74 }
75
76 /* A line number and column number within a source file.  Both are 1-based.  If
77    only a line number is available, 'column' is zero.  If neither is available,
78    'line' and 'column' are zero.
79
80    Column numbers are measured according to the width of characters as shown in
81    a typical fixed-width font, in which CJK characters have width 2 and
82    combining characters have width 0.  */
83 struct msg_point
84   {
85     int line;
86     int column;
87   };
88
89 struct msg_point msg_point_advance (struct msg_point, struct substring);
90
91 /* Location of the cause of an error. */
92 struct msg_location
93   {
94     /* Interned file name, or NULL. */
95     const char *file_name;
96
97     /* Nonnull if this came from a source file. */
98     struct lex_source *src;
99
100     /* The starting and ending point of the cause.  One of:
101
102        - Both empty, with all their members zero.
103
104        - A range of lines, with 0 < start.line <= end.line and start.column =
105          end.column = 0.
106
107        - A range of columns spanning one or more lines.  If it's on a single
108          line, then start.line = end.line and 0 < start.column <= end.column.
109          If it's across multiple lines, then 0 < start.line < end.line and the
110          column members are both positive.
111
112        Both 'start' and 'end' are inclusive, line-wise and column-wise.
113     */
114     struct msg_point start, end;
115
116     /* Normally, 'start' and 'end' contain column information, then displaying
117        the message will underline the location.  Setting this to true disables
118        displaying underlines. */
119     bool omit_underlines;
120   };
121
122 void msg_location_uninit (struct msg_location *);
123 void msg_location_destroy (struct msg_location *);
124 struct msg_location *msg_location_dup (const struct msg_location *);
125
126 void msg_location_remove_columns (struct msg_location *);
127
128 void msg_location_merge (struct msg_location **, const struct msg_location *);
129 struct msg_location *msg_location_merged (const struct msg_location *,
130                                           const struct msg_location *);
131
132 bool msg_location_is_empty (const struct msg_location *);
133 void msg_location_format (const struct msg_location *, struct string *);
134
135 struct msg_stack
136   {
137     struct msg_location *location;
138     char *description;
139   };
140
141 void msg_stack_destroy (struct msg_stack *);
142 struct msg_stack *msg_stack_dup (const struct msg_stack *);
143
144 /* A message. */
145 struct msg
146   {
147     enum msg_category category; /* Message category. */
148     enum msg_severity severity; /* Message severity. */
149     struct msg_location *location; /* Code location. */
150     struct msg_stack **stack;
151     size_t n_stack;
152     char *command_name;         /* Name of erroneous command, or NULL.  */
153     char *text;                 /* Error text. */
154   };
155
156 /* Initialization. */
157 struct msg_handler
158   {
159     void (*output_msg) (const struct msg *, void *aux);
160     void *aux;
161
162     struct lex_source *(*lex_source_ref) (const struct lex_source *);
163     void (*lex_source_unref) (struct lex_source *);
164     struct substring (*lex_source_get_line) (const struct lex_source *,
165                                              int line);
166   };
167 void msg_set_handler (const struct msg_handler *);
168
169 /* Working with messages. */
170 struct msg *msg_dup (const struct msg *);
171 void msg_destroy(struct msg *);
172 char *msg_to_string (const struct msg *);
173
174 /* Emitting messages. */
175 void vmsg (enum msg_class, const struct msg_location *,
176            const char *format, va_list args)
177      PRINTF_FORMAT (3, 0);
178 void msg (enum msg_class, const char *format, ...)
179      PRINTF_FORMAT (2, 3);
180 void msg_at (enum msg_class, const struct msg_location *,
181              const char *format, ...)
182      PRINTF_FORMAT (3, 4);
183 void msg_emit (struct msg *);
184
185 void msg_error (int errnum, const char *format, ...)
186   PRINTF_FORMAT (2, 3);
187
188
189 /* Enable and disable messages. */
190 void msg_enable (void);
191 void msg_disable (void);
192
193 /* Error context. */
194 bool msg_ui_too_many_errors (void);
195 void msg_ui_reset_counts (void);
196 bool msg_ui_any_errors (void);
197 void msg_ui_disable_warnings (bool);
198
199
200 /* Used in panic situations only. */
201 const char * prepare_diagnostic_information (void);
202 const char * prepare_fatal_error_message (void);
203 void request_bug_report (const char *msg);
204
205
206 #endif /* message.h */