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