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.