home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 145.lha / sonixpeek.c < prev    next >
C/C++ Source or Header  |  1986-11-21  |  9KB  |  411 lines

  1. /*
  2.  * SONIXPEEK.C             (C) Copyright Eddy Carroll, 1988
  3.  *
  4.  * Scans one or more Aegis Sonix files building a list of unique
  5.  * instruments used within those files. At the end, a list of the
  6.  * instruments found is printed (can be redirected to a file if
  7.  * desired).
  8.  *
  9.  * Usage: SonixPeek {-i} {-n} {-ofile} {-xdirectory} filename
  10.  *
  11.  * If filename is a sonix file, then only that file is scanned. If
  12.  * filename is a directory, then all the files in that directory which
  13.  * contain Sonix files are scanned.
  14.  * 
  15.  * If the -i (interactive) flag is present, then after each file is
  16.  * found, the user is asked whether it should be included or not when
  17.  * building the list of instruments.
  18.  *
  19.  * If the -o flag is present, then the list of instruments is stored
  20.  * in the specified file, rather than being displayed on the screen.
  21.  *
  22.  * If the -x flag is present, then the output is given in the form
  23.  * of an executable file which consists of a line for each instrument
  24.  * found of the form COPY <instrument> TO <directory>, where <directory>
  25.  * is given immediately after the -x switch.
  26.  *
  27.  * If the -n flag is present, then the list of instruments found in each
  28.  * file, when a directory is being searched, is not printed.
  29.  *
  30.  * Note: Compile with Aztec C V3.20 or later. Should also compile with
  31.  *       Lattice C.
  32.  */
  33.  
  34. #include <libraries/dos.h>
  35.  
  36. #define EOL      '\012'
  37. #define EOF      '\037'
  38. #define TAB      '\011'
  39. #define CR       '\015'
  40.  
  41. #define MAXINS 1000   /* Only 200 instruments allowed */
  42. #define MAXFILENUM 200 /* No more than 200 scores allowed */
  43.  
  44. /* IFF defines */
  45.  
  46. #define MakeID(a,b,c,d) (long)((long)(a)<<24 | (long)(b)<<16 | (c)<<8 | (d))
  47. #define FORM MakeID('F','O','R','M')
  48. #define SMUS MakeID('S','M','U','S')
  49. #define NAME MakeID('N','A','M','E')
  50. #define SNX1 MakeID('S','N','X','1')
  51. #define INS1 MakeID('I','N','S','1')
  52. #define TRAK MakeID('T','R','A','K')
  53.  
  54. #define roundup(a) ((a + 1L) & ~1L)
  55.  
  56.  
  57. int interactive = 0  ;  /* TRUE if interactive selection of files            */
  58. int multi = 0;            /* TRUE if a directory specified instead of file     */
  59. int supress = 0;        /* TRUE if listing of instruments is supressed        */
  60. char *dirname = NULL;    /* Directory to copy to for -x option                */
  61. char *rname = NULL;        /* Real filename of directory or single file        */
  62. char *suffix[] =
  63.     {".ss", ".instr"};    /* For creating 'copy' batch file                    */
  64.  
  65. LONG Examine(), ExNext(), Read(), Write();
  66. LONG Lock(), CurrentDir();
  67.  
  68. char *malloc();
  69. int numins = 1;                /* Current number of instruments    */
  70. char *ins[MAXINS];            /* Room for 1000 instruments        */
  71. int numfiles = 0;            /* Current number of files             */
  72. char *files[MAXFILENUM];    /* Room for 200 files                */
  73.  
  74. struct FileInfoBlock *stdin, *stdout; /* File pointers */
  75. struct FileInfoBlock *Open(), *Output(), *Input(), *infile, *outfile;
  76. struct FileInfoBlock myfib;
  77.  
  78.  
  79. /*
  80.  * Output string to file
  81.  *
  82.  */
  83.  
  84. void fprint(f, s)
  85. struct FileInfoBlock *f;
  86. char *s;
  87. {
  88.     char *p;
  89.     for (p = s; *p; p++)
  90.         ;
  91.     Write(f, s, (long)(p - s));
  92. }
  93.  
  94.  
  95. /*
  96.  * Output string to stdout
  97.  *
  98.  */
  99.  
  100. void print(s)
  101. char *s;
  102. {
  103.     fprint(stdout,s);
  104. }
  105.  
  106.  
  107. /*
  108.  * Abort program due to error
  109.  *
  110.  */
  111.  
  112. void abort(string,code)
  113. char *string;
  114. int code;
  115. {
  116.     print(string);
  117.     if (outfile != stdout && outfile)
  118.         Close(outfile);
  119.     exit(code);
  120. }
  121.  
  122. #define P print
  123.  
  124. /*
  125.  * Prints help message to standard output
  126.  *
  127.  */
  128. void help()
  129. {
  130. P("\nSonixPeek Instrument Lister (C) Eddy Carroll, March 1988\n\n");
  131. P("Usage: SonixPeek {-i} {-n} {-ofile} {-xdirectory} filename\n\n");
  132. P("Filename is the Aegis Sonix file for which the instruments are to\n");
  133. P("be listed. If it is a directory, then all the Sonix files in\n");
  134. P("that directory are checked, and a sorted list of the instruments\n");
  135. P("contained in all of them is prepared. The flags operate as follows:\n\n");
  136. P(" -i  For a directory search, get user to verify whether or not\n");
  137. P("     to include each Sonix file (interactively).\n\n");
  138. P(" -n  Don't list instruments as they are found (for directories only).\n\n");
  139. P(" -o  Redirect sorted output to named file.\n\n");
  140. P(" -x  Format output as an execute file which will copy all the\n");
  141. P("     instruments found to the named directory\n\n");
  142. }
  143.  
  144.  
  145. /*** Start of actual program ***/
  146.  
  147. main(argc, argv)
  148. int argc;
  149. char *argv[];
  150. {
  151.  
  152.     void addinstrument(), skip(), dumpins();
  153.     char ch, charin(), ch1, ch2;
  154.     int argc2, i;
  155.     LONG mylock, oldlock;
  156.     char *fname, nextfile[40], *p;
  157.  
  158.     stdin = Input();
  159.     outfile = stdout = Output();
  160.     infile = 0;
  161.  
  162.     /* Scan command line for possible switches */
  163.  
  164.     for (argc2 = 1; argc2 < argc && *argv[argc2] == '-'; argc2++) {
  165.         switch (tolower(*(argv[argc2]+1))) {
  166.  
  167.         case 'i':    interactive = 1;
  168.                     break;
  169.  
  170.         case 'n':   supress = 1;
  171.                     break;
  172.  
  173.         case 'o':    if ((outfile = Open(argv[argc2]+2,MODE_NEWFILE)) == 0)
  174.                         abort("Can't open output file\n", 20);
  175.                     break;
  176.  
  177.         case 'x':    dirname = argv[argc2] + 2;
  178.                     break;
  179.  
  180.         default:    print("Unknown option ");
  181.                     print(argv[argc2]);
  182.                     print("ignored\n");
  183.                     break;
  184.         }
  185.     }
  186.  
  187.     /* If missing filename, or filename == '?', print instructions */
  188.  
  189.     if (argc2 != (argc-1) || *argv[argc2] == '?') {
  190.         help();
  191.         abort(NULL,0);
  192.     }
  193.  
  194.     fname = argv[argc2];
  195.  
  196.     if ((mylock = Lock(fname,ACCESS_READ)) == 0L)
  197.         abort("Can't open input file.\n",20);
  198.  
  199.     Examine(mylock,&myfib);
  200.     rname = malloc(strlen(myfib.fib_FileName)+1);
  201.     strcpy(rname,myfib.fib_FileName); /* Save filename for later */
  202.  
  203.     if (myfib.fib_DirEntryType > 0L) {
  204.         multi = 1;
  205.         oldlock = CurrentDir(mylock);
  206.         while (ExNext(mylock, &myfib))
  207.             if (myfib.fib_DirEntryType < 0L)
  208.                 scan(&(myfib.fib_FileName)); 
  209.         oldlock = CurrentDir(oldlock);
  210.     } else
  211.         scan(fname);
  212.  
  213.     dumpins();
  214.  
  215.     if (outfile != stdout)
  216.         Close(outfile);
  217.  
  218.     UnLock(mylock);
  219.     exit(0);
  220. }
  221.  
  222. /*
  223.  * Scans filename for instruments. If found, they are added to the
  224.  * list of instruments already in memory. Returns 0 for success, -1
  225.  * if invalid file.
  226.  *
  227.  */
  228.  
  229. int scan(filename)
  230. char *filename;
  231. {
  232.     LONG header[3];
  233.     char instr[50];
  234.     char response[50];
  235.  
  236.     if ((infile = Open(filename,MODE_OLDFILE)) == 0L) {
  237.         print("Can't open file ");
  238.         print(filename);
  239.         print(" for input\n");
  240.         return(-1);
  241.     }
  242.  
  243.     if (Read(infile,header,8L) != 8L || header[0] != FORM) {
  244.         Close(infile);
  245.         return(-1);
  246.     }
  247.  
  248.     if (Read(infile,header,4L) != 4L || header[0] != SMUS) {
  249.         Close(infile);
  250.         return(-1);
  251.     }
  252.  
  253.     if (interactive) {
  254.         print("Include file ");
  255.         print(filename);
  256.         print(" (CR = no)? ");
  257.         Read(stdin, response, 50L);
  258.         if (tolower(*response) != 'y')
  259.             return(-1);
  260.     } else if (multi && !supress) {
  261.         print("\nFile ");
  262.         print(filename);
  263.         print(":\n");
  264.     }
  265.  
  266.     files[numfiles] = malloc(strlen(filename) + 1);
  267.     strcpy(files[numfiles++], filename);
  268.  
  269.     while (Read(infile,header,8L) == 8L) {
  270.         if (header[0] != INS1) {
  271.             skip(infile,header[1]);
  272.         } else {
  273.             skip(infile,4L); /* skip position of instrument parameter */
  274.             (void)Read(infile, instr, roundup(header[1]) - 4L);
  275.             instr[header[1] - 4L] = '\0';
  276.             addinstrument(instr);
  277.         }
  278.     }
  279.     Close(infile);
  280.     return(0);
  281. }
  282.  
  283. void skip(file,size)
  284. struct FileInfoBlock *file;
  285. LONG size;
  286. {
  287.     char s[256];
  288.     LONG len = 1L;
  289.     size = roundup(size);
  290.     while (size > 256L && len) {
  291.         len = Read(file, s, 256L);
  292.         size -= 256L;
  293.     }
  294.     (void)Read(file, s, size);
  295. }
  296.  
  297.  
  298. /*
  299.  * Adds instrument of length len into list of instruments, but only
  300.  * if its not already present in the list.
  301.  *
  302.  */
  303.  
  304. void addinstrument(instr)
  305. char *instr;
  306. {
  307.     int pos, i;
  308.     if (pos = matchins(instr)) {
  309.         for (i = numins++; i > pos; i--)
  310.             ins[i] = ins[i-1];
  311.         ins[pos] = malloc(strlen(instr)+1);
  312.         strcpy(ins[pos], instr);
  313.     }
  314.     if (multi && !supress) {
  315.         print("    ");
  316.         print(instr);
  317.         print("\n");
  318.     }
  319. }
  320.  
  321. /*
  322.  * Compares string p to string s, ignoring case of alpha chars.
  323.  * Returns -ve if p < s, 0 if p = s, +ve if p > s.
  324.  *
  325.  */
  326.  
  327. int mystrcmp(p,s)
  328. char *p, *s;
  329. {
  330.     while (*p && *s && tolower(*p) == tolower(*s))
  331.         p++, s++;
  332.     return(tolower(*p) - tolower(*s));
  333. }
  334.  
  335. /*
  336.  * Searches instrument array for a match with given instrument. 
  337.  * Returns 0 if found, else position in array to insert new element.
  338.  *
  339.  */
  340.  
  341. int matchins(instr)
  342. char *instr;
  343. {
  344.     int i, z;
  345.     char *p, *s;
  346.  
  347.     if (numins < 2)
  348.         return (1); /* Must be first entry */
  349.  
  350.     for (i = 1; i < numins; i++) {
  351.         if ((z = mystrcmp(instr, ins[i])) <= 0) {
  352.             if (z)
  353.                 return(i); /* If less, insert here */
  354.             else
  355.                 return(0); /* If equal, don't insert  */
  356.         }
  357.     }
  358.     return (i); /* Must be at end of list, so return last item */
  359. }
  360.  
  361. /*
  362.  * Dumps instrument list to outfile
  363.  *
  364.  */
  365.  
  366. void dumpins()
  367. {
  368.     int tofile, i, j;
  369.  
  370.     if (numins <= 1) {
  371.         print("No instruments found.\n");
  372.         return;
  373.     }
  374.  
  375.     if (numfiles == 0)
  376.         return;
  377.  
  378.     fprint(outfile,";\n; Sorted list of instruments\n");
  379.     fprint(outfile,   "; --------------------------\n;\n");
  380.     if (numfiles == 1) {
  381.         fprint(outfile, "; Taken from file ");
  382.         fprint(outfile, files[0]);
  383.         fprint(outfile, "\n");
  384.     } else {
  385.         fprint(outfile,"; Taken from these files:\n;\n");
  386.         for (i = 0; i < numfiles; i++) {
  387.             fprint(outfile, ";     ");
  388.             fprint(outfile,files[i]);
  389.             fprint(outfile,"\n");
  390.         }
  391.     }
  392.     fprint(outfile,";\n");
  393.  
  394.     for (i = 1; i < numins; i++) {
  395.         for (j = (dirname != 0); j >= 0; j--) {
  396.             if (dirname) {
  397.                 fprint(outfile, "copy ");
  398.             } else {
  399.                 fprint(outfile,"      ");
  400.             }
  401.             fprint(outfile,ins[i]);
  402.             if (dirname) {
  403.                 fprint(outfile,suffix[j]);
  404.                 fprint(outfile, " to ");
  405.                 fprint(outfile, dirname);
  406.             }
  407.             fprint(outfile,"\n");
  408.         }
  409.     }
  410. }
  411.