Actual source code: verboseinfo.c
1: /*
2: PetscInfo() is contained in a different file from the other profiling to
3: allow it to be replaced at link time by an alternative routine.
4: */
5: #include <petsc/private/petscimpl.h>
7: /*
8: The next set of variables determine which, if any, PetscInfo() calls are used.
9: If PetscLogPrintInfo is false, no info messages are printed.
11: If PetscInfoFlags[OBJECT_CLASSID - PETSC_SMALLEST_CLASSID] is zero, no messages related
12: to that object are printed. OBJECT_CLASSID is, for example, MAT_CLASSID.
13: Note for developers: the PetscInfoFlags array is currently 160 entries large, to ensure headroom. Perhaps it is worth
14: dynamically allocating this array intelligently rather than just some big number.
16: PetscInfoFilename determines where PetscInfo() output is piped.
17: PetscInfoClassnames holds a char array of classes which are filtered out/for in PetscInfo() calls.
18: */
19: const char * const PetscInfoCommFlags[] = {"all", "no_self", "only_self", "PetscInfoCommFlag", "PETSC_INFO_COMM_", NULL};
20: static PetscBool PetscInfoClassesLocked = PETSC_FALSE, PetscInfoInvertClasses = PETSC_FALSE, PetscInfoClassesSet = PETSC_FALSE;
21: static char **PetscInfoClassnames = NULL;
22: static char *PetscInfoFilename = NULL;
23: static PetscInt PetscInfoNumClasses = -1;
24: static PetscInfoCommFlag PetscInfoCommFilter = PETSC_INFO_COMM_ALL;
25: static int PetscInfoFlags[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
26: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
27: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
28: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
29: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
30: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
31: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
32: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
33: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
34: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
35: PetscBool PetscLogPrintInfo = PETSC_FALSE;
36: FILE *PetscInfoFile = NULL;
38: /*@
39: PetscInfoEnabled - Checks whether a given OBJECT_CLASSID is allowed to print using PetscInfo()
41: Not Collective
43: Input Parameters:
44: . classid - PetscClassid retrieved from a PetscObject e.g. VEC_CLASSID
46: Output Parameter:
47: . enabled - PetscBool indicating whether this classid is allowed to print
49: Notes:
50: Use PETSC_SMALLEST_CLASSID to check if "sys" PetscInfo() calls are enabled. When PETSc is configured with debugging
51: support this function checks if classid >= PETSC_SMALLEST_CLASSID, otherwise it assumes valid classid.
53: Level: advanced
55: .seealso: PetscInfo(), PetscInfoAllow(), PetscInfoGetInfo(), PetscObjectGetClassid()
56: @*/
57: PetscErrorCode PetscInfoEnabled(PetscClassId classid, PetscBool *enabled)
58: {
60: *enabled = (PetscBool) (PetscLogPrintInfo && PetscInfoFlags[classid - PETSC_SMALLEST_CLASSID]);
61: return 0;
62: }
64: /*@
65: PetscInfoAllow - Enables/disables PetscInfo() messages
67: Not Collective
69: Input Parameter:
70: . flag - PETSC_TRUE or PETSC_FALSE
72: Level: advanced
74: .seealso: PetscInfo(), PetscInfoEnabled(), PetscInfoGetInfo(), PetscInfoSetFromOptions()
75: @*/
76: PetscErrorCode PetscInfoAllow(PetscBool flag)
77: {
78: PetscLogPrintInfo = flag;
79: return 0;
80: }
82: /*@C
83: PetscInfoSetFile - Sets the printing destination for all PetscInfo() calls
85: Not Collective
87: Input Parameters:
88: + filename - Name of the file where PetscInfo() will print to
89: - mode - Write mode passed to PetscFOpen()
91: Notes:
92: Use filename=NULL to set PetscInfo() to write to PETSC_STDOUT.
94: Level: advanced
96: .seealso: PetscInfo(), PetscInfoSetFile(), PetscInfoSetFromOptions(), PetscFOpen()
97: @*/
98: PetscErrorCode PetscInfoSetFile(const char filename[], const char mode[])
99: {
100: char fname[PETSC_MAX_PATH_LEN], tname[11];
101: PetscMPIInt rank;
103: if (!PetscInfoFile) PetscInfoFile = PETSC_STDOUT;
104: PetscFree(PetscInfoFilename);
105: if (filename) {
106: PetscBool oldflag;
108: PetscFixFilename(filename, fname);
109: PetscStrallocpy(fname, &PetscInfoFilename);
110: MPI_Comm_rank(MPI_COMM_WORLD, &rank);
111: sprintf(tname, ".%d", rank);
112: PetscStrcat(fname, tname);
113: oldflag = PetscLogPrintInfo; PetscLogPrintInfo = PETSC_FALSE;
114: PetscFOpen(MPI_COMM_SELF, fname, mode, &PetscInfoFile);
115: PetscLogPrintInfo = oldflag;
116: /* PetscFOpen will write to PETSC_STDOUT and not PetscInfoFile here, so we disable the PetscInfo call inside it, and
117: call it afterwards so that it actually writes to file */
118: PetscInfo(NULL, "Opened PetscInfo file %s\n", fname);
119: }
120: return 0;
121: }
123: /*@C
124: PetscInfoGetFile - Gets the name and FILE pointer of the file where PetscInfo() prints to
126: Not Collective
128: Output Parameters:
129: + filename - The name of the output file
130: - InfoFile - The FILE pointer for the output file
132: Level: advanced
134: Note:
135: This routine allocates and copies the filename so that the filename survives PetscInfoDestroy(). The user is
136: therefore responsible for freeing the allocated filename pointer afterwards.
138: Fortran Note:
139: This routine is not supported in Fortran.
141: .seealso: PetscInfo(), PetscInfoSetFile(), PetscInfoSetFromOptions(), PetscInfoDestroy()
142: @*/
143: PetscErrorCode PetscInfoGetFile(char **filename, FILE **InfoFile)
144: {
147: PetscStrallocpy(PetscInfoFilename, filename);
148: *InfoFile = PetscInfoFile;
149: return 0;
150: }
152: /*@C
153: PetscInfoSetClasses - Sets the classes which PetscInfo() is filtered for/against
155: Not Collective
157: Input Parameters:
158: + exclude - Whether or not to invert the filter, i.e. if exclude is true, PetscInfo() will print from every class that
159: is NOT one of the classes specified
160: . N - Number of classes to filter for (size of classnames)
161: - classnames - String array containing the names of classes to filter for, e.g. "vec"
163: Notes:
164: Not for use in Fortran
166: This function CANNOT be called after PetscInfoGetClass() or PetscInfoProcessClass() has been called.
168: Names in the classnames list should correspond to the names returned by PetscObjectGetClassName().
170: This function only sets the list of class names.
171: The actual filtering is deferred to PetscInfoProcessClass(), except of sys which is processed right away.
172: The reason for this is that we need to set the list of included/excluded classes before their classids are known.
173: Typically the classid is assigned and PetscInfoProcessClass() called in <Class>InitializePackage() (e.g. VecInitializePackage()).
175: Level: developer
177: .seealso: PetscInfo(), PetscInfoGetClass(), PetscInfoProcessClass(), PetscInfoSetFromOptions(), PetscStrToArray(), PetscObjectGetName()
178: @*/
179: PetscErrorCode PetscInfoSetClasses(PetscBool exclude, PetscInt N, const char *const *classnames)
180: {
182: PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames);
183: PetscStrNArrayallocpy(N, classnames, &PetscInfoClassnames);
184: PetscInfoNumClasses = N;
185: PetscInfoInvertClasses = exclude;
186: {
187: /* Process sys class right away */
188: PetscClassId sysclassid = PETSC_SMALLEST_CLASSID;
189: PetscInfoProcessClass("sys", 1, &sysclassid);
190: }
191: PetscInfoClassesSet = PETSC_TRUE;
192: return 0;
193: }
195: /*@C
196: PetscInfoGetClass - Indicates whether the provided classname is marked as a filter in PetscInfo() as set by PetscInfoSetClasses()
198: Not Collective
200: Input Parameter:
201: . classname - Name of the class to search for
203: Output Parameter:
204: . found - PetscBool indicating whether the classname was found
206: Notes:
207: Use PetscObjectGetName() to retrieve an appropriate classname
209: Level: developer
211: .seealso: PetscInfo(), PetscInfoSetClasses(), PetscInfoSetFromOptions(), PetscObjectGetName()
212: @*/
213: PetscErrorCode PetscInfoGetClass(const char *classname, PetscBool *found)
214: {
215: PetscInt idx;
218: PetscEListFind(PetscInfoNumClasses, (const char *const *) PetscInfoClassnames, classname ? classname : "sys", &idx, found);
219: PetscInfoClassesLocked = PETSC_TRUE;
220: return 0;
221: }
223: /*@
224: PetscInfoGetInfo - Returns the current state of several important flags for PetscInfo()
226: Not Collective
228: Output Parameters:
229: + infoEnabled - PETSC_TRUE if PetscInfoAllow(PETSC_TRUE) has been called
230: . classesSet - PETSC_TRUE if the list of classes to filter for has been set
231: . exclude - PETSC_TRUE if the class filtering for PetscInfo() is inverted
232: . locked - PETSC_TRUE if the list of classes to filter for has been locked
233: - commSelfFlag - Enum indicating whether PetscInfo() will print for communicators of size 1, any size != 1, or all
234: communicators
236: Notes:
237: Initially commSelfFlag = PETSC_INFO_COMM_ALL
239: Level: developer
241: .seealso: PetscInfo(), PetscInfoAllow(), PetscInfoSetFilterCommSelf, PetscInfoSetFromOptions()
242: @*/
243: PetscErrorCode PetscInfoGetInfo(PetscBool *infoEnabled, PetscBool *classesSet, PetscBool *exclude, PetscBool *locked, PetscInfoCommFlag *commSelfFlag)
244: {
245: if (infoEnabled) *infoEnabled = PetscLogPrintInfo;
246: if (classesSet) *classesSet = PetscInfoClassesSet;
247: if (exclude) *exclude = PetscInfoInvertClasses;
248: if (locked) *locked = PetscInfoClassesLocked;
249: if (commSelfFlag) *commSelfFlag = PetscInfoCommFilter;
250: return 0;
251: }
253: /*@C
254: PetscInfoProcessClass - Activates or deactivates a class based on the filtering status of PetscInfo()
256: Not Collective
258: Input Parameters:
259: + classname - Name of the class to activate/deactivate PetscInfo() for
260: . numClassID - Number of entries in classIDs
261: - classIDs - Array containing all of the PetscClassids associated with classname
263: Level: developer
265: .seealso: PetscInfo(), PetscInfoActivateClass(), PetscInfoDeactivateClass(), PetscInfoSetFromOptions()
266: @*/
267: PetscErrorCode PetscInfoProcessClass(const char classname[], PetscInt numClassID, PetscClassId classIDs[])
268: {
269: PetscInt i;
270: PetscBool enabled, exclude, found, opt, pkg;
271: char logList[256];
274: PetscInfoGetInfo(&enabled, NULL, &exclude, NULL, NULL);
275: /* -info_exclude is DEPRECATED */
276: PetscOptionsGetString(NULL,NULL,"-info_exclude",logList,sizeof(logList),&opt);
277: if (opt) {
278: PetscStrInList(classname,logList,',',&pkg);
279: if (pkg) {
280: for (i = 0; i < numClassID; ++i) {
281: PetscInfoDeactivateClass(classIDs[i]);
282: }
283: }
284: }
285: PetscInfoGetClass(classname, &found);
286: if ((found && exclude) || (!found && !exclude)) {
287: if (PetscInfoNumClasses > 0) {
288: /* Check if -info was called empty */
289: for (i = 0; i < numClassID; ++i) {
290: PetscInfoDeactivateClass(classIDs[i]);
291: }
292: }
293: } else {
294: for (i = 0; i < numClassID; ++i) {
295: PetscInfoActivateClass(classIDs[i]);
296: }
297: }
298: return 0;
299: }
301: /*@
302: PetscInfoSetFilterCommSelf - Sets PetscInfoCommFlag enum to determine communicator filtering for PetscInfo()
304: Not Collective
306: Input Parameter:
307: . commSelfFlag - Enum value indicating method with which to filter PetscInfo() based on the size of the communicator of the object calling PetscInfo()
309: Level: advanced
311: .seealso: PetscInfo(), PetscInfoGetInfo()
312: @*/
313: PetscErrorCode PetscInfoSetFilterCommSelf(PetscInfoCommFlag commSelfFlag)
314: {
315: PetscInfoCommFilter = commSelfFlag;
316: return 0;
317: }
319: /*@
320: PetscInfoSetFromOptions - Configure PetscInfo() using command line options, enabling or disabling various calls to PetscInfo()
322: Not Collective
324: Input Parameter:
325: . options - Options database, use NULL for default global database
327: Options Database Keys:
328: . -info [filename][:[~]<list,of,classnames>[:[~]self]] - specify which informative messages are printed, See PetscInfo().
330: Notes:
331: This function is called automatically during PetscInitialize() so users usually do not need to call it themselves.
333: Level: advanced
335: .seealso: PetscInfo(), PetscInfoAllow(), PetscInfoSetFile(), PetscInfoSetClasses(), PetscInfoSetFilterCommSelf(), PetscInfoDestroy()
336: @*/
337: PetscErrorCode PetscInfoSetFromOptions(PetscOptions options)
338: {
339: char optstring[PETSC_MAX_PATH_LEN], *loc0_ = NULL, *loc1_ = NULL, *loc2_ = NULL;
340: char **loc1_array = NULL;
341: PetscBool set, loc1_invert = PETSC_FALSE, loc2_invert = PETSC_FALSE, foundSelf = PETSC_FALSE;
342: size_t size_loc0_ = 0, size_loc1_ = 0, size_loc2_ = 0;
343: int nLoc1_ = 0;
344: PetscInfoCommFlag commSelfFlag = PETSC_INFO_COMM_ALL;
346: PetscOptionsDeprecated_Private(NULL,"-info_exclude", NULL, "3.13", "Use -info instead");
347: PetscOptionsGetString(options, NULL, "-info", optstring, sizeof(optstring), &set);
348: if (set) {
349: PetscInfoClassesSet = PETSC_TRUE;
350: PetscInfoAllow(PETSC_TRUE);
351: PetscStrallocpy(optstring,&loc0_);
352: PetscStrchr(loc0_,':',&loc1_);
353: if (loc1_) {
354: *loc1_++ = 0;
355: if (*loc1_ == '~') {
356: loc1_invert = PETSC_TRUE;
357: ++loc1_;
358: }
359: PetscStrchr(loc1_,':',&loc2_);
360: }
361: if (loc2_) {
362: *loc2_++ = 0;
363: if (*loc2_ == '~') {
364: loc2_invert = PETSC_TRUE;
365: ++loc2_;
366: }
367: }
368: PetscStrlen(loc0_, &size_loc0_);
369: PetscStrlen(loc1_, &size_loc1_);
370: PetscStrlen(loc2_, &size_loc2_);
371: if (size_loc1_) {
372: PetscStrtolower(loc1_);
373: PetscStrToArray(loc1_, ',', &nLoc1_, &loc1_array);
374: }
375: if (size_loc2_) {
376: PetscStrtolower(loc2_);
377: PetscStrcmp("self", loc2_, &foundSelf);
378: if (foundSelf) {
379: if (loc2_invert) {
380: commSelfFlag = PETSC_INFO_COMM_NO_SELF;
381: } else {
382: commSelfFlag = PETSC_INFO_COMM_ONLY_SELF;
383: }
384: }
385: }
386: PetscInfoSetFile(size_loc0_ ? loc0_ : NULL, "w");
387: PetscInfoSetClasses(loc1_invert, (PetscInt) nLoc1_, (const char *const *) loc1_array);
388: PetscInfoSetFilterCommSelf(commSelfFlag);
389: PetscStrToArrayDestroy(nLoc1_, loc1_array);
390: PetscFree(loc0_);
391: }
392: return 0;
393: }
395: /*@
396: PetscInfoDestroy - Destroys and resets internal PetscInfo() data structures.
398: Not Collective
400: Notes:
401: This is automatically called in PetscFinalize(). Useful for changing filters mid-program, or culling subsequent
402: PetscInfo() calls down the line.
404: Level: developer
406: .seealso: PetscInfo(), PetscInfoSetFromOptions()
407: @*/
408: PetscErrorCode PetscInfoDestroy(void)
409: {
410: int err;
411: size_t i;
413: PetscInfoAllow(PETSC_FALSE);
414: PetscStrNArrayDestroy(PetscInfoNumClasses, &PetscInfoClassnames);
415: err = fflush(PetscInfoFile);
417: if (PetscInfoFilename) {
418: PetscFClose(MPI_COMM_SELF, PetscInfoFile);
419: }
420: PetscFree(PetscInfoFilename);
421: for (i=0; i<sizeof(PetscInfoFlags)/sizeof(PetscInfoFlags[0]); i++) PetscInfoFlags[i] = 1;
422: PetscInfoClassesLocked = PETSC_FALSE;
423: PetscInfoInvertClasses = PETSC_FALSE;
424: PetscInfoClassesSet = PETSC_FALSE;
425: PetscInfoNumClasses = -1;
426: PetscInfoCommFilter = PETSC_INFO_COMM_ALL;
427: return 0;
428: }
430: /*@
431: PetscInfoDeactivateClass - Deactivates PetscInfo() messages for a PETSc object class.
433: Not Collective
435: Input Parameter:
436: . classid - The object class, e.g., MAT_CLASSID, SNES_CLASSID, etc.
438: Notes:
439: One can pass 0 to deactivate all messages that are not associated with an object.
441: Level: developer
443: .seealso: PetscInfoActivateClass(), PetscInfo(), PetscInfoAllow(), PetscInfoSetFromOptions()
444: @*/
445: PetscErrorCode PetscInfoDeactivateClass(PetscClassId classid)
446: {
447: if (!classid) classid = PETSC_SMALLEST_CLASSID;
448: PetscInfoFlags[classid - PETSC_SMALLEST_CLASSID] = 0;
449: return 0;
450: }
452: /*@
453: PetscInfoActivateClass - Activates PetscInfo() messages for a PETSc object class.
455: Not Collective
457: Input Parameter:
458: . classid - The object class, e.g., MAT_CLASSID, SNES_CLASSID, etc.
460: Notes:
461: One can pass 0 to activate all messages that are not associated with an object.
463: Level: developer
465: .seealso: PetscInfoDeactivateClass(), PetscInfo(), PetscInfoAllow(), PetscInfoSetFromOptions()
466: @*/
467: PetscErrorCode PetscInfoActivateClass(PetscClassId classid)
468: {
469: if (!classid) classid = PETSC_SMALLEST_CLASSID;
470: PetscInfoFlags[classid - PETSC_SMALLEST_CLASSID] = 1;
471: return 0;
472: }
474: /*
475: If the option -history was used, then all printed PetscInfo()
476: messages are also printed to the history file, called by default
477: .petschistory in ones home directory.
478: */
479: PETSC_INTERN FILE *petsc_history;
481: /*MC
482: PetscInfo - Logs informative data
484: Synopsis:
485: #include <petscsys.h>
486: PetscErrorCode PetscInfo(PetscObject obj, const char message[])
487: PetscErrorCode PetscInfo(PetscObject obj, const char formatmessage[],arg1)
488: PetscErrorCode PetscInfo(PetscObject obj, const char formatmessage[],arg1,arg2)
489: ...
491: Collective on obj
493: Input Parameters:
494: + obj - object most closely associated with the logging statement or NULL
495: . message - logging message
496: . formatmessage - logging message using standard "printf" format
497: - arg1, arg2, ... - arguments of the format
499: Notes:
500: PetscInfo() prints only from the first processor in the communicator of obj.
501: If obj is NULL, the PETSC_COMM_SELF communicator is used, i.e. every rank of PETSC_COMM_WORLD prints the message.
503: Extent of the printed messages can be controlled using the option database key -info as follows.
505: $ -info [filename][:[~]<list,of,classnames>[:[~]self]]
507: No filename means standard output PETSC_STDOUT is used.
509: The optional <list,of,classnames> is a comma separated list of enabled classes, e.g. vec,mat,ksp.
510: If this list is not specified, all classes are enabled.
511: Prepending the list with ~ means inverted selection, i.e. all classes except the listed are enabled.
512: A special classname sys relates to PetscInfo() with obj being NULL.
514: The optional self keyword specifies that PetscInfo() is enabled only for communicator size = 1 (e.g. PETSC_COMM_SELF), i.e. only PetscInfo() calls which print from every rank of PETSC_COMM_WORLD are enabled.
515: By contrast, ~self means that PetscInfo() is enabled only for communicator size > 1 (e.g. PETSC_COMM_WORLD), i.e. those PetscInfo() calls which print from every rank of PETSC_COMM_WORLD are disabled.
517: All classname/self matching is case insensitive. Filename is case sensitive.
519: Example of Usage:
520: $ Mat A;
521: $ PetscInt alpha;
522: $ ...
523: $ PetscInfo(A,"Matrix uses parameter alpha=%" PetscInt_FMT "\n",alpha);
525: Options Examples:
526: Each call of the form
527: $ PetscInfo(obj, msg);
528: $ PetscInfo(obj, msg, arg1);
529: $ PetscInfo(obj, msg, arg1, arg2);
530: is evaluated as follows.
531: $ -info or -info :: prints msg to PETSC_STDOUT, for any obj regardless class or communicator
532: $ -info :mat:self prints msg to PETSC_STDOUT only if class of obj is Mat, and its communicator has size = 1
533: $ -info myInfoFileName:~vec:~self prints msg to file named myInfoFileName, only if the obj's class is NULL or other than Vec, and obj's communicator has size > 1
534: $ -info :sys prints to PETSC_STDOUT only if obj is NULL
535: Note that
536: $ -info :sys:~self
537: deactivates all info messages because sys means obj = NULL which implies PETSC_COMM_SELF but ~self filters out everything on PETSC_COMM_SELF.
539: Fortran Note:
540: This function does not take the obj argument, there is only the PetscInfo()
541: version, not PetscInfo() etc.
543: Level: intermediate
545: .seealso: PetscInfoAllow(), PetscInfoSetFromOptions()
546: M*/
547: PetscErrorCode PetscInfo_Private(const char func[],PetscObject obj, const char message[], ...)
548: {
549: va_list Argp;
550: PetscMPIInt rank = 0,urank,size = 1;
551: PetscClassId classid;
552: PetscBool enabled = PETSC_FALSE, oldflag;
553: char string[8*1024];
554: size_t fullLength,len;
555: int err;
558: classid = obj ? obj->classid : PETSC_SMALLEST_CLASSID;
559: PetscInfoEnabled(classid, &enabled);
560: if (!enabled) return 0;
562: if (obj) {
563: MPI_Comm_rank(obj->comm, &rank);
564: MPI_Comm_size(obj->comm, &size);
565: }
566: /* rank > 0 always jumps out */
567: if (rank) return 0;
568: if (!PetscInfoCommFilter && (size < 2)) {
569: /* If no self printing is allowed, and size too small get out */
570: return 0;
571: } else if ((PetscInfoCommFilter == PETSC_INFO_COMM_ONLY_SELF) && (size > 1)) {
572: /* If ONLY self printing, and size too big, get out */
573: return 0;
574: }
575: /* Mute info messages within this function */
576: oldflag = PetscLogPrintInfo; PetscLogPrintInfo = PETSC_FALSE;
577: MPI_Comm_rank(MPI_COMM_WORLD, &urank);
578: va_start(Argp, message);
579: sprintf(string, "[%d] %s(): ",urank,func);
580: PetscStrlen(string, &len);
581: PetscVSNPrintf(string+len, 8*1024-len,message,&fullLength, Argp);
582: PetscFPrintf(PETSC_COMM_SELF,PetscInfoFile, "%s", string);
583: err = fflush(PetscInfoFile);
585: if (petsc_history) {
586: va_start(Argp, message);
587: (*PetscVFPrintf)(petsc_history, message, Argp);
588: }
589: va_end(Argp);
590: PetscLogPrintInfo = oldflag;
591: return 0;
592: }