home *** CD-ROM | disk | FTP | other *** search
- /*
- * SONIXPEEK.C by Eddy Carroll, April 1988
- * ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * Scans one or more Aegis Sonix music files building a list of unique
- * instruments used within those files. At the end, a list of the
- * instruments found is printed (can be redirected to a file if
- * desired).
- *
- * Usage: SonixPeek {-h} {-i} {-n} {-ofile} {-xdirectory} filename ...
- *
- * If filename is a Sonix file, then only that file is scanned. If
- * filename is a directory, then all the files in that directory which
- * contain Sonix files are scanned.
- *
- * The -h flag suppresses the printing of the header which is normally
- * present at the top of the list of instruments.
- *
- * If the -i (interactive) flag is present, then after each file is
- * found, the user is asked whether it should be included or not when
- * building the list of instruments.
- *
- * If the -o flag is present, then the list of instruments is stored
- * in the specified file, rather than being displayed on the screen.
- *
- * If the -x flag is present, then the output is given in the form
- * of an executable file which consists of a line for each instrument
- * found of the form COPY <instrument> TO <directory>, where <directory>
- * is given immediately after the -x switch.
- *
- * If the -n flag is present, then the list of instruments found in each
- * file, when a directory is being searched, is not printed.
- *
- * DISTRIBUTION
- * I retain copyright to the source and executable code for SonixPeek, but
- * it may be freely redistributed as long as no profit is made from it.
- *
- * Compiles under Lattice C V4.0
- *
- * Note: Some of this code is messy. Have patience with it :-)
- *
- */
-
- #include <exec/types.h>
- #include <libraries/dos.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #include <proto/intuition.h>
- #include <string.h>
-
- /* The following is a quick hack to avoid having to link with lc.lib */
- #define strcat(p,q) (strcpy((p)+strlen(p),(q)))
-
- /*
- * New handler for Ctrl-C. Checks if CTRL-C received, and if it has, sets
- * the global CtrlC variable to true.
- */
- int CtrlC;
- #define chkabort() (CtrlC |= ((SetSignal(0,0) & SIGBREAKF_CTRL_C)))
-
- #define tolower(c) ((c) >= 'A' && (c) <= 'Z' ? (c) + 'a' - 'A' : (c))
-
- #define EOL '\012'
- #define EOF '\037'
- #define TAB '\011'
- #define CR '\015'
-
- #define MAXINS 1000 /* Only 200 instruments allowed */
- #define MAXFILENUM 200 /* No more than 200 scores allowed */
- #define MAXSTRING 256 /* Maximum length of a string */
-
- #define INDENT (" ") /* Amount to indent instruments by */
-
- /* IFF ID definitions */
-
- #define MakeID(a,b,c,d) (long)((long)(a)<<24 | (long)(b)<<16 | (c)<<8 | (d))
- #define FORM MakeID('F','O','R','M')
- #define SMUS MakeID('S','M','U','S')
- #define NAME MakeID('N','A','M','E')
- #define SNX1 MakeID('S','N','X','1')
- #define INS1 MakeID('I','N','S','1')
- #define TRAK MakeID('T','R','A','K')
-
- #define roundup(a) ((a + 1L) & ~1L)
-
- int interactive; /* TRUE if interactive selection of files */
- int multi; /* TRUE if a directory specified instead of file */
- int supress; /* TRUE if listing of instruments is supressed */
- int noheader; /* TRUE if no header ouput at start of instr. list */
- char *dirname; /* Directory to copy to for -x option */
- char *suffix[] =
- {".ss", ".instr"}; /* For creating 'copy' batch file */
-
- LONG Examine(), ExNext(), Read(), Write();
- BPTR Lock(), CurrentDir();
-
- int numins; /* Current number of instruments */
- int numfiles; /* Current number of files */
- char *ins[MAXINS]; /* Room for 1000 instruments */
- char *files[MAXFILENUM]; /* Room for 200 files */
-
- BPTR stdin, stdout, stderr, infile, outfile;
- struct FileInfoBlock myfib;
-
- /*
- * The following lets us use our own version of malloc(). The only
- * additional requirements are that we open intuition.library first,
- * and call FreeRemember(&memkey,TRUE) just before exiting.
- */
- struct Remember *memkey; /* Used for tracking memory */
- #define malloc(n) (AllocRemember(&memkey,n,0L))
- struct IntuitionBase *IntuitionBase;
-
- /*
- * Output string to file. Note that if CTRL-C has been typed,
- * output is suppressed.
- */
-
- void fprint(f, s)
- BPTR f;
- char *s;
- {
- if (!CtrlC) {
- Write(f, s, strlen(s));
- chkabort();
- }
- }
-
- /*
- * Outputs 3 strings to file f (handy for printing "String" var "String")
- * The strings are concatenated first to ensure that they are printed
- * as a single unit, and won't be interrupted by ^C, or even just the
- * user pressing space, if the output is stdout or stderr.
- */
- void fprint3(f,s1,s2,s3)
- BPTR f;
- char *s1,*s2,*s3;
- {
- static char buf[MAXSTRING * 3];
- strcpy(buf,s1);
- strcat(buf,s2);
- strcat(buf,s3);
- fprint(f,buf);
- }
-
- /*
- * print() and print3() are similar to fprint() and fprint3(), but
- * they output directly to stderr.
- */
- #define print(s) fprint(stderr,s)
- #define print3(s1,s2,s3) fprint3(stderr,s1,s2,s3)
-
- /*
- * Standard exit routine for program. Deallocates resources and exits.
- * If it spots CtrlC has been pressed, it prints an appropriate message.
- */
-
- void abort(code)
- int code; /* Exit code */
- {
- if (CtrlC)
- Write(stderr,"^C\n",3); /* print() won't work when CtrlC is true */
- if (outfile != stdout && outfile != NULL)
- Close(outfile);
- if (stderr)
- Close(stderr);
- if (memkey)
- FreeRemember(&memkey,TRUE);
- if (IntuitionBase)
- CloseLibrary(IntuitionBase);
- exit(code);
- }
-
- /*
- * Prints help message to standard output
- */
- void help()
- {
- fprint3(stderr,"\n\
- SonixPeek Instrument Lister Copyright Eddy Carroll April 1988\n\
- \n\
- Usage: SonixPeek {-h} {-i} {-n} {-ofile} {-xdirectory} file ...\n\
- \n\
- File is the Aegis Sonix file for which the instruments are to\n","\
- be listed. If it is a directory, then all the Sonix files in\n\
- that directory are checked, and a sorted list of the instruments\n\
- contained in all of them is prepared. The flags operate as follows:\n\
- \n","\
- -h Suppress output of header at start of instrument listing\n\
- \n\
- -i Ask user whether or not to include each score found\n\
- \n\
- -n Don't list instruments as they are found\n\
- \n");fprint(stderr,"\
- -o Redirect sorted output to named file\n\
- \n\
- -x Format output as an execute file which will copy all the\n\
- instruments found to the named directory\n\
- \n");
- }
-
- /*** Start of actual program ***/
-
- void main(argc, argv)
- int argc;
- char *argv[];
- {
-
- void addinstrument(), skip(), dumpins();
- char charin();
- BPTR mylock, oldlock;
- char *fname;
-
- stdin = Input();
- stderr = Open("*",MODE_NEWFILE);
- outfile = stdout = Output();
- infile = 0;
-
- if ((IntuitionBase = OpenLibrary("intuition.library",0L)) == NULL)
- abort(99);
-
- /* Scan command line for possible switches */
-
- for ( argv++; argc > 1 && argv[0][0] == '-'; argc--,argv++) {
- switch (tolower(argv[0][1])) {
-
- case 'h': noheader = 1;
- break;
-
- case 'i': interactive = 1;
- break;
-
- case 'n': supress = 1;
- break;
-
- case 'o': if ((outfile = Open(argv[0]+2,MODE_NEWFILE)) == 0) {
- print3("Can't open file ",argv[0]+2," for output.\n");
- abort(20);
- }
- break;
-
- case 'x': dirname = argv[0] + 2;
- break;
-
- default: print3("Unknown option ", argv[0], " ignored.\n");
- break;
- }
- }
-
- /* If missing filename, or filename == '?', print instructions */
-
- if (argc == 1 || argv[0][0] == '?') {
- help();
- abort(0);
- }
- if (argc > 2) /* More than one file specified */
- multi = 1; /* so enable printing of instrument list for each file */
-
- /*
- * Now scan each of the files or directories specified, reading
- * the instruments from each one, and adding them to the list.
- */
- for ( ; argc > 1; argc--, argv++) {
- fname = argv[0];
- if ((mylock = Lock(fname, ACCESS_READ)) == 0L) {
- print3("Can't open file ",fname," for input.\n");
- abort(20);
- }
- Examine(mylock,&myfib);
- if (myfib.fib_DirEntryType > 0L) {
- multi = 1;
- oldlock = CurrentDir(mylock);
- while (chkabort(), ExNext(mylock, &myfib) && !CtrlC)
- if (myfib.fib_DirEntryType < 0L)
- scan(&(myfib.fib_FileName), fname);
- oldlock = CurrentDir(oldlock);
- } else
- scan(fname,NULL);
- }
- dumpins();
- UnLock(mylock);
- abort(0);
- }
-
- /*
- * Scans filename for instruments. If found, they are added to the
- * list of instruments already in memory. Returns 0 for success, -1
- * if invalid file. The path parameter, which may be NULL, is the
- * path to be prefixed to the filename before it is stored in memory.
- * Note that this may entail adding a trailing '/' to the path.
- */
-
- int scan(filename,path)
- char *filename;
- char *path;
- {
- LONG header[3];
- char instr[50], response[50], *p;
- int plen, foundinstr = 0;
-
- if ((infile = Open(filename,MODE_OLDFILE)) == 0L) {
- print3("Can't open file ", filename, " for input\n");
- return(-1);
- }
-
- if (Read(infile,(char *)header,8L) != 8L || header[0] != FORM) {
- Close(infile);
- return(-1);
- }
-
- if (Read(infile,(char *)header,4L) != 4L || header[0] != SMUS) {
- Close(infile);
- return(-1);
- }
-
- if (interactive) {
- print3("Include file ", filename, " (CR = no)? ");
- Read(stdin, response, 50L);
- if (tolower(*response) != 'y')
- return(-1);
- } else if (multi && !supress)
- fprint3(stdout, filename, ":\n", "");
-
- while (chkabort(), Read(infile,(char *)header,8L) == 8L && !CtrlC) {
- if (header[0] != INS1) {
- skip(infile,header[1]);
- } else {
- skip(infile,4L); /* skip position of instrument parameter */
- Read(infile, instr, roundup(header[1]) - 4L);
- instr[header[1] - 4L] = '\0'; /* Null-terminate string */
- addinstrument(instr);
- foundinstr = 1;
- }
- }
- if (multi && !supress)
- fprint(stdout,"\n");
- if (foundinstr) {
- if (path) {
- plen = strlen(path);
- p = malloc(strlen(filename)+plen+2);
- /* Allocate extra byte for zero terminator and for possible '/' */
- strcpy(p, path);
- if (plen && p[plen-1] != ':' && p[plen-1] != '/')
- strcat(p,"/");
- strcat(p,filename);
- } else {
- p = malloc(strlen(filename)+1);
- strcpy(p,filename);
- }
- files[numfiles++] = p;
- }
- Close(infile);
- return(0);
- }
-
- void skip(file,size)
- BPTR file;
- LONG size;
- {
- char s[256];
- LONG len = 1L;
- size = roundup(size);
- while (chkabort(), size > 0 && len && !CtrlC) {
- len = Read(file, s, (size > 256 ? 256 : size));
- size -= 256;
- }
- }
-
-
- /*
- * Adds instrument of length len into list of instruments, but only
- * if its not already present in the list.
- */
-
- void addinstrument(instr)
- char *instr;
- {
- int pos, i;
- if ((pos = matchins(instr)) != -1) {
- for (i = numins++; i > pos; i--)
- ins[i] = ins[i-1];
- ins[pos] = malloc(strlen(instr)+1);
- strcpy(ins[pos], instr);
- }
- if (multi && !supress) {
- fprint3(stdout, INDENT, instr, "\n");
- }
- }
-
- /*
- * Compares string p to string s, ignoring case of alpha chars.
- * Returns -ve if p < s, 0 if p = s, +ve if p > s.
- */
-
- int mystrcmp(p,s)
- char *p, *s;
- {
- while (*p && *s && tolower(*p) == tolower(*s))
- p++, s++;
- return(tolower(*p) - tolower(*s));
- }
-
- /*
- * Searches instrument array for a match with given instrument.
- * Returns -1 if found, else position in array to insert new element.
- */
-
- int matchins(instr)
- char *instr;
- {
- int i, z;
-
- for (i = 0; i < numins; i++) {
- if ((z = mystrcmp(instr, ins[i])) <= 0) {
- if (z)
- return(i); /* If less, insert here */
- else
- return(-1); /* If equal, don't insert */
- }
- }
- return (i); /* Must be at end of list, so return last item */
- }
-
- /*
- * Dumps instrument list to outfile
- */
- void dumpins()
- {
- int i, j;
-
- if (numins == 0) {
- print("No instruments found.\n");
- return;
- }
-
- if (!noheader) {
- fprint(outfile,";\n; Sorted list of instruments\n");
- fprint(outfile, "; --------------------------\n;\n");
- if (numfiles == 1)
- fprint3(outfile, "; Taken from file ", files[0], "\n");
- else {
- fprint(outfile,"; Taken from these files:\n;\n");
- for (i = 0; i < numfiles && !CtrlC; i++) {
- fprint3(outfile, "; ", files[i], "\n");
- }
- }
- fprint(outfile,";\n");
- }
- if (dirname)
- fprint(outfile,"failat 30\n");
- for (i = 0; i < numins && !CtrlC; i++) {
- for (j = (dirname != 0); j >= 0 && !CtrlC; j--) {
- if (dirname) {
- fprint3(outfile, "copy ", ins[i], " to ");
- fprint3(outfile, dirname, "\n", "");
- } else
- fprint3(outfile, INDENT, ins[i], "\n");
- }
- }
- }
-