[comp.sources.amiga] v91i064: MP 1.0 - the MIDI Playground, Part01/02

amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (03/16/91)

Submitted-by: barrett@server.cs.jhu.edu
Posting-number: Volume 91, Issue 064
Archive-name: midi/mp-1.0/part01

[ includes uuencoded executable  ...tad ]

	This is a submission for comp.sources.amiga, entitled "MIDI
Playground", written by me.  It's a versatile utility for making your Amiga
communicate with a MIDI instrument.  It's helpful for learning about MIDI,
designing MIDI software, and other related tasks.

	Uuencoded binary is included.

                                                        Dan

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  CONTENTS Examples Examples.DOC Examples/CHORD-OFF
#   Examples/CHORD-ON Examples/DISPLAY-FUN README Scripts
#   Scripts/Converse Scripts/PatchChange Scripts/Text2Midi
#   Scripts/TwoWindows Source Source/Makefile Source/amigados.c
#   Source/cli.c Source/files.c Source/getopt.c Source/help.c
#   Source/iofunctions.c Source/main.c Source/midi.h Source/mp.h
#   Source/serial.c Source/text.c Source/version.h Source/wb.c
# Wrapped by tadguy@ab20 on Fri Mar 15 14:25:13 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'CONTENTS' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CONTENTS'\"
else
echo shar: Extracting \"'CONTENTS'\" \(353 characters\)
sed "s/^X//" >'CONTENTS' <<'END_OF_FILE'
XMIDI_Playground	A small, useful utility for sending any MIDI data back and
X		forth between an Amiga and a MIDI instrument.  Helpful for
X		learning about MIDI, writing/debugging MIDI software,
X		figuring out your instrument's system-exclusive
X		implementation, and more.  Very versatile.  Version 1.0,
X		includes source.
X		Author:  Daniel J. Barrett
X			
END_OF_FILE
if test 353 -ne `wc -c <'CONTENTS'`; then
    echo shar: \"'CONTENTS'\" unpacked with wrong size!
fi
# end of 'CONTENTS'
fi
if test ! -d 'Examples' ; then
    echo shar: Creating directory \"'Examples'\"
    mkdir 'Examples'
fi
if test -f 'Examples.DOC' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Examples.DOC'\"
else
echo shar: Extracting \"'Examples.DOC'\" \(907 characters\)
sed "s/^X//" >'Examples.DOC' <<'END_OF_FILE'
XRead MP.DOC before you read this file.
X
XMP is very flexible because:
X
X	o	It can translate between 3 kinds of data formats:
X
X		-	Text.
X		-	Binary data.
X		-	MIDI data.
X
X	o	The input/output can be sent to/from:
X
X		-	Your CLI window.
X		-	Files, using -g and -p.
X		-	Files, using the CLI redirection symbols "<" and
X			">".
X		-	Newly-created windows, by specifying a file
X			name like "CON:0/0/640/100/MP Input".
X		-	The MIDI port.
X
XMP does not have a window/mouse/icon graphic interface; instead, YOU
Xdesign the interface using CLI scripts.  See the "Scripts" directory
Xfor some small examples.  You can use MP in AREXX scripts too.
X
XFor a Workbench interface, use the IconX program (supplied with your
XAmiga) to attach an icon to a CLI script.  Then fill the CLI script
Xwith MP commands.
X
XThe directory "Examples" has some sample files that use the input
Xtext language.  You can send them to your synthesizer.
END_OF_FILE
if test 907 -ne `wc -c <'Examples.DOC'`; then
    echo shar: \"'Examples.DOC'\" unpacked with wrong size!
fi
# end of 'Examples.DOC'
fi
if test -f 'Examples/CHORD-OFF' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Examples/CHORD-OFF'\"
else
echo shar: Extracting \"'Examples/CHORD-OFF'\" \(72 characters\)
sed "s/^X//" >'Examples/CHORD-OFF' <<'END_OF_FILE'
X; Cease playing a C major triad on MIDI channel 0.
X
X0x90 60 0 64 0 67 0
END_OF_FILE
if test 72 -ne `wc -c <'Examples/CHORD-OFF'`; then
    echo shar: \"'Examples/CHORD-OFF'\" unpacked with wrong size!
fi
# end of 'Examples/CHORD-OFF'
fi
if test -f 'Examples/CHORD-ON' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Examples/CHORD-ON'\"
else
echo shar: Extracting \"'Examples/CHORD-ON'\" \(69 characters\)
sed "s/^X//" >'Examples/CHORD-ON' <<'END_OF_FILE'
X; Play a C major triad on MIDI channel 0.
X
X0x90 60 127 64 127 67 127
END_OF_FILE
if test 69 -ne `wc -c <'Examples/CHORD-ON'`; then
    echo shar: \"'Examples/CHORD-ON'\" unpacked with wrong size!
fi
# end of 'Examples/CHORD-ON'
fi
if test -f 'Examples/DISPLAY-FUN' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Examples/DISPLAY-FUN'\"
else
echo shar: Extracting \"'Examples/DISPLAY-FUN'\" \(340 characters\)
sed "s/^X//" >'Examples/DISPLAY-FUN' <<'END_OF_FILE'
X; An example of sending text to the Matrix-12 display.
X; Xpander users must change the 4th byte to 0x05.
X; You MUST send exactly 80 characters or the Oberheim ignores you.
X; Send this with:
X;	mp  -g  DISPLAY-FUN  -it  -om 
X
X0xf0 0x10 0x02 0x06 0x01
X"I THINK THAT I SHALL NEVER SEE          "
X"A POEM AS LOVELY AS LITTLE OL' ME       "
X0xf7
END_OF_FILE
if test 340 -ne `wc -c <'Examples/DISPLAY-FUN'`; then
    echo shar: \"'Examples/DISPLAY-FUN'\" unpacked with wrong size!
fi
# end of 'Examples/DISPLAY-FUN'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(461 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XMP:		A MIDI Playground
XAuthor:		Daniel J. Barrett, barrett@cs.jhu.edu.
XNo Copyright:	100% Public Domain.
X		Please share this program with others.
X
X	MP is a small program that lets your Amiga communicate with a
XMIDI instrument.  It runs from the CLI only (but can be made to run
Xfrom the Workbench by using "IconX").
X
XSee the file MP.DOC for full instructions on how to use this program.
XSee EXAMPLES.DOC for information about the supplied examples and scripts.
END_OF_FILE
if test 461 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test ! -d 'Scripts' ; then
    echo shar: Creating directory \"'Scripts'\"
    mkdir 'Scripts'
fi
if test -f 'Scripts/Converse' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Scripts/Converse'\"
else
echo shar: Extracting \"'Scripts/Converse'\" \(151 characters\)
sed "s/^X//" >'Scripts/Converse' <<'END_OF_FILE'
Xrun <NIL: >NIL: mp -it -om -g "CON:0/1/640/75/Send MIDI; end with ^\"
Xwait 1
Xrun <NIL: >NIL: mp -im -ot -p "CON:0/76/640/75/Receive MIDI; end with ^C"
END_OF_FILE
if test 151 -ne `wc -c <'Scripts/Converse'`; then
    echo shar: \"'Scripts/Converse'\" unpacked with wrong size!
fi
# end of 'Scripts/Converse'
fi
if test -f 'Scripts/PatchChange' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Scripts/PatchChange'\"
else
echo shar: Extracting \"'Scripts/PatchChange'\" \(172 characters\)
sed "s/^X//" >'Scripts/PatchChange' <<'END_OF_FILE'
X.KEY patchnum/a
X.BRA {
X.KET }
X
Xecho "Changing to patch {patchnum} on MIDI channel 0..."
Xecho > pipe:patchchange "0xC0 {patchnum}"
Xmp -it -om -g pipe:patchchange
Xecho Done!
END_OF_FILE
if test 172 -ne `wc -c <'Scripts/PatchChange'`; then
    echo shar: \"'Scripts/PatchChange'\" unpacked with wrong size!
fi
# end of 'Scripts/PatchChange'
fi
if test -f 'Scripts/Text2Midi' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Scripts/Text2Midi'\"
else
echo shar: Extracting \"'Scripts/Text2Midi'\" \(137 characters\)
sed "s/^X//" >'Scripts/Text2Midi' <<'END_OF_FILE'
X.KEY TextFile/a
X.BRA {
X.KET }
X
Xecho "Converting {TextFile} to {TextFile}.midi..."
Xmp -it -ob -g {TextFile} -p {TextFile}.midi
Xecho Done!
END_OF_FILE
if test 137 -ne `wc -c <'Scripts/Text2Midi'`; then
    echo shar: \"'Scripts/Text2Midi'\" unpacked with wrong size!
fi
# end of 'Scripts/Text2Midi'
fi
if test -f 'Scripts/TwoWindows' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Scripts/TwoWindows'\"
else
echo shar: Extracting \"'Scripts/TwoWindows'\" \(107 characters\)
sed "s/^X//" >'Scripts/TwoWindows' <<'END_OF_FILE'
Xmp -it -ot -g "CON:0/1/640/75/Type commands Here..." -p "CON:0/76/640/75/...and watch them come out here!"
END_OF_FILE
if test 107 -ne `wc -c <'Scripts/TwoWindows'`; then
    echo shar: \"'Scripts/TwoWindows'\" unpacked with wrong size!
fi
# end of 'Scripts/TwoWindows'
fi
if test ! -d 'Source' ; then
    echo shar: Creating directory \"'Source'\"
    mkdir 'Source'
fi
if test -f 'Source/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/Makefile'\"
else
echo shar: Extracting \"'Source/Makefile'\" \(2707 characters\)
sed "s/^X//" >'Source/Makefile' <<'END_OF_FILE'
X###########################################################################
X# Makefile:	Makefile for Manx Aztec C, version 5.0.
X#		Part of MP, the MIDI Playground.
X#
X# Author:	Daniel Barrett
X# Version:	See the file "version.h".
X# Copyright:	None!  This program is in the Public Domain.
X#		Please share it with others.
X###########################################################################
X
X	
XOPTIMIZE	= -so
XDEBUGGING	= #-bs
XLDEBUGGING	= #-g
X	
XLFLAGS		= $(LDEBUGGING) +Q
XCFLAGS          = $(OPTIMIZE) -hi $(COMP_INC) $(DEBUGGING)
XLIBS		= -lc
XCOMP_INC	= headers.comp
XLIBS		= -lc
X
XBACKUPDIR	= df1:sysex
X	
X##############################################################################
X# Files used for all programs.
X##############################################################################
X
XPROG		= mp
XMAINHEADER	= mp.h
XHEADERS		= $(MAINHEADER) version.h midi.h
XSRC		= text.c main.c serial.c getopt.c iofunctions.c help.c \
X		  files.c wb.c cli.c amigados.c
XOBJ		= text.o main.o serial.o getopt.o iofunctions.o help.o \
X		  files.o wb.o cli.o amigados.o
X
X##############################################################################
X# The program.
X##############################################################################
X
X$(PROG):	$(COMP_INC) $(OBJ)
X		@echo ""
X		@echo "Ignore messages about _abort overriding library."
X		@echo ""
X		ln $(LFLAGS) $(OBJ) -o $(PROG) $(LIBS)
X
X$(OBJ):		$(MAINHEADER)
X
X##############################################################################
X# Individual dependencies.
X##############################################################################
X
Xhelp.o:		help.c        $(MAINHEADER) version.h
Xiofunctions.o:	iofunctions.c $(MAINHEADER) midi.h
Xserial.o:	serial.c      $(MAINHEADER) midi.h
X	
X##############################################################################
X# Compiled headers.
X##############################################################################
X
X$(COMP_INC):	$(MAINHEADER)
X		@echo "Compiling headers because of $?"
X		cc $(OPTIMIZE) $(DEBUGGING) -ho $(COMP_INC) $(MAINHEADER)
X
X#$(MAINHEADER):	$(HEADERS)
X
X##############################################################################
X# Clean up
X##############################################################################
X
Xclean:
X		delete \#?.o \#?.pro
X
Xveryclean:	clean
X		delete $(COMP_INC) $(PROG) \#?.dbg
X
Xcbackup:
X		copy \#?.c $(BACKUPDIR)
X		copy \#?.h $(BACKUPDIR)
X		copy Makefile $(BACKUPDIR)
X
Xbackup:		cbackup
X		copy README $(BACKUPDIR)
X		copy \#?.DOC $(BACKUPDIR)
X		copy Scripts $(BACKUPDIR)/Scripts   all
X		copy Examples $(BACKUPDIR)/Examples all
X
Xzoo:		$(PROG)
X		delete ram:mp.zoo quiet
X		zoo a ram:mp.zoo Source/* Scripts/* Examples/* \
X				 $(PROG) *.DOC README Makefile
END_OF_FILE
if test 2707 -ne `wc -c <'Source/Makefile'`; then
    echo shar: \"'Source/Makefile'\" unpacked with wrong size!
fi
# end of 'Source/Makefile'
fi
if test -f 'Source/amigados.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/amigados.c'\"
else
echo shar: Extracting \"'Source/amigados.c'\" \(1684 characters\)
sed "s/^X//" >'Source/amigados.c' <<'END_OF_FILE'
X/**************************************************************************
X* amigados.c:	Requestor and Environment Variable routines.
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#include <exec/types.h>
X#include <stdlib.h>
X#include <functions.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X
X	
Xvoid DisableRequestors(void);
Xvoid EnableRequestors(void);
X
X	
X#define	ENV_NAME_LENGTH		BUFSIZ
X
X	
X/* Return the value of ENV: environment variable "variableName", if it
X * exists.   We use this instead of the built-in getenv() because we
X * want to turn off requestors during the search for ENV:, in case it
X * is not mounted. */
X
Xchar *GetEnv(char *variableName)
X{
X	char *result;
X
X	DisableRequestors();		/* In case ENV: is non-existent. */
X	result = getenv(variableName);
X	EnableRequestors();
X	return(result);
X}
X
X
X/***************************************************************************
X* Deal with requestors.
X***************************************************************************/
X
Xstatic APTR oldWindowPtr;
Xstatic struct Process *theProc;
X
X/* Turn off system requestors for this process. */
X
Xvoid DisableRequestors(void)
X{
X	theProc = (struct Process *)FindTask(NULL);
X	oldWindowPtr = theProc->pr_WindowPtr;
X	theProc->pr_WindowPtr = (APTR)(-1L);
X}
X
X
X/* Turn on system requestors for this process, after they have been
X * turned off by DisableRequestors(), above. */
X
Xvoid EnableRequestors(void)
X{
X	theProc->pr_WindowPtr = oldWindowPtr;
X}
END_OF_FILE
if test 1684 -ne `wc -c <'Source/amigados.c'`; then
    echo shar: \"'Source/amigados.c'\" unpacked with wrong size!
fi
# end of 'Source/amigados.c'
fi
if test -f 'Source/cli.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/cli.c'\"
else
echo shar: Extracting \"'Source/cli.c'\" \(2379 characters\)
sed "s/^X//" >'Source/cli.c' <<'END_OF_FILE'
X/**************************************************************************
X* cli.c:	The command-line interface for MP.
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#include "mp.h"
X
X
X/* The main program from the CLI.  Check the command-line arguments, set
X * up the input and output files, and call MIDIPlayground(). */
X	
XBOOL CommandLineProgram(int argc, char *argv[])
X{
X	FILE *in, *out;
X	char *infile, *outfile;
X	FLAGS theFlags[NUM_FLAGS];
X	
X	InitStuff(theFlags, &in, &out, &infile, &outfile);
X
X	if ((argc == 1)   ||   (argc == 2 && !strcmp(argv[1], "?")))
X		Help(argv[0]);
X	else if (!HandleOptions(argc, argv, theFlags, &infile, &outfile))
X	{
X		fprintf(stderr, "There is an error in your options/flags.\n");
X		BegForUsage(argv[0]);
X	}
X	else if (!SetupFiles(infile, outfile, &in, &out))
X		;
X	else if (optind < argc)
X	{
X		fprintf(stderr, "You gave me too many arguments.\n");
X		BegForUsage(argv[0]);
X	}
X	else
X		(void)MIDIPlayground(theFlags, in, out);
X
X	CloseFiles(in, out, infile, outfile);
X}
X
X	
X/************************************************************************
X* Handling command-line options.
X************************************************************************/
X
XBOOL HandleOptions(int argc, char *argv[], FLAGS theFlags[], char **infile,
X		   char **outfile)
X{
X	int c;
X	BOOL success = TRUE;
X	static char options[] = GETOPT_OPTIONS;
X	
X	while ((c = getopt(argc, argv, options)) != EOF)
X	{
X		switch (c)
X		{
X		  case OPT_INPUT:
X		     success &= !theFlags[FLAG_ITYPE];
X		     success &= CheckIOType(*optarg, FLAG_ITYPE, theFlags);
X		     break;
X		  case OPT_OUTPUT:
X		     success &= !theFlags[FLAG_OTYPE];
X		     success &= CheckIOType(*optarg, FLAG_OTYPE, theFlags);
X		     break;
X		  case OPT_INFILE:
X		     success &= (optarg[0] != '\0');
X		     success &= MakeFilename(infile, optarg);
X		     break;
X		  case OPT_OUTFILE:
X		     success &= (optarg[0] != '\0');
X		     success &= MakeFilename(outfile, optarg);
X		     break;
X		  case OPT_SYSEX:
X		     success &= !theFlags[FLAG_SYSEX];
X		     theFlags[FLAG_SYSEX]++;
X		     break;
X		  default:
X		     success = FALSE;
X		     break;
X		}
X	}
X	return(success && CheckFlags(theFlags));
X}
X
X	
END_OF_FILE
if test 2379 -ne `wc -c <'Source/cli.c'`; then
    echo shar: \"'Source/cli.c'\" unpacked with wrong size!
fi
# end of 'Source/cli.c'
fi
if test -f 'Source/files.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/files.c'\"
else
echo shar: Extracting \"'Source/files.c'\" \(3363 characters\)
sed "s/^X//" >'Source/files.c' <<'END_OF_FILE'
X/**************************************************************************
X* files.c:	File open/close, input/output, etc.
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#include <stdio.h>
X#include <exec/types.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X
X
X/* Open a file and return a pointer to it. */
X	
XFILE *OpenAFile(char *filename, char *mode, char *readOrWrite)
X{
X	FILE *fp;
X
X    	if ((fp = fopen(filename, mode)) == NULL)
X		fprintf(stderr, "Cannot %s the file \"%s\",\n",
X			readOrWrite, filename);
X	return(fp);
X}
X
X	
X/* Open a file for reading.  We might also have a macro with the same name,
X * so we used ifdef's. */
X
X#ifndef OpenReadFile	
XFILE *OpenReadFile(char *filename)
X{
X	return(OpenAFile(filename, "r", "read"));
X}
X#endif
X
X	
X/* Open a file for writing.  We might also have a macro with the same name,
X * so we used ifdef's. */
X
X#ifndef OpenWriteFile
XFILE *OpenWriteFile(char *filename)
X{
X	return(OpenAFile(filename, "w", "write"));
X}
X#endif
X
X	
X/* Tell me whether or not a file exists. */
X
XBOOL FileExists(char *filename)
X{
X	BPTR lock;
X
X	if ((lock = Lock(filename, ACCESS_READ)) != NULL)
X	{
X		UnLock(lock);
X		return(TRUE);
X	}
X	return(FALSE);
X}
X
X	
X/* See if we want to overwrite an existing file. */
X
X/* BUFSIZ is too large, perhaps -- change later -- but don't compromise
X * on correct reading of the user's input.  Too small, and extra unread
X * chars are read on the NEXT call (yuck).  If you use gets(), too much
X * input crashes the program. */
X
XBOOL DontOverwriteExistingFile(char *filename)
X{
X	char buf[BUFSIZ];
X	BOOL safety = TRUE;
X
X	if (FileExists(filename))
X	{
X		fprintf(stderr,
X		     "File \"%s\" already exists.\nOVERWRITE it? [%s]: ",
X		     filename, "Yes/No, RETURN=No");
X		fflush(stderr);
X
X		if (fgets(buf, BUFSIZ-1, stdin))
X			safety = (toupper(buf[0]) != 'Y');
X		else
X			safety = TRUE;
X	}
X	else
X		safety = FALSE;			/* File doesn't exist. */
X
X	if (safety)
X		fprintf(stderr, "%s not overwritten.\n\n", filename);
X
X	return(safety);
X}
X
X
X/* Open the input and output files.
X * We open input AFTER output in case the user has specified CON: windows,
X * so the input window is the active one. */
X
XBOOL SetupFiles(char *infile, char *outfile, FILE **in, FILE **out)
X{
X	if (!outfile || (outfile[0] == '\0'))
X		*out = stdout;
X	else if (DontOverwriteExistingFile(outfile))
X		return(FALSE);
X	else if ((*out = OpenWriteFile(outfile)) == NULL)
X		return(FALSE);
X
X	if (!infile || (infile[0] == '\0'))
X		*in = stdin;
X	else if ((*in = OpenReadFile(infile)) == NULL)
X		return(FALSE);
X
X	return(TRUE);
X}
X
X	
X/* Close the files used by the program, and deallocate the arrays used
X * for storing the filenames. */
X
Xvoid CloseFiles(FILE *in, FILE *out, char *filein, char *fileout)
X{
X	if (in && (in != stdin))	fclose(in);
X	if (out && (out != stdout))	fclose(out);
X	if (filein)			free(filein);
X	if (fileout)			free(fileout);
X}
X
X	
X/* Allocate space to store a filename, and copy the contents of "src" into
X * it. */
X
XBOOL MakeFilename(char **dest, char *src)
X{
X	if ((!src) || (*src == '\0')
X	||  ((*dest = (char *)malloc(strlen(src)+1)) == NULL))
X		return(FALSE);
X	else
X	{
X		strcpy(*dest, src);
X		return(TRUE);
X	}
X}
END_OF_FILE
if test 3363 -ne `wc -c <'Source/files.c'`; then
    echo shar: \"'Source/files.c'\" unpacked with wrong size!
fi
# end of 'Source/files.c'
fi
if test -f 'Source/getopt.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/getopt.c'\"
else
echo shar: Extracting \"'Source/getopt.c'\" \(7295 characters\)
sed "s/^X//" >'Source/getopt.c' <<'END_OF_FILE'
X/****************************************************************************
X * getopt():	Return the next user option on each iteration. 
X *		This is a clone of the usual UNIX getopt() function.
X *		If you have never used a getopt() before, you'll have to
X * 		 read about it on any UNIX machine or other C system that
X * 		 documents it.
X *
X * Author:	Daniel Barrett, barrett@cs.jhu.edu.
X * Date:	February 20, 1991.
X * Version:	1.1.
X *
X * License:	This code is placed in the Public Domain.
X *		Give it away to anybody for free!
X *		Use it for any purpose you like!
X *
X *		If you use this code in a program, please give me credit
X *		for my work.  Thanks!
X *
X * Why I wrote it:
X *
X *		Because every other getopt() function I have ever seen
X *		 had source code that was difficult to understand.
X *		I wrote this code to be very modular and readable.
X *		I hope you find it instructive and/or helpful.
X *
X * REVISION HISTORY:
X *	Version:	1.1
X *	Date:		February 20, 1991.
X *	Comments:	Bug fix in Pass().  Forgot to check that the
X *			current argument is non-empty and starts with
X *			a DASH.
X *
X *			Got rid of the unnecessary "g_" at the beginning
X *			of each function name.  Since they're static, we
X *			don't have to worry about duplication of names
X *			by the calling program.
X *
X *	Version:	1.0
X *	Date:		April 12, 1990.
X *	Comments:	First released version.
X *
X ****************************************************************************/
X
X#ifndef __STDIO_H	/* If we haven't already included stdio.h, do it. */
X#include <stdio.h>	/* Maybe someday I'll eliminate this. */
X#endif
X
X/************************************************************************
X* Some constants.
X************************************************************************/
X
X#define	DASH		'-'	/* This preceeds an option. */
X#define	ARG_COMING	':'	/* In the option string, this indicates that
X				 * that the option requires an argument. */
X#define	UNKNOWN_OPT	'?'	/* The char returned for unknown option. */
X
X/************************************************************************
X* Internal error codes.
X************************************************************************/
X
X#define	ERROR_BAD_OPTION	1
X#define	ERROR_MISSING_ARGUMENT	2
X
X/************************************************************************
X* Mnemonic macros.
X************************************************************************/
X
X
X
X/************************************************************************
X* ANSI function prototypes.
X************************************************************************/
X
Xint		getopt(int argc, char *argv[], char *optString);
Xstatic int	NextOption(char *argv[], char *optString);
Xstatic int	RealOption(char *argv[], char *str, int *skip, int *ind,
X			     int opt);
Xstatic void	HandleArgument(char *argv[], int *optind, int *skip);
Xstatic void	Error(int err, int c);
Xstatic void	Pass(char *argv[], int *optind, int *optsSkipped);
X
Xextern char	*index();
X
X/************************************************************************
X* Global variables.  You must declare these externs in your program
X* if you want to see their values!
X************************************************************************/
X	
Xchar	*optarg	= NULL;	/* This will point to a required argument, if any. */
Xint	optind	= 1;	/* The index of the next argument in argv. */
Xint	opterr	= 1;	/* 1 == print internal error messages.  0 else. */
Xint	optopt;		/* The actual option letter that was found. */
X
X
Xint getopt(int argc, char *argv[], char *optString)
X{
X	optarg = NULL;
X	if (optind < argc)		/* More arguments to check. */
X		return(NextOption(argv, optString));
X	else				/* We're done. */
X		return(EOF);
X}
X
X
X/* If the current argument does not begin with DASH, it is not an option.
X * Return EOF.
X * If we have ONLY a DASH, and nothing after it... return EOF as well.
X * If we have a DASH followed immediately by another DASH, this is the
X * special "--" option that means "no more options follow."  Return EOF.
X * Otherwise, we have an actual option or list of options.  Process it. */
X	
Xstatic int NextOption(char *argv[], char *optString)
X{
X	static int optsSkipped = 0;	/* In a single argv[i]. */
X	
X	if ((argv[optind][0] == DASH)
X	&&  ((optopt = argv[optind][1+optsSkipped]) != '\0'))
X	{
X		if (optopt == DASH)
X		{
X			optind++;
X			return(EOF);
X		}
X		else
X			return(RealOption(argv, optString, &optsSkipped,
X					    &optind, optopt));
X	}
X	else
X		return(EOF);
X}
X
X
X/* At this point, we know that argv[optind] is an option or list of
X * options.  If this is a list of options, *optsSkipped tells us how
X * many of those options have ALREADY been parsed on previous calls
X * to getopt().
X * If the option is not legal (not in optString), complain and return
X * UNKNOWN_OPT.
X * If the option requires no argument, just return the option letter.
X * If the option requires an argument, call HandleArgument and return
X * the option letter. */
X	
Xstatic int RealOption(char *argv[], char *optString, int *optsSkipped,
X			int *optind, int optopt)
X{
X	char *where;
X
X	(*optsSkipped)++;
X	if (where = index(optString, optopt))
X	{
X		if (*(where+1) == ARG_COMING)
X			HandleArgument(argv, optind, optsSkipped);
X
X		Pass(argv, optind, optsSkipped);
X		return(optopt);
X	}
X	else
X	{
X		Error(ERROR_BAD_OPTION, optopt);
X		Pass(argv, optind, optsSkipped);
X		return(UNKNOWN_OPT);
X	}
X}
X
X
X/* We have an option in argv[optind] that requires an argument.  If there
X * is no whitespace after the option letter itself, take the rest of
X * argv[optind] to be the argument.
X * If there IS whitespace after the option letter, take argv[optind+1] to
X * be the argument.
X * Otherwise, if there is NO argument, complain! */
X
Xstatic void HandleArgument(char *argv[], int *optind, int *optsSkipped)
X{
X	if (argv[*optind][1+(*optsSkipped)])
X		optarg = argv[*optind] + 1 + (*optsSkipped);
X	else if (argv[(*optind)+1])
X	{
X		optarg = argv[(*optind)+1];
X		(*optind)++;
X	}
X	else
X		Error(ERROR_MISSING_ARGUMENT, optopt);
X
X	(*optsSkipped) = 0;
X	(*optind)++;
X}
X
X
X/* Print an appropriate error message. */
X
Xstatic void Error(int err, int c)
X{
X	static char *optmsg = "Illegal option.\n";
X	static char *argmsg = "An argument is required, but missing.\n";
X
X	if (opterr)
X	{
X		if (err == ERROR_BAD_OPTION)
X			fprintf(stderr, "-%c: %s", c, optmsg);
X		else if (err == ERROR_MISSING_ARGUMENT)
X			fprintf(stderr, "-%c: %s", c, argmsg);
X
X		else	/* Sanity check! */
X			fprintf(stderr, "-%c: an unknown error occurred\n",
X				c);
X	}
X}
X
X
X/* We have reached the end of argv[optind]... there are no more options
X * in it to parse.  Skip to the next item in argv. */
X
Xstatic void Pass(char *argv[], int *optind, int *optsSkipped)
X{
X	if (argv[*optind]
X	&&  (argv[*optind][0] == DASH)
X	&&  (argv[*optind][1+(*optsSkipped)] == NULL))
X	{
X		(*optind)++;
X		(*optsSkipped) = 0;
X	}
X}
X
X/***************************************************************************
X* A test program.  Compile this file with -DTESTME as an option.
X***************************************************************************/
X
X#ifdef TESTME
Xmain(int argc, char *argv[])
X{
X	char c;
X
X	while ((c = getopt(argc, argv, "a:b:cde")) != EOF)
X    	{
X		printf("OPTION %c", c);
X		if ((c == 'a') || (c == 'b'))
X			printf(", %s\n", optarg);
X		else
X			printf("\n");
X		printf("argc=%d, optind=%d\n", argc, optind);
X	}
X	exit(0);
X}
X#endif
END_OF_FILE
if test 7295 -ne `wc -c <'Source/getopt.c'`; then
    echo shar: \"'Source/getopt.c'\" unpacked with wrong size!
fi
# end of 'Source/getopt.c'
fi
if test -f 'Source/help.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/help.c'\"
else
echo shar: Extracting \"'Source/help.c'\" \(2340 characters\)
sed "s/^X//" >'Source/help.c' <<'END_OF_FILE'
X/**************************************************************************
X* help.c:	Functions for giving help to the user.
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#include "mp.h"
X#include "version.h"
X
X	
X/* Print a detailed help message. */
X
Xvoid Help(char *progName)
X{
X	FILE *fp = stderr;
X
X	fprintf(fp, "MIDI Playground (%s), version %s, by Daniel Barrett."
X		    "  100%% Public Domain!\n",
X		progName, VERSION);
X	fprintf(fp,
X	   "Usage: %s -%c<FORMAT> -%c<FORMAT> [-%c infile] [-%c outfile]\n",
X	   progName,
X	   OPT_INPUT, OPT_OUTPUT, OPT_INFILE, OPT_OUTFILE);
X
X	fprintf(fp,
X		"The program quits at end-of-file, or when ^C is pressed.\n");
X
X	fprintf(fp, "\nThe flags may appear in any order:\n");
X	fprintf(fp, "\t-%c\tSpecify the input format.   [MANDATORY]\n",
X		OPT_INPUT);
X	fprintf(fp, "\t-%c\tSpecify the output format.  [MANDATORY]\n",
X		OPT_OUTPUT);
X	fprintf(fp, "\t\t\"-%c\" and \"-%c\" must EACH be followed by",
X		OPT_INPUT, OPT_OUTPUT);
X	fprintf(fp, " exactly one of:\n");
X	fprintf(fp, "\t\t\t%c\tText (readable by humans).\n", OPT_TEXT);
X	fprintf(fp, "\t\t\t%c\tBinary data (for files).\n", OPT_BINARY);
X	fprintf(fp, "\t\t\t%c\tMIDI (using MIDI port).\n", OPT_MIDI);
X	fprintf(fp, "\t-%c\tGet data from this file.    [Default=keyboard]\n",
X		OPT_INFILE);
X	fprintf(fp, "\t-%c\tPut data into this file.    [Default=screen]\n",
X		OPT_OUTFILE);
X
X	fprintf(fp, "\nExamples:\n");
X	fprintf(fp, "\t%s -%c%c -%c%c -%c data\t%s\n",
X		progName,
X		OPT_INPUT, OPT_MIDI, OPT_OUTPUT, OPT_BINARY,
X		OPT_OUTFILE,
X		"Read MIDI & put it into binary file \"data\".");
X	fprintf(fp,
X		"\t%s -%c%c -%c%c\t\tRead typed text, send to MIDI (fun!).\n",
X		progName,
X		OPT_INPUT, OPT_TEXT, OPT_OUTPUT, OPT_MIDI);
X
X	fprintf(fp, "\n\"%s -%c%c\" understands decimal, octal, hex,",
X		progName, OPT_INPUT, OPT_TEXT);
X	fprintf(fp, " binary, characters, and strings.\n");
X	fprintf(fp, "For details, type %c while in \"-%c%c\" mode.\n",
X		HELP_SYMBOL, OPT_INPUT, OPT_TEXT);
X}
X
X	
X/* Tell the user how to get more help. */
X
Xvoid BegForUsage(char *progName)
X{
X	fprintf(stderr, "Please type \"%s ?\" for instructions.\n",
X		progName);
X}
END_OF_FILE
if test 2340 -ne `wc -c <'Source/help.c'`; then
    echo shar: \"'Source/help.c'\" unpacked with wrong size!
fi
# end of 'Source/help.c'
fi
if test -f 'Source/iofunctions.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/iofunctions.c'\"
else
echo shar: Extracting \"'Source/iofunctions.c'\" \(3430 characters\)
sed "s/^X//" >'Source/iofunctions.c' <<'END_OF_FILE'
X/**************************************************************************
X* iofunctions.c:
X*		Functions for input/output in a variety of formats.	
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#include "mp.h"
X#include "midi.h"
X
X
X/* Read data from MIDI.  Return the value of the next MIDI byte.  Because
X * reading byte-by-byte from the MIDI port is inefficient, we read as
X * much as we can and keep it in a static buffer. */
X	
XMIDI_RESULT FromMidi(FILE *in, MIDI_VALUE *value)
X{
X	static long bytesWaiting = 0L;	/* # bytes waiting at serial port. */
X	static UBYTE buf[BUFSIZ];	/* Static buffer. */
X	static long currentByte = 0L;	/* Index of next byte to return. */
X
X	if (currentByte >= bytesWaiting)
X	{
X		bytesWaiting = FastSerialRead(buf);
X		currentByte = 0L;
X	}
X
X	if (bytesWaiting == CTRL_C_NO_BYTES)
X	{
X		bytesWaiting = currentByte = 0L;
X		return(RESULT_STOP);
X	}
X	else if (bytesWaiting <= 0)
X	{
X		bytesWaiting = currentByte = 0L;
X		return(RESULT_ERROR);
X	}
X	else
X	{
X		*value = buf[currentByte++];
X		return(RESULT_OK);
X	}
X}
X
X
X/* Write a byte to MIDI.  It is inefficient to write 1 byte at a time, but
X * we want instant transmission.  I will rewrite this eventually. */
X	
XBOOL ToMidi(FILE *dummy, MIDI_VALUE value)
X{
X	PrepareToWriteMidi(&value, 1);
X	return(DoTheIO() == 1L);
X}
X
X/* Read 1 byte from text.  We use a finite state automaton.
X * If an error occurs, assign the value of the last character read
X * to *answer. */
X	
XMIDI_RESULT FromText(FILE *in, MIDI_VALUE *value)
X{
X	STATE_T state = STATE_NORMAL;
X	int c;
X	
X	*value = 0L;
X
X	while ((state != STATE_SUCCESS) && (state != STATE_ERROR)
X	&&     (state != STATE_OVERFLOW)
X	&&     ((c = getc(in)) != EOF))
X
X		state = NewState(c, state, value);
X
X	if (state == STATE_SUCCESS)
X		return(RESULT_OK);
X	else if (c == EOF && state == STATE_NORMAL)
X		return(RESULT_STOP);
X	else if (c == EOF)
X		return(RESULT_ERROR);
X	else if (state == STATE_OVERFLOW)
X		return(RESULT_OVERFLOW);
X	else
X	{
X		*value = c;
X		return(RESULT_ERROR);
X	}
X}
X
X
X/* Write 1 MIDI value as text. */
X	
XBOOL ToText(FILE *out, MIDI_VALUE value)
X{
X	static long byt = 0L;
X
X	fprintf(out, "<%6ld>   ", ++byt);
X	PrintNumber(value, out);
X}
X
X
X/* Read 1 MIDI value from a binary file.  Inefficient. */
X	
XMIDI_RESULT FromBinary(FILE *in, MIDI_VALUE *value)
X{
X	int c;
X	if ((c = getc(in)) != EOF)
X	{
X	    	*value = (MIDI_VALUE)c;
X		return(RESULT_OK);
X	}
X
X	return(RESULT_STOP);
X}
X
X
X/* Write 1 MIDI value to a binary file.  Inefficient. */
X	
XBOOL ToBinary(FILE *out, MIDI_VALUE value)
X{
X	return(putc(value, out) != EOF);
X}
X
X	
X/****************************************************************************
X* Skipping input.
X****************************************************************************/
X
X	
X/* Skip to the next valid text input. */
X
Xvoid SkipText(FILE *in, MIDI_VALUE value)
X{
X	register int c;
X
X	if (isspace(value))
X		return;
X
X	while ((c = getc(in)) != EOF && !isspace(c))
X		;
X	if (c != EOF)
X		ungetc(c, in);
X}
X
X
X/* Skip to the next valid MIDI input by clearing the serial port buffer. */
X	
Xvoid SkipMidi(FILE *dummy, MIDI_VALUE junk)
X{
X	ResetSerialPort();
X}
X
X
X/* Skip to the next valid binary value.  This is currently just a stub. */
X	
Xvoid SkipBinary(FILE *in, MIDI_VALUE junk)
X{
X	return;
X}
END_OF_FILE
if test 3430 -ne `wc -c <'Source/iofunctions.c'`; then
    echo shar: \"'Source/iofunctions.c'\" unpacked with wrong size!
fi
# end of 'Source/iofunctions.c'
fi
if test -f 'Source/main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/main.c'\"
else
echo shar: Extracting \"'Source/main.c'\" \(4433 characters\)
sed "s/^X//" >'Source/main.c' <<'END_OF_FILE'
X/**************************************************************************
X* main.c:	The main program and supporting stuff.
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#include "mp.h"
X
XBOOL WorkbenchProgram(char *argv[]);
XBOOL CommandLineProgram(int argc, char *argv[]);
X	
Xmain(int argc, char *argv[])
X{
X	BOOL success;
X
X	if (argc == 0)
X	    success = WorkbenchProgram(argv);
X	else
X	    success = CommandLineProgram(argc, argv);
X
X	exit(success ? RETURN_OK : RETURN_FAIL);
X}
X
X	
X/************************************************************************
X* Initialization of important variables.
X************************************************************************/
X
Xvoid InitStuff(FLAGS theFlags[], FILE **in, FILE **out, char **inFile,
X		char **outFile)
X{
X	int i;
X
X	for (i=0; i<NUM_FLAGS; i++)	/* Flags. */
X		theFlags[i] = (FLAGS)0;
X
X	*in 	 = stdin;		/* Input file. */
X	*out	 = stdout;		/* Output file. */
X	*inFile  = NULL;		/* Input file name. */
X	*outFile = NULL;		/* Output file name. */
X}
X
X	
X/************************************************************************
X* Open the serial port if necessary, and have fun!
X************************************************************************/
X
XBOOL MIDIPlayground(FLAGS theFlags[], FILE *in, FILE *out)
X{
X	if ((theFlags[FLAG_ITYPE] == OPT_MIDI)
X	||  (theFlags[FLAG_OTYPE] == OPT_MIDI))
X	{
X		if (!SerialSetup(theFlags[FLAG_SYSEX]))
X			return(FALSE);
X		ResetSerialPort();
X	}
X
X	ReadAndWriteStuff(theFlags, in, out);
X
X
X	if ((theFlags[FLAG_ITYPE] == OPT_MIDI)
X	||  (theFlags[FLAG_OTYPE] == OPT_MIDI))
X		SerialShutdown();
X
X	return(TRUE);		/* Stub. */
X}
X
X	
X/************************************************************************
X* Use the appropriate I/O functions until we're done.
X************************************************************************/
X
Xvoid ReadAndWriteStuff(FLAGS theFlags[], FILE *in, FILE *out)
X{
X	MIDI_RESULT	result;
X	MIDI_VALUE	value;
X	MIDI_RESULT	(*getfcn)(FILE *f, MIDI_VALUE *value);
X	BOOL		(*putfcn)(FILE *f, MIDI_VALUE value);
X	void		(*skipfcn)(FILE *f, MIDI_VALUE value);
X
X	SetTheFunctions(&getfcn, &putfcn, &skipfcn, theFlags);
X	
X	while ((result = getfcn(in, &value)) != RESULT_STOP)
X	{
X		switch (result)
X		{
X			case RESULT_OK:
X				putfcn(out, value);
X				break;
X			case RESULT_ERROR:
X				fprintf(out, "ERROR\n");
X				skipfcn(in, value);
X				break;
X			case RESULT_OVERFLOW:
X				fprintf(out, "VALUE TOO BIG (overflow)\n");
X				skipfcn(in, value);
X				break;
X			default:
X				skipfcn(in, value);
X				fprintf(out, "An unknown error occurred.\n");
X				break;
X		}
X	}
X}
X
X
X/************************************************************************
X* Choose the appropriate I/O functions.
X************************************************************************/
X
Xvoid SetTheFunctions(MIDI_RESULT (**getfcn)(), BOOL (**putfcn)(),
X		    void (**skipfcn)(), FLAGS theFlags[])
X{
X	switch (theFlags[FLAG_ITYPE])
X	{
X		case OPT_TEXT:
X			*getfcn = FromText;
X			*skipfcn = SkipText;
X			break;
X		case OPT_BINARY:
X			*getfcn = FromBinary;
X			*skipfcn = SkipBinary;
X			break;
X		case OPT_MIDI:
X			*getfcn = FromMidi;
X			*skipfcn = SkipMidi;
X			break;
X		default:
X			*getfcn = FromText;	/* Least dangerous fcn. */
X			*skipfcn = SkipText;	/* Least dangerous fcn. */
X	}
X
X	switch (theFlags[FLAG_OTYPE])
X	{
X		case OPT_TEXT:
X			*putfcn = ToText;
X			break;
X		case OPT_BINARY:
X			*putfcn = ToBinary;
X			break;
X		case OPT_MIDI:
X			*putfcn = ToMidi;
X			break;
X		default:
X			*putfcn = ToText;	/* Least dangerous fcn. */
X			break;
X	}
X}
X
X
X/* Is "opt" a valid input/output type?  Set the flag too. */
X	
XBOOL CheckIOType(char opt, int ioFlag, FLAGS theFlags[])
X{
X	return(IsIOType(theFlags[ioFlag] = opt));
X}
X
X
X/* Is "ioType" a valid input/output type? */
X	
XBOOL IsIOType(char ioType)
X{
X	return(	(ioType == OPT_TEXT)
X	||	(ioType == OPT_BINARY)
X	||	(ioType == OPT_MIDI));
X}
X
X
X/* Did user specify both input and output types? */
X	
XBOOL CheckFlags(FLAGS theFlags[])
X{
X	return(theFlags[FLAG_ITYPE] && theFlags[FLAG_OTYPE]);
X}
X
X	
X/************************************************************************
X* ^C handling -- Manx stuff.
X************************************************************************/
X
Xvoid _abort(void)
X{
X	SerialShutdown();
X	exit(RETURN_FAIL);
X}
END_OF_FILE
if test 4433 -ne `wc -c <'Source/main.c'`; then
    echo shar: \"'Source/main.c'\" unpacked with wrong size!
fi
# end of 'Source/main.c'
fi
if test -f 'Source/midi.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/midi.h'\"
else
echo shar: Extracting \"'Source/midi.h'\" \(1182 characters\)
sed "s/^X//" >'Source/midi.h' <<'END_OF_FILE'
X#ifndef _MIDI_H
X#define _MIDI_H	1
X
X/***************************************************************************
X * MIDI values that are independent of any particular synthesizer.
X ***************************************************************************/
X
X/***************************************************************************
X * Some system-exclusive message constants.
X ***************************************************************************/
X
X#define	SYSEX_BEGIN	0xF0
X#define	SYSEX_END	0xF7
X
X/***************************************************************************
X * Allow use of MIDI interfaces not attached to the internal serial port,
X * unit 0.  Here are the defaults.
X ***************************************************************************/
X
X#define	DEFAULT_MIDI_DEVICE	"serial.device"
X#define	DEFAULT_MIDI_UNIT	0
X#define	MIDI_ENV_VAR		"MP_MIDI_DEVICE"
X
X#define	MIDI_BAUD_RATE		31250
X
X#ifndef CTRL_C_NO_BYTES
X#define CTRL_C_NO_BYTES		(-1)
X#endif
X
X/***************************************************************************
X * End of this header file.
X ***************************************************************************/
X
X#endif /* _MIDI_H */
END_OF_FILE
if test 1182 -ne `wc -c <'Source/midi.h'`; then
    echo shar: \"'Source/midi.h'\" unpacked with wrong size!
fi
# end of 'Source/midi.h'
fi
if test -f 'Source/mp.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/mp.h'\"
else
echo shar: Extracting \"'Source/mp.h'\" \(8727 characters\)
sed "s/^X//" >'Source/mp.h' <<'END_OF_FILE'
X/**************************************************************************
X* mp.h:		Main header file.
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#ifndef _MP_H
X
X#include <devices/serial.h>
X#include <exec/devices.h>
X#include <exec/memory.h>
X#include <exec/ports.h>
X#include <exec/types.h>
X#include <exec/interrupts.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <workbench/startup.h>
X#include <workbench/workbench.h>
X#include <functions.h>
X#include <stdio.h>
X
X#ifndef __C_MACROS__
X#define __C_MACROS__
X#endif
X#include <ctype.h>
X
X
X/**************************************************************************
X* Types.
X**************************************************************************/
X	
Xtypedef unsigned char	STATE_T;	/* An automaton state.		*/
Xtypedef UBYTE		MIDI_VALUE;	/* A single MIDI data value.	*/
Xtypedef	signed char	MIDI_RESULT;	/* What happened while reading?	*/
Xtypedef char		FLAGS;		/* Internal flags.		*/
X	
X/**************************************************************************
X* Return values from our input routine.
X**************************************************************************/
X	
X#define	RESULT_OK		(MIDI_RESULT)(1)    /* Legal value read.   */
X#define	RESULT_ERROR		(MIDI_RESULT)(2)    /* Illegal value read. */
X#define	RESULT_OVERFLOW		(MIDI_RESULT)(3)    /* Value overflowed.   */
X#define	RESULT_STOP		(MIDI_RESULT)(4)    /* End of data.        */
X	
X/**************************************************************************
X* States of our finite automaton for reading input.
X**************************************************************************/
X	
X#define	STATE_SUCCESS		1	/* Got a legal value. */
X#define	STATE_ERROR		2	/* Had an input error. */
X#define	STATE_OVERFLOW		3	/* Read too big a value. */
X#define	STATE_NORMAL		4	/* Haven't read anything yet. */
X#define	STATE_INCOMMENT		5	/* Skipping a comment. */
X#define	STATE_INDECIMAL		6	/* Reading a base 10 number. */
X#define	STATE_LEADZERO		7	/* Read a leading zero. */
X#define	STATE_INOCTAL		8	/* Reading an octal number. */
X#define	STATE_STARTHEX		9	/* Read 1st digit of hex number. */
X#define	STATE_INHEX		10	/* Reading a hex number. */
X#define	STATE_STARTBINARY	11	/* Read 1st symbol of binary num. */
X#define	STATE_INBINARY		12	/* Reading a binary number. */
X#define	STATE_NEGATIVE		13	/* UNUSED.  FOR FUTURE UPDATE. */
X#define	STATE_INCHAR		14	/* Reading a char constant. */
X#define	STATE_EXPECTQUOTE	15	/* Finishing a char constant. */
X#define	STATE_BACKSLASHINCHAR	16	/* Backslash in a char constant. */
X#define	STATE_BACKSLASHINSTRING	17	/* Backslash in a string constant. */
X#define	STATE_INCLUDEFILE	18	/* UNUSED.  FOR FUTURE UPDATE. */
X
X	
X/**************************************************************************
X* Macros for converting characters to numbers:
X*
X*	D_TO_INT(c)	Convert a digit to its numeric value.
X*	L_TO_INT(c)	Convert a letter (A..F) to its base 16 value.
X*	H_TO_INT(c)	Convert a hex digit to its numeric value.
X**************************************************************************/
X	
X#define	D_TO_INT(c)	((long)((c) - '0'))
X#define	L_TO_INT(c)	((long)((toupper(c)) - 'A') + 10)
X#define	H_TO_INT(c)	(isdigit(c) ? D_TO_INT(c) : L_TO_INT(c))
X	
X/**************************************************************************
X* Macros for classifying types of input.  The rest are in <ctype.h>.
X**************************************************************************/
X	
X#define	isoctal(c)	(((c) >= '0') && ((c) <= '7'))
X
X/**************************************************************************
X* Other macros.
X**************************************************************************/
X
X#define	MAX(a,b)	(((a) > (b)) ? (a) : (b))
X#define	MIN(a,b)	(((a) < (b)) ? (a) : (b))
X
X#define OpenReadFile(filename)	OpenAFile(filename, "r", "read")
X#define OpenWriteFile(filename)	OpenAFile(filename, "w", "write")
X
X	
X/**************************************************************************
X* The largest legal value our input routine can handle.
X**************************************************************************/
X	
X#define	LARGEST_VALUE		(MIDI_VALUE)(255)
X#define	BITS_IN_MIDI_VALUE	BITSPERBYTE		/* in types.h */
X
X/***************************************************************************
X* Character constants for classifying the input.
X***************************************************************************/
X
X#define	START_BINARY	'#'	/* Symbol for start of binary number. */
X#define	HELP_SYMBOL	'?'	/* Symbol for help request from user. */
X#define	START_COMMENT	';'	/* Start-comment symbol. */
X	
X/***************************************************************************
X* Command-line Options.
X***************************************************************************/
X
X#define	OPT_INPUT	'i'		/* Input format. */
X#define	OPT_OUTPUT	'o'		/* Output format. */
X#define	OPT_TEXT	't'		/* Text I/O. */
X#define	OPT_BINARY	'b'		/* Binary I/O. */
X#define	OPT_MIDI	'm'		/* MIDI I/O. */
X#define	OPT_SYSEX	'x'		/* UNUSED. FOR FUTURE UPDATE. */
X#define	OPT_INFILE	'g'		/* Get from file. */
X#define	OPT_OUTFILE	'p'		/* Put to file. */
X
X/* For getopt(). */
X#define	GETOPT_OPTIONS	"i:o:g:p:x";
Xextern int optind;
Xextern char *optarg;
X
X/***************************************************************************
X* Flags, and their associated macros.
X***************************************************************************/
X
X#define	NUM_FLAGS	3	/* How many flags? */
X
X#define	FLAG_ITYPE	0	/* Flag ID's. */
X#define	FLAG_OTYPE	1
X#define	FLAG_SYSEX	2
X
X	
X/***************************************************************************
X* Prototypes.
X***************************************************************************/
X
X/* read.c */
XSTATE_T NewState(int c, STATE_T state, MIDI_VALUE *answer);
XSTATE_T NonStringState(int c, STATE_T state, MIDI_VALUE *answer);
XSTATE_T DoNormal(int c, MIDI_VALUE *answer);
XSTATE_T DoDecimal(int c, MIDI_VALUE *answer);
XSTATE_T DoOctal(int c, MIDI_VALUE *answer);
XSTATE_T DoHex(int c, MIDI_VALUE *answer);
XSTATE_T DoInHex(int c, MIDI_VALUE *answer);
XSTATE_T DoBinary(int c, MIDI_VALUE *answer);
XSTATE_T DoInBinary(int c, MIDI_VALUE *answer);
XSTATE_T DoLeadZero(int c, MIDI_VALUE *answer);
XSTATE_T IncreaseIfPossible(MIDI_VALUE *answer, int newNum, int base, 
X				STATE_T newState);
XSTATE_T DoInChar(int c, MIDI_VALUE *answer);
XSTATE_T DoExpectQuote(int c, MIDI_VALUE *answer);
XSTATE_T DoBackslash(int c, MIDI_VALUE *answer, STATE_T newState);
XSTATE_T DoInString(int c, STATE_T state, MIDI_VALUE *answer,
X			 short *inString);
XSTATE_T DoComment(int c);
Xvoid InputHelp();
X
Xvoid PrintNumber(MIDI_VALUE number, FILE *out);
Xvoid PrintBinary(MIDI_VALUE number, FILE *out);
X
X/* serial.c */
Xshort SerialSetup(FLAGS sysex);
Xvoid SerialShutdown(void);
Xvoid ResetSerialPort(void);
Xlong AnyMidiData(void);
Xvoid PrepareToReadMidi(UBYTE *buf, int len);
Xvoid PrepareToWriteMidi(UBYTE *buf, int len);
Xlong DoTheIO(void);
Xlong FastSerialRead(UBYTE buf[]);
X
X/* iofunctions.c */
XMIDI_RESULT FromMidi(FILE *in, MIDI_VALUE *value);
XBOOL ToMidi(FILE *in, MIDI_VALUE value);
XMIDI_RESULT FromText(FILE *in, MIDI_VALUE *value);
XBOOL ToText(FILE *in, MIDI_VALUE value);
XMIDI_RESULT FromBinary(FILE *in, MIDI_VALUE *value);
XBOOL ToBinary(FILE *in, MIDI_VALUE value);
Xvoid SkipText(FILE *in, MIDI_VALUE value);
Xvoid SkipMidi(FILE *in, MIDI_VALUE junk);
Xvoid SkipBinary(FILE *in, MIDI_VALUE junk);
X
X/* main.c */
XBOOL IsIOType(char ioType);
XBOOL CheckIOType(char opt, int ioFlag, FLAGS theFlags[]);
XBOOL HandleOptions(int argc, char *argv[], FLAGS theFlags[],
X		   char **infile, char **outfile);
Xvoid ReadAndWriteStuff(FLAGS theFlags[], FILE *in, FILE *out);
Xvoid SetTheFunctions(MIDI_RESULT (**getfcn)(), BOOL (**putfcn)(),
X		    void (**skipfcn)(), FLAGS theFlags[]);
XBOOL CheckFlags(FLAGS theFlags[]);
Xvoid InitStuff(FLAGS theFlags[], FILE **in, FILE **out, char **inFile,
X		char **outFile);
XBOOL MIDIPlayground(FLAGS theFlags[], FILE *in, FILE *out);
X
X/* wb.c */
X
X/* help.c */
Xvoid BegForUsage(char *progName);
Xvoid Help(char *progName);
X
X/* files.c */
XFILE *OpenAFile(char *filename, char *mode, char *readOrWrite);
XBOOL FileExists(char *filename);
XBOOL DontOverwriteExistingFile(char *filename);
XBOOL SetupFiles(char *infile, char *outfile, FILE **in, FILE **out);
Xvoid CloseFiles(FILE *in, FILE *out, char *filein, char *fileout);
XBOOL MakeFilename(char **dest, char *src);
X
X#ifndef OpenReadFile
XFILE *OpenReadFile(char *filename);
X#endif
X
X#ifndef OpenWriteFile
XFILE *OpenWriteFile(char *filename);
X#endif
X
X
X#endif /* _MP_H */
END_OF_FILE
if test 8727 -ne `wc -c <'Source/mp.h'`; then
    echo shar: \"'Source/mp.h'\" unpacked with wrong size!
fi
# end of 'Source/mp.h'
fi
if test -f 'Source/serial.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/serial.c'\"
else
echo shar: Extracting \"'Source/serial.c'\" \(7123 characters\)
sed "s/^X//" >'Source/serial.c' <<'END_OF_FILE'
X/**************************************************************************
X* serial.c:	Serial port access functions.
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#include "mp.h"
X#include "midi.h"
X
Xstatic struct MsgPort	*MidiPort	= NULL;
Xstatic struct IOExtSer	*Midi		= NULL;
Xlong serialFlags			= 0L;
X
X#define	F_MIDIPORT	1
X#define	F_MIDI		2
X#define	F_DEVICE	4
X#define	F_SERPARAMS	8
X
X
XBOOL AllDigits(char *str);
Xchar *GetEnv(char *str);
XBOOL MakeSerialDeviceName(char *str, char *device, int *unit);
X
X	
X/****************************************************************************
X * SerialSetup:  Open the serial port and its message port.
X * Allow for an alternate MIDI device in an environment variable.
X ***************************************************************************/
X
XBOOL SerialSetup(FLAGS sysex)
X{
X	char deviceName[BUFSIZ], *envVar;
X	int unit;
X
X	/* Set the defaults. */
X
X	strcpy(deviceName, DEFAULT_MIDI_DEVICE);
X	unit = DEFAULT_MIDI_UNIT;
X
X	/* If environment variable is set, find the real MIDI device info. */
X
X	if ((envVar = GetEnv(MIDI_ENV_VAR))
X	&& (!MakeSerialDeviceName(envVar, deviceName, &unit)))
X		return(FALSE);
X
X	/* Create a port. */
X
X	if (! (MidiPort = CreatePort(0, 0)) )
X	{
X		fprintf(stderr, "Cannot create port\n");
X		SerialShutdown();
X		return(FALSE);
X	}
X	else
X		serialFlags |= F_MIDIPORT;
X
X	/* Create an extended I/O structure. */
X
X	if (! (Midi = (struct IOExtSer *)
X	CreateExtIO(MidiPort, sizeof(struct IOExtSer))))
X	{
X		fprintf(stderr, "Cannot create extended I/O structure\n");
X		SerialShutdown();
X		return(FALSE);
X	}
X	else
X		serialFlags |= F_MIDI;
X
X	/* Open the serial device. */
X
X	Midi->io_SerFlags = SERF_SHARED;
X	if (OpenDevice(deviceName, unit, (struct IORequest *)Midi, 0))
X	{
X		fprintf(stderr,
X			"Cannot open serial device \"%s\", unit %d.\n",
X			deviceName, unit);
X		SerialShutdown();
X		return(FALSE);
X	}
X	else
X		serialFlags |= F_DEVICE;
X
X	/* Set the serial device parameters. */
X
X	Midi->io_SerFlags		= SERF_RAD_BOOGIE;
X	if (sysex)
X	{
X		Midi->io_TermArray.TermArray0	= 0xF7F7F7F7;
X		Midi->io_TermArray.TermArray1	= 0xF7F7F7F7;
X		Midi->io_SerFlags |= SERF_EOFMODE;
X	}
X	Midi->io_Baud			= MIDI_BAUD_RATE;
X	Midi->io_ExtFlags		= 0;	/* For future compatibility */
X	Midi->IOSer.io_Command		= SDCMD_SETPARAMS;
X
X	if (DoIO((struct IORequest *)Midi) != 0)
X 	{
X		fprintf(stderr, "Cannot set serial parameters.\n");
X		SerialShutdown();
X		return(FALSE);
X	}
X	else
X		serialFlags |= F_SERPARAMS;
X
X	return(TRUE);
X}
X
X
X/****************************************************************************
X * SerialShutdown:  Close the serial port and its message port.
X ***************************************************************************/
X
Xvoid SerialShutdown(void)
X{
X	if (serialFlags & F_DEVICE)
X	{
X		ResetSerialPort();
X		AbortIO((struct IORequest *)Midi);
X		WaitIO((struct IORequest *)Midi);
X		CloseDevice((struct IORequest *)Midi);
X	}
X
X	if (serialFlags & F_MIDI)
X		DeleteExtIO((struct IORequest *)Midi);
X
X	if (serialFlags & F_MIDIPORT)
X		DeletePort(MidiPort);
X}
X
X/****************************************************************************
X * ResetSerialPort:  Clear all data from the serial port.
X ***************************************************************************/
X
Xvoid ResetSerialPort(void)
X{
X	Midi->IOSer.io_Command = CMD_CLEAR;
X	DoIO((struct IORequest *)Midi);
X}
X
X
X/****************************************************************************
X * Is any data there?
X ***************************************************************************/
X
Xlong AnyMidiData(void)
X{
X	Midi->IOSer.io_Command = SDCMD_QUERY;
X	DoIO((struct IORequest *)Midi);
X	return(Midi->IOSer.io_Actual);
X}
X
X	
X/****************************************************************************
X * PrepareToReadMidi:	Prepare a READ request for the MIDI port.
X * PrepareToWriteMidi:	Prepare a WRITE request for the MIDI port.
X ***************************************************************************/
X
Xvoid PrepareToReadMidi(UBYTE buf[], int len)
X{
X	Midi->IOSer.io_Command = CMD_READ;
X	Midi->IOSer.io_Data = (APTR)buf;
X	Midi->IOSer.io_Length = len;
X}
X
X
Xvoid PrepareToWriteMidi(UBYTE buf[], int len)
X{
X	Midi->IOSer.io_Command = CMD_WRITE;
X	Midi->IOSer.io_Data = (APTR)buf;
X	Midi->IOSer.io_Length = len;
X}
X
X
X/****************************************************************************
X* DoTheIO:  General-purpose MIDI I/O routine.  Quits on ^C.
X****************************************************************************/
X
Xlong DoTheIO(void)
X{
X	int mask, temp;
X	long bytesDone = 0L;
X
X	mask = SIGBREAKF_CTRL_C | (1L << MidiPort->mp_SigBit);
X	SendIO((struct IORequest *)Midi);
X
X	while (1)
X	{
X		temp = Wait(mask);
X		if (temp & SIGBREAKF_CTRL_C)
X		{
X			bytesDone = CTRL_C_NO_BYTES;
X			break;
X		}
X
X		if (CheckIO((struct IORequest *)Midi))
X		{
X			WaitIO((struct IORequest *)Midi);
X			bytesDone = Midi->IOSer.io_Actual;
X			break;
X		}
X	}
X
X	AbortIO((struct IORequest *)Midi);
X	WaitIO((struct IORequest *)Midi);
X	return(bytesDone);
X}
X
X
X/****************************************************************************
X* Fast serial reading routine, from idea on 1.3 RKM's page 863.
X* If any data is waiting, get all of it with DoIO().  Otherwise, post an
X* asynchronous request for 1 byte.  Repeat this in the calling program.
X****************************************************************************/
X
Xlong FastSerialRead(UBYTE buf[])
X{
X	long bytesWaiting, bytesRead;
X
X	if ((bytesWaiting = AnyMidiData()) > 0)
X	{
X		PrepareToReadMidi(buf, MIN(bytesWaiting, BUFSIZ));
X		DoIO((struct IORequest *)Midi);
X		return(Midi->IOSer.io_Actual);
X	}
X	else
X	{
X		PrepareToReadMidi(buf, 1);
X		return(DoTheIO());
X	}
X}
X
X	
X/****************************************************************************
X* Allow the use of another MIDI device than serial.device.
X* Environment variable syntax is "DEVICENAME:UNITNUMBER".
X* For example:  "midi.device:2".
X*
X* "device" MUST be preallocated.
X****************************************************************************/
X
XBOOL MakeSerialDeviceName(char *str, char *device, int *unit)
X{
X	while (str && *str && (*str != ':'))
X		*(device++) = *(str++);
X
X	*device = '\0';
X
X	if ((*str != ':') || *(str+1) == '\0')
X	{
X		fprintf(stderr,
X			"Your MIDI device name (variable "
X			MIDI_ENV_VAR
X			") is missing a colon\nand/or a unit number.\n");
X		return(FALSE);
X	}
X	str++;
X
X	if (!AllDigits(str))
X	{
X		fprintf(stderr,
X			"Your MIDI device unit number (variable "
X			MIDI_ENV_VAR
X			") must be\na positive integer.\n");
X		return(FALSE);
X	}
X	else
X		*unit = atoi(str);
X
X	return(TRUE);
X}
X
X
X/* AllDigits:	Return TRUE iff the string "str" consists only of digits. */
X
XBOOL AllDigits(char *str)
X{
X	if ((!str) || (*str == '\0'))		/* NULL or empty string. */
X		return(FALSE);
X	else
X		while (*str)			/* For each character... */
X			if (!isdigit(*str))	/*  if not a digit...    */
X				return(FALSE);	/*  goodbye!             */
X			else
X				str++;
X	return(TRUE);				/* All were digits.      */
X}
END_OF_FILE
if test 7123 -ne `wc -c <'Source/serial.c'`; then
    echo shar: \"'Source/serial.c'\" unpacked with wrong size!
fi
# end of 'Source/serial.c'
fi
if test -f 'Source/text.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/text.c'\"
else
echo shar: Extracting \"'Source/text.c'\" \(9628 characters\)
sed "s/^X//" >'Source/text.c' <<'END_OF_FILE'
X/**************************************************************************
X* text.c:	Functions for text input/output.
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#include "mp.h"
X
X
X/* Given the currently read character and the current state, compute
X * the new state and the MIDI value. */
X	
XSTATE_T NewState(int c, STATE_T state, MIDI_VALUE *answer)
X{
X	static BOOL inString = FALSE;
X
X	if (inString)
X		return(DoInString(c, state, answer, &inString));
X	else if (c == HELP_SYMBOL)
X	{
X		InputHelp();
X		return(state);
X	}
X	else if (state == STATE_NORMAL && c == '\"')
X	{
X		inString = TRUE;
X		return(STATE_NORMAL);	/* Doesn't matter. */
X	}
X	else
X		return(NonStringState(c, state, answer));
X}
X
X/****************************************************************************
X* Our finite automaton for non-strings.  Process the character and return
X* the new state.
X****************************************************************************/
X	
XSTATE_T NonStringState(int c, STATE_T state, MIDI_VALUE *answer)
X{
X	switch (state)
X	{
X		case STATE_NORMAL:	return(DoNormal(c, answer));
X		case STATE_INCOMMENT:	return(DoComment(c));
X		case STATE_INDECIMAL:	return(DoDecimal(c, answer));
X		case STATE_INOCTAL:	return(DoOctal(c, answer));
X		case STATE_STARTHEX:	return(DoHex(c, answer));
X		case STATE_INHEX:	return(DoInHex(c, answer));
X		case STATE_LEADZERO:	return(DoLeadZero(c, answer));
X		case STATE_INCHAR:	return(DoInChar(c, answer));
X		case STATE_STARTBINARY:	return(DoBinary(c, answer));
X		case STATE_INBINARY:	return(DoInBinary(c, answer));
X		case STATE_EXPECTQUOTE:	return(DoExpectQuote(c, answer));
X		case STATE_BACKSLASHINCHAR:
X			return(DoBackslash(c, answer, STATE_EXPECTQUOTE));
X		case STATE_SUCCESS:	
X		case STATE_OVERFLOW:	
X		case STATE_ERROR:	return(state);
X	}
X}
X
X
X/****************************************************************************
X* We are not currently in a number.  A character is read; decide what to
X* do with it.
X****************************************************************************/
X	
XSTATE_T DoNormal(int c, MIDI_VALUE *answer)
X{
X	if (isspace(c))
X		return(STATE_NORMAL);
X	else if (c == START_COMMENT)
X		return(STATE_INCOMMENT);
X	else if (c == START_BINARY)
X		return(STATE_STARTBINARY);
X	else if (c == '\'')
X		return(STATE_INCHAR);
X	else if (c == '0')
X		return(STATE_LEADZERO);
X	else if (toupper(c) == 'H')
X		return(STATE_STARTHEX);
X	else if (isdigit(c))
X	{
X		*answer = D_TO_INT(c);
X		return(STATE_INDECIMAL);
X	}
X	else if (isxdigit(c))
X	{
X		*answer = H_TO_INT(c);
X		return(STATE_INHEX);
X	}
X	else
X		return(STATE_ERROR);
X}
X
X	
X/****************************************************************************
X* Base 10 (decimal) numbers.
X****************************************************************************/
X	
XSTATE_T DoDecimal(int c, MIDI_VALUE *answer)
X{
X	if (isdigit(c))
X		return(IncreaseIfPossible(answer, D_TO_INT(c), 10, 
X			STATE_INDECIMAL));
X	else if (isspace(c))
X		return(STATE_SUCCESS);
X	else
X		return(STATE_ERROR);
X}
X
X	
X/****************************************************************************
X* Octal numbers.
X****************************************************************************/
X	
XSTATE_T DoOctal(int c, MIDI_VALUE *answer)
X{
X	if (isoctal(c))
X		return(IncreaseIfPossible(answer, D_TO_INT(c), 8, 
X			STATE_INOCTAL));
X	else if (isspace(c))
X		return(STATE_SUCCESS);
X	else
X		return(STATE_ERROR);
X}
X
X
X/****************************************************************************
X* Hexadecimal numbers.
X****************************************************************************/
X	
XSTATE_T DoHex(int c, MIDI_VALUE *answer)
X{
X	if (isxdigit(c))
X	{
X		*answer = H_TO_INT(c);
X		return(STATE_INHEX);
X	}
X	else
X		return(STATE_ERROR);
X}
X
X
XSTATE_T DoInHex(int c, MIDI_VALUE *answer)
X{
X	if (isxdigit(c))
X		return(IncreaseIfPossible(answer, H_TO_INT(c), 16, 
X			STATE_INHEX));
X	else if (isspace(c))
X		return(STATE_SUCCESS);
X	else
X		return(STATE_ERROR);
X}
X
X
X/****************************************************************************
X* Binary numbers.
X****************************************************************************/
X	
XSTATE_T DoBinary(int c, MIDI_VALUE *answer)
X{
X	if ((c == '0') || (c == '1'))
X	{
X	    	*answer = D_TO_INT(c);
X		return(STATE_INBINARY);
X	}
X	else
X		return(STATE_ERROR);
X}
X
X	
XSTATE_T DoInBinary(int c, MIDI_VALUE *answer)
X{
X	if ((c == '0') || (c == '1'))
X		return(IncreaseIfPossible(answer, D_TO_INT(c), 2, 
X			STATE_INBINARY));
X	else if (isspace(c))
X		return(STATE_SUCCESS);
X	else
X		return(STATE_ERROR);
X}
X
X	
X/****************************************************************************
X* Hook for negative numbers.  Commented out right now.
X****************************************************************************/
X	
X#ifdef ALLOW_NEGATIVE
XSTATE_T DoNegative(int c, MIDI_VALUE *answer)
X{
X	if (c == '0')
X		return(STATE_LEADZERO);
X	else if (isdigit(c))
X	{
X		return(STATE_INDECIMAL);
X	}
X	else
X		return(STATE_ERROR);
X}
X#endif /* ALLOW_NEGATIVE */
X
X	
X/****************************************************************************
X* Leading zero was found:  Do octal or hexadecimal as required.
X****************************************************************************/
X	
XSTATE_T DoLeadZero(int c, MIDI_VALUE *answer)
X{
X	if (toupper(c) == 'X')
X		return(STATE_STARTHEX);
X	else if (isoctal(c))
X	{
X		*answer = D_TO_INT(c);
X		return(STATE_INOCTAL);
X	}
X	else if (isspace(c))
X		return(STATE_SUCCESS);
X	else
X		return(STATE_ERROR);
X}
X
X	
X/****************************************************************************
X* Append the digit "newNum" onto the right of the number *answer.
X* Don't allow overflow.  Works for any base.  Return newState on success.
X****************************************************************************/
X	
XSTATE_T IncreaseIfPossible(MIDI_VALUE *answer, int newNum, int base,
X			   STATE_T newState)
X{
X	if ((*answer) > (LARGEST_VALUE / base))
X		return(STATE_OVERFLOW);
X	else
X	{
X		*answer *= base;
X
X		if ((*answer) > (LARGEST_VALUE - newNum))
X			return(STATE_OVERFLOW);
X		else
X		{
X			*answer += newNum;
X			return(newState);
X		}
X	}
X}
X
X
X/****************************************************************************
X* Character-oriented routines.
X****************************************************************************/
X	
XSTATE_T DoInChar(int c, MIDI_VALUE *answer)
X{
X	if (c == '\\')
X		return(STATE_BACKSLASHINCHAR);
X	else
X	{
X		*answer = c;
X		return(STATE_EXPECTQUOTE);
X	}
X}
X
X	
XSTATE_T DoExpectQuote(int c, MIDI_VALUE *answer)
X{
X	return((c == '\'') ? STATE_SUCCESS : STATE_ERROR);
X}
X
X
XSTATE_T DoBackslash(int c, MIDI_VALUE *answer, STATE_T newState)
X{
X	switch (c)
X	{
X		case '0':	*answer = '\0';		break;
X		case 'a':	*answer = '\a';		break;
X		case 'b':	*answer = '\b';		break;
X	    	case 'f':	*answer = '\f';		break;
X		case 'n':	*answer = '\n';		break;
X		case 'r':	*answer = '\r';		break;
X		case 't':	*answer = '\t';		break;
X		case 'v':	*answer = '\v';		break;
X		case '\\':
X		case '\'':
X		case '\"':	*answer = c;		break;
X		default:	return(STATE_ERROR);
X	}
X	return(newState);
X}
X
X
X/****************************************************************************
X* String-oriented routines.
X****************************************************************************/
X	
XSTATE_T DoInString(int c, STATE_T state, MIDI_VALUE *answer, BOOL *inString)
X{
X	switch (state)
X	{
X		case STATE_NORMAL:
X			if (c == '\"')
X			{
X				*inString = FALSE;
X			    	return(STATE_NORMAL);
X			}
X			else if (c == '\\')
X				return(STATE_BACKSLASHINSTRING);
X			else
X			{
X				*answer = isspace(c) ? ' ' : c;
X				return(STATE_SUCCESS);
X			}
X			break;
X		case STATE_BACKSLASHINSTRING:
X			return(DoBackslash(c, answer, STATE_SUCCESS));
X	}
X}
X
X
X/****************************************************************************
X* Handling comments.  Everything from comment symbol to the end of the
X* line is a comment.
X****************************************************************************/
X
XSTATE_T DoComment(int c)
X{
X	return( (c == '\n') ? STATE_NORMAL : STATE_INCOMMENT );
X}
X	
X/****************************************************************************
X* Getting help.
X****************************************************************************/
X	
X
Xvoid InputHelp()
X{
X	fprintf(stderr, "INPUT\tMEANING\n"
X			"1-9...\tDecimal number.\n"
X			"0...\tOctal number.\n"
X			"0x...\tHexadecimal number (case-insensitive).\n"
X			"H...\tHexadecimal number (case-insensitive).\n"
X			"A-F...\tHexadecimal number (case-insensitive).\n"
X			"#...\tBinary number.\n"
X			"'x'\tThe character 'x'."
X			"  C character syntax like \\n and \\t is valid.\n"
X			"\"...\"\tA text string."
X			"  (Newlines turn into space characters.)\n"
X			"Largest legal input value is %ld (base 10).\n"
X			"All values must be separated by whitespace.\n\n",
X		LARGEST_VALUE);
X}
X
X
X/****************************************************************************
X* Text output functions.
X****************************************************************************/
X	
Xvoid PrintNumber(MIDI_VALUE number, FILE *out)
X{
X	fprintf(out, "Dec %3ld, Oct %3lo, Hex %3lX",
X		number, number, number);
X
X	PrintBinary(number, out);
X
X	if (isprint((char)number))
X		fprintf(out, ", Char '%c'", number);
X
X	putc('\n', out);
X}
X
X
Xvoid PrintBinary(MIDI_VALUE number, FILE *out)
X{
X	char buf[BITS_IN_MIDI_VALUE + 1];
X	int i, on;
X
X	for (i=0; i<BITS_IN_MIDI_VALUE; i++)
X	{
X		on = number & (1 << i);
X		buf[BITS_IN_MIDI_VALUE-i-1] = '0' + (char)(on && 1);
X	}
X
X	buf[BITS_IN_MIDI_VALUE] = '\0';
X	fprintf(out, ", Bin %s", buf);
X}
END_OF_FILE
if test 9628 -ne `wc -c <'Source/text.c'`; then
    echo shar: \"'Source/text.c'\" unpacked with wrong size!
fi
# end of 'Source/text.c'
fi
if test -f 'Source/version.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/version.h'\"
else
echo shar: Extracting \"'Source/version.h'\" \(628 characters\)
sed "s/^X//" >'Source/version.h' <<'END_OF_FILE'
X/**************************************************************************
X* version.h:	The version number.
X*		Part of MP, the MIDI Playground.
X*
X* Author:	Daniel Barrett
X* Version:	See the file "version.h".
X* Copyright:	None!  This program is in the Public Domain.
X*		Please share it with others.
X***************************************************************************/
X
X	
X#ifndef _VERSION_H
X
X/**************************************************************************
X* Program version number.
X**************************************************************************/
X	
X#define	VERSION		"1.0"
X	
X#endif /* _VERSION_H */
END_OF_FILE
if test 628 -ne `wc -c <'Source/version.h'`; then
    echo shar: \"'Source/version.h'\" unpacked with wrong size!
fi
# end of 'Source/version.h'
fi
if test -f 'Source/wb.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Source/wb.c'\"
else
echo shar: Extracting \"'Source/wb.c'\" \(86 characters\)
sed "s/^X//" >'Source/wb.c' <<'END_OF_FILE'
XBOOL WorkbenchProgram(char *argv[])
X{
X	/* For future expansion. */
X
X	return(FALSE);
X}
END_OF_FILE
if test 86 -ne `wc -c <'Source/wb.c'`; then
    echo shar: \"'Source/wb.c'\" unpacked with wrong size!
fi
# end of 'Source/wb.c'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.misc.