home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / nums / nums.c < prev   
Encoding:
C/C++ Source or Header  |  1986-11-30  |  4.8 KB  |  232 lines

  1. /*
  2.  * Print a list of numbers.
  3.  * See the manual entry for details.
  4.  */
  5.  
  6. #include <stdio.h>
  7.  
  8.  
  9. /*********************************************************************
  10.  * MISCELLANEOUS GLOBAL VALUES:
  11.  */
  12.  
  13. #define    PROC                /* null; easy to find procs */
  14. #define    FALSE    0
  15. #define    TRUE    1
  16. #define    CHNULL    ('\0')
  17. #define    CPNULL    ((char *) NULL)
  18. #define    REG    register
  19.  
  20. char *usage[] = {
  21.     "usage: %s [-lr] [-s size] [-w width] value [value2]",
  22.     "-l print all one one line (default: one number per line)",
  23.     "-r print numbers in random order",
  24.     "-s set step size (increment, default = 1)",
  25.     "-w print numbers in fields of given width (default: no padding)",
  26.     "Prints numbers from 1 to value, or value to value2",
  27.     CPNULL,
  28. };
  29.  
  30. char    *myname;            /* how program was invoked    */
  31.  
  32. int    lflag = FALSE;            /* -l (all one line) option    */
  33. int    rflag = FALSE;            /* -r (randomize) option    */
  34.  
  35. int    step  = 1;            /* value from -s option        */
  36. int    width = 0;            /* value from -w option        */
  37.  
  38.  
  39. /************************************************************************
  40.  * M A I N
  41.  */
  42.  
  43. PROC main (argc, argv)
  44.     int    argc;
  45.     char    **argv;
  46. {
  47. extern    int    optind;            /* from getopt()    */
  48. extern    char    *optarg;        /* from getopt()    */
  49. REG    int    option;            /* option "letter"    */
  50. REG    int    value1 = 1;        /* first value        */
  51. REG    int    value2;            /* second value        */
  52.     char    format [20];        /* for printing numbers    */
  53. REG    char    sep;            /* leading separator    */
  54.  
  55. /*
  56.  * PARSE ARGUMENTS:
  57.  */
  58.  
  59.     myname = *argv;
  60.  
  61.     while ((option = getopt (argc, argv, "lrs:w:")) != EOF)
  62.     {
  63.         switch (option)
  64.         {
  65.         case 'l':    lflag = TRUE;    break;
  66.         case 'r':    rflag = TRUE;    break;
  67.  
  68.         case 's':    step  = atoi (optarg);  break;
  69.         case 'w':    width = atoi (optarg);  break;
  70.  
  71.         default:    Usage();
  72.         }
  73.     }
  74.  
  75.     argc -= optind;            /* skip options    */
  76.     argv += optind;
  77.  
  78. /*
  79.  * MORE ARGUMENT CHECKS:
  80.  */
  81.  
  82.     if (argc == 1)
  83.     {
  84.         value2 = atoi (argv [0]);
  85.     }
  86.     else if (argc == 2)
  87.     {
  88.         value1 = atoi (argv [0]);
  89.         value2 = atoi (argv [1]);
  90.     }
  91.     else
  92.     {
  93.         Usage();
  94.     }
  95.  
  96.     if (step == 0)
  97.         Error ("step size cannot be zero");
  98.  
  99. /*
  100.  * FINISH INITIALIZING:
  101.  */
  102.  
  103.     if (((step < 0) && (value1 < value2))
  104.      || ((step > 0) && (value1 > value2)))    /* harmless if values equal */
  105.     {
  106.         step = -step;            /* invert */
  107.     }
  108.  
  109.     sprintf (format, (width ? "%%%dd" : "%%d"), width);
  110.     sep = lflag ? ' ' : '\n';
  111.  
  112. /*
  113.  * PRINT NUMBERS:
  114.  */
  115.  
  116.     if (rflag)
  117.         PrintRandom (value1, value2, format, sep);
  118.     else
  119.     {
  120.         REG int forward = (step > 0);
  121.  
  122.         printf (format, value1);
  123.  
  124.         while (forward ? ((value1 += step) <= value2)
  125.                : ((value1 += step) >= value2))
  126.         {
  127.         putchar (sep);
  128.         printf (format, value1);
  129.         }
  130.     }
  131.  
  132.     putchar ('\n');        /* finish last line */
  133.     exit (0);
  134.  
  135. } /* main */
  136.  
  137.  
  138. /************************************************************************
  139.  * P R I N T   R A N D O M
  140.  *
  141.  * Given value limits, print format, leading separator, and global step size
  142.  * (positive or negative matching value limits), print numbers in random
  143.  * order.  Don't print the trailing newline for the last line.
  144.  */
  145.  
  146. PROC PrintRandom (value1, value2, format, sep)
  147. REG    int    value1;        /* base limit    */
  148.     int    value2;        /* end limit    */
  149. REG    char    *format;    /* how to print    */
  150. REG    char    sep;        /* leading char    */
  151. {
  152. REG    int    remain = (value2 - value1) / step;
  153. REG    int    count  = remain + 1;    /* total to print    */
  154. REG    int    *done;            /* this number printed?    */
  155. REG    int    which;            /* index in done[]    */
  156.  
  157. /*
  158.  * INITIALIZE:
  159.  */
  160.  
  161.     if ((done = (int *) calloc (count, sizeof (int))) == (int *) NULL)
  162.         Error ("calloc %d integers failed", count);
  163.  
  164.     srand48 (time ((int *) 0) + getpid() + getuid() + getgid());
  165.  
  166.     done [which = (lrand48() % count)] = TRUE;
  167.     printf (format, value1 + (which * step));    /* first one */
  168.  
  169. /*
  170.  * PRINT RANDOM NUMBERS:
  171.  */
  172.  
  173.     while (remain-- > 0)            /* more to do */
  174.     {
  175.         which = lrand48() % count;        /* not *precisely* random */
  176.  
  177.         while (done [which])        /* already taken */
  178.         {
  179.         if (--which < 0)        /* wrap around */
  180.             which = count - 1;
  181.         }
  182.  
  183.         done [which] = TRUE;
  184.         putchar (sep);
  185.         printf (format, value1 + (which * step));
  186.     }
  187.  
  188. } /* PrintRandom */
  189.  
  190.  
  191. /************************************************************************
  192.  * U S A G E
  193.  *
  194.  * Print usage messages (char *usage[]) to stderr and exit nonzero.
  195.  * Each message is followed by a newline.
  196.  */
  197.  
  198. PROC Usage()
  199. {
  200. REG    int    which = 0;        /* current line */
  201.  
  202.     while (usage [which] != CPNULL)
  203.     {
  204.         fprintf (stderr, usage [which++], myname);
  205.         putc ('\n', stderr);
  206.     }
  207.  
  208.     exit (1);
  209.  
  210. } /* Usage */
  211.  
  212.  
  213. /************************************************************************
  214.  * E R R O R
  215.  *
  216.  * Print an error message to stderr and exit nonzero.  Message is preceded
  217.  * by "<myname>: " using global char *myname, and followed by a newline.
  218.  */
  219.  
  220. /* VARARGS */
  221. PROC Error (message, arg1, arg2, arg3, arg4)
  222.     char    *message;
  223.     long    arg1, arg2, arg3, arg4;
  224. {
  225.     fprintf (stderr, "%s: ", myname);
  226.     fprintf (stderr, message, arg1, arg2, arg3, arg4);
  227.     putc ('\n', stderr);
  228.  
  229.     exit (1);
  230.  
  231. } /* Error */
  232.