home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
530b.lha
/
AMenu_v1.3
/
Parse.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-03
|
12KB
|
404 lines
/*********************************************************************\
** ________________________________ **
** A n t h o n y |________ __ __ ________| **
** | |o_| |o_| | **
** T h y s s e n __| __ __ |__ **
** __| __| | | |__ |__ **
** `` Dragon Computing ! '' __| __| | | |__ |__ **
** |_____| |__| |_____| **
** **
\*********************************************************************/
/* Parse the users configuration file to set up the extra workbench
** menus to execute various commands is various ways.
** (See documentation)
*/
#undef DBUG /* don't debug this unless nessary! */
#include "AMenu.h"
#include "AllocStr.h" /* allocation/copy macro routines */
/* Externs */
extern UBYTE Color[], TColor[];
extern UWORD FontWidth;
extern USHORT ItemStyle;
extern unsigned MenuGap, WBMenus;
extern void Warn(char *);
extern void StartMenu(), AddTitle(char *), AddSkip();
extern struct ExtMenuItem *AddItem(char *, char);
extern void AddMenu(char *, int), AddSubMenu(char *, int);
extern void EndMenu(), EndSubMenu();
extern BOOL FinishMenu();
enum status { /* Parse structure levels */
STAT_ENTRY, STAT_MENU, STAT_SUB
};
/* Multi character tokens */
enum {
EOF = -1, STRING,
CONSOLE, DIRECTORY, COLOR, TCOLOR, STYLE, COMP, BOX, MENUGAP,
MENU, SUBMENU, ENDMENU, ENDSUBMENU, COLUMNS, ITEM, TITLE, SKIP,
RB, RUNBACK, CLI, SCR, SCRIPT, WB, STK, PRI, CON, DIR, EndToken
}; /* Note command the modes `RB' to `WB' must be in together */
/* The Arp keyword parsing string - in numeral order of tokens above */
char *TokenTemplate =
"CONSOLE,DIRECTORY,COLOR,TCOLOR,STYLE,COMP,BOX,MENUGAP,MENU,SUBMENU,ENDMENU,ENDSUBMENU,COLUMNS,ITEM,TITLE,SKIP,RB,RUNBACK,CLI,SCR,SCRIPT,WB,STK,PRI,CON,DIR";
/* checks on the type of a commands argument */
#define isstring(t) ( (t)<EndToken ) /* is the token any string */
#define isnumber(t) ( isstring(t) && isdigit(*String) )
#define S_SIZE 80
char String[S_SIZE], NextChar; /* string token, char after string */
BPTR Config; /* File Handle */
/* NOTE :- The Lattice 5.04 library function `isalnum()' is
** incorrect in that the characters :;<=>?@ are true (is an
** alphanumeric character). The library functions `isdigit()'
** and `isalpha()' is correct, and thus used instead.
** The macro isalnum() in "ctype.h" works correctly, but
** involves the linking of the 256 byte flag buffer `_ctype[]'
** used by the macros.
*/
#define isalnum(c) (isalpha(c) || isdigit(c))
/*--------------------------------------*/
static int LineNum = 0; /* Line number in config file - 0 = No Need */
/* return a True on any error given to the user */
#define ReportError(Msg) { UserReport(Msg); return TRUE; }
static void
UserReport(Msg)
char *Msg;
{
if( LineNum )
SPrintf(String, "%s : Line %ld \"%s\"", VERSION, LineNum, Msg);
else
SPrintf(String, "%s : \"%s\"", VERSION, Msg);
Printf("\n%s\n", String); /* CLI Report */
Warn(String); /* WB Report */
}
static char
GetC()
{
char c = EOF;
Read(Config, &c, 1);
if( c == '\n' )
LineNum++;
return c;
}
static char
GetToken()
{
char quote;
register char tok, *p;
register int i;
retry:
while(isspace(tok=GetC())); /* skip extra spaces */
if( tok == '#' ) { /* comment */
while( (tok=GetC()) != '\n' && tok != EOF ) ;
goto retry;
}
quote = (tok == '"');
if( !quote && !isalnum(tok) ) /* individual Char */
return tok;
if( quote ) /* remove open quote */
tok=GetC();
/* scan string token -- while !EOF, space in buffer */
for( i=0, p=String;
tok != EOF && i < (S_SIZE-1) && (quote ? tok!='"' : !isspace(tok));
*p++=tok, i++, tok=GetC() );
*p = '\0';
NextChar = tok; /* record the next character after String */
/* Use ARP to sort the keywords from the strings */
tok = GetKeywordIndex( String, TokenTemplate ) + 1; /* convert token */
DB( Printf( "%s ", String ); )
return tok;
}
static BOOL
ParseConfig()
{
register char t, Statement;
struct ExtMenuItem *EItem;
char Name[80], CommandChar, *p;
BOOL OptionLoop;
enum status status = STAT_ENTRY;
int Columns;
LineNum = 1; /* report config line number on errors */
DB( Printf("\n"); )
while ( (Statement=GetToken()) != EOF ) {
switch( Statement ) {
case CONSOLE:
if( !isstring(GetToken()) )
ReportError("Bad CONSOLE Argument");
if( M->Console ) FreeStr(M->Console);
M->Console = AllocStr(String);
break;
case DIRECTORY:
if( !isstring(GetToken()) )
ReportError("Bad DIRECTORY Argument");
if( M->Directory ) FreeStr(M->Directory);
M->Directory = AllocStr(String);
break;
case COLOR:
if( !isnumber(GetToken()) )
ReportError("Bad COLOR Argument 1");
Color[0] = (UWORD)Atol(String);
if( !isnumber(GetToken()) )
ReportError("Bad COLOR Argument 2");
Color[1] = (UWORD)Atol(String);
break;
case TCOLOR:
if( !isnumber(GetToken()) )
ReportError("Bad TCOLOR Argument 1");
TColor[0] = (UWORD)Atol(String);
if( !isnumber(GetToken()) )
ReportError("Bad TCOLOR Argument 2");
TColor[1] = (UWORD)Atol(String);
break;
case STYLE:
switch( GetToken() ) {
case COMP: ItemStyle = HIGHCOMP; break;
case BOX: ItemStyle = HIGHBOX; break;
default:
ReportError("Bad STYLE Argument");
}
break;
case MENUGAP:
if( !isnumber(GetToken()) )
ReportError("Bad MENUGAP Argument");
MenuGap = (UWORD)Atol(String);
if( MenuGap<1 || MenuGap>50 )
ReportError("MENUGAP out of range");
MenuGap *= FontWidth;
break;
case MENU:
switch( status ) { /* fall through switch */
case STAT_SUB:
EndSubMenu();
case STAT_MENU:
EndMenu();
}
status = STAT_MENU;
Columns = 1;
if( (t=GetToken() == COLUMNS ) ) {
if( !isnumber(t=GetToken()) )
ReportError("Bad COLUMNS Argument");
Columns = Atol(String);
t=GetToken();
}
if( !isstring(t) )
ReportError("Missing Menu Name");
AddMenu( String, Columns );
break;
case SUBMENU:
switch( status ) {
case STAT_ENTRY:
ReportError("Menu Statement expected");
case STAT_SUB:
EndSubMenu();
}
status = STAT_SUB;
Columns = 1;
if( (t=GetToken() == COLUMNS ) ) {
if( !isnumber(t=GetToken()) )
ReportError("Bad COLUMNS Argument");
Columns = Atol(String);
t=GetToken();
}
if( !isstring(t) )
ReportError("Missing SubMenu Name");
AddSubMenu( String, Columns );
break;
case ENDMENU:
switch( status ) {
case STAT_ENTRY:
ReportError("Menu Statment expected");
case STAT_SUB:
EndSubMenu();
}
EndMenu();
status = STAT_ENTRY;
break;
case ENDSUBMENU:
if( status != STAT_SUB ) {
ReportError("SubMenu Statment expected");
}
EndSubMenu();
status = STAT_MENU;
break;
case SKIP: /* these are pretty simular */
case TITLE:
case ITEM:
switch( status ) {
case STAT_ENTRY:
ReportError("Menu Statement expected");
}
if( Statement == SKIP ) { /* if Skip finish up */
AddSkip();
break;
}
if( !isstring(GetToken()) )
ReportError("Missing Item/Title Name");
strcpy(Name, String);
if( Statement == TITLE ) { /* if Title finish up */
AddTitle(Name);
break;
}
CommandChar = '\0';
if( (t=GetToken()) == '<' ) { /* command char */
CommandChar = GetC();
if( GetToken() != '>' )
ReportError("Missing closing '>'");
t = GetToken();
}
if( t != '|' )
ReportError("Missing '|' separator");
DB( Printf("| "); )
EItem = AddItem(Name, CommandChar);
if( (t=GetToken()) < RB || t > WB )
ReportError("Missing Execution Mode");
EItem->Mode = Toupper(String[0]); /* R,C,S,W as appropiate */
EItem->Stack = DEF_STACK; /* Default Stack Size */
EItem->Pri = 0; /* Default Prioity */
for( OptionLoop=TRUE; OptionLoop; ) {
switch( t=GetToken() ) {
case STK: /* Stack -- All modes */
if( !isnumber(t=GetToken()) )
ReportError("Bad STK Argument");
EItem->Stack = (ULONG)Atol(String);
if( EItem->Stack < 500 || EItem->Stack > 1000000 )
ReportError("Bad STACK Size given");
break;
case PRI: /* Prioity -- All modes */
{ BOOL neg;
if( neg = ( (t=GetToken()) == '-') ) t=GetToken();
if( !isnumber(t) )
ReportError("Bad PRI Argument");
EItem->Pri = (BYTE)Atol(String);
if(neg) EItem->Pri = -EItem->Pri;
}
break;
case CON: /* Console -- CLI & SCRIPT only */
if( EItem->Mode != 'C' && EItem->Mode != 'S' )
ReportError("`CON' -- CLI or SCRIPT modes only");
if( !isstring(t=GetToken()) )
ReportError("Bad CON Argument");
if( EItem->Console ) FreeStr(M->Console);
EItem->Console = AllocStr(String);
break;
case DIR: /* Current Directory -- not WB */
if( EItem->Mode == 'W' )
ReportError("`DIR' -- not in WB mode");
if( !isstring(t=GetToken()) )
ReportError("Bad DIR Argument");
if( EItem->Directory ) FreeStr(M->Directory);
EItem->Directory = AllocStr(String);
break;
default:
OptionLoop = FALSE;
break;
} /* switch */
} /* option loop */
/* command */
if( !isstring(t) )
ReportError("Bad Command Given");
EItem->Cmd = AllocStr(String);
/* read arguments */
t = NextChar; /* char following command string*/
while( t != '\n' && t != EOF && isspace(t) )
t=GetC(); /* skip space */
p = String;
while( t != '\n' && t != EOF ) {
*p++ = t; /* read in rest of line */
t = GetC(t);
}
*p++ = '\n'; /* make it a proper command line */
*p = '\0';
if( EItem->Mode != 'W' && EItem->Mode != 'S' ) /* ignore args? */
EItem->Args = AllocStr(String);
break; /* end of ITEM statement */
default:
ReportError("Keyword Expected");
}
DB( Printf("-END\n"); )
} /* While Token */
switch( status ) {
case STAT_SUB:
EndSubMenu();
case STAT_MENU:
EndMenu();
}
LineNum = 0; /* finished config file - no more syntax errors */
return FALSE;
}
BOOL
ParseMenus()
/* Open and Read the Config File -- return FALSE if no error */
{
BOOL Error;
if( M->Directory ) FreeStr(M->Directory);
M->Directory = AllocStr(DEF_DIRECTORY);
if( M->Console ) FreeStr(M->Console);
M->Console = AllocStr(DEF_CONSOLE);
StartMenu();
if( WBMenus != 3 )
ReportError("Unusual Workbench Menus Found!");
Config = ArpOpen(AMENU_CONFIG, MODE_OLDFILE);
if( !Config ) {
Config = ArpOpen(AMENU_CONFIG2, MODE_OLDFILE); /* closed by Arp */
if( !Config )
ReportError("Can't find file");
}
Error = ParseConfig();
if( !Error && FinishMenu() ) {
SPrintf(String, "%s : \"%s\"", VERSION,
"Warning: Menu Overflows WorkBench Screen!");
Warn(String); /* Warning - don't abort */
}
return Error;
}