home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1990 / 02 / mcmahon.lst < prev    next >
File List  |  1989-12-26  |  9KB  |  299 lines

  1. _MULTIPLEXING ERROR CODES_
  2. by William J. McMahon
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. /* ----------------------------------------------------------------------
  8.     ERR_CODE.C Written by: William J. McMahon
  9.     This module contains the functions used to manipulate error codes.
  10.     Global Functions Defined Herein:
  11.     err_combine(), err_format(), err_print() 
  12. ----------------------------------------------------------------------- */
  13. #include <stdio.h>
  14. #include <limits.h>
  15.  
  16. #define ERR_BUMPER      10
  17. #define ERR_THRESHOLD   (UINT_MAX/ERR_BUMPER)      /* ... for overflow. */
  18.  
  19. /* ----- Local Functions Defined Herein: ----- */
  20. unsigned err_pop();
  21. void     err_push();
  22.  
  23. #ifdef TEST             /* -------------- Test Harness ---------------- */
  24.  
  25. #define FIRST_ARG   0   /* Varies with compiler (0 or 1).               */
  26. #define NCODES      32
  27.  
  28. main(argc, argv)
  29.     int argc;
  30.     char *argv[];
  31. {
  32.     unsigned err_combine();
  33.     void     err_format();
  34.     void     err_print();
  35.  
  36.     unsigned err_code;
  37.     int      adder = 1;
  38.     int      i;
  39.  
  40.     if (argc > FIRST_ARG)
  41.     /* Override default starting code. */
  42.     adder = atoi(argv[FIRST_ARG]);
  43.  
  44.     err_code = adder;
  45.     printf("\nInput should be a mirror image of output.\n");
  46.     printf("\n Input sequence: %d", err_code);
  47.     for (i = 0; i < NCODES; ++i)        /* Build an error code, using   */
  48.     {                                   /* multiple err_combine() calls.*/
  49.     ++adder;
  50.     if (adder >= ERR_BUMPER)
  51.         adder = 1;
  52.     printf("%d", adder);            /* Output RAW codes.            */
  53.     err_code = err_combine(err_code, adder);
  54.     }
  55.  
  56.     printf("\nOutput sequence: ");
  57.     err_print(stdout, err_code);
  58. }
  59. #endif                  
  60. /* ----------------------------------------------------------------------
  61.     ERR_COMBINE Combines an new individual error code with an existing one.
  62.     Returns: Combined error code.
  63. ----------------------------------------------------------------------- */
  64. unsigned err_combine(
  65.     unsigned original,      /* Original error code.                     */
  66.     unsigned to_add)        /* Code to be added to it.                  */
  67. {
  68.     if ((original % ERR_BUMPER) == 0)   /* Some special codes are not   */
  69.     return (original);              /* changed.                     */
  70.  
  71.     to_add %= ERR_BUMPER;               /* Make sure its in range.      */
  72.  
  73.     if (original > ERR_THRESHOLD)
  74.     {   /* Prevent overflow. */
  75.     err_push(original);
  76.     original = 0;
  77.     }
  78.  
  79.     return (original * ERR_BUMPER + to_add);
  80. }
  81.  
  82. /* ----------------------------------------------------------------------
  83.     ERR_FORMAT Decode and format an error code (and any overflow) 
  84.     into a string. Returns: Nothing.
  85. ----------------------------------------------------------------------- */
  86. void err_format(
  87.     char     *buffer,       /* Buffer to put formated code into.        */
  88.     unsigned  err_code)     /* Error code to format.                    */
  89. {
  90.     char *p;
  91.     p = buffer;
  92.     while (err_code)
  93.     {
  94.     do
  95.     {
  96.         sprintf(buffer, "%d", err_code % ERR_BUMPER);
  97.         buffer += strlen(buffer);
  98.     }
  99.     while ((err_code /= ERR_BUMPER) > 0);
  100.     err_code = err_pop();
  101.     }
  102. }
  103. /* ----------------------------------------------------------------------
  104.     ERR_PRINT  Decode and output an error code (and any overflow).
  105.     Returns: Nothing.
  106. ----------------------------------------------------------------------- */
  107. void err_print(
  108.     FILE     *stream,       /* Streem to output formated code to.       */
  109.     unsigned  err_code)     /* Error code to output.                    */
  110. {
  111.     while (err_code)
  112.     {
  113.     do
  114.     {
  115.         fprintf(stream, "%d", err_code % ERR_BUMPER);
  116.     }
  117.     while ((err_code /= ERR_BUMPER) > 0);
  118.     err_code = err_pop();
  119.     }
  120. }
  121.  
  122. /* ================= Local stack for overflow codes. ================== */
  123. #define MAX_OVERFLOWS 10
  124.  
  125. static unsigned err_stack[MAX_OVERFLOWS];
  126. static unsigned err_stack_top = 0;
  127.  
  128. /* ----------------------------------------------------------------------
  129.     ERR_POP  Returns: Combined error code of most recent overflow, 0 if none.
  130. ----------------------------------------------------------------------- */
  131. static unsigned err_pop()
  132. {
  133.     if (err_stack_top <= 0)
  134.     return (0);
  135.  
  136.     --err_stack_top;
  137.     return (err_stack[err_stack_top]);
  138. }
  139.  
  140. /* ----------------------------------------------------------------------
  141.     ERR_PUSH  Push error code onto stack.
  142.     Returns: Nothing.
  143. ----------------------------------------------------------------------- */
  144. static void err_push(
  145.     unsigned err_code)       /* Error code to save.                     */
  146. {
  147.     if (err_stack_top < MAX_OVERFLOWS)
  148.     {
  149.     err_stack[err_stack_top] = err_code;
  150.     ++err_stack_top;
  151.     }
  152. }
  153.  
  154.  
  155.  
  156. Examplσ 1║ Combininτ code≤ anΣ returninτ t∩ thσ nex⌠ level
  157.  
  158.                unsigned mid_level(char *parm)
  159.                {
  160.                     unsigned err, low_level();
  161.                     if (parm == NULL)
  162.                          return (1);
  163.                     ...
  164.                     err = low_level(i, j);
  165.                     if (err)
  166.                          return (ERR_COMBINE(err, 3));
  167.                     ...
  168.                     return (0);
  169.                }
  170.  
  171.                unsigned low_level(int x, int y)
  172.                {
  173.                     if (x > 0)
  174.                          return (1);                
  175.                     if (x > y)
  176.                          return (2);
  177.                     ...
  178.                     return (0)
  179.                }
  180.  
  181.  
  182. Examplσ 2║ Defininτ ß simplσ ERR_COMBIN┼ macro
  183.  
  184.  
  185.      #define ERR_BUMPER  10
  186.      #define ERR_COMBINE(orig, to_add)   ((orig * ERR_BUMPER) + to_add)
  187.  
  188.  
  189. Examplσ 3║ Thi≤ functioε wil∞ decodσ thσ combineΣ erro≥ codσ anΣ ì
  190. displa∙ thσ individua∞ codes
  191.  
  192.           void err_print(FILE *stream, unsigned err_code)
  193.           {
  194.                do
  195.                {
  196.                     fprintf(stream, "%d", (err_code % ERR_BUMPER));
  197.                }
  198.                while ((err_code /= ERR_BUMPER) > 0);
  199.           }
  200.  
  201. Examplσ 4: Code produced once function failure has been located
  202.  
  203.           main()
  204.           {
  205.                unsigned err, function();
  206.                ...
  207.                err = function();
  208.                if (err)
  209.                     abort(ERR_COMBINE(err, 3));
  210.                ...
  211.           }
  212.           void abort(unsigned err_code);
  213.           {
  214.                fprintf(stderr, "\n ERROR:");
  215.                err_printf(stderr, err_code);
  216.                exit (err_code);
  217.           }
  218.  
  219.  
  220. Examplσ 5║ Usinτ ß functioε insteaΣ oµ ß macro
  221.  
  222.                unsigned err_combine(unsigned original, unsigned to_add)
  223.                {
  224.                     if (original > UINT_MAX / ERR_BUMPER) 
  225.                     {    /* UINT_MAX is in limits.h */
  226.                          err_push(original);
  227.                          original = 0;          
  228.                     }
  229.                     return (original * ERR_BUMPER + to_add);
  230.                }
  231.  
  232.                #define MAX_OVERFLOWS    10     
  233.                static unsigned err_stack[MAX_OVERFLOWS];
  234.                static unsigned err_stack_top = 0;
  235.  
  236.                unsigned err_pop()
  237.                {
  238.                     if (err_stack_top <= 0)
  239.                          return (0);
  240.                     
  241.                     --err_stack_top;
  242.  
  243.                     return (err_stack[err_stack_top]);
  244.                }
  245.  
  246.                void err_push(unsigned err_code)
  247.                {
  248.                    if (err_stack_top < MAX_OVERFLOWS)
  249.                    {
  250.                          err_stack[err_stack_top] = err;  
  251.                          ++err_stack_top;
  252.                     }
  253.                }
  254.                
  255.  
  256.  
  257.  
  258. Examplσ 6║ Changinτ ERR_PRIN╘ t∩ displa∙ thσ entirσ erro≥ code
  259.  
  260.           void err_print(FILE *stream, unsigned in err_code)
  261.           {
  262.                 while (err_code)
  263.                 {
  264.                     do
  265.                     {
  266.                          fprintf(stream, "%d", (err % ERR_BUMPER));
  267.                     }
  268.                     while ((err_code /= ERR_BUMPER) > 0);
  269.                     err_code = err_pop();
  270.                }         
  271.           }
  272.  
  273.  
  274.  
  275. Examplσ 7║ Expandinτ thσ abor⌠ function
  276.  
  277.           void abort(err)
  278.           {
  279.                switch (err)
  280.                {
  281.                case DISK_SPACE_ERROR:
  282.                     printf("\n Not enough disk space to run program");
  283.                     break;
  284.                case MEMORY_ERROR:
  285.                     printf("\n Not enough memory to run program.");
  286.                     break;
  287.                case USER_ABORT:
  288.                     printf(stderr, "\n Program aborted by user.");
  289.                     break;
  290.                default:
  291.                     printf("\n Unexpected error: %d ", err);
  292.                     printf("\n Please record this error number,");
  293.                     printf("\n and call technical support at");
  294.                     printf("\n 1-800-555-1234.");
  295.                break;
  296.                }
  297.                exit(err);
  298.           }
  299.