1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2 Contributed by Oracle.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21 #include "config.h"
22 #include <stdarg.h>
23
24 #include "util.h"
25 #include "Emsg.h"
26 #include "StringBuilder.h"
27
28 // The Emsg, experiment message, has as objects I18N'd messages
29 // in a structure suitable for attaching to and fetching
30 // from a queue of such messages. It is intended to
31 // be used for collector errors, collector warnings, parser
32 // errors, and er_archive errors that are encountered when
33 // reading an experiment
34
35 // ----------------------- Message --------------------------
36
Emsg(Cmsg_warn w,const char * i18n_text)37 Emsg::Emsg (Cmsg_warn w, const char *i18n_text)
38 {
39 warn = w;
40 flavor = 0;
41 par = NULL;
42 text = strdup (i18n_text);
43 next = NULL;
44 }
45
Emsg(Cmsg_warn w,StringBuilder & sb)46 Emsg::Emsg (Cmsg_warn w, StringBuilder& sb)
47 {
48 warn = w;
49 flavor = 0;
50 par = NULL;
51 text = sb.toString ();
52 next = NULL;
53 }
54
Emsg(Cmsg_warn w,int f,const char * param)55 Emsg::Emsg (Cmsg_warn w, int f, const char *param)
56 {
57 char *type;
58 warn = w;
59 flavor = f;
60 if (param != NULL)
61 par = dbe_strdup (param);
62 else
63 par = dbe_strdup ("");
64 next = NULL;
65
66 // determine type
67 switch (warn)
68 {
69 case CMSG_WARN:
70 type = GTXT ("*** Collector Warning");
71 break;
72 case CMSG_ERROR:
73 type = GTXT ("*** Collector Error");
74 break;
75 case CMSG_FATAL:
76 type = GTXT ("*** Collector Fatal Error");
77 break;
78 case CMSG_COMMENT:
79 type = GTXT ("Comment");
80 break;
81 case CMSG_PARSER:
82 type = GTXT ("*** Log Error");
83 break;
84 case CMSG_ARCHIVE:
85 type = GTXT ("*** Archive Error");
86 break;
87 default:
88 type = GTXT ("*** Internal Error");
89 break;
90 };
91
92 // now convert the message to its I18N'd string
93 switch (flavor)
94 {
95 case COL_ERROR_NONE:
96 text = dbe_sprintf (GTXT ("%s: No error"), type);
97 break;
98 case COL_ERROR_ARGS2BIG:
99 text = dbe_sprintf (GTXT ("%s: Data argument too long"), type);
100 break;
101 case COL_ERROR_BADDIR:
102 text = dbe_sprintf (GTXT ("%s: Bad experiment directory name"), type);
103 break;
104 case COL_ERROR_ARGS:
105 text = dbe_sprintf (GTXT ("%s: Data argument format error `%s'"), type, par);
106 break;
107 case COL_ERROR_PROFARGS:
108 text = dbe_sprintf (GTXT ("%s: [UNUSED] Bad clock-profiling argument"), type);
109 break;
110 case COL_ERROR_SYNCARGS:
111 text = dbe_sprintf (GTXT ("%s: [UNUSED] Bad synchronization tracing argument"), type);
112 break;
113 case COL_ERROR_HWCARGS:
114 text = dbe_sprintf (GTXT ("%s: Bad hardware counter profiling argument"), type);
115 break;
116 case COL_ERROR_DIRPERM:
117 text = dbe_sprintf (GTXT ("%s: Experiment directory is not writeable; check umask and permissions"), type);
118 break;
119 case COL_ERROR_NOMSACCT:
120 text = dbe_sprintf (GTXT ("%s: Turning on microstate accounting failed"), type);
121 break;
122 case COL_ERROR_PROFINIT:
123 text = dbe_sprintf (GTXT ("%s: Initializing clock-profiling failed"), type);
124 break;
125 case COL_ERROR_SYNCINIT:
126 text = dbe_sprintf (GTXT ("%s: Initializing synchronization tracing failed"), type);
127 break;
128 case COL_ERROR_HWCINIT:
129 text = dbe_sprintf (GTXT ("%s: Initializing hardware counter profiling failed -- %s"), type, par);
130 break;
131 case COL_ERROR_HWCFAIL:
132 text = dbe_sprintf (GTXT ("%s: HW counter data collection failed; likely cause is that another process preempted the counters"), type);
133 break;
134 case COL_ERROR_EXPOPEN:
135 text = dbe_sprintf (GTXT ("%s: Experiment initialization failed, %s"), type, par);
136 break;
137 case COL_ERROR_SIZELIM:
138 text = dbe_sprintf (GTXT ("%s: Experiment size limit exceeded, writing %s"), type, par);
139 break;
140 case COL_ERROR_SYSINFO:
141 text = dbe_sprintf (GTXT ("%s: system name can not be determined"), type);
142 break;
143 case COL_ERROR_OVWOPEN:
144 text = dbe_sprintf (GTXT ("%s: Can't open overview %s"), type, par);
145 break;
146 case COL_ERROR_OVWWRITE:
147 text = dbe_sprintf (GTXT ("%s: Can't write overview %s"), type, par);
148 break;
149 case COL_ERROR_OVWREAD:
150 text = dbe_sprintf (GTXT ("%s: Can't read overview data for %s"), type, par);
151 break;
152 case COL_ERROR_NOZMEM:
153 text = dbe_sprintf (GTXT ("%s: Open of /dev/zero failed: %s"), type, par);
154 break;
155 case COL_ERROR_NOZMEMMAP:
156 text = dbe_sprintf (GTXT ("%s: Mmap of /dev/zero failed: %s"), type, par);
157 break;
158 case COL_ERROR_NOHNDL:
159 text = dbe_sprintf (GTXT ("%s: Out of data handles for %s"), type, par);
160 break;
161 case COL_ERROR_FILEOPN:
162 text = dbe_sprintf (GTXT ("%s: Open failed %s"), type, par);
163 break;
164 case COL_ERROR_FILETRNC:
165 text = dbe_sprintf (GTXT ("%s: Truncate failed for file %s"), type, par);
166 break;
167 case COL_ERROR_FILEMAP:
168 text = dbe_sprintf (GTXT ("%s: Mmap failed %s"), type, par);
169 break;
170 case COL_ERROR_HEAPINIT:
171 text = dbe_sprintf (GTXT ("%s: Initializing heap tracing failed"), type);
172 break;
173 case COL_ERROR_DISPINIT:
174 text = dbe_sprintf (GTXT ("%s: Initializing SIGPROF dispatcher failed"), type);
175 break;
176 case COL_ERROR_ITMRINIT:
177 text = dbe_sprintf (GTXT ("%s: Initializing interval timer failed; %s"), type, par);
178 break;
179 case COL_ERROR_SMPLINIT:
180 text = dbe_sprintf (GTXT ("%s: Initializing periodic sampling failed"), type);
181 break;
182 case COL_ERROR_MPIINIT:
183 text = dbe_sprintf (GTXT ("%s: Initializing MPI tracing failed"), type);
184 break;
185 case COL_ERROR_JAVAINIT:
186 text = dbe_sprintf (GTXT ("%s: Initializing Java profiling failed"), type);
187 break;
188 case COL_ERROR_LINEINIT:
189 text = dbe_sprintf (GTXT ("%s: Initializing descendant process lineage failed"), type);
190 break;
191 case COL_ERROR_NOSPACE:
192 text = dbe_sprintf (GTXT ("%s: Out of disk space writing `%s'"), type, par);
193 break;
194 case COL_ERROR_ITMRRST:
195 text = dbe_sprintf (GTXT ("%s: Resetting interval timer failed: %s"), type, par);
196 break;
197 case COL_ERROR_MKDIR:
198 text = dbe_sprintf (GTXT ("%s: Unable to create directory `%s'"), type, par);
199 break;
200 case COL_ERROR_JVM2NEW:
201 text = dbe_sprintf (GTXT ("%s: JVM version with JVMTI requires more recent release of the performance tools; please upgrade"), type);
202 break;
203 case COL_ERROR_JVMNOTSUPP:
204 text = dbe_sprintf (GTXT ("%s: JVM version does not support JVMTI; no java profiling is available"), type);
205 break;
206 case COL_ERROR_JVMNOJSTACK:
207 text = dbe_sprintf (GTXT ("%s: JVM version does not support java callstacks; java mode data will not be recorded"), type);
208 break;
209 case COL_ERROR_DYNOPEN:
210 text = dbe_sprintf (GTXT ("%s: Can't open dyntext file `%s'"), type, par);
211 break;
212 case COL_ERROR_DYNWRITE:
213 text = dbe_sprintf (GTXT ("%s: Can't write dyntext file `%s'"), type, par);
214 break;
215 case COL_ERROR_MAPOPEN:
216 text = dbe_sprintf (GTXT ("%s: Can't open map file `%s'"), type, par);
217 break;
218 case COL_ERROR_MAPREAD:
219 text = dbe_sprintf (GTXT ("%s: Can't read map file `%s'"), type, par);
220 break;
221 case COL_ERROR_MAPWRITE:
222 text = dbe_sprintf (GTXT ("%s: Can't write map file"), type);
223 break;
224 case COL_ERROR_RESOLVE:
225 text = dbe_sprintf (GTXT ("%s: Can't resolve map file `%s'"), type, par);
226 break;
227 case COL_ERROR_OMPINIT:
228 text = dbe_sprintf (GTXT ("%s: Initializing OpenMP tracing failed"), type);
229 break;
230 case COL_ERROR_DURATION_INIT:
231 text = dbe_sprintf (GTXT ("%s: Initializing experiment-duration setting to `%s' failed"), type, par);
232 break;
233 case COL_ERROR_RDTINIT:
234 text = dbe_sprintf (GTXT ("%s: Initializing RDT failed"), type);
235 break;
236 case COL_ERROR_GENERAL:
237 if (strlen (par))
238 text = dbe_sprintf (GTXT ("%s: %s"), type, par);
239 else
240 text = dbe_sprintf (GTXT ("%s: General error"), type);
241 break;
242 case COL_ERROR_EXEC_FAIL:
243 text = dbe_sprintf (GTXT ("%s: Exec of process failed"), type);
244 break;
245 case COL_ERROR_THR_MAX:
246 text = dbe_sprintf (GTXT ("%s: Thread count exceeds maximum (%s); set SP_COLLECTOR_NUMTHREADS for higher value"), type, par);
247 break;
248 case COL_ERROR_IOINIT:
249 text = dbe_sprintf (GTXT ("%s: Initializing IO tracing failed"), type);
250 break;
251 case COL_ERROR_NODATA:
252 text = dbe_sprintf (GTXT ("%s: No data was recorded in the experiment"), type);
253 break;
254 case COL_ERROR_DTRACE_FATAL:
255 text = dbe_sprintf (GTXT ("%s: Fatal error reported from DTrace -- %s"), type, par);
256 break;
257 case COL_ERROR_MAPSEEK:
258 text = dbe_sprintf (GTXT ("%s: Seek error on map file `%s'"), type, par);
259 break;
260 case COL_ERROR_UNEXP_FOUNDER:
261 text = dbe_sprintf (GTXT ("%s: Unexpected value for founder `%s'"), type, par);
262 break;
263 case COL_ERROR_LOG_OPEN:
264 text = dbe_sprintf (GTXT ("%s: Failure to open log file"), type);
265 break;
266 case COL_ERROR_TSD_INIT:
267 text = dbe_sprintf (GTXT ("%s: TSD could not be initialized"), type);
268 break;
269 case COL_ERROR_UTIL_INIT:
270 text = dbe_sprintf (GTXT ("%s: libcol_util.c initialization failed"), type);
271 break;
272 case COL_ERROR_MAPCACHE:
273 text = dbe_sprintf (GTXT ("%s: Unable to cache mappings; internal error (`%s')"), type, par);
274 break;
275 case COL_WARN_NONE:
276 text = dbe_sprintf (GTXT ("%s: No warning"), type);
277 break;
278 case COL_WARN_FSTYPE:
279 text = dbe_sprintf (GTXT ("%s: Experiment was written to a filesystem of type `%s'; data may be distorted"), type, par);
280 break;
281 case COL_WARN_PROFRND:
282 text = dbe_sprintf (GTXT ("%s: Profiling interval was changed from requested %s (microsecs.) used"), type, par);
283 break;
284 case COL_WARN_SIZELIM:
285 text = dbe_sprintf (GTXT ("%s: Experiment size limit exceeded"), type);
286 break;
287 case COL_WARN_SIGPROF:
288 text = dbe_sprintf (GTXT ("%s: SIGPROF handler was changed (%s) during the run; profile data may be unreliable"), type, par);
289 break;
290 case COL_WARN_SMPLADJ:
291 text = dbe_sprintf (GTXT ("%s: Periodic sampling rate adjusted %s microseconds"), type, par);
292 break;
293 case COL_WARN_ITMROVR:
294 text = dbe_sprintf (GTXT ("%s: Application's attempt to set interval timer period to %s was ignored; its behavior may be changed"), type, par);
295 break;
296 case COL_WARN_ITMRREP:
297 text = dbe_sprintf (GTXT ("%s: Collection interval timer period was changed (%s); profile data may be unreliable"), type, par);
298 break;
299 case COL_WARN_SIGEMT:
300 text = dbe_sprintf (GTXT ("%s: SIGEMT handler was changed during the run; profile data may be unreliable"), type);
301 break;
302 case COL_WARN_CPCBLK:
303 text = dbe_sprintf (GTXT ("%s: libcpc access blocked for hardware counter profiling"), type);
304 break;
305 case COL_WARN_VFORK:
306 text = dbe_sprintf (GTXT ("%s: vfork(2) replaced by %s; execution may be affected"), type, par);
307 break;
308 case COL_WARN_EXECENV:
309 text = dbe_sprintf (GTXT ("%s: exec environment augmented with %s missing collection variables"), type, par);
310 break;
311 case COL_WARN_SAMPSIGUSED:
312 text = dbe_sprintf (GTXT ("%s: target installed handler for sample signal %s; samples may be lost"), type, par);
313 break;
314 case COL_WARN_PAUSESIGUSED:
315 text = dbe_sprintf (GTXT ("%s: target installed handler for pause/resume signal %s; data may be lost or unexpected"),
316 type, par);
317 break;
318 case COL_WARN_CPCNOTRESERVED:
319 text = dbe_sprintf (GTXT ("%s: unable to reserve HW counters; data may be distorted by other users of the counters"), type);
320 break;
321 case COL_WARN_LIBTHREAD_T1: /* par contains the aslwpid... do we want to report it? */
322 text = dbe_sprintf (GTXT ("%s: application ran with a libthread version that may distort data; see collect(1) man page"), type);
323 break;
324 case COL_WARN_SIGMASK:
325 text = dbe_sprintf (GTXT ("%s: Blocking %s ignored while in use for collection"), type, par);
326 break;
327 case COL_WARN_NOFOLLOW:
328 text = dbe_sprintf (GTXT ("%s: Following disabled for uncollectable target (%s)"), type, par);
329 break;
330 case COL_WARN_RISKYFOLLOW:
331 text = dbe_sprintf (GTXT ("%s: Following unqualified target may be unreliable (%s)"), type, par);
332 break;
333 case COL_WARN_IDCHNG:
334 text = dbe_sprintf (GTXT ("%s: Imminent process ID change (%s) may result in an inconsistent experiment"), type, par);
335 break;
336 case COL_WARN_OLDJAVA:
337 text = dbe_sprintf (GTXT ("%s: Java profiling requires JVM version 1.4.2_02 or later"), type);
338 break;
339 case COL_WARN_ITMRPOVR:
340 text = dbe_sprintf (GTXT ("%s: Collector reset application's profile timer %s; application behavior may be changed"), type, par);
341 break;
342 case COL_WARN_NO_JAVA_HEAP:
343 text = dbe_sprintf (GTXT ("%s: Java heap profiling is not supported by JVMTI; disabled "), type);
344 break;
345 case COL_WARN_RDT_PAUSE_NOMEM:
346 text = dbe_sprintf (GTXT ("%s: Data race detection paused at %s because of running out of internal memory"), type, par);
347 break;
348 case COL_WARN_RDT_RESUME:
349 text = dbe_sprintf (GTXT ("%s: Data race detection resumed"), type);
350 break;
351 case COL_WARN_RDT_THROVER:
352 text = dbe_sprintf (GTXT ("%s: Too many concurrent/created threads; accesses with thread IDs above limit are not checked"), type);
353 break;
354 case COL_WARN_THR_PAUSE_RESUME:
355 text = dbe_sprintf (GTXT ("%s: The collector_thread_pause/collector_thread_resume APIs are deprecated, and will be removed in a future release"), type);
356 break;
357 case COL_WARN_NOPROF_DATA:
358 text = dbe_sprintf (GTXT ("%s: No profile data recorded in experiment"), type);
359 break;
360 case COL_WARN_LONG_FSTAT:
361 text = dbe_sprintf (GTXT ("%s: Long fstat call -- %s"), type, par);
362 break;
363 case COL_WARN_LONG_READ:
364 text = dbe_sprintf (GTXT ("%s: Long read call -- %s"), type, par);
365 break;
366 case COL_WARN_LINUX_X86_APICID:
367 text = dbe_sprintf (GTXT ("%s: Linux libc sched_getcpu() not found; using x86 %s IDs rather than CPU IDs"), type, par);
368 break;
369
370 case COL_COMMENT_NONE:
371 text = dbe_sprintf (GTXT ("%s"), par);
372 break;
373 case COL_COMMENT_CWD:
374 text = dbe_sprintf (GTXT ("Initial execution directory `%s'"), par);
375 break;
376 case COL_COMMENT_ARGV:
377 text = dbe_sprintf (GTXT ("Argument list `%s'"), par);
378 break;
379 case COL_COMMENT_MAYASSNAP:
380 text = dbe_sprintf (GTXT ("Mayas snap file `%s'"), par);
381 break;
382
383 case COL_COMMENT_LINEFORK:
384 text = dbe_sprintf (GTXT ("Target fork: %s"), par);
385 break;
386 case COL_COMMENT_LINEEXEC:
387 text = dbe_sprintf (GTXT ("Target exec: %s"), par);
388 break;
389 case COL_COMMENT_LINECOMBO:
390 text = dbe_sprintf (GTXT ("Target fork/exec: %s"), par);
391 break;
392 case COL_COMMENT_FOXSNAP:
393 text = dbe_sprintf (GTXT ("Fox snap file `%s'"), par);
394 break;
395 case COL_COMMENT_ROCKSNAP:
396 text = dbe_sprintf (GTXT ("Rock simulator snap file `%s'"), par);
397 break;
398 case COL_COMMENT_BITINSTRDATA:
399 text = dbe_sprintf (GTXT ("Bit instrument data file `%s'"), par);
400 break;
401 case COL_COMMENT_BITSNAP:
402 text = dbe_sprintf (GTXT ("Bit snap file `%s'"), par);
403 break;
404 case COL_COMMENT_SIMDSPSNAP:
405 text = dbe_sprintf (GTXT ("Simulator dataspace profiling snap file `%s'"), par);
406 break;
407 case COL_COMMENT_HWCADJ:
408 text = dbe_sprintf (GTXT ("%s: HWC overflow interval adjusted: %s"), type, par);
409 break;
410 case COL_WARN_APP_NOT_READY:
411 text = dbe_sprintf (GTXT ("*** Collect: %s"), par);
412 break;
413 case COL_WARN_RDT_DL_TERMINATE:
414 text = dbe_sprintf (GTXT ("%s: Actual deadlock detected; process terminated"), type);
415 break;
416 case COL_WARN_RDT_DL_TERMINATE_CORE:
417 text = dbe_sprintf (GTXT ("%s: Actual deadlock detected; process terminated and core dumped"), type);
418 break;
419 case COL_WARN_RDT_DL_CONTINUE:
420 text = dbe_sprintf (GTXT ("%s: Actual deadlock detected; process allowed to continue"), type);
421 break;
422 default:
423 text = dbe_sprintf (GTXT ("%s: Number %d (\"%s\")"), type, flavor, par);
424 break;
425 };
426 }
427
~Emsg()428 Emsg::~Emsg ()
429 {
430 free (par);
431 free (text);
432 }
433
434 // ----------------------- Message Queue --------------------
Emsgqueue(char * _qname)435 Emsgqueue::Emsgqueue (char *_qname)
436 {
437 first = NULL;
438 last = NULL;
439 qname = strdup (_qname);
440 }
441
~Emsgqueue()442 Emsgqueue::~Emsgqueue ()
443 {
444 free (qname);
445 clear ();
446 }
447
448 Emsg *
find_msg(Cmsg_warn w,char * msg)449 Emsgqueue::find_msg (Cmsg_warn w, char *msg)
450 {
451 for (Emsg *m = first; m; m = m->next)
452 if (m->get_warn () == w && strcmp (m->get_msg (), msg) == 0)
453 return m;
454 return NULL;
455 }
456
457 Emsg *
append(Cmsg_warn w,char * msg)458 Emsgqueue::append (Cmsg_warn w, char *msg)
459 {
460 Emsg *m = find_msg (w, msg);
461 if (m)
462 return m;
463 m = new Emsg (w, msg);
464 append (m);
465 return m;
466 }
467
468 // Append a single message to a queue
469 void
append(Emsg * m)470 Emsgqueue::append (Emsg* m)
471 {
472 m->next = NULL;
473 if (last == NULL)
474 {
475 first = m;
476 last = m;
477 }
478 else
479 {
480 last->next = m;
481 last = m;
482 }
483 }
484
485 // Append a queue of messages to a queue
486 void
appendqueue(Emsgqueue * mq)487 Emsgqueue::appendqueue (Emsgqueue* mq)
488 {
489 Emsg *m = mq->first;
490 if (m == NULL)
491 return;
492 if (last == NULL)
493 first = m;
494 else
495 last->next = m;
496 // now find the new last
497 while (m->next != NULL)
498 m = m->next;
499 last = m;
500 }
501
502 Emsg *
fetch(void)503 Emsgqueue::fetch (void)
504 {
505 return first;
506 }
507
508 // Empty the queue, deleting all messages
509 void
clear(void)510 Emsgqueue::clear (void)
511 {
512 Emsg *pp;
513 Emsg *p = first;
514 while (p != NULL)
515 {
516 pp = p;
517 p = p->next;
518 delete pp;
519 }
520 first = NULL;
521 last = NULL;
522 }
523
524 // Mark the queue empty, without deleting the messages --
525 // used when the messages have been requeued somewhere else
526 void
mark_clear(void)527 Emsgqueue::mark_clear (void)
528 {
529 first = NULL;
530 last = NULL;
531 }
532
DbeMessages()533 DbeMessages::DbeMessages ()
534 {
535 msgs = NULL;
536 }
537
~DbeMessages()538 DbeMessages::~DbeMessages ()
539 {
540 if (msgs)
541 {
542 msgs->destroy ();
543 delete msgs;
544 }
545 }
546
547 Emsg *
get_error()548 DbeMessages::get_error ()
549 {
550 for (int i = msgs ? msgs->size () - 1 : -1; i >= 0; i--)
551 {
552 Emsg *msg = msgs->get (i);
553 if (msg->get_warn () == CMSG_ERROR)
554 return msg;
555 }
556 return NULL;
557 }
558
559 void
remove_msg(Emsg * msg)560 DbeMessages::remove_msg (Emsg *msg)
561 {
562 for (int i = 0, sz = msgs ? msgs->size () : 0; i < sz; i++)
563 if (msg == msgs->get (i))
564 {
565 msgs->remove (i);
566 delete msg;
567 return;
568 }
569 }
570
571 Emsg *
append_msg(Cmsg_warn w,const char * fmt,...)572 DbeMessages::append_msg (Cmsg_warn w, const char *fmt, ...)
573 {
574 char buffer[256];
575 size_t buf_size;
576 Emsg *msg;
577 va_list vp;
578
579 va_start (vp, fmt);
580 buf_size = vsnprintf (buffer, sizeof (buffer), fmt, vp) + 1;
581 va_end (vp);
582 if (buf_size < sizeof (buffer))
583 msg = new Emsg (w, buffer);
584 else
585 {
586 va_start (vp, fmt);
587 char *buf = (char *) malloc (buf_size);
588 vsnprintf (buf, buf_size, fmt, vp);
589 va_end (vp);
590 msg = new Emsg (w, buf);
591 free (buf);
592 }
593
594 if (msgs == NULL)
595 msgs = new Vector<Emsg*>();
596 msgs->append (msg);
597 Dprintf (DEBUG_ERR_MSG, NTXT ("Warning: %s\n"), msg->get_msg ());
598 return msg;
599 }
600
601 void
append_msgs(Vector<Emsg * > * lst)602 DbeMessages::append_msgs (Vector<Emsg*> *lst)
603 {
604 if (lst && (lst->size () != 0))
605 {
606 if (msgs == NULL)
607 msgs = new Vector<Emsg*>();
608 for (int i = 0, sz = lst->size (); i < sz; i++)
609 {
610 Emsg *m = lst->fetch (i);
611 msgs->append (new Emsg (m->get_warn (), m->get_msg ()));
612 }
613 }
614 }
615