~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Tina4/src/file/dicom.old/CTN/condition.c

Version: ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2           Copyright (C) 1993, 1994, RSNA and Washington University
  3 
  4           The software and supporting documentation for the Radiological
  5           Society of North America (RSNA) 1993, 1994 Digital Imaging and
  6           Communications in Medicine (DICOM) Demonstration were developed
  7           at the
  8                   Electronic Radiology Laboratory
  9                   Mallinckrodt Institute of Radiology
 10                   Washington University School of Medicine
 11                   510 S. Kingshighway Blvd.
 12                   St. Louis, MO 63110
 13           as part of the 1993, 1994 DICOM Central Test Node project for, and
 14           under contract with, the Radiological Society of North America.
 15 
 16           THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND NEITHER RSNA NOR
 17           WASHINGTON UNIVERSITY MAKE ANY WARRANTY ABOUT THE SOFTWARE, ITS
 18           PERFORMANCE, ITS MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
 19           USE, FREEDOM FROM ANY COMPUTER DISEASES OR ITS CONFORMITY TO ANY
 20           SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND PERFORMANCE OF
 21           THE SOFTWARE IS WITH THE USER.
 22 
 23           Copyright of the software and supporting documentation is
 24           jointly owned by RSNA and Washington University, and free access
 25           is hereby granted as a license to use this software, copy this
 26           software and prepare derivative works based upon this software.
 27           However, any distribution of this software source code or
 28           supporting documentation or derivative works (source code and
 29           supporting documentation) must include the three paragraphs of
 30           the copyright notice.
 31 */
 32 /* Copyright marker.  Copyright will be inserted above.  Do not remove */
 33 /*
 34 ** @$=@$=@$=
 35 */
 36 /*
 37 **                              DICOM 93
 38 **                   Electronic Radiology Laboratory
 39 **                 Mallinckrodt Institute of Radiology
 40 **              Washington University School of Medicine
 41 **
 42 ** Module Name(s):      COND_PushCondition
 43 **                      COND_ExtractConditions
 44 **                      COND_TopCondition
 45 **                      COND_PopCondition
 46 **                      COND_DumpConditions
 47 **                      COND_CopyText
 48 **                      COND_WriteConditions
 49 ** Author, Date:        Stephen M. Moore, 15-Apr-93
 50 ** Intent:              This file contains functions implementing a simple
 51 **                      error facility.  It was first written by Stephen Moore
 52 **                      (smm@wuerl.wustl.edu) to support PACS development at
 53 **                      the Mallinckrodt Institute of Radiology.  The function
 54 **                      names have been modified to have a slightly more
 55 **                      generic name, but the basic model and concepts are
 56 **                      the same.
 57 **
 58 **                      The condition package maintains a stack of
 59 **                      <condition, message> pairs that callers can push or
 60 **                      pop.  When a routine returns an abnormal value, it
 61 **                      should push a condition onto the stack so that the
 62 **                      caller can examine the value at a later time.  Nested
 63 **                      routines may push a number of conditions onto the
 64 **                      stack providing more detailed information about why
 65 **                      a routine did not return normally.
 66 **
 67 **                      The stack is maintained as a simple stack array.  If
 68 **                      it overflows, we dump the stack to stdout and reset it.
 69 **
 70 ** Last Update:         $Author: smm $, $Date: 1998/07/31 19:13:32 $
 71 ** Source File:         $RCSfile: condition.c,v $
 72 ** Revision:            $Revision: 1.17 $
 73 ** Status:              $State: Exp $
 74 */
 75 
 76 static char rcsid[] = "$Revision: 1.17 $ $RCSfile: condition.c,v $";
 77 
 78 
 79 /*
 80 **
 81 **  INCLUDE FILES
 82 **
 83 */
 84 
 85 #include <stdio.h>
 86 #include <string.h>
 87 #include <stdarg.h>
 88 #include "dicom.h"
 89 #include "lst.h"
 90 #include "condition.h"
 91 #include "ctnthread.h"
 92 
 93 typedef struct {
 94     CONDITION statusCode;
 95     char statusText[256];
 96 }   EDB;
 97 
 98 #define MAXEDB  100
 99 
100 static int stackPtr = -1;
101 static EDB EDBStack[MAXEDB];
102 static void (*ErrorCallback) () = NULL;
103 static void dumpstack(FILE * fp);
104 
105 
106 /*
107 **++
108 **  FUNCTIONAL DESCRIPTION:
109 **
110 **      COND_PushCondition
111 **      This routine is used to log a condition on the stack.  The user
112 **      passes an error code (currently uninterpreted), a format string
113 **      and optional format arguments.  We use the vsprintf routine to
114 **      interpret the user's format string and arguments, and we place the
115 **      error condition and resultant string on the stack.
116 **
117 **  FORMAL PARAMETERS:
118 **
119 **      code:
120 **          The condition code of the error/warning.
121 **
122 **      controlString:
123 **          format string for vsprintf statement
124 **
125 **      [varargs]:
126 **          variable arguments to be used with controlString
127 **
128 **  RETURN VALUE:
129 **
130 **      code (as passed in by the user)
131 **
132 **  SIDE EFFECTS:
133 **
134 **      Places a new entry on the stack.  If the stack
135 **      fills up, drop the last condition.
136 **      Calls a user-established callback just before return.
137 **
138 */
139 CONDITION
140 COND_PushCondition(CONDITION cond, char *controlString,...)
141 {
142     va_list
143         args;
144     char
145         buffer[1024];
146 
147 /*lint -e40 -e50 */
148     va_start(args, controlString);
149     if (controlString == NULL)
150         controlString = "NULL Control string passedto PushCondition";
151     (void) vsprintf(buffer, controlString, args);
152     va_end(args);
153 /*lint +e40 +e50 */
154 
155     stackPtr++;
156     EDBStack[stackPtr].statusCode = cond;
157     buffer[256] = '\0';
158 
159 #ifdef CTN_USE_THREADS
160     if (THR_ObtainMutex(FAC_COND) != THR_NORMAL) {
161         fprintf(stderr, "COND_PushCondition unable to obtain mutex\n");
162         return cond;
163     }
164 #endif
165 
166     (void) strcpy(EDBStack[stackPtr].statusText, buffer);
167     if (ErrorCallback != NULL)
168         ErrorCallback(EDBStack[stackPtr].statusCode,
169                       EDBStack[stackPtr].statusText);
170 
171     if (stackPtr >= MAXEDB - 2) {
172         dumpstack(stderr);
173         fprintf(stderr, "CONDITION Stack overflow\n");
174         stackPtr = 0;
175     }
176 #ifdef CTN_USE_THREADS
177     if (THR_ReleaseMutex(FAC_COND) != THR_NORMAL) {
178         fprintf(stderr, "COND_PushCondition unable to release mutex, exiting\n");
179         exit(1);
180     }
181 #endif
182 
183     return cond;
184 
185 }
186 
187 
188 /*
189 **++
190 **  FUNCTIONAL DESCRIPTION:
191 **
192 **  COND_ExtractConditions
193 **      This routine walks through the stack and passes the condition
194 **      codes and text back to the user.  The caller supplies a
195 **      callback routine.  We start at the top of the stack and
196 **      call the user's callback for each message on the stack.  The
197 **      user can terminate the process at any time by returning
198 **      a zero from his callback.
199 **
200 **  FORMAL PARAMETERS:
201 **
202 **      callback:
203 **          User routine to call for each message on the stack.
204 **
205 **  RETURN VALUE:
206 **
207 **      1
208 **
209 **  SIDE EFFECTS:
210 **
211 **
212 **  DESIGN:
213 **
214 **      None
215 **--
216 */
217 
218 CONDITION
219 COND_ExtractConditions(CTNBOOLEAN(*callback) ())
220 {
221     int
222         index,
223         returnflag;
224 
225 #ifdef CTN_USE_THREADS
226     if (THR_ObtainMutex(FAC_COND) != THR_NORMAL) {
227         fprintf(stderr, "COND_ExtractConditions unable to obtain mutex, exiting\n");
228         exit(1);
229     }
230 #endif
231 
232     for (index = stackPtr, returnflag = 1; index >= 0 && returnflag != 0;
233          index--) {
234         returnflag = callback(EDBStack[index].statusCode,
235                               EDBStack[index].statusText);
236     }
237 
238 #ifdef CTN_USE_THREADS
239     if (THR_ReleaseMutex(FAC_COND) != THR_NORMAL) {
240         fprintf(stderr, "COND_ExtractConditions unable to release mutex, exiting\n");
241         exit(1);
242     }
243 #endif
244     return COND_NORMAL;
245 }
246 
247 /*
248 **++
249 **  FUNCTIONAL DESCRIPTION:
250 **
251 **      COND_TopCondition
252 **      This routine is used to look at the top condition message on
253 **      the stack.  The user passes pointers to areas to place
254 **      the error message.  The function also returns the code
255 **      for the top error message.  If the stack is empty, the
256 **      success code (0) is returned.
257 **
258 **  FORMAL PARAMETERS:
259 **
260 **      code:
261 **          Pointer to the user's area to hold the error code
262 **
263 **      text
264 **          Pointer to the user's area to hold the error text
265 **
266 **      maxlength
267 **          Maximum buffer length in the user's text area
268 **
269 **  RETURN VALUE:
270 **
271 **      top error code on the stack
272 **
273 **  SIDE EFFECTS:
274 **
275 **
276 */
277 
278 CONDITION
279 COND_TopCondition(CONDITION * code, char *text, unsigned long maxlength)
280 {
281     CONDITION rtnValue;
282 #ifdef CTN_USE_THREADS
283     if (THR_ObtainMutex(FAC_COND) != THR_NORMAL) {
284         fprintf(stderr, "COND_TopCondition unable to obtain mutex, exiting\n");
285         exit(1);
286     }
287 #endif
288 
289     if (stackPtr >= 0) {
290         *code = EDBStack[stackPtr].statusCode;
291         (void) strncpy(text, EDBStack[stackPtr].statusText, maxlength - 1);
292         text[maxlength - 1] = '\0';
293         rtnValue = EDBStack[stackPtr].statusCode;
294     } else {
295         *code = COND_NORMAL;
296         *text = '\0';
297         rtnValue = COND_NORMAL;
298     }
299 
300 #ifdef CTN_USE_THREADS
301     if (THR_ReleaseMutex(FAC_COND) != THR_NORMAL) {
302         fprintf(stderr, "COND_TopCondition unable to release mutex, exiting\n");
303         exit(1);
304     }
305 #endif
306     return rtnValue;
307 }
308 
309 /*
310 **++
311 **  FUNCTIONAL DESCRIPTION:
312 **
313 **      COND_PopCondition
314 **      This routine pops one or all conditions off the stack.
315 **      The user passes a flag which indicates the operation.
316 **      After the clear, the current top error code is returned.
317 **      If the stack is empty at this point, the success code (0)
318 **      is returned.
319 **
320 **  FORMAL PARAMETERS:
321 **
322 **      clearstack:
323 **          Flag which indicates if the entire stack is to be cleared.
324 **              0           Just pop the top error
325 **              non zero    Clear the entire stack
326 **
327 **  RETURN VALUE:
328 **
329 **      The new top error code.  0 if the stack is empty
330 **
331 **  SIDE EFFECTS:
332 **
333 **
334 */
335 
336 CONDITION
337 COND_PopCondition(CTNBOOLEAN clearstack)
338 {
339     CONDITION
340         value;
341 
342 #ifdef CTN_USE_THREADS
343     if (THR_ObtainMutex(FAC_COND) != THR_NORMAL) {
344         fprintf(stderr, "COND_PopCondition unable to obtain mutex, exiting\n");
345         exit(1);
346     }
347 #endif
348 
349     if (stackPtr >= 0)
350         value = EDBStack[stackPtr].statusCode;
351     else
352         value = COND_NORMAL;
353 
354     if (clearstack) {
355         stackPtr = -1;
356     } else if (stackPtr <= 0) {
357         stackPtr = -1;
358     } else {
359         stackPtr--;
360     }
361 
362 #ifdef CTN_USE_THREADS
363     if (THR_ReleaseMutex(FAC_COND) != THR_NORMAL) {
364         fprintf(stderr, "COND_PopCondition unable to release mutex, exiting\n");
365         exit(1);
366     }
367 #endif
368 
369     return value;
370 }
371 
372 /*
373 **++
374 **  FUNCTIONAL DESCRIPTION:
375 **
376 **      COND_EstablishCallback
377 **      Establishes a callback routine to be called whenever a
378 **      new condition is placed on the stack.  There is no stack
379 **      mechanism for these callbacks, so each new callback routine
380 **      completely supersedes the previous one.
381 **
382 **  FORMAL PARAMETERS:
383 **
384 **      callback:
385 **          The new callback routine.  If NULL, this will
386 **          disable callbacks.
387 **
388 **  RETURN VALUE:
389 **
390 **      0
391 **
392 **  SIDE EFFECTS:
393 **
394 **
395 */
396 
397 CONDITION
398 COND_EstablishCallback(void (*callback) ())
399 {
400 #ifdef CTN_USE_THREADS
401     if (THR_ObtainMutex(FAC_COND) != THR_NORMAL) {
402         fprintf(stderr, "COND_EstablishCallback unable to obtain mutex, exiting\n");
403         exit(1);
404     }
405 #endif
406 
407     ErrorCallback = callback;
408 
409 #ifdef CTN_USE_THREADS
410     if (THR_ReleaseMutex(FAC_COND) != THR_NORMAL) {
411         fprintf(stderr, "COND_EstablishCallback unable to release mutex, exiting\n");
412         exit(1);
413     }
414 #endif
415     return COND_NORMAL;
416 }
417 
418 
419 /* function name
420 **
421 ** Purpose:
422 **      Describe the purpose of the function
423 **
424 ** Parameter Dictionary:
425 **      Define the parameters to the function
426 **
427 ** Return Values:
428 **
429 ** Algorithm:
430 **      Description of the algorithm (optional) and any other notes.
431 */
432 
433 void
434 COND_DumpConditions(void)
435 {
436 #ifdef CTN_USE_THREADS
437     if (THR_ObtainMutex(FAC_COND) != THR_NORMAL) {
438         fprintf(stderr, "COND_DumpConditions unable to obtain mutex\n");
439         return;
440     }
441 #endif
442 
443     dumpstack(stderr);
444     stackPtr = -1;
445 
446 #ifdef CTN_USE_THREADS
447     if (THR_ReleaseMutex(FAC_COND) != THR_NORMAL) {
448         fprintf(stderr, "COND_DumpConditions unable to release mutex\n");
449         return;
450     }
451 #endif
452 }
453 
454 static void
455 dumpstack(FILE * lfp)
456 {
457     int
458         index;
459 
460     for (index = 0; index <= stackPtr; index++)
461         fprintf(lfp, "%8x %s\n", EDBStack[index].statusCode,
462                 EDBStack[index].statusText);
463 }
464 
465 /*
466 **++
467 **  FUNCTIONAL DESCRIPTION:
468 **
469 **      COND_CopyText
470 **      This function copies as much text as possible from the
471 **      condition stack and places it in the caller's buffer.
472 **
473 **  FORMAL PARAMETERS:
474 **
475 **      txt
476 **          Pointer to the user's area to hold the error text
477 **
478 **      length
479 **          Maximum buffer length in the user's text area
480 **
481 **  RETURN VALUE:
482 **
483 **      none
484 **
485 **  SIDE EFFECTS:
486 **
487 */
488 
489 void
490 COND_CopyText(char *txt, size_t length)
491 {
492     size_t i;
493     int j;
494 
495     txt[0] = '\0';
496 
497 #ifdef CTN_USE_THREADS
498     if (THR_ObtainMutex(FAC_COND) != THR_NORMAL) {
499         fprintf(stderr, "COND_CopyText unable to obtain mutex\n");
500         return;
501     }
502 #endif
503 
504     j = stackPtr;
505     while (length > 2 && j >= 0) {
506         i = strlen(EDBStack[j].statusText);
507         if (i > length)
508             i = length - 2;
509         strncpy(txt, EDBStack[j].statusText, i);
510         txt[i++] = '\n';
511         txt[i] = '\0';
512         length -= i;
513         txt += i;
514         j--;
515     }
516 
517 #ifdef CTN_USE_THREADS
518     if (THR_ReleaseMutex(FAC_COND) != THR_NORMAL) {
519         fprintf(stderr, "COND_CopyText unable to release mutex, exiting\n");
520         exit(1);
521     }
522 #endif
523 }
524 
525 /* COND_WriteConditions
526 **
527 ** Purpose:
528 **      Write the condition stack to a file, ie stdout or stderr.
529 **
530 ** Parameter Dictionary:
531 **      File * lfp, the file to which the stack is written.
532 **
533 ** Return Values:
534 **
535 ** Algorithm:
536 **      A reiteration of the COND_DumpConditions except this takes an argument.
537 */
538 
539 void
540 COND_WriteConditions(FILE * lfp)
541 {
542 #ifdef CTN_USE_THREADS
543     if (THR_ObtainMutex(FAC_COND) != THR_NORMAL) {
544         fprintf(stderr, "COND_WriteConditions unable to obtain mutex\n");
545         return;
546     }
547 #endif
548     dumpstack(lfp);
549     stackPtr = -1;
550 
551 #ifdef CTN_USE_THREADS
552     if (THR_ReleaseMutex(FAC_COND) != THR_NORMAL) {
553         fprintf(stderr, "COND_WriteConditions unable to release mutex\n");
554         return;
555     }
556 #endif
557 }
558 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.