home *** CD-ROM | disk | FTP | other *** search
/ CD/PC Actual 14 / CDACTUAL.iso / cdactual / demobin / share / program / c / ZBC.ZIP / ZBC.C
Encoding:
C/C++ Source or Header  |  1980-01-01  |  8.6 KB  |  386 lines

  1. From mnetor!utzoo!utgpu!water!watnot!watmath!clyde!rutgers!mit-eddie!uw-beaver!tektronix!reed!psu-cs!omepd!omssw1!argent!flamer Mon Apr 13 20:01:30 EDT 1987
  2. Article 4284 of net.sources:
  3. Path: lsuc!mnetor!utzoo!utgpu!water!watnot!watmath!clyde!rutgers!mit-eddie!uw-beaver!tektronix!reed!psu-cs!omepd!omssw1!argent!flamer
  4. >From: flamer@argent.UUCP
  5. Newsgroups: net.sources
  6. Subject: ZIP codes in bar code
  7. Message-ID: <12@argent.UUCP>
  8. Date: 2 Apr 87 20:47:23 GMT
  9. Reply-To: flamer@aahz.UUCP (Jim Trethewey @mithril)
  10. Distribution: world
  11. Organization: Bitbus Engineering, Intel Corp., Hillsboro, OR
  12. Lines: 370
  13.  
  14.  
  15. /*
  16.  *   Program:      zbc.c   ZIP Bar Code
  17.  *   Author:       Jim Trethewey
  18.  *                 Intel OMS BITBUS Engineering.
  19.  *   Version:      V1.0.
  20.  *   Date:         02-Apr-1987.
  21.  *   Language:     Microsoft C 286.
  22.  *   Ppn:          ..!argent!mithril!flamer  [or]  flamer@mithril.hf.intel.COM
  23.  *
  24.  *   Description:
  25.  *
  26.  *      This program will provide you interest for about two minutes.
  27.  *      It was an exercise in reverse engineering the little bar codes
  28.  *      that the U.S. Postal Service puts at the bottom of envelopes,
  29.  *      and this program was written primarily for hack value.
  30.  *
  31.  *      This program takes one of four options, summarized as follows:
  32.  *
  33.  *         1.  Encode in Bar Code the given ZIP.
  34.  *                zbc -e <zip>
  35.  *                zbc -e <zip+4>
  36.  *         2.  Encode in Bar Code the given ZIP, and be verbose about it.
  37.  *                zbc -ev <zip>
  38.  *                zbc -ev <zip+4>
  39.  *         3.  Decode the given Bar Code to ZIP.
  40.  *                zbc -d "<barcode>"
  41.  *         4.  Decode the given Bar Code to ZIP, and be verbose about it.
  42.  *                zbc -dv "<barcode>"
  43.  *
  44.  *      Because the two functions are inverses, you can do neat things like:
  45.  *
  46.  *         zbc -d "`zbc -e 94601`"
  47.  *
  48.  *   Modification History:
  49.  *
  50.  *      M000   02-Apr-1987   flamer           Original issue.
  51.  *
  52.  */
  53.  
  54. #include <stdio.h>
  55. #include <ctype.h>
  56.  
  57. #ifdef UCB
  58. #define strchr          index
  59. #endif
  60. extern char *strchr ();
  61.  
  62. /*
  63.  *   The definitions for ZERO and ONE indicate which characters are
  64.  *   used and accepted for the bar code bits.  They can be anything
  65.  *   you want so long as they're different.  Depending upon your
  66.  *   CRT or printer, '.' is best for ZERO and '|' for ONE.
  67.  */
  68.  
  69. #ifdef LASERJET
  70. #define ZERO            ','
  71. #define ONE             '|'
  72. #else
  73. #define ZERO            '.'
  74. #define ONE             '|'
  75. #endif
  76.  
  77. #define FALSE           0
  78. #define TRUE            !FALSE
  79. #define SAME            0
  80.  
  81.  
  82. char zbc [10][6] = {
  83.    { ONE,  ONE,  ZERO, ZERO, ZERO, 0 },   /* 0 = "||..." */
  84.    { ZERO, ZERO, ZERO, ONE,  ONE,  0 },   /* 1 = "...||" */
  85.    { ZERO, ZERO, ONE,  ZERO, ONE,  0 },   /* 2 = "..|.|" */
  86.    { ZERO, ZERO, ONE,  ONE,  ZERO, 0 },   /* 3 = "..||." */
  87.    { ZERO, ONE,  ZERO, ZERO, ONE,  0 },   /* 4 = ".|..|" */
  88.    { ZERO, ONE,  ZERO, ONE,  ZERO, 0 },   /* 5 = ".|.|." */
  89.    { ZERO, ONE,  ONE,  ZERO, ZERO, 0 },   /* 6 = ".||.." */
  90.    { ONE,  ZERO, ZERO, ZERO, ONE,  0 },   /* 7 = "|...|" */
  91.    { ONE,  ZERO, ZERO, ONE,  ZERO, 0 },   /* 8 = "|..|." */
  92.    { ONE,  ZERO, ONE,  ZERO, ZERO, 0 }    /* 9 = "|.|.." */
  93. };
  94.  
  95. int encode_flag, decode_flag, verbose_flag;
  96. int valid_flag;
  97.  
  98.  
  99. value_of (bit)
  100.    
  101.    char bit;
  102.  
  103.    {
  104.       if (bit == ZERO)
  105.      {
  106.         return (0);
  107.      }
  108.       else if (bit == ONE)
  109.      {
  110.         return (1);
  111.      }
  112.       else
  113.      {
  114.         return (-1);
  115.      }
  116.    }
  117.  
  118. put_start_bit (position)
  119.  
  120.    char *position;
  121.  
  122.    {
  123.       *position = (ONE);
  124.    }
  125.  
  126. put_stop_bit (position)
  127.  
  128.    char *position;
  129.  
  130.    {
  131.       *position = (ONE);
  132.    }
  133.  
  134. char *ztob (zipcode)
  135.  
  136.    char *zipcode;
  137.  
  138.    {
  139.       static char barcode [100];
  140.       char *ch_p;
  141.       char *out_p;
  142.       int checksum;
  143.       int i, j;
  144.  
  145.       checksum = 0;
  146.       out_p = &barcode [0];
  147.       put_start_bit (out_p++);
  148.       for (ch_p = zipcode, i = 0; ch_p && *ch_p; ch_p++, i++)
  149.      {
  150.         if (isdigit (*ch_p))
  151.            {
  152.           strcpy (out_p, zbc [*ch_p - '0']);
  153.           out_p += 5;
  154.           checksum += (*ch_p - '0');
  155.            }
  156.      }
  157.       checksum = 10 - checksum % 10;
  158.       strcpy (out_p, zbc [checksum]);
  159.       out_p += 5;
  160.       put_stop_bit (out_p++);
  161.       *out_p = '\0';
  162.       return (barcode);
  163.    }
  164.  
  165. char *btoz (barcode)
  166.  
  167.    char *barcode;
  168.  
  169.    {
  170.       static char zipcode [100];
  171.       char *ch_p;
  172.       char *out_p;
  173.       int i, j;
  174.       int checksum;
  175.       int expected_checksum;
  176.       int parity;
  177.       int found;
  178.       int digits_seen;
  179.       int digit_length;
  180.       int checksum_flag;
  181.       int error_flag;
  182.       int new_digit;
  183.  
  184.       error_flag = FALSE;
  185.       checksum = 0;
  186.       expected_checksum = -1;
  187.       out_p = &zipcode [0];
  188.       digits_seen = 0;
  189.       digit_length = (strlen (barcode) - 2) / 5;
  190.       for (ch_p = barcode, i = 0; ch_p && *ch_p; ch_p++, i++)
  191.      {
  192.         if (ch_p == barcode)   /* at the start bit */
  193.            {
  194.           if (*ch_p != ONE)
  195.              {
  196.             fprintf (stderr, "Invalid start bit.\n");
  197.              }
  198.           else if (verbose_flag)
  199.              {
  200.             *out_p++ = ('_');
  201.              }
  202.            }
  203.         else if (*(ch_p + 1) == 0)   /* at the stop bit */
  204.            {
  205.           if (checksum % 10 != 0)
  206.              {
  207.             fprintf (stderr, 
  208.                "Checksum error (actual = %d, expected = %d).\n", 
  209.                checksum % 10, expected_checksum);
  210.             if (error_flag == 0)
  211.                {
  212.                   fprintf (stderr, "Too many bit errors to fix.\n");
  213.                   fprintf (stderr, "Can't find position of error,");
  214.                   fprintf (stderr, " bad ZIP code returned.\n");
  215.                }
  216.              }
  217.           if (*ch_p != ONE)
  218.              {
  219.             fprintf (stderr, "Invalid stop bit.\n");
  220.              }
  221.           else
  222.              {
  223.             if (verbose_flag)
  224.                {
  225.                   *out_p++ = ('_');
  226.                }
  227.              }
  228.           if (error_flag > 1)
  229.              {
  230.             fprintf (stderr, "Too many bit errors to fix.\n");
  231.              }
  232.           else if (error_flag == 1)
  233.              {
  234.             new_digit = (10 - checksum % 10) % 10;
  235.             fprintf (stderr, "Correcting digit to a \"%d\".\n",
  236.                new_digit);
  237.             if (!checksum_flag || verbose_flag)
  238.                {
  239.                   *strchr (zipcode, '?') = new_digit + '0';
  240.                }
  241.             else
  242.                {
  243.                   *strchr (zipcode, '?') = '\0';
  244.                }
  245.              }
  246.            }
  247.         else   /* in the middle somewhere */
  248.            {
  249.           checksum_flag = (digits_seen == digit_length - 1);
  250.           if ((digits_seen == 5) && !checksum_flag)
  251.              {
  252.             *out_p++ = ('-');
  253.              }
  254.           found = FALSE;
  255.           for (j = 0; j < 10; j++)
  256.              {
  257.             if (strncmp (ch_p, zbc [j], 5) == SAME)
  258.                {
  259.                   found = TRUE;
  260.                   if (checksum_flag && verbose_flag)
  261.                  {
  262.                     *out_p++ = ('[');
  263.                  }
  264.                   if (!checksum_flag || verbose_flag)
  265.                  {
  266.                     *out_p++ = (j + '0');
  267.                  }
  268.                   if (checksum_flag)
  269.                  {
  270.                     expected_checksum = j;
  271.                  }
  272.                   if (checksum_flag && verbose_flag)
  273.                  {
  274.                     *out_p++ = (']');
  275.                  }
  276.                   break;
  277.                }
  278.              }
  279.           if (!found)
  280.              {
  281.             /*
  282.              *   Check parity.
  283.              */
  284.             parity = value_of (*ch_p) 
  285.                    + value_of (*(ch_p + 1))
  286.                    + value_of (*(ch_p + 2))
  287.                    + value_of (*(ch_p + 3))
  288.                    + value_of (*(ch_p + 4));
  289.             if (parity != 2)
  290.                {
  291.                   error_flag++;
  292.                   fprintf (stderr, 
  293.       "Parity error (actual = %d, expected = 2) in \"%5.5s\" at position %d.\n",
  294.                  parity, ch_p, digits_seen + 1);
  295.                   if (checksum_flag && verbose_flag)
  296.                  {
  297.                     *out_p++ = ('[');
  298.                  }
  299.                   *out_p++ = '?';
  300.                   if (checksum_flag && verbose_flag)
  301.                  {
  302.                     *out_p++ = (']');
  303.                  }
  304.                }
  305.              }
  306.           else
  307.              {
  308.             checksum += j;
  309.              }
  310.           digits_seen++;
  311.           ch_p += 4;
  312.            }
  313.      }
  314.       *out_p = '\0';
  315.       return (zipcode);
  316.    }
  317.  
  318.  
  319.  
  320. main (argc, argv)
  321.  
  322.    int argc;
  323.    char *argv [];
  324.  
  325.    {
  326.       /*
  327.        *   Check out the command line arguments.
  328.        */
  329.       valid_flag = FALSE;
  330.       encode_flag = FALSE;
  331.       decode_flag = FALSE;
  332.       verbose_flag = FALSE;
  333.       if (argc != 3)
  334.      {
  335.         valid_flag = FALSE;
  336.      }
  337.       else if (strncmp (argv [1], "-e", 2) == SAME)
  338.      {
  339.         valid_flag++;
  340.         encode_flag++;
  341.         if (argv [1][2] == 'v')
  342.            {
  343.           verbose_flag++;
  344.            }
  345.      }
  346.       else if (strncmp (argv [1], "-d", 2) == SAME)
  347.      {
  348.         valid_flag++;
  349.         decode_flag++;
  350.         if (argv [1][2] == 'v')
  351.            {
  352.           verbose_flag++;
  353.            }
  354.      }
  355.       if (!valid_flag)
  356.      {
  357. fprintf (stderr, 
  358.    "Usage: %s -e <zipcode>        Encode ZIPcode in bar code.\n",
  359.    argv [0]);
  360. fprintf (stderr, 
  361.    "       %s -ev <zipcode>       Encode ZIPcode in bar code verbosely.\n",
  362.    argv [0]);
  363. fprintf (stderr, 
  364.    "       %s -d \"<barcode>\"      Decode bar code to ZIPcode.\n", 
  365.    argv [0]);
  366. fprintf (stderr, 
  367.    "       %s -dv \"<barcode>\"     Decode bar code to ZIPcode verbosely.\n", 
  368.    argv [0]);
  369.         exit (1);
  370.      }
  371.  
  372.       /*
  373.        *   Do the requested conversion.
  374.        */
  375.       if (encode_flag)
  376.      {
  377.         printf ("%s\n", ztob (argv [2]));
  378.      }
  379.       else if (decode_flag)
  380.      {
  381.         printf ("%s\n", btoz (argv [2]));
  382.      }
  383.    }
  384.  
  385.