home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / disks / disk429.lzh / Dr / source / whichever.c < prev   
C/C++ Source or Header  |  1991-01-10  |  4KB  |  186 lines

  1. /*
  2. This command, "Whichever", takes a list of filenames (or anything) in its
  3. standard input, picks one line of that input at random, and substitutes that
  4. line into its argument line where it finds "[]", and executes the resulting
  5. string as a command.  Use it whenever you want to use a program on a random
  6. file or anything.  I use it to pick a random 8svx sound to use for a beep. 
  7. Like this:    Whichever < beepses Installbeep []
  8. where beepses contains a list of 8svx filenames, one per line.  You might
  9. want to pipe the output of some directory lister program into the input.
  10.  
  11. Limitations:  It sucks the entire input into memory, so keep it small.  It
  12. has a preset limit to the number of lines it can read (see the #define for
  13. LINELIMIT) and will stop reading when it reaches this limit.  It ignores
  14. blank lines and lines that would produce a command longer than CMDLIMIT
  15. characters.  CMDLIMIT must be 255 or less due to limitations of the dos
  16. Execute() function.
  17.  
  18. By Paul Kienitz 7/5/90 public domain.  Last update 12/30/90.
  19. */
  20.  
  21. #define LINELIMIT 1000
  22. #define CMDLIMIT 255
  23. #define IBSIZE 2000
  24.  
  25. #include <libraries/dos.h>
  26. #include <Paul.h>
  27.  
  28.  
  29. /* maybe I'll make it pure later but not today. */
  30.  
  31. str lineys[LINELIMIT];
  32. short tot = 0;                /* number of lines in lineys */
  33.  
  34. char inputbuf[IBSIZE];            /* used by Read1 */
  35. short ibpos = IBSIZE;
  36. short ibfill = IBSIZE;
  37.  
  38.  
  39.  
  40. /* This here is an allocation efficiencizer which assumes that no
  41. space is freed between allocations.  The size is in bytes.  The result is
  42. shortword aligned.  I happened to have this in another program. */
  43.  
  44. str slablist = null;
  45. #define slabsize 4000
  46. ushort slabused = slabsize;
  47.  
  48.  
  49.  
  50. adr Shal(size) ushort size;
  51. {
  52.     adr t;
  53.     void Spew();
  54.  
  55.     if (size & 1) size++;
  56.     if (size > slabsize - slabused) {
  57.     if (!(t = Alloc(slabsize))) {
  58.         Spew("Whichever: ran out of memory!\n");
  59.         return null;
  60.     }
  61.     *((str *) t) = slablist;   /* chain old onto new */
  62.     slabused = 4;
  63.     slablist = t;
  64.     }
  65.     t = slablist + slabused;
  66.     slabused += size;
  67.     return (t);
  68. }
  69.  
  70.  
  71.  
  72. void FreeShalls()
  73. {
  74.     register str t;
  75.     while (slablist) {
  76.     t = slablist;
  77.     slablist = *((str *) slablist);
  78.     FreeMem(t, (long) slabsize);
  79.     }
  80. }
  81.  
  82.  
  83.  
  84. void Spew(s) str s;
  85. {
  86.     register BPTR o = Output();
  87.     if (o) Write(o, s, (long) strlen(s));
  88. }
  89.  
  90.  
  91.  
  92. /* buffered read function; returns true when eof, result put in *c */
  93. bool Read1(c) char *c;
  94. {
  95.     if (ibpos >= ibfill) {
  96.     ibfill = Read(Input(), inputbuf, (long) IBSIZE);
  97.     ibpos = 0;
  98.     if (ibfill <= 0) return true;        /* eof */
  99.     }
  100.     *c = inputbuf[ibpos++];
  101.     return false;
  102. }
  103.  
  104.  
  105.  
  106. void ReadLines(maxsub) short maxsub;
  107. {
  108.     bool eof;
  109.     char linebuf[CMDLIMIT + 2];
  110.     short lbpos;
  111.     char c;
  112.  
  113.     do {
  114.     lbpos = 0;
  115.     while (!(eof = Read1(&c)) && c != '\n' && c != '\f')
  116.         if (lbpos <= maxsub)
  117.         linebuf[lbpos++] = c;
  118.     linebuf[lbpos] = 0;
  119.     if (!(lineys[tot] = Shal(lbpos + 1)))
  120.         break;
  121.     if (lbpos > 0 && lbpos <= maxsub) {
  122.         strcpy(lineys[tot], linebuf);
  123.         tot++;
  124.     }
  125.     } while (tot < LINELIMIT && !eof);
  126. }
  127.  
  128.  
  129.  
  130. bool Stubbitute(oldlen, old, new, insert) short oldlen; str old, new, insert;
  131. {
  132.     register str p = old;
  133.     register short i = oldlen;
  134.  
  135.     while (--i)
  136.     if (*(p++) == '[' && *p == ']')
  137.         break;
  138.     if (!i) {
  139.     Spew("Whichever:  Command arg must mark where to substitute with [].\n");
  140.     return true;
  141.     }
  142.     while (old < p)
  143.     *(new++) = *(old++);
  144.     new--;                    /* un-copy the '[' */
  145.     while (*insert)
  146.     *(new++) = *(insert++);
  147.     old++;                    /* skip the marker */
  148.     if (!i)
  149.     return false;
  150.     while (--i)
  151.     *(new++) = *(old++);
  152.     *new = 0;
  153.     return false;
  154. }
  155.  
  156.  
  157.  
  158. long _main(alen, aptr) long alen; str aptr;
  159. {
  160.     char command[CMDLIMIT + 1];
  161.     long date[3];
  162.     str which;
  163.     short len = alen;
  164.  
  165.     if (!Input()) {
  166.     Spew("Whichever:  No input file!\n");
  167.     return 20;
  168.     }
  169.     if (aptr[len - 1] == '\n')            /* usually true */
  170.     len--;
  171.     ReadLines(CMDLIMIT + 2 - len);
  172.     if (!tot) {
  173.     Spew("Whichever:  no usable lines in input file!\n");
  174.     FreeShalls();
  175.     return 10;
  176.     }
  177.     DateStamp((adr) date);
  178.     srand((int) (date[0] ^ date[1] ^ date[2]));
  179.     which = lineys[rand() % tot];
  180.     if (Stubbitute(len, aptr, command, which))
  181.     return 10;
  182.     Execute(command, 0, Output());
  183.     FreeShalls();
  184.     return 0;
  185. }
  186.