PIPS
message.c
Go to the documentation of this file.
1 /*
2 
3  $Id: message.c 23461 2018-01-24 10:07:15Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif // HAVE_CONFIG_H
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <stdarg.h>
31 #include <ctype.h>
32 
33 #include "genC.h"
34 #include "misc.h"
35 
36 // use real system abort/exit here
37 #ifdef abort
38 #undef abort
39 #endif // abort
40 
41 #ifdef exit
42 #undef exit
43 #endif // exit
44 
45 /* FC 2015-07-20: yuk, moved out to prevent an include cycle dependency
46  * #include "properties.h"
47  */
48 extern bool properties_initialized_p(void);
49 extern bool get_bool_property(const string);
50 extern char* get_string_property(const char*);
51 extern int get_int_property(const string);
52 extern bool too_many_property_errors_pending_p(void);
53 
54 /* CATCH/TRY/UNCATCH/THROW stuff is here. */
55 #include "linear.h"
56 
57 /**************************************************** CURRENT PIPSMAKE STUFF */
58 
59 /* pips meta information from pipsmake are made available here...
60  * (current phase and module...)
61  */
62 static string current_phase = NULL;
63 static string current_module = NULL;
64 
65 void set_pips_current_computation(const char* rname, const char* oname)
66 {
67  pips_assert("no current computation", !current_module && !current_phase);
68 
69  current_phase = strdup(rname);
70  current_module = strdup(oname);
71 }
72 
73 /* Export this piece of information to customize warning functions in passes
74  *
75  * Passes are also called "phases" in PIPS jargon.
76  */
78 {
79  return current_phase;
80 }
81 
83 {
84  return current_module;
85 }
86 
88 {
89  pips_assert("some current computation", current_module && current_phase);
90 
93 }
94 
95 
96 /********************************************************* META INFORMATIONS */
97 
98 static string pips_revisions = NULL;
99 static string pips_date = NULL;
100 static string pips_cc = NULL;
101 
103  const char * revs,
104  const char * date,
105  const char * comp)
106 {
107  pips_revisions = (string) revs;
108  pips_date = (string) date;
109  pips_cc = (string) comp;
110 }
111 
112 /************************************************************** USER REQUEST */
113 
114 /* USER_REQUEST is a function that should be called to request some data
115  * from the user. It returns the string typed by the user until the
116  * return key is typed.
117  * USER_REQUEST should be called as:
118  *
119  * USER_REQUEST(format [, arg] ... )
120  *
121  * where format and arg-list are passed as arguments to vprintf.
122  */
123 
124 string default_user_request(const char * fmt, va_list * args)
125 {
126  va_list acpy;
127  va_copy(acpy, *args);
128  fprintf(stdout, "\nWaiting for your response: ");
129  vfprintf(stdout, fmt, acpy);
130  fflush(stdout);
131  va_end(acpy);
132  return safe_readline(stdin);
133 }
134 
135 /* default assignment of pips_request_handler is default_user_request. Some
136  * top-level (eg. wpips) may need a special user_request proceedure; they
137  * should let pips_request_handler point toward it.
138  */
139 string (* pips_request_handler)(const char *, va_list *) = default_user_request;
140 
141 /* The generic fonction to ask something to the user. Note that if
142  * the user cancels his/her request,the empty string "" is returned:
143  */
144 string user_request(const char * a_message_format, ...)
145 {
146  va_list args;
147  va_start(args, a_message_format);
148  string str = (* pips_request_handler)(a_message_format, &args);
149  va_end(args);
150  return str;
151 }
152 
153 /******************************************************************* LOGFILE */
154 
155 #define LOG_FILE "Logfile"
156 
157 /* The log file is closed by default
158  */
159 static FILE * log_file = NULL;
160 
161 void
163 {
164  if (log_file != NULL && get_bool_property("USER_LOG_P") )
165  if (fclose(log_file) != 0)
166  pips_internal_error("Could not close log file");
167  log_file = NULL;
168 }
169 
170 void
171 open_log_file(const string dir)
172 {
173  if (log_file != NULL)
174  close_log_file();
175 
176  if (get_bool_property("USER_LOG_P"))
177  {
178  string log_file_name = strdup(concatenate(dir, "/", LOG_FILE, NULL));
179 
180  if ((log_file = fopen(log_file_name, "a")) == NULL) {
181  pips_user_error("Cannot open log file in workspace %s. "
182  "Check access rights.");
183  }
184 
185  free(log_file_name);
186  }
187 }
188 
189 void
190 log_on_file(const char * desc)
191 {
192  pips_log_desc(info_log, NULL, NULL,
193  NULL, NULL, -1, NULL, NULL, -1, -1,
194  NULL, NULL, (const string) desc);
195 }
196 
197 /****************************************************************** USER LOG */
198 
199 /* USER_LOG is a function that should be called to log the current
200  * PIPS request, as soon as it is relevant. loging will occure if property
201  * USER_LOG_P is TRUE. USER_LOG should be called as:
202  *
203  * USER_LOG(format [, arg] ... )
204  *
205  * where format and arg-list are passed as arguments to vprintf.
206  */
207 
208 /* default assignment of pips_log_handler is default_user_log. Some
209  * top-level (eg. wpips) may need a special user_log proceedure; they
210  * should let pips_log_handler point toward it.
211  *
212  * Every procedure pointed to by pips_log_handler must test the property
213  * USER_LOG_P; this is necessary because (* pips_log_handler) may be called
214  * anywhere (because VARARGS), whithout verifying it.
215  */
216 void (* pips_log_handler)(const char * fmt, va_list * args) = NULL;
217 
218 static void pips_user_log_alist(const char * format, va_list * args)
219 {
220  pips_log_alist(info_log, NULL, NULL,
221  NULL, NULL, -1, NULL, NULL, -1, -1,
222  NULL, NULL, (const string) format, args);
223 }
224 
225 void pips_user_log_func(const char * format, ...)
226 {
227  va_list args;
228  va_start(args, format);
229  pips_user_log_alist(format, &args);
230  va_end(args);
231 }
232 
233 // ??? Hmmm... PYPS needs this...
234 void user_log(const char * format, ...)
235 {
236  va_list args;
237  va_start(args, format);
238  pips_user_log_alist(format, &args);
239  va_end(args);
240 }
241 
242 /******************************************************************** THANKS */
243 
244 #include <unistd.h> // isatty
245 
246 /* The # "stringificator" only works in a macro expansion... */
247 #define PIPS_THANKS_STRING(arch) \
248  "%s (ARCH=" arch ")\n running as %s\n" \
249  "\n" \
250  " (c) 1989-2018 MINES ParisTech\n" \
251  " Centre de recherche en informatique.\n" \
252  "\n" \
253  " CRI URL: http://www.cri.mines-paristech.fr/\n" \
254  " PIPS URL: http://pips4u.org/\n" \
255  " EMAIL: pips-support at cri dot mines-paristech dot fr\n" \
256  "\n" \
257  " This software is provided as is, under the terms of the GPL.\n" \
258  " It includes and uses software from GNU (gnulib, readline),\n" \
259  " Berkeley (fsplit), INRIA, IRISA and others (polylib, janus)...\n" \
260  "\n"
261 
262 /* display pips thanks on startup, if it on a tty.
263  */
264 void
265 pips_thanks(string name, string path)
266 {
267  if (isatty(fileno(stdout)))
268  {
269  fprintf(stdout, PIPS_THANKS_STRING(STRINGIFY(SOFT_ARCH)), name, path);
270  fflush(stdout);
271  }
272 }
273 
274 /***************************************************************** WARNINGS */
275 
276 /* USER_WARNING issues a warning and don't stop the program (cf. user_error
277  * for infos.)
278  */
279 
280 // Could be in constants.h, naming.h or pipsdbm.h
281 #define WARNING_FILE_NAME "Warnings"
282 
283 static FILE * warning_file = NULL;
284 static string warning_file_name = NULL;
285 
286 void open_warning_file(const char* dir)
287 {
288  assert(warning_file_name == NULL && warning_file == NULL);
291 }
292 
294 {
295  if (warning_file)
296  {
298 
299  warning_file = (FILE*) NULL;
301  warning_file_name = (string) NULL;
302  }
303 }
304 
305 /* To be used in error handling functions */
307  const char * calling_function_name,
308  const char * format,
309  va_list * args)
310 {
311  if (properties_initialized_p() && get_bool_property("NO_USER_WARNING"))
312  return;
313 
316  (const string) calling_function_name, NULL, -1,
317  NULL, NULL, -1, -1,
318  NULL, NULL, (const string) format, args);
319 }
320 
321 /* default assignment of pips_warning_handler is default_user_warning. Some
322  * top-level (eg. wpips) may need a special user_warning proceedure; they
323  * should let pips_warning_handler point toward it.
324  */
325 void (* pips_warning_handler)(const char *, const char *, va_list *) = NULL;
326 
327 void
329  const char * function_name,
330  const char * funcfile,
331  const int funcline,
332  const char * format,
333  va_list * args)
334 {
335  if (properties_initialized_p() && get_bool_property("NO_USER_WARNING"))
336  return;
337 
340  (const string) function_name, (const string)funcfile, funcline,
341  NULL, NULL, -1, -1,
342  NULL, NULL, (const string) format, args);
343 }
344 
345 void
347  const char * calling_function_name,
348  const char * funcfile,
349  const int funcline,
350  const char * format,
351  ...)
352 {
353  va_list args;
354  va_start(args, format);
355  pips_user_warning_alist(calling_function_name, funcfile, funcline,
356  format, &args);
357  va_end(args);
358 }
359 
360 /* fallback version without a calling function name */
361 void
363  const char * format,
364  ...)
365 {
366  va_list args;
367  va_start(args, format);
368  pips_user_warning_alist(pips_unknown_function, NULL, -1, format, &args);
369  va_end(args);
370 }
371 
372 /******************************************************* PIPS INTERNAL ERROR */
373 
374 static void _NORETURN_
376  const char * funcname,
377  const char * funcfile,
378  const int funcline,
379  const char * format,
380  va_list * args)
381 {
385  (const string) funcname, (const string) funcfile, funcline,
386  NULL, NULL, -1, -1,
387  NULL, NULL, (const string) format, args);
388 
389  // dead code, stopped from pips_log_desc
390  abort();
391 }
392 
393 void _NORETURN_
395  const char * funcname,
396  const char * funcfile,
397  const int funcline,
398  const char * fmt,
399  ...)
400 {
401  va_list args;
402  va_start(args, fmt);
403  pips_internal_error_alist(funcname, funcfile, funcline, fmt, &args);
404  va_end(args);
405 }
406 
407 void _NORETURN_
409  const char * format,
410  ...)
411 {
412  va_list args;
413  va_start(args, format);
415  format, &args);
416  va_end(args);
417 }
418 
419 /* PROMPT_USER schould be implemented. (its a warning with consent of the user)
420 The question is: how schould it be called?
421 */
422 
423 /* USER_ERROR is a function that should be called to terminate the current
424  PIPS request execution or to restore the previous saved stack environment
425  when an error in a Fortran file or elsewhere is detected.
426  USER_ERROR first prints on stderr a description of the error, then tests
427  the property ABORT_ON_USER_ERROR and aborts case true. Else it will restore
428  the last saved stack environment (ie. come back to the last executed
429  setjmp(pips_top_level) ), except for eventuality it has already been
430  called. In this case, it terminates execution with exit.
431  USER_ERROR should be called as:
432 
433  USER_ERROR(fonction, format [, arg] ... )
434 
435  where function is a string containing the name of the function
436  calling USER_ERROR, and where format and arg-list are passed as
437  arguments to vprintf.
438 
439  Modifications:
440 
441  - user_error() was initially called when a Fortran syntax error was
442  encountered by the parser; execution was stopped; this had to be changed
443  because different kind of errors can occur and because pips is no longer
444  structured using exec(); one has to go back to PIPS top level, in tpips
445  or in wpips; (Francois Irigoin, 19 November 1990)
446  - user_error() calls (* pips_error_handler) which can either be
447  default_user_error or a user_error function specific to the used top-level.
448  But each user_error function should have the same functionalities.
449 */
450 
451 /* default assignment of pips_error_handler is default_user_error. Some
452  * top-level (eg. wpips) may need a special user_error proceedure; they
453  * should let pips_error_handler point toward it.
454  */
455 void (* pips_error_handler)(const char *, const char *, va_list *) = NULL;
456 
457 static void _NORETURN_
459  const char * calling_function_name,
460  const char * funcfile,
461  const int funcline,
462  const char * format,
463  va_list * args)
464 {
469  (const string) calling_function_name, (const string) funcfile, funcline,
470  NULL, NULL, -1, -1,
471  NULL, NULL, (const string) format, args);
472 
473  // dead code, should not get there...
474  abort();
475 }
476 
477 void _NORETURN_
479  const char * func_name,
480  const char * funcfile,
481  const int funcline,
482  const char * format,
483  ...)
484 {
485  va_list args;
486  va_start(args, format);
487  pips_user_error_alist(func_name, funcfile, funcline, format, &args);
488  va_end(args);
489 }
490 
491 void _NORETURN_
493  const char * format,
494  ...)
495 {
496  va_list args;
497  va_start(args, format);
498  pips_user_error_alist(pips_unknown_function, NULL, -1, format, &args);
499  va_end(args);
500 }
501 
502 /* PIPS_ERROR is a function that should be called to terminate PIPS
503 execution when data structures are corrupted. PIPS_ERROR should be
504 called as:
505  PIPS_ERROR(fonction, format [, arg] ... )
506 where function is a string containing the name of the function
507 calling PIPS_ERROR, and where format and arg-list are passed as
508 arguments to vprintf. PIPS_ERROR terminates execution with abort.
509 */
510 
511 void (*pips_internal_error_handler)(const char *, const char *, ...) = NULL;
512 
513 /************************************************** IRRECOVERABLE USER ERROR */
514 
515 void _NORETURN_
517  const char * func_name,
518  const char * funcfile,
519  const int funcline,
520  const char * format,
521  va_list *args)
522 {
526  (const string) func_name, (const string) funcfile, funcline,
527  NULL, NULL, -1, -1,
528  NULL, NULL, (const string) format, args);
529 
530  // dead code, stopped in previous call
531  exit(1);
532 }
533 
534 void _NORETURN_
536  const char * func_name,
537  const char * funcfile,
538  const int funcline,
539  const char * format,
540  ...)
541 {
542  va_list args;
543  va_start(args, format);
544  pips_user_irrecoverable_error_alist(func_name, funcfile, funcline,
545  format, &args);
546  va_end(args);
547 }
548 
549 void _NORETURN_
551  const char * format,
552  ...)
553 {
554  va_list args;
555  va_start(args, format);
556  pips_user_irrecoverable_error_alist("UNKNOWN...", NULL, -1, format, &args);
557  va_end(args);
558 }
559 
560 bool function_same_string_p(const char * s1, const char * s2)
561 {
562  return strcmp(s1, s2) == 0;
563 }
564 
565 /******************************************************************* XML LOG */
566 
567 static FILE * xml_logfile = NULL;
568 static string xml_logfile_name = NULL;
569 
570 /*
571  * Warning/UserError
572  * - (debug) PipsFunction/PipsFile/PipsLine
573  * - AppFunction/AppFile/AppLine
574  * - Pass
575  * - Message
576  * - Statement
577  * // - Proposition ??
578  *
579  * vs UserError -> spear_user_error -> pips_user_warning
580  *
581  * pips_user_error => exception levée
582  * - tpips selon "ABORT_ON_USER_ERROR" => pour spear s'arrêter !
583  *
584  * pips_internal_error => stderr + abort()
585  * - message
586  *
587  * * InternalError => script
588  * - Status/Code?
589  *
590  * * facultatifs
591  */
592 
593 /* generate xml: attribute="escaped-stuff"
594  */
597  const string attribute,
598  const string value)
599 {
600  string_buffer_append(sb, attribute);
601  string_buffer_append(sb, "=\"");
602  if (value && *value)
604  string_buffer_append(sb, "\" ");
605 }
606 
607 void open_xml_logfile(const char *filename)
608 {
609  xml_logfile_name = (string) filename;
610  xml_logfile = safe_fopen(filename, "w");
611 
612  // put version as an XML comment...
613  if (!getenv("PIPS_VALIDATION_IN_PROGRESS"))
614  {
616  string_buffer_append(sb, "<!-- pips informations:\n ");
617  append_xml_attribute(sb, "Architecture", STRINGIFY(SOFT_ARCH));
618  string_buffer_append(sb, "\n ");
619  append_xml_attribute(sb, "Revisions", pips_revisions);
620  string_buffer_append(sb, "\n ");
622  string_buffer_append(sb, "\n ");
623  append_xml_attribute(sb, "Compiler", pips_cc);
624  string_buffer_append(sb, "\n-->\n");
626  fflush(xml_logfile);
628  }
629 }
630 
632 {
633  if (xml_logfile)
634  {
636  xml_logfile = NULL;
637  xml_logfile_name = NULL;
638  }
639 }
640 
643  const string attribute,
644  int val1, int val2)
645 {
646  if (val1 > 0)
647  {
648  if (val1 < val2)
649  string_buffer_printf(sb, "%s=\"%d-%d\" ", attribute, val1, val2);
650  else
651  string_buffer_printf(sb, "%s=\"%d\" ", attribute, val1);
652  }
653  else
654  string_buffer_printf(sb, "%s=\"\" ", attribute);
655 }
656 
658 {
659  switch (tag) {
660  case info_log: return "Info";
661  case warning_log: return "Warning";
662  case spear_warning_log: return "SpearWarning";
663  case spear_error_log: return "SpearError";
664  case user_error_log: return "UserError";
665  case internal_error_log: return "InternalError";
666  case irrecoverable_error_log: return "InternalError";
667  default: abort();
668  }
669 }
670 
671 /* append pips-level stuff (function, file, line) to xml file
672  */
675  const string pips_pass,
676  const string pips_owner,
677  const string pips_func,
678  const string pips_file,
679  const int pips_line)
680 {
681  // pips level information
682  append_xml_attribute(sb, "Pass", pips_pass);
683  append_xml_attribute(sb, "Owner", pips_owner);
684  append_xml_attribute(sb, "PipsFunction", pips_func);
685  if (pips_file && getenv("PIPS_VALIDATION_IN_PROGRESS"))
686  {
687  // just show a short version of the file & hide the line
688  string short_file = strstr(pips_file, "/src/");
689  append_xml_attribute(sb, "PipsFile", short_file? short_file: "...");
690  append_xml_attribute(sb, "PipsLine", "...");
691  }
692  else
693  {
694  append_xml_attribute(sb, "PipsFile", pips_file);
695  append_xml_line_numbers(sb, "PipsLine", pips_line, 0);
696  }
697 }
698 
699 /* add a full log entry to the xml log file
700  */
701 static void pips_log_xml(
702  const pips_log_t tag,
703  const string pips_pass,
704  const string pips_owner,
705  const string pips_func,
706  const string pips_file,
707  const int pips_line,
708  const string user_func,
709  const string user_file,
710  const int user_line,
711  const int user_line2,
712  const string stmt,
713  const string suggestion,
714  const string description)
715 {
716  // only tag warnings & above...
717  if (tag == info_log) return;
718 
719  assert(xml_logfile != NULL);
720 
721  // build XML in a string buffer
723  string field = pips_log_xml_tag(tag);
724 
725  string_buffer_cat(sb, "<", field, ">\n <Description ", NULL);
726  // user level information
727  append_xml_attribute(sb, "AppFunction", user_func);
728  append_xml_attribute(sb, "AppFile", user_file);
729  append_xml_line_numbers(sb, "AppLine", user_line, user_line2);
730 
731  pips_log_xml_pips_level(sb, pips_pass, pips_owner,
732  pips_func, pips_file, pips_line);
733 
734  if (stmt)
735  {
736  char * s = stmt;
737  while (*s && (*s == '\n' || *s == '\t' || *s == ' ')) s++;
738  append_xml_attribute(sb, "Statement", s);
739  }
740  else
741  append_xml_attribute(sb, "Statement", NULL);
742 
743  // remove leading spaces for xml
744  string desc = description;
745  while (desc && *desc && *desc == ' ') desc++;
746 
747  append_xml_attribute(sb, "Message", desc);
748  append_xml_attribute(sb, "Proposition", suggestion);
749  string_buffer_cat(sb, "/>\n</", field, ">\n", NULL);
750 
753 
754  fflush(xml_logfile);
755 }
756 
757 /***************************************************************** STOP PIPS */
758 
759 static string code2status(int code)
760 {
761  switch (code)
762  {
763  case -1: return "ABORT";
764  case 0: return "OK";
765  case 1: return "INTERNAL_ERROR";
766  case TIMEOUT_CODE: return "TIMEOUT";
767  default: return "USER_ERROR";
768  }
769 }
770 
771 static void pips_stop_xml(
772  pips_log_t tag,
773  int code,
774  const string pips_func,
775  const string pips_file,
776  const int pips_line,
777  const string description)
778 {
779  assert(xml_logfile != NULL);
780 
783  "<Exit Code=\"%d\" Status=\"%s\" Source=\"%s\">\n",
785  code? pips_log_tag_name(tag): "pips");
787  " <Description AppFunction=\"\" AppFile=\"\" "
788  "AppLine=\"\" Statement=\"\" Proposition=\"\" ");
791  pips_func, pips_file, pips_line);
792  append_xml_attribute(sb, "Message", description);
793  string_buffer_append(sb, "/>\n</Exit>\n");
794 
796  fflush(xml_logfile);
797 
799 }
800 
801 static void pips_stop_file(
802  FILE * out,
803  pips_log_t tag,
804  int code,
805  const char * pips_func,
806  const char * pips_file,
807  const int pips_line,
808  const string description)
809 {
810  if (code)
811  {
812  // some error, precise report
813  string
816 
817  if (pass)
818  fprintf(out, "%s[%s] ", pass, owner? owner: "<unknown");
819 
820  if (pips_func)
821  fprintf(out, "(%s) ", pips_func);
822 
823  fprintf(out, "[%s] ", pips_log_tag_name(tag));
824 
825  fprintf(out, "stopping pips on code %d (%s) ", code, code2status(code));
826 
827  // not good for validation, this might move easily... so only on abort
828  if (pips_file && code == -1)
829  fprintf(out, "at (\"%s\":%d) ", pips_file, pips_line);
830 
831  if (description && *description)
832  {
833  fputs("for ", out);
834  fputs(description, out);
835  }
836  fputs("\n", out);
837  }
838  else // short output for normal exit(0)
839  fprintf(out, "Pips is done: %s\n", description);
840 
841  fflush(out);
842 }
843 
844 static void _NORETURN_
846  pips_log_t tag,
847  int code,
848  const string pips_func,
849  const string pips_file,
850  const int pips_line,
851  const string desc)
852 {
853  // trace
854  pips_stop_file(stderr, tag, code, pips_func, pips_file, pips_line, desc);
855 
856  if (log_file && tag == info_log)
857  pips_stop_file(log_file, tag, code, pips_func, pips_file, pips_line, desc);
858 
859  if (log_file)
860  fclose(log_file);
861 
862  if (warning_file && tag >= warning_log)
864  tag, code, pips_func, pips_file, pips_line, desc);
865 
866  if (warning_file)
867  fclose(warning_file);
868 
869  if (xml_logfile)
870  {
871  pips_stop_xml(tag, code, pips_func, pips_file, pips_line, desc);
872  fclose(xml_logfile);
873  }
874 
875  // do the deed
876  if (code < 0)
877  abort();
878  else
879  exit(code);
880 }
881 
882 static void _NORETURN_
884  pips_log_t tag,
885  int code,
886  const string pips_func,
887  const string pips_file,
888  const int pips_line,
889  const string format,
890  va_list * args)
891 {
892  string description;
893  va_list acpy;
894  va_copy(acpy, *args);
895  vasprintf(&description, format, acpy);
896  va_end(acpy);
897 
898  pips_stop_desc(tag, code, pips_func, pips_file, pips_line, description);
899 
900  free(description);
901 }
902 
903 void _NORETURN_
905  // added parameters
906  const char * pips_func,
907  const char * pips_file,
908  const int pips_line,
909  // provided arguments
910  pips_log_t tag,
911  int code,
912  const string format,
913  ...)
914 {
915  va_list args;
916  va_start(args, format);
918  (const string) pips_func, (const string) pips_file, pips_line,
919  format, &args);
920  va_end(args);
921 }
922 
923 void _NORETURN_
925  pips_log_t tag,
926  int code,
927  const string format,
928  ...)
929 {
930  va_list args;
931  va_start(args, format);
932  pips_stop_alist(tag, code, NULL, NULL, -1, format, &args);
933  va_end(args);
934 }
935 
936 /******************************************************************* ALL LOG */
937 
939 {
940  switch (tag)
941  {
942  case none_log: return "none";
943  case info_log: return "information";
944  case warning_log: return "warning";
945  case spear_warning_log: return "spear warning";
946  case spear_error_log: return "spear error";
947  case user_error_log: return "user error";
948  case internal_error_log: return "internal error";
949  case irrecoverable_error_log: return "irrecoverable error";
950  default: return "<missing tag name>";
951  }
952 }
953 
954 static void pips_log_file(
955  FILE * out,
956  const pips_log_t tag,
957  const string pips_pass,
958  const string pips_owner,
959  const string pips_func,
960  const string pips_file,
961  const int pips_line,
962  const string user_func,
963  const string user_file,
964  const int user_line,
965  const int user_line2,
966  const string stmt,
967  const string suggestion,
968  const string description)
969 {
970  // whether to add a new line after line headers
971  bool nl = false;
972 
973  if (pips_pass) {
974  fprintf(out, "%s[%s] ", pips_pass, pips_owner? pips_owner: "?");
975  }
976 
977  if (pips_func && tag >= warning_log)
978  fprintf(out, "(%s) ", pips_func);
979 
980  if (tag >= user_error_log)
981  fprintf(out, "[%s] ", pips_log_tag_name(tag));
982 
983  if (pips_file && tag >= internal_error_log) {
984  fprintf(out, "(%s:%d) ", pips_file, pips_line);
985  nl = true;
986  }
987 
988  if (user_func && !pips_owner) {
989  fprintf(out, "in function %s ", user_func);
990  nl = true;
991  }
992 
993  if (user_file)
994  {
995  fprintf(out, "(\"%s\"", user_file);
996  if (user_line >= 0)
997  {
998  fprintf(out, ":%d", user_line);
999  if (user_line < user_line2)
1000  fprintf(out, "-%d", user_line2);
1001  }
1002  fputs(") ", out);
1003  nl = true;
1004  }
1005  else
1006  {
1007  if (user_line >= 0)
1008  {
1009  fprintf(out, "line %d", user_line);
1010  if (user_line < user_line2)
1011  fprintf(out, "-%d", user_line2);
1012  fputs(" ", out);
1013  nl = true;
1014  }
1015  }
1016 
1017  if (nl || stmt) fputc('\n', out);
1018 
1019  if (stmt) {
1020  string s = stmt;
1021  while (*s && *s == '\n') s++; // skip leading newlines
1022  fprintf(out, "at statement:\n\n\t%s\n\n", s);
1023  }
1024 
1025  if (description) {
1026  fputs(description, out);
1027  fputc('\n', out);
1028  }
1029 
1030  if (suggestion) {
1031  fputs(suggestion, out);
1032  fputc('\n', out);
1033  }
1034 
1035  fflush(out);
1036 }
1037 
1038 /* manage "displaying" a log entry, on stderr, in files...
1039  */
1040 static void pips_log_display(
1041  const pips_log_t tag,
1042  const string pips_pass,
1043  const string pips_owner,
1044  const string pips_func,
1045  const string pips_file,
1046  const int pips_line,
1047  const string user_func,
1048  const string user_file,
1049  const int user_line,
1050  const int user_line2,
1051  const string stmt,
1052  const string suggestion,
1053  const string desc)
1054 {
1055  // always show on stderr
1056  pips_log_file(stderr, tag,
1057  pips_pass, pips_owner,
1058  pips_func, pips_file, pips_line,
1059  user_func, user_file, user_line, user_line2,
1060  stmt, suggestion, desc);
1061 
1062  // send to logfile if there
1063  if (log_file && tag == info_log)
1065  pips_pass, pips_owner,
1066  pips_func, pips_file, pips_line,
1067  user_func, user_file, user_line, user_line2,
1068  stmt, suggestion, desc);
1069 
1070  // send to WARNINGS?
1071  if (warning_file && tag >= warning_log)
1073  pips_pass, pips_owner,
1074  pips_func, pips_file, pips_line,
1075  user_func, user_file, user_line, user_line2,
1076  stmt, suggestion, desc);
1077 
1078  // XML output
1079  if (xml_logfile)
1080  pips_log_xml(tag,
1081  pips_pass, pips_owner,
1082  pips_func, pips_file, pips_line,
1083  user_func, user_file, user_line, user_line2,
1084  stmt, suggestion, desc);
1085 }
1086 
1088 
1090  const char * pips_func,
1091  const char * pips_file,
1092  const int pips_line)
1093 {
1094  // deep recursion detection, should never get there...
1095  if (pips_log_recursion_count ++ > 3)
1096  {
1097  // hmmm... cannot call pips_log!
1098  fprintf(stderr, "pips_log recursion (%d) from %s (%s:%d)\n",
1099  pips_log_recursion_count, pips_func, pips_file, pips_line);
1100  fflush(stderr);
1101 
1102  if (pips_log_recursion_count > 10)
1103  pips_stop_func(pips_func, pips_file, pips_line,
1104  internal_error_log, -1,
1105  "deep pips_log recursion (%d)", pips_log_recursion_count);
1106  }
1107 }
1108 
1109 static void pips_log_done(void)
1110 {
1112 }
1113 
1114 /* end of log entry (nothing, exception, abort, exit...)
1115  */
1117 {
1118  pips_log_done();
1119 
1120  if (tag <= spear_warning_log)
1121  return;
1122 
1123  // just in case, flush stuff before stopping?
1124  fflush(stderr);
1125  fflush(stdout);
1126  if (xml_logfile) fflush(xml_logfile);
1127  if (warning_file) fflush(warning_file);
1128  if (log_file) fflush(log_file);
1129 
1130  // ??? get_bool_property("CLOSE_WORKSPACE_AND_QUIT_ON_ERROR")
1131 
1132  // handle various stops
1133  if (tag == internal_error_log)
1134  pips_stop(tag, -1, "internal error raised");
1135 
1137  pips_stop(tag, 1, "irrecoverable error raised");
1138 
1139  if (tag == user_error_log || tag == spear_error_log)
1140  {
1141  if (properties_initialized_p() &&
1142  get_bool_property("CLOSE_WORKSPACE_AND_QUIT_ON_ERROR"))
1143  // the close workspace part only works for tpips user error handler
1144  pips_stop(tag, 2, "CLOSE_WORKSPACE_AND_QUIT_ON_ERROR");
1145 
1147  pips_stop(tag, -1, "too many property errors pending");
1148 
1149  if (properties_initialized_p() &&
1150  get_bool_property("ABORT_ON_USER_ERROR"))
1151  pips_stop(tag, -1, "ABORT_ON_USER_ERROR");
1152 
1153  static int user_error_called = 0;
1154 
1155  if (properties_initialized_p() &&
1156  user_error_called > get_int_property("MAXIMUM_USER_ERROR"))
1157  {
1159  "over MAXIMUM_USER_ERROR=%d user errors",
1160  get_int_property("MAXIMUM_USER_ERROR"));
1161  }
1162 
1163  user_error_called++;
1164 
1165  // throw according to linear exception stack
1166  // If it is OK there, we should do a reset_property_error()
1168  }
1169 }
1170 
1171 /* log entry with preprocessed format/arguments
1172  */
1174  const pips_log_t tag,
1175  const string pips_pass,
1176  const string pips_owner,
1177  const string pips_func,
1178  const string pips_file,
1179  const int pips_line,
1180  const string user_func,
1181  const string user_file,
1182  const int user_line,
1183  const int user_line2,
1184  const string stmt,
1185  const string suggestion,
1186  const string description)
1187 {
1188  pips_log_in_progress(pips_func, pips_file, pips_line);
1189 
1190  pips_log_display(tag, pips_pass, pips_owner,
1191  pips_func, pips_file, pips_line,
1192  user_func, user_file, user_line, user_line2,
1193  stmt, suggestion, description);
1194 
1195  pips_log_end(tag);
1196 }
1197 
1198 /* log entry with unprocessed format/alist arguments
1199  */
1201  // what kind of log, somehow a severity information
1202  const pips_log_t tag,
1203  // what is going on
1204  const string pips_pass,
1205  const string pips_owner,
1206  // where it comes from (pips)
1207  const string pips_func,
1208  const string pips_file,
1209  const int pips_line,
1210  // where it comes from (user)
1211  const string user_func,
1212  const string user_file,
1213  const int user_line,
1214  const int user_line2,
1215  //const statement stmt,
1216  const string stmt,
1217  // what to tell
1218  const string suggestion,
1219  const string format,
1220  va_list * args)
1221 {
1222  pips_log_in_progress(pips_func, pips_file, pips_line);
1223 
1224  // process issue description once and for all
1225  string description = NULL;
1226  va_list acpy;
1227  va_copy(acpy, *args);
1228  // BUG: if a timeout is raised while being in malloc, this call is deadlocked
1229  // as a lock is already held and vasprintf needs to allocate... Also, XML
1230  // output generation also requires malloc later on...
1231  vasprintf(&description, format, acpy);
1232  va_end(acpy);
1233 
1234  // trim leading newlines/tabs and trailing newlines/tabs/spaces
1235  string desc = description;
1236  while (*desc && (*desc == '\n' || *desc == '\t' || *desc == '\r'))
1237  desc ++;
1238  int last = strlen(desc) - 1;
1239  while (last >= 0 &&
1240  (desc[last] == '\n' || desc[last] == '\t' || desc[last] == ' ' ||
1241  desc[last] == '\r'))
1242  desc[last--] = '\0';
1243 
1244  // display part
1245  pips_log_display(tag, pips_pass, pips_owner,
1246  pips_func, pips_file, pips_line,
1247  user_func, user_file, user_line, user_line2,
1248  stmt, suggestion, desc);
1249 
1250  // cleanup
1251  free(description);
1252 
1253  // (legacy?) alist level callbacks...
1254  if (tag == info_log && pips_log_handler)
1255  {
1256  va_copy(acpy, *args);
1257  pips_log_handler(format, &acpy);
1258  va_end(acpy);
1259  }
1260  else if ((tag == warning_log || tag == spear_warning_log) &&
1262  {
1263  va_copy(acpy, *args);
1264  pips_warning_handler(pips_func, format, &acpy);
1265  va_end(acpy);
1266  }
1267  else if (tag == user_error_log && pips_error_handler)
1268  {
1269  va_copy(acpy, *args);
1270  pips_error_handler(pips_func, format, &acpy);
1271  va_end(acpy);
1272  }
1274  {
1275  va_copy(acpy, *args);
1276  pips_internal_error_handler(pips_func, format, &acpy);
1277  va_end(acpy);
1278  }
1279 
1280  // conclusion (exit, abort, whatever), although it may never be reached...
1281  pips_log_end(tag);
1282 }
1283 
1284 /* direct pips_log call with format and free arguments ("...")
1285  */
1287  // where it comes from (pips)
1288  const string pips_func,
1289  const string pips_file,
1290  const int pips_line,
1291  // what kind of log, somehow a severity information
1292  const pips_log_t tag,
1293  // what is going on
1294  const string pips_pass,
1295  const string pips_owner,
1296  // where it comes from (user)
1297  const string user_func,
1298  const string user_file,
1299  const int user_line,
1300  const int user_line2,
1301  //const statement stmt,
1302  const string stmt,
1303  // what to tell
1304  const string suggestion,
1305  const string format,
1306  ...
1307  )
1308 {
1309  va_list args;
1310  va_start(args, format);
1312  pips_pass, pips_owner,
1313  pips_func, pips_file, pips_line,
1314  user_func, user_file, user_line, user_line2,
1315  stmt, suggestion, format, &args);
1316  va_end(args);
1317 }
1318 
1319 /* quick log and stop, called on timeout
1320  * this must not invoke malloc as it may still held locks if interrupted
1321  * this implementation is missing XML escapes...
1322  */
1324  const char * function,
1325  const char * file,
1326  const int lineno,
1327  const pips_log_t tag,
1328  const int code,
1329  const string format,
1330  ...)
1331 {
1332  // STDERR
1333  va_list args;
1334  va_start(args, format);
1335  fprintf(stderr, "(%s) [%s] stopping pips on code %d (%s) for ",
1336  function, pips_log_tag_name(tag), code, code2status(code));
1337  vfprintf(stderr, format, args);
1338  va_end(args);
1339  fputs("\n", stderr);
1340  fflush(stderr);
1341 
1342  // XML
1343  if (xml_logfile)
1344  {
1346  "<Exit Code=\"%d\" Status=\"%s\" Source=\"%s\">\n",
1348 
1349  string
1350  pass = get_pips_current_pass_name(),
1352 
1354  " <Description AppFunction=\"\" AppFile=\"\" "
1355  "AppLine=\"\" Statement=\"\" Proposition=\"\" "
1356  "Pass=\"%s\" Owner=\"%s\" PipsFunction=\"%s\" ",
1357  pass? pass: "", module? module: "", function);
1358 
1359  if (file && getenv("PIPS_VALIDATION_IN_PROGRESS"))
1360  {
1361  // just show a short version of the file & hide the line
1362  string short_file = strstr(file, "/src/");
1364  "PipsFile=\"%s\" PipsLine=\"...\" ",
1365  short_file? short_file: "...");
1366  }
1367  else
1368  {
1369  fprintf(xml_logfile, "PipsFile=\"%s\" PipsLine=\"%d\" ", file, lineno);
1370  }
1371 
1372  fprintf(xml_logfile, "Message=\"");
1373 
1374  va_start(args, format);
1375  vfprintf(xml_logfile, format, args);
1376  va_end(args);
1377 
1378  fprintf(xml_logfile, "\" />\n</Exit>\n");
1379  fflush(xml_logfile);
1380  }
1381 
1382  exit(code);
1383 }
1384 
1385 
1386 // void pips_log_func2()
1387 
1388 /********************************************************************* UTILS */
1389 
1390 #ifdef asprintf
1391 #undef asprintf
1392 #endif // asprintf
1393 
1394 #ifdef vasprintf
1395 #undef vasprintf
1396 #endif // vasprintf
1397 
1398 int safe_vasprintf(char ** strp, const char * fmt, va_list args)
1399 {
1400  va_list acpy;
1401  va_copy(acpy, args);
1402  int ret = vasprintf(strp, fmt, acpy);
1403  pips_assert("vasprintf is ok", ret >= 0);
1404  va_end(acpy);
1405  return ret;
1406 }
1407 
1408 int safe_asprintf(char ** strp, const char * fmt, ...)
1409 {
1410  va_list args;
1411  va_start(args, fmt);
1412  return safe_vasprintf(strp, fmt, args);
1413  va_end(args);
1414 }
bool too_many_property_errors_pending_p(void)
void _NORETURN_ pips_user_error_func2(const char *format,...)
Definition: message.c:492
void _NORETURN_ pips_stop_func(const char *pips_func, const char *pips_file, const int pips_line, pips_log_t tag, int code, const string format,...)
expecititely declare "noreturn" functions...
Definition: message.c:904
static void pips_stop_xml(pips_log_t tag, int code, const string pips_func, const string pips_file, const int pips_line, const string description)
Definition: message.c:771
int get_int_property(const string)
bool function_same_string_p(const char *s1, const char *s2)
Definition: message.c:560
static void pips_log_display(const pips_log_t tag, const string pips_pass, const string pips_owner, const string pips_func, const string pips_file, const int pips_line, const string user_func, const string user_file, const int user_line, const int user_line2, const string stmt, const string suggestion, const string desc)
manage "displaying" a log entry, on stderr, in files...
Definition: message.c:1040
void _NORETURN_ pips_internal_error_func2(const char *format,...)
Definition: message.c:408
void pips_log_func(const string pips_func, const string pips_file, const int pips_line, const pips_log_t tag, const string pips_pass, const string pips_owner, const string user_func, const string user_file, const int user_line, const int user_line2, const string stmt, const string suggestion, const string format,...)
direct pips_log call with format and free arguments ("...")
Definition: message.c:1286
static void _NORETURN_ pips_user_error_alist(const char *calling_function_name, const char *funcfile, const int funcline, const char *format, va_list *args)
Definition: message.c:458
void pips_thanks(string name, string path)
display pips thanks on startup, if it on a tty.
Definition: message.c:265
void open_warning_file(const char *dir)
Definition: message.c:286
void(* pips_internal_error_handler)(const char *, const char *,...)
PIPS_ERROR is a function that should be called to terminate PIPS execution when data structures are c...
Definition: message.c:511
static string current_phase
CATCH/TRY/UNCATCH/THROW stuff is here.
Definition: message.c:62
static void pips_log_done(void)
Definition: message.c:1109
void pips_log_desc(const pips_log_t tag, const string pips_pass, const string pips_owner, const string pips_func, const string pips_file, const int pips_line, const string user_func, const string user_file, const int user_line, const int user_line2, const string stmt, const string suggestion, const string description)
log entry with preprocessed format/arguments
Definition: message.c:1173
void close_log_file(void)
Definition: message.c:162
static string pips_log_xml_tag(pips_log_t tag)
Definition: message.c:657
static void pips_log_end(pips_log_t tag)
end of log entry (nothing, exception, abort, exit...)
Definition: message.c:1116
void _NORETURN_ pips_stop_func2(pips_log_t tag, int code, const string format,...)
Definition: message.c:924
int safe_vasprintf(char **strp, const char *fmt, va_list args)
Definition: message.c:1398
void open_xml_logfile(const char *filename)
Definition: message.c:607
static void _NORETURN_ pips_stop_desc(pips_log_t tag, int code, const string pips_func, const string pips_file, const int pips_line, const string desc)
Definition: message.c:845
int safe_asprintf(char **strp, const char *fmt,...)
Definition: message.c:1408
void user_log(const char *format,...)
Definition: message.c:234
static string current_module
Definition: message.c:63
static string pips_revisions
Definition: message.c:98
static void pips_log_file(FILE *out, const pips_log_t tag, const string pips_pass, const string pips_owner, const string pips_func, const string pips_file, const int pips_line, const string user_func, const string user_file, const int user_line, const int user_line2, const string stmt, const string suggestion, const string description)
Definition: message.c:954
void log_on_file(const char *desc)
Definition: message.c:190
void _NORETURN_ pips_user_irrecoverable_error_func2(const char *format,...)
Definition: message.c:550
void pips_log_alist(const pips_log_t tag, const string pips_pass, const string pips_owner, const string pips_func, const string pips_file, const int pips_line, const string user_func, const string user_file, const int user_line, const int user_line2, const string stmt, const string suggestion, const string format, va_list *args)
log entry with unprocessed format/alist arguments
Definition: message.c:1200
static string code2status(int code)
Definition: message.c:759
static void pips_log_xml_pips_level(string_buffer sb, const string pips_pass, const string pips_owner, const string pips_func, const string pips_file, const int pips_line)
append pips-level stuff (function, file, line) to xml file
Definition: message.c:673
void _NORETURN_ pips_internal_error_func(const char *funcname, const char *funcfile, const int funcline, const char *fmt,...)
Definition: message.c:394
void pips_user_log_func(const char *format,...)
Definition: message.c:225
void open_log_file(const string dir)
Definition: message.c:171
char * get_string_property(const char *)
bool properties_initialized_p(void)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define LOG_FILE
Definition: message.c:155
static void append_xml_line_numbers(string_buffer sb, const string attribute, int val1, int val2)
Definition: message.c:641
static string pips_date
Definition: message.c:99
#define WARNING_FILE_NAME
USER_WARNING issues a warning and don't stop the program (cf.
Definition: message.c:281
static void _NORETURN_ pips_internal_error_alist(const char *funcname, const char *funcfile, const int funcline, const char *format, va_list *args)
Definition: message.c:375
static void pips_stop_file(FILE *out, pips_log_t tag, int code, const char *pips_func, const char *pips_file, const int pips_line, const string description)
Definition: message.c:801
static string xml_logfile_name
Definition: message.c:568
static void _NORETURN_ pips_stop_alist(pips_log_t tag, int code, const string pips_func, const string pips_file, const int pips_line, const string format, va_list *args)
Definition: message.c:883
void _NORETURN_ pips_user_irrecoverable_error_func(const char *func_name, const char *funcfile, const int funcline, const char *format,...)
Definition: message.c:535
static string pips_cc
Definition: message.c:100
void close_warning_file(void)
Definition: message.c:293
void set_pips_current_computation(const char *rname, const char *oname)
message.c
Definition: message.c:65
string get_pips_current_pass_name(void)
Export this piece of information to customize warning functions in passes.
Definition: message.c:77
static void pips_log_in_progress(const char *pips_func, const char *pips_file, const int pips_line)
Definition: message.c:1089
static FILE * xml_logfile
Definition: message.c:567
static FILE * warning_file
Definition: message.c:283
void reset_pips_current_computation(void)
Definition: message.c:87
static void pips_user_log_alist(const char *format, va_list *args)
Definition: message.c:218
static FILE * log_file
The log file is closed by default.
Definition: message.c:159
static void append_xml_attribute(string_buffer sb, const string attribute, const string value)
generate xml: attribute="escaped-stuff"
Definition: message.c:595
void(* pips_log_handler)(const char *fmt, va_list *args)
USER_LOG is a function that should be called to log the current PIPS request, as soon as it is releva...
Definition: message.c:216
string(* pips_request_handler)(const char *, va_list *)
default assignment of pips_request_handler is default_user_request.
Definition: message.c:139
#define PIPS_THANKS_STRING(arch)
The # "stringificator" only works in a macro expansion...
Definition: message.c:247
string pips_log_tag_name(pips_log_t tag)
Definition: message.c:938
void(* pips_error_handler)(const char *, const char *, va_list *)
PROMPT_USER schould be implemented.
Definition: message.c:455
string get_pips_current_module(void)
Definition: message.c:82
void _NORETURN_ pips_user_irrecoverable_error_alist(const char *func_name, const char *funcfile, const int funcline, const char *format, va_list *args)
Definition: message.c:516
void pips_user_warning_alist(const char *function_name, const char *funcfile, const int funcline, const char *format, va_list *args)
Definition: message.c:328
static string warning_file_name
Definition: message.c:284
void _NORETURN_ pips_user_error_func(const char *func_name, const char *funcfile, const int funcline, const char *format,...)
Definition: message.c:478
void pips_user_warning_func2(const char *format,...)
fallback version without a calling function name
Definition: message.c:362
void pips_user_warning_func(const char *calling_function_name, const char *funcfile, const int funcline, const char *format,...)
Definition: message.c:346
string default_user_request(const char *fmt, va_list *args)
USER_REQUEST is a function that should be called to request some data from the user.
Definition: message.c:124
void close_xml_logfile(void)
Definition: message.c:631
void set_pips_meta_informations(const char *revs, const char *date, const char *comp)
Definition: message.c:102
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void append_to_warning_file(const char *calling_function_name, const char *format, va_list *args)
To be used in error handling functions.
Definition: message.c:306
static int pips_log_recursion_count
Definition: message.c:1087
void(* pips_warning_handler)(const char *, const char *, va_list *)
default assignment of pips_warning_handler is default_user_warning.
Definition: message.c:325
static void pips_log_xml(const pips_log_t tag, const string pips_pass, const string pips_owner, const string pips_func, const string pips_file, const int pips_line, const string user_func, const string user_file, const int user_line, const int user_line2, const string stmt, const string suggestion, const string description)
add a full log entry to the xml log file
Definition: message.c:701
void pips_log_stop(const char *function, const char *file, const int lineno, const pips_log_t tag, const int code, const string format,...)
quick log and stop, called on timeout this must not invoke malloc as it may still held locks if inter...
Definition: message.c:1323
static FILE * out
Definition: alias_check.c:128
@ user_exception_error
#define THROW(what)
#define ret(why, what)
true if not a remapping for old.
Definition: dynamic.c:986
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
char * safe_readline(FILE *file)
returns the allocated line read, whatever its length.
Definition: file.c:497
static FILE * user_file
These functions implements the writing of objects.
Definition: genClib.c:1485
void free(void *)
#define TIMEOUT_CODE
Definition: misc-local.h:43
#define STRINGIFY(symbol)
If not using this 2-stage macro evaluation, the generated string is not the value of the macro but th...
Definition: misc-local.h:50
#define _NORETURN_
Definition: misc-local.h:233
#define pips_unknown_function
Definition: misc-local.h:63
pips_log_t
Definition: misc-local.h:31
@ warning_log
Definition: misc-local.h:34
@ internal_error_log
Definition: misc-local.h:38
@ user_error_log
Definition: misc-local.h:37
@ spear_warning_log
Definition: misc-local.h:35
@ spear_error_log
Definition: misc-local.h:36
@ none_log
Definition: misc-local.h:32
@ info_log
Definition: misc-local.h:33
@ irrecoverable_error_log
Definition: misc-local.h:39
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define pips_stop
Definition: misc-local.h:151
#define exit(code)
Definition: misc-local.h:54
#define abort()
Definition: misc-local.h:53
#define pips_user_error
Definition: misc-local.h:147
string user_request(const char *,...)
#define assert(ex)
Definition: newgen_assert.h:41
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
void string_buffer_append(string_buffer, const string)
append string s (if non empty) to string buffer sb, the duplication is done if needed according to th...
void string_buffer_printf(string_buffer, const string,...)
append a formatted string to sb
void string_buffer_to_file(const string_buffer, FILE *)
put string buffer into file.
void string_buffer_free(string_buffer *)
free string buffer structure, also free string contents according to the dup field
Definition: string_buffer.c:82
string_buffer string_buffer_make(bool dup)
allocate a new string buffer
Definition: string_buffer.c:58
void string_buffer_cat(string_buffer, const string,...)
append a NULL terminated list of string to sb.
void string_buffer_append_xml_text(string_buffer, const string, bool)
append a string with XML escapes
int tag
TAG.
Definition: newgen_types.h:92
char * string
STRING.
Definition: newgen_types.h:39
static char * module
Definition: pips.c:74
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
s1
Definition: set.c:247
internally defined structure.
Definition: string_buffer.c:47
Definition: statement.c:4047
Definition: statement.c:54
int vasprintf(char **resultp, const char *format, va_list args)
Formatted output to strings.
Definition: vasprintf.c:33