home *** CD-ROM | disk | FTP | other *** search
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /* |_o_o|\\ Copyright (c) 1986 The Software Distillery. All Rights Reserved */
- /* |. o.| || This program may not be distributed without the permission of */
- /* | . | || the authors. */
- /* | o | || Dave Baker Ed Burnette Stan Chow Jay Denebeim */
- /* | . |// Gordon Keener Jack Rouse John Toebes Doug Walker */
- /* ====== BBS:(919)-471-6436 VOICE:(919)-469-4210 */
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /*
- * VERY loosely based on the input.device example by Rob Peck, 12/1/85
- */
-
- #include "popcli.h"
- #include "popbug.h"
-
- /* KLUDGE: (sort of) These strings can ONLY be accessed if gptr->stdout */
- /* is non-zero, since they *should* be in the PopCLI hunk that */
- /* gets thrown away. */
- #define CSI "\x9B"
- #define HILIT CSI "0;33m"
- #define BOLD CSI "1m"
- #define PLAIN CSI "0m"
- #define COPYR "\xA9"
-
- char killmsg[] =
- HILIT "PopCLI IV" PLAIN " Terminating\n";
-
- char banner[] =
- HILIT "PopCLI IV" PLAIN
- " - Copyright " COPYR " 1987,1989 The Software Distillery\n"
- " 235 Trillingham Lane, Cary NC 27513 BBS:(919)-471-6436\n";
-
- char helpmsg[] =
- "Usage:\n"
- " " BOLD "POPCLI" PLAIN " [[secs | ADD | REPL] [key]] [[cmdmods] [CMD] cmnd]\n"
- " " BOLD "POPCLI" PLAIN " FREE [key]\n"
- " " BOLD "POPCLI" PLAIN " EXEC [key]\n"
- " " BOLD "POPCLI" PLAIN " BLANK\n"
- " " BOLD "POPCLI" PLAIN " UNBLANK\n"
- " " BOLD "POPCLI" PLAIN " TIME n\n"
- " " BOLD "POPCLI" PLAIN " QUIT\n"
- " cmdmods: [NOWB] [MINMEM n] [MINCHIP n]\n"
- "where:\n"
- " secs is the number of seconds before blanking screen\n"
- " key is the scan code for the key to press with Left Amiga\n"
- " <decimal>, 0x<hex>, F{1-10}, DEL, ESC, or 'c',\n"
- " where c is any ASCII character from ' ' to '~'\n"
- " ADD Activates Left Amiga-<key> without altering the blanking time\n"
- " REPL Same as ADD, but more mnemonic for redefining a key\n"
- " NOWB don't bring the workbench screen to front before executing command\n"
- " MINMEM Make sure at least n bytes are available before executing command\n"
- " MINCHIP Like MINMEM, but checks for chip memory only.\n"
- " CMD Optional tag, in case command starts with a keyword or number\n"
- " cmnd is to be executed when Left Amiga-<key> is pressed\n"
- " FREE Deactivates Left Amiga-<key>, but leaves POPCLI up\n"
- " EXEC Executes the given key\n"
- " BLANK Blanks the screen immediately\n"
- " UNBLANK Unblanks the screen, resetting the timer countdown\n"
- " TIME Sets the timeout value without clobbering any key definitions\n"
- " QUIT Brings down POPCLI and all command keys.\n"
- "\n"
- "From ARexx: ADDRESS POPCLI4 <popcli-arguments>\n";
-
- /* Make this a multiple of 2 bytes long!!! */
- struct KEYWORD {
- char name[8];
- char command;
- char wherenum;
- };
-
- #define KW_QUIT 0
- #define KW_NOWB 1
- #define KW_CMD 2
- #define KW_ESC 3
- #define KW_DEL 4
- #define KW_ADD 5
- #define KW_REPL 6
- #define KW_FREE 7
- #define KW_TIME 8
- #define KW_MEM 9
- #define KW_CHIP 10
- #define KW_EXEC 11
- #define KW_BLNK 12
- #define KW_UNBL 13
-
- #define NUM_NONE 0
- #define NUM_KEY 1
- #define NUM_TIME 2
- #define NUM_MEM -1
- #define NUM_CHIP -2
-
- #define ISMEMNUM(n) (n < 0)
-
- #ifdef CONST_KLUDGE
- #define PARSETBL_KLUDGE \
- "quit\0\0\0\0" "\04" "\01" \
- "nowb\0\0\0\0" "\00" "\01" \
- "cmd\0\0\0\0\0" "\00" "\01" \
- "esc\0\0\0\0\0" "\00" "\01" \
- "del\0\0\0\0\0" "\00" "\01" \
- "add\0\0\0\0\0" "\01" "\01" \
- "repl\0\0\0\0" "\01" "\01" \
- "free\0\0\0\0" "\02" "\01" \
- "time\0\0\0\0" "\07" "\02" \
- "minmem\0\0" "\00" "\xff" \
- "minchip\0" "\00" "\xfe" \
- "exec\0\0\0\0" "\03" "\01" \
- "blank\0\0\0" "\05" "\01" \
- "unblank\0" "\06" "\01" \
- "\00" /* To ensure even alignment */
-
- #define KW_MAX 14
-
-
- #else
- const struct KEYWORD parsetbl[] = {
- { "quit", MSG_SHUTDOWN, NUM_KEY },
- { "nowb", MSG_NONE, NUM_KEY },
- { "cmd", MSG_NONE, NUM_KEY },
- { "esc", MSG_NONE, NUM_KEY },
- { "del", MSG_NONE, NUM_KEY },
- { "add", MSG_ADDKEY, NUM_KEY },
- { "repl", MSG_ADDKEY, NUM_KEY },
- { "free", MSG_DELKEY, NUM_KEY },
- { "time", MSG_SETTIME, NUM_TIME },
- { "minmem", MSG_NONE, NUM_MEM },
- { "minchip", MSG_NONE, NUM_CHIP },
- { "exec", MSG_EXECUTE, NUM_KEY },
- { "blank", MSG_BLANK, NUM_KEY },
- { "unblank", MSG_UNBLANK, NUM_KEY }
- };
- #define KW_MAX ((sizeof(parsetbl))/(sizeof(struct KEYWORD)))
- #endif
-
- #define MAXKWLEN 8
-
- #define KWCMP(a,b) ((*(long *)a) == (*(long *)b) && \
- ((long *)a)[1] == ((long *)b)[1])
-
- /* SCODE table characters are in the following order: */
-
- /* !"#$%&'()*+,-./ */
- /* @ABCDEFGHIJKLMNO */
- /* PQRSTUVWXYZ[\]^_ */
- /* `abcdefghijklmno */
- /* pqrstuvwxyz{|}~ */
-
- #define SCODE \
- "\x40\x01\x2a\x03\x04\x05\x07\x2a\x09\x0a\x08\x0c\x38\x0b\x39\x3a" \
- "\x0a\x01\x02\x03\x04\x05\x06\x07\x08\x09\x29\x29\x38\x0b\x39\x3a" \
- "\x02\x20\x35\x33\x22\x12\x23\x24\x25\x17\x26\x27\x28\x37\x36\x18" \
- "\x19\x10\x13\x21\x14\x16\x34\x11\x32\x15\x31\x1a\x0d\x1b\x06\x0a" \
- "\x00\x20\x35\x33\x22\x12\x23\x24\x25\x17\x26\x27\x28\x37\x36\x18" \
- "\x19\x10\x13\x21\x14\x16\x34\x11\x32\x15\x31\x1a\x0d\x1b\x00\x46"
-
- static void WriteOut( GLOBAL_DATA *, char *, int );
-
- void popbanner( gptr )
- GLOBAL_DATA *gptr;
- {
- WriteOut( gptr, banner, sizeof(banner)-1 );
- }
-
- void poptrailer( gptr )
- GLOBAL_DATA *gptr;
- {
- WriteOut( gptr, killmsg, sizeof(killmsg)-1 );
- }
-
- int popparse( gptr, cmd, msg )
- GLOBAL_DATA *gptr;
- register char *cmd;
- register struct OURMSG *msg;
- {
- long buff[MAXKWLEN/sizeof(long)+1];
- char *p, *q;
- int kw;
- int len;
- int value;
- char wherenum;
- #ifdef CONST_KLUDGE
- struct KEYWORD *parsetbl = (struct KEYWORD *)PARSETBL_KLUDGE;
- #endif
-
- msg->type = MSG_ADDKEY;
- msg->interval = 0;
- msg->key = DEFKEY;
- msg->minmem = 0;
- msg->minchip = 0;
- strcpy( msg->command, DEFCMD );
- msg->cmdflags = 0;
-
- wherenum = NUM_TIME;
-
- /* if we were run from CLI then output our banner and process parameters */
- if (!cmd)
- return( OK );
-
- if (*cmd == '?')
- {
- WriteOut(gptr, helpmsg, sizeof(helpmsg)-1);
-
- return( LEAVE );
- }
-
- while( *cmd )
- {
- while (*cmd && *cmd <= ' ') cmd++;
-
- /* Fetch the next keyword into a temp. buffer, lowercasing */
- buff[0] = buff[1] = 0;
-
- for (p = cmd, q = (char *)buff; *p > ' '; *q++ = (*p++ | ' '))
- {
- /* Too long to be a keyword... */
- if (q >= ((char *)buff)+MAXKWLEN)
- goto gotacmd;
- }
-
- for (kw = 0; kw < KW_MAX; kw++)
- {
- if (KWCMP(parsetbl[kw].name, buff))
- {
- /* We found a valid keyword! */
-
- wherenum = parsetbl[kw].wherenum;
- if (parsetbl[kw].command != MSG_NONE)
- msg->type = parsetbl[kw].command;
-
- switch( kw ) {
- case KW_QUIT:
- return(SHUTDOWN);
- break;
-
- case KW_NOWB:
- msg->cmdflags |= FLAG_NOWB2F;
- break;
-
- case KW_CMD:
- /* Skip intervening blanks, then treat as a command */
- for (cmd = p; *cmd && *cmd == ' '; cmd++);
-
- goto gotacmd;
- break;
-
- case KW_ESC:
- msg->key = 0x45;
- break;
-
- case KW_DEL:
- msg->key = 0x46;
- break;
-
- /* These are all handled by the table code!! */
- /* NOTE: I have arranged the parse table such that all */
- /* of these have larger values than the keywords which */
- /* actually *do* something here. I have to comment out */
- /* the case labels, though, because the compiler would */
- /* put them in the jump table anyway. */
- /* case KW_ADD: */
- /* case KW_REPL: */
- /* case KW_FREE: */
- /* case KW_TIME: */
- /* case KW_MEM: */
- /* case KW_CHIP: */
- /* case KW_EXEC: */
- /* case KW_BLNK: */
- /* case KW_UNBL: */
- default:
- break;
- }
-
- goto kwdone;
- }
- }
-
- /* No keywords found; must be a key, number, or command */
-
- if (*((char *)buff) == 'f')
- {
- /* User possibly typed F1-F10, but if not, we don't */
- /* want to complain, just get the command */
- len = stcd_i( ((char *)buff)+1, &value ) + 1;
-
- if (((char *)buff)[len] || (value < 1) || (value > 10))
- /* Treat it as a command */
- goto gotacmd;
- else
- {
- wherenum = NUM_KEY;
- value += 0x4f; /* Translate to scan code */
- }
- }
- else if (*((short *)buff) == 0x3078) /* "0x" */
- {
- /* Number is in hex, rather than decimal */
- len = stch_i( ((char *)buff)+2, &value ) + 2;
- }
- else if (*((char *)buff) == '\'') /* ' */
- {
- /* Number is an actual key picture */
- value = SCODE[(((char *)buff)[1] & 0x7f)-' '];
- len = 3;
- }
- else
- len = stcd_i( (char *)buff, &value );
-
- /* Make sure we got a valid value. If not, must be a */
- /* start of a command. */
- if (((char *)buff)[len])
- {
- goto gotacmd; /* Leaves the function */
- }
-
- if (value && ISMEMNUM(wherenum))
- {
- value = ((value >> 10) + 1);
- if (wherenum == NUM_MEM)
- msg->minmem = value;
- else
- msg->minchip = value;
- }
- else if (wherenum == NUM_TIME)
- msg->interval = value;
- else
- msg->key = value;
-
- kwdone:
- cmd = p;
- }
-
- gotacmd:
- if (*cmd)
- {
- strncpy( msg->command, cmd, MAXCMD-1 );
- msg->command[MAXCMD-1] = '\0';
- }
-
- return(OK);
- }
-
- static void WriteOut( gptr, msg, len )
- GLOBAL_DATA *gptr;
- char *msg;
- int len;
- {
- if (gptr->stdout)
- Write( gptr->stdout, msg, len );
- }
-
-