xref: /petsc/src/sys/fileio/mprint.c (revision dced61a5cfeeeda68dfa4ee3e53b34d3cfb8da9f)
1 /*
2       Utilites routines to add simple ASCII IO capability.
3 */
4 #include <../src/sys/fileio/mprint.h>
5 #include <errno.h>
6 /*
7    If petsc_history is on, then all Petsc*Printf() results are saved
8    if the appropriate (usually .petschistory) file.
9 */
10 extern FILE *petsc_history;
11 /*
12      Allows one to overwrite where standard out is sent. For example
13      PETSC_STDOUT = fopen("/dev/ttyXX","w") will cause all standard out
14      writes to go to terminal XX; assuming you have write permission there
15 */
16 FILE *PETSC_STDOUT = 0;
17 /*
18      Allows one to overwrite where standard error is sent. For example
19      PETSC_STDERR = fopen("/dev/ttyXX","w") will cause all standard error
20      writes to go to terminal XX; assuming you have write permission there
21 */
22 FILE *PETSC_STDERR = 0;
23 
24 /*
25      Return the maximum expected new size of the format
26 */
27 #define PETSC_MAX_LENGTH_FORMAT(l) (l+l/8)
28 
29 #undef __FUNCT__
30 #define __FUNCT__ "PetscFormatConvert"
31 /*@C
32      PetscFormatConvert - Takes a PETSc format string and converts it to a reqular C format string
33 
34    Input Parameters:
35 +   format - the PETSc format string
36 .   newformat - the location to put the standard C format string values
37 -   size - the length of newformat
38 
39     Note: this exists so we can have the same code when PetscInt is either int or long long and PetscScalar is either __float128, double, or float
40 
41  Level: developer
42 
43 @*/
44 PetscErrorCode  PetscFormatConvert(const char *format,char *newformat,size_t size)
45 {
46   PetscInt i = 0,j = 0;
47 
48   PetscFunctionBegin;
49   while (format[i] && j < (PetscInt)size-1) {
50     if (format[i] == '%' && format[i+1] == '%') {
51       newformat[j++] = format[i++];
52       newformat[j++] = format[i++];
53     } else if (format[i] == '%') {
54       /* Find the letter */
55       for (; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i];
56       switch (format[i]) {
57       case 'D':
58 #if !defined(PETSC_USE_64BIT_INDICES)
59         newformat[j++] = 'd';
60 #else
61         newformat[j++] = 'l';
62         newformat[j++] = 'l';
63         newformat[j++] = 'd';
64 #endif
65         break;
66       case 'G':
67         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"%%G format is no longer supported, use %%g and cast the argument to double");
68         break;
69       case 'F':
70         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"%%F format is no longer supported, use %%f and cast the argument to double");
71         break;
72       default:
73         newformat[j++] = format[i];
74         break;
75       }
76       i++;
77     } else newformat[j++] = format[i++];
78   }
79   newformat[j] = 0;
80   PetscFunctionReturn(0);
81 }
82 
83 #undef __FUNCT__
84 #define __FUNCT__ "PetscVSNPrintf"
85 /*@C
86      PetscVSNPrintf - The PETSc version of vsnprintf(). Converts a PETSc format string into a standard C format string and then puts all the
87        function arguments into a string using the format statement.
88 
89    Input Parameters:
90 +   str - location to put result
91 .   len - the amount of space in str
92 +   format - the PETSc format string
93 -   fullLength - the amount of space in str actually used.
94 
95     Developer Notes: this function may be called from an error handler, if an error occurs when it is called by the error handler than likely
96       a recursion will occur and possible crash.
97 
98  Level: developer
99 
100 @*/
101 PetscErrorCode  PetscVSNPrintf(char *str,size_t len,const char *format,size_t *fullLength,va_list Argp)
102 {
103   char           *newformat;
104   char           formatbuf[8*1024];
105   size_t         oldLength,length;
106   PetscErrorCode ierr;
107 
108   PetscFunctionBegin;
109   ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr);
110   if (oldLength < 8*1024) {
111     newformat = formatbuf;
112     oldLength = 8*1024-1;
113   } else {
114     oldLength = PETSC_MAX_LENGTH_FORMAT(oldLength);
115     ierr      = PetscMalloc1(oldLength, &newformat);CHKERRQ(ierr);
116   }
117   PetscFormatConvert(format,newformat,oldLength);
118   ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr);
119 #if 0
120   if (length > len) newformat[len] = '\0';
121 #endif
122 #if defined(PETSC_HAVE_VSNPRINTF_CHAR)
123   (void) vsnprintf(str,len,newformat,(char*)Argp);
124 #elif defined(PETSC_HAVE_VSNPRINTF)
125   (void) vsnprintf(str,len,newformat,Argp);
126 #elif defined(PETSC_HAVE__VSNPRINTF)
127   (void) _vsnprintf(str,len,newformat,Argp);
128 #else
129 #error "vsnprintf not found"
130 #endif
131   if (oldLength >= 8*1024) {
132     ierr = PetscFree(newformat);CHKERRQ(ierr);
133   }
134 #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
135   /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
136   {
137     size_t cnt = 0,ncnt = 0,leng;
138     ierr = PetscStrlen(str,&leng);CHKERRQ(ierr);
139     if (leng > 5) {
140       for (cnt=0; cnt<leng-4; cnt++) {
141         if (str[cnt] == 'e' && (str[cnt+1] == '-' || str[cnt+1] == '+') && str[cnt+2] == '0'  && str[cnt+3] >= '0' && str[cnt+3] <= '9' && str[cnt+4] >= '0' && str[cnt+4] <= '9') {
142           str[ncnt] = str[cnt]; ncnt++; cnt++;
143           str[ncnt] = str[cnt]; ncnt++; cnt++; cnt++;
144           str[ncnt] = str[cnt];
145         } else {
146           str[ncnt] = str[cnt];
147         }
148         ncnt++;
149       }
150       while (cnt < leng) {
151         str[ncnt] = str[cnt]; ncnt++; cnt++;
152       }
153       str[ncnt] = 0;
154     }
155   }
156 #endif
157   if (fullLength) {
158     ierr = PetscStrlen(str,fullLength);CHKERRQ(ierr);
159   }
160   PetscFunctionReturn(0);
161 }
162 
163 #undef __FUNCT__
164 #define __FUNCT__ "PetscVFPrintfDefault"
165 /*@C
166      PetscVFPrintf -  All PETSc standard out and error messages are sent through this function; so, in theory, this can
167         can be replaced with something that does not simply write to a file.
168 
169       To use, write your own function for example,
170 $PetscErrorCode mypetscvfprintf(FILE *fd,const char format[],va_list Argp)
171 ${
172 $  PetscErrorCode ierr;
173 $
174 $  PetscFunctionBegin;
175 $   if (fd != stdout && fd != stderr) {  handle regular files
176 $      ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERR(ierr);
177 $  } else {
178 $     char   buff[BIG];
179 $     size_t length;
180 $     ierr = PetscVSNPrintf(buff,BIG,format,&length,Argp);CHKERRQ(ierr);
181 $     now send buff to whatever stream or whatever you want
182 $ }
183 $ PetscFunctionReturn(0);
184 $}
185 then before the call to PetscInitialize() do the assignment
186 $    PetscVFPrintf = mypetscvfprintf;
187 
188       Notes: For error messages this may be called by any process, for regular standard out it is
189           called only by process 0 of a given communicator
190 
191       Developer Notes: this could be called by an error handler, if that happens then a recursion of the error handler may occur
192                        and a crash
193 
194   Level:  developer
195 
196 .seealso: PetscVSNPrintf(), PetscErrorPrintf()
197 
198 @*/
199 PetscErrorCode  PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp)
200 {
201   char           str[8*1024];
202   PetscErrorCode ierr;
203 
204   PetscFunctionBegin;
205   ierr = PetscVSNPrintf(str,sizeof(str),format,NULL,Argp);CHKERRQ(ierr);
206   fprintf(fd,"%s",str);CHKERRQ(ierr);
207   fflush(fd);
208   PetscFunctionReturn(0);
209 }
210 
211 #undef __FUNCT__
212 #define __FUNCT__ "PetscSNPrintf"
213 /*@C
214     PetscSNPrintf - Prints to a string of given length
215 
216     Not Collective
217 
218     Input Parameters:
219 +   str - the string to print to
220 .   len - the length of str
221 .   format - the usual printf() format string
222 -   any arguments
223 
224    Level: intermediate
225 
226 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
227           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
228 @*/
229 PetscErrorCode  PetscSNPrintf(char *str,size_t len,const char format[],...)
230 {
231   PetscErrorCode ierr;
232   size_t         fullLength;
233   va_list        Argp;
234 
235   PetscFunctionBegin;
236   va_start(Argp,format);
237   ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr);
238   PetscFunctionReturn(0);
239 }
240 
241 #undef __FUNCT__
242 #define __FUNCT__ "PetscSNPrintfCount"
243 /*@C
244     PetscSNPrintfCount - Prints to a string of given length, returns count
245 
246     Not Collective
247 
248     Input Parameters:
249 +   str - the string to print to
250 .   len - the length of str
251 .   format - the usual printf() format string
252 .   countused - number of characters used
253 -   any arguments
254 
255    Level: intermediate
256 
257 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(),
258           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscSNPrintf()
259 @*/
260 PetscErrorCode  PetscSNPrintfCount(char *str,size_t len,const char format[],size_t *countused,...)
261 {
262   PetscErrorCode ierr;
263   va_list        Argp;
264 
265   PetscFunctionBegin;
266   va_start(Argp,countused);
267   ierr = PetscVSNPrintf(str,len,format,countused,Argp);CHKERRQ(ierr);
268   PetscFunctionReturn(0);
269 }
270 
271 /* ----------------------------------------------------------------------- */
272 
273 PrintfQueue petsc_printfqueue       = 0,petsc_printfqueuebase = 0;
274 int         petsc_printfqueuelength = 0;
275 
276 #undef __FUNCT__
277 #define __FUNCT__ "PetscSynchronizedPrintf"
278 /*@C
279     PetscSynchronizedPrintf - Prints synchronized output from several processors.
280     Output of the first processor is followed by that of the second, etc.
281 
282     Not Collective
283 
284     Input Parameters:
285 +   comm - the communicator
286 -   format - the usual printf() format string
287 
288    Level: intermediate
289 
290     Notes:
291     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
292     from all the processors to be printed.
293 
294     Fortran Note:
295     The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
296     That is, you can only pass a single character string from Fortran.
297 
298 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(),
299           PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
300 @*/
301 PetscErrorCode  PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...)
302 {
303   PetscErrorCode ierr;
304   PetscMPIInt    rank;
305 
306   PetscFunctionBegin;
307   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
308   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
309 
310   /* First processor prints immediately to stdout */
311   if (!rank) {
312     va_list Argp;
313     va_start(Argp,format);
314     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
315     if (petsc_history) {
316       va_start(Argp,format);
317       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
318     }
319     va_end(Argp);
320   } else { /* other processors add to local queue */
321     va_list     Argp;
322     PrintfQueue next;
323     size_t      fullLength = 8191;
324 
325     ierr = PetscNew(&next);CHKERRQ(ierr);
326     if (petsc_printfqueue) {
327       petsc_printfqueue->next = next;
328       petsc_printfqueue       = next;
329       petsc_printfqueue->next = 0;
330     } else petsc_printfqueuebase = petsc_printfqueue = next;
331     petsc_printfqueuelength++;
332     next->size = -1;
333     while ((PetscInt)fullLength >= next->size) {
334       next->size = fullLength+1;
335 
336       ierr = PetscMalloc1(next->size, &next->string);CHKERRQ(ierr);
337       va_start(Argp,format);
338       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
339       ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr);
340       va_end(Argp);
341     }
342   }
343   PetscFunctionReturn(0);
344 }
345 
346 #undef __FUNCT__
347 #define __FUNCT__ "PetscSynchronizedFPrintf"
348 /*@C
349     PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
350     several processors.  Output of the first processor is followed by that of the
351     second, etc.
352 
353     Not Collective
354 
355     Input Parameters:
356 +   comm - the communicator
357 .   fd - the file pointer
358 -   format - the usual printf() format string
359 
360     Level: intermediate
361 
362     Notes:
363     REQUIRES a intervening call to PetscSynchronizedFlush() for the information
364     from all the processors to be printed.
365 
366 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(),
367           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
368 
369 @*/
370 PetscErrorCode  PetscSynchronizedFPrintf(MPI_Comm comm,FILE *fp,const char format[],...)
371 {
372   PetscErrorCode ierr;
373   PetscMPIInt    rank;
374 
375   PetscFunctionBegin;
376   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
377   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
378 
379   /* First processor prints immediately to fp */
380   if (!rank) {
381     va_list Argp;
382     va_start(Argp,format);
383     ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr);
384     if (petsc_history && (fp !=petsc_history)) {
385       va_start(Argp,format);
386       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
387     }
388     va_end(Argp);
389   } else { /* other processors add to local queue */
390     va_list     Argp;
391     PrintfQueue next;
392     size_t      fullLength = 8191;
393     ierr = PetscNew(&next);CHKERRQ(ierr);
394     if (petsc_printfqueue) {
395       petsc_printfqueue->next = next;
396       petsc_printfqueue       = next;
397       petsc_printfqueue->next = 0;
398     } else petsc_printfqueuebase = petsc_printfqueue = next;
399     petsc_printfqueuelength++;
400     next->size = -1;
401     while ((PetscInt)fullLength >= next->size) {
402       next->size = fullLength+1;
403       ierr = PetscMalloc1(next->size, &next->string);CHKERRQ(ierr);
404       va_start(Argp,format);
405       ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
406       ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr);
407       va_end(Argp);
408     }
409   }
410   PetscFunctionReturn(0);
411 }
412 
413 #undef __FUNCT__
414 #define __FUNCT__ "PetscSynchronizedFlush"
415 /*@C
416     PetscSynchronizedFlush - Flushes to the screen output from all processors
417     involved in previous PetscSynchronizedPrintf() calls.
418 
419     Collective on MPI_Comm
420 
421     Input Parameters:
422 +   comm - the communicator
423 -   fd - the file pointer (valid on process 0 of the communicator)
424 
425     Level: intermediate
426 
427     Notes:
428     Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with
429     different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush().
430 
431 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(),
432           PetscViewerASCIISynchronizedPrintf()
433 @*/
434 PetscErrorCode  PetscSynchronizedFlush(MPI_Comm comm,FILE *fd)
435 {
436   PetscErrorCode ierr;
437   PetscMPIInt    rank,size,tag,i,j,n = 0,dummy = 0;
438   char          *message;
439   MPI_Status     status;
440 
441   PetscFunctionBegin;
442   ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr);
443   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
444   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
445 
446   /* First processor waits for messages from all other processors */
447   if (!rank) {
448     if (!fd) fd = PETSC_STDOUT;
449     for (i=1; i<size; i++) {
450       /* to prevent a flood of messages to process zero, request each message separately */
451       ierr = MPI_Send(&dummy,1,MPI_INT,i,tag,comm);CHKERRQ(ierr);
452       ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
453       for (j=0; j<n; j++) {
454         PetscMPIInt size = 0;
455 
456         ierr = MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr);
457         ierr = PetscMalloc1(size, &message);CHKERRQ(ierr);
458         ierr = MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr);
459         ierr = PetscFPrintf(comm,fd,"%s",message);CHKERRQ(ierr);
460         ierr = PetscFree(message);CHKERRQ(ierr);
461       }
462     }
463   } else { /* other processors send queue to processor 0 */
464     PrintfQueue next = petsc_printfqueuebase,previous;
465 
466     ierr = MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr);
467     ierr = MPI_Send(&petsc_printfqueuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
468     for (i=0; i<petsc_printfqueuelength; i++) {
469       ierr     = MPI_Send(&next->size,1,MPI_INT,0,tag,comm);CHKERRQ(ierr);
470       ierr     = MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);CHKERRQ(ierr);
471       previous = next;
472       next     = next->next;
473       ierr     = PetscFree(previous->string);CHKERRQ(ierr);
474       ierr     = PetscFree(previous);CHKERRQ(ierr);
475     }
476     petsc_printfqueue       = 0;
477     petsc_printfqueuelength = 0;
478   }
479   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
480   PetscFunctionReturn(0);
481 }
482 
483 /* ---------------------------------------------------------------------------------------*/
484 
485 #undef __FUNCT__
486 #define __FUNCT__ "PetscFPrintf"
487 /*@C
488     PetscFPrintf - Prints to a file, only from the first
489     processor in the communicator.
490 
491     Not Collective
492 
493     Input Parameters:
494 +   comm - the communicator
495 .   fd - the file pointer
496 -   format - the usual printf() format string
497 
498     Level: intermediate
499 
500     Fortran Note:
501     This routine is not supported in Fortran.
502 
503    Concepts: printing^in parallel
504    Concepts: printf^in parallel
505 
506 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
507           PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush()
508 @*/
509 PetscErrorCode  PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...)
510 {
511   PetscErrorCode ierr;
512   PetscMPIInt    rank;
513 
514   PetscFunctionBegin;
515   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
516   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
517   if (!rank) {
518     va_list Argp;
519     va_start(Argp,format);
520     ierr = (*PetscVFPrintf)(fd,format,Argp);CHKERRQ(ierr);
521     if (petsc_history && (fd !=petsc_history)) {
522       va_start(Argp,format);
523       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
524     }
525     va_end(Argp);
526   }
527   PetscFunctionReturn(0);
528 }
529 
530 #undef __FUNCT__
531 #define __FUNCT__ "PetscPrintf"
532 /*@C
533     PetscPrintf - Prints to standard out, only from the first
534     processor in the communicator. Calls from other processes are ignored.
535 
536     Not Collective
537 
538     Input Parameters:
539 +   comm - the communicator
540 -   format - the usual printf() format string
541 
542    Level: intermediate
543 
544     Fortran Note:
545     The call sequence is PetscPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran.
546     That is, you can only pass a single character string from Fortran.
547 
548    Concepts: printing^in parallel
549    Concepts: printf^in parallel
550 
551 .seealso: PetscFPrintf(), PetscSynchronizedPrintf()
552 @*/
553 PetscErrorCode  PetscPrintf(MPI_Comm comm,const char format[],...)
554 {
555   PetscErrorCode ierr;
556   PetscMPIInt    rank;
557 
558   PetscFunctionBegin;
559   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
560   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
561   if (!rank) {
562     va_list Argp;
563     va_start(Argp,format);
564     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
565     if (petsc_history) {
566       va_start(Argp,format);
567       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
568     }
569     va_end(Argp);
570   }
571   PetscFunctionReturn(0);
572 }
573 
574 /* ---------------------------------------------------------------------------------------*/
575 #undef __FUNCT__
576 #define __FUNCT__ "PetscHelpPrintfDefault"
577 /*@C
578      PetscHelpPrintf -  All PETSc help messages are passing through this function. You can change how help messages are printed by
579         replacinng it  with something that does not simply write to a stdout.
580 
581       To use, write your own function for example,
582 $PetscErrorCode mypetschelpprintf(MPI_Comm comm,const char format[],....)
583 ${
584 $ PetscFunctionReturn(0);
585 $}
586 then before the call to PetscInitialize() do the assignment
587 $    PetscHelpPrintf = mypetschelpprintf;
588 
589   Note: the default routine used is called PetscHelpPrintfDefault().
590 
591   Level:  developer
592 
593 .seealso: PetscVSNPrintf(), PetscVFPrintf(), PetscErrorPrintf()
594 @*/
595 PetscErrorCode  PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...)
596 {
597   PetscErrorCode ierr;
598   PetscMPIInt    rank;
599 
600   PetscFunctionBegin;
601   if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
602   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
603   if (!rank) {
604     va_list Argp;
605     va_start(Argp,format);
606     ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr);
607     if (petsc_history) {
608       va_start(Argp,format);
609       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
610     }
611     va_end(Argp);
612   }
613   PetscFunctionReturn(0);
614 }
615 
616 /* ---------------------------------------------------------------------------------------*/
617 
618 
619 #undef __FUNCT__
620 #define __FUNCT__ "PetscSynchronizedFGets"
621 /*@C
622     PetscSynchronizedFGets - Several processors all get the same line from a file.
623 
624     Collective on MPI_Comm
625 
626     Input Parameters:
627 +   comm - the communicator
628 .   fd - the file pointer
629 -   len - the length of the output buffer
630 
631     Output Parameter:
632 .   string - the line read from the file, at end of file string[0] == 0
633 
634     Level: intermediate
635 
636 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
637           PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf()
638 
639 @*/
640 PetscErrorCode  PetscSynchronizedFGets(MPI_Comm comm,FILE *fp,size_t len,char string[])
641 {
642   PetscErrorCode ierr;
643   PetscMPIInt    rank;
644 
645   PetscFunctionBegin;
646   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
647 
648   if (!rank) {
649     char *ptr = fgets(string, len, fp);
650 
651     if (!ptr) {
652       string[0] = 0;
653       if (!feof(fp)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno);
654     }
655   }
656   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
657   PetscFunctionReturn(0);
658 }
659 
660 #if defined(PETSC_HAVE_CLOSURES)
661 int (^SwiftClosure)(const char*) = 0;
662 
663 #undef __FUNCT__
664 #define __FUNCT__ "PetscVFPrintfToString"
665 PetscErrorCode  PetscVFPrintfToString(FILE *fd,const char format[],va_list Argp)
666 {
667   PetscErrorCode ierr;
668 
669   PetscFunctionBegin;
670   if (fd != stdout && fd != stderr) { /* handle regular files */
671     ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERRQ(ierr);
672   } else {
673     size_t len=8*1024,length;
674     char   buf[len];
675 
676     ierr = PetscVSNPrintf(buf,len,format,&length,Argp);CHKERRQ(ierr);
677     ierr = SwiftClosure(buf);CHKERRQ(ierr);
678   }
679   PetscFunctionReturn(0);
680 }
681 
682 /*
683    Provide a Swift function that processes all the PETSc calls to PetscVFPrintf()
684 */
685 PetscErrorCode PetscVFPrintfSetClosure(int (^closure)(const char*))
686 {
687   PetscVFPrintf = PetscVFPrintfToString;
688   SwiftClosure  = closure;
689   return 0;
690 }
691 #endif
692 
693 #if defined(PETSC_HAVE_MATLAB_ENGINE)
694 #include <mex.h>
695 #undef __FUNCT__
696 #define __FUNCT__ "PetscVFPrintf_Matlab"
697 PetscErrorCode  PetscVFPrintf_Matlab(FILE *fd,const char format[],va_list Argp)
698 {
699   PetscErrorCode ierr;
700 
701   PetscFunctionBegin;
702   if (fd != stdout && fd != stderr) { /* handle regular files */
703     ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERRQ(ierr);
704   } else {
705     size_t len=8*1024,length;
706     char   buf[len];
707 
708     ierr = PetscVSNPrintf(buf,len,format,&length,Argp);CHKERRQ(ierr);
709     mexPrintf("%s",buf);
710   }
711   PetscFunctionReturn(0);
712 }
713 #endif
714 
715 #undef __FUNCT__
716 #define __FUNCT__ "PetscFormatStrip"
717 /*@C
718      PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to % operations
719 
720    Input Parameters:
721 .   format - the PETSc format string
722 
723  Level: developer
724 
725 @*/
726 PetscErrorCode  PetscFormatStrip(char *format)
727 {
728   size_t loc1 = 0, loc2 = 0;
729 
730   PetscFunctionBegin;
731   while (format[loc2]) {
732     if (format[loc2] == '%') {
733       format[loc1++] = format[loc2++];
734       while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++;
735     }
736     format[loc1++] = format[loc2++];
737   }
738   PetscFunctionReturn(0);
739 }
740 
741