home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume13
/
okbridge
/
part03
/
startup.c
< prev
Wrap
C/C++ Source or Header
|
1992-01-12
|
11KB
|
419 lines
/* startup.c
!
! Copyright (C) 1991 by Matthew Clegg
!
! This program may be copied and distributed freely. Please do not
! charge money for this program or for any program derived from it.
! If you modify this program, then include a notice stating plainly
! that your program is derived from the okbridge program and is not
! the same as the official okbridge program.
!
! I welcome any suggestions for improvement to okbridge, and
! I would be especially happy to receive improved source code.
! If you have comments or suggestions, or if you would like to
! join the okbridge mailing list, then write to
!
! mclegg@cs.ucsd.edu
!
*
* This file contains procedures for reading the okbridge startup
* file .okbridgerc. Each line in this file is either a comment line
* or a (field, value) pair. Comment lines begin with the pound sign
* '#' character. Field, value pairs are of the format
* <Field-name> <value>
*
* The fields which are currently recognized are as follows:
*
* BELL ON | OFF
* When requesting input (a bid or a play), the terminal's
* bell is rung by default. However, this can be disabled
* by specifying 'BELL OFF'. This has the same effect as the
* '/BELL OFF' command.
*
* DEFAULT ON | OFF
* This controls whether or not default inputs will be provided for
* bids, plays and questions.
*
* HELPFILE <directory-name>
* This field specifies the directory to be used for reading
* the okbridge help files.
*
* LOAD <email-duplicate-filename>
* This field is only valid if the position is north and the
* scoring mode is email duplicate. In this case, okbridge will
* automatically read a set of email duplicate boards from the
* named file.
*
* LOG <filename>
* If this statement is present in the startup file, then
* the hands will automatically be logged to the given filename.
* If the first character of <filename> is '+', then logs the
* hands to the end of the file rather than erasing the old file.
*
* NAME <local-player-name>
* This field specifies the name that will be used to identify
* the local player to the other players.
*
* POSITION NORTH | EAST | SOUTH | WEST
* This field specifies the local player's position.
*
* PORT <positive-integer>
* This field specifies the internet port number that will be
* used for communications with the server.
*
* PROMPT NO | YES
* The value of this field is only relevant in hands where the
* local player is the dummy. In this case, the dummy is
* ordinarily prompted to press RETURN at the end of each trick.
* This allows the dummy to see the cards that are played as they
* are played. However, if 'PROMPT NO' is specified, then the
* dummy will not be prompted.
*
* REPLAY <email-duplicate-filename>
* This field is only valid if the position is north and the
* scoring mode is email duplicate. In this case, a set of
* boards will automatically be read from the named file.
* After they have been played, the results will automatically
* be written back to the file from which the boards were read.
*
* SCORING RUBBER | CHICAGO | DUPLICATE | EMAIL | IMP
* This field is only relevant if the local player is north.
* In this case, the SCORING field determines the type of scoring
* that will be used by default in the game.
*
* SERVER ME | <internet-name-or-number>
* If the value of this field is 'ME', then the local player
* will assume the role of server. If the value of this field
* is anything else, then it is interpreted as an internet name
* or number of the machine where the server is running.
*
*/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "globals.h"
extern char *getenv ();
extern char *strdup ();
#ifdef HPUX
#define index(X,Y) strchr(X,Y)
#else
#ifndef index
extern char *index ();
#endif
#endif
#define MAX_LENGTH 100
typedef void (*field_handler) ();
typedef struct Field_Descriptor_struct {
char *field_name;
char *parameter_type;
field_handler handler;
} Field_Descriptor;
void Bell_Field (), Default_Field (), Helpfile_Field (), Load_Field (),
Log_Field (), Name_Field (), Position_Field (), Port_Field (),
Prompt_Field (), Replay_Field (), Scoring_Field (), Server_Field ();
static Field_Descriptor Fields [] = {
{"BELL", "OFF,ON", Bell_Field},
{"DEFAULT", "OFF,ON", Default_Field},
{"HELPFILE", "*", Helpfile_Field},
{"LOAD", "*", Load_Field},
{"LOG", "*", Log_Field},
{"NAME", "*", Name_Field},
{"POSITION", "NORTH,EAST,SOUTH,WEST", Position_Field},
{"PORT", "#", Port_Field},
{"PROMPT", "NO,YES", Prompt_Field},
{"REPLAY", "*", Replay_Field},
{"SCORING", "RUBBER,CHICAGO,DUPLICATE,EMAIL,IMP", Scoring_Field},
{"SERVER", "*", Server_Field},
{NULL, NULL, NULL}
};
static char line_buffer [MAX_LENGTH];
static int current_char, last_pos;
static int line_length;
static int line_no;
static FILE *init_file;
static int error_flag;
extern int errno;
extern char *sys_errlist[];
extern int ring_my_bell;
extern char *help_file_name;
extern FILE *logfile;
extern int local_player;
extern int network_port;
extern int server_mode;
extern char *server_name;
extern char *local_player_name;
extern char *autoload_file, *autosave_file;
static Field_Error (error_msg)
char *error_msg;
/* Prints out the current line from the field file along with an error
message.
*/
{
int i;
fprintf (stderr, "line %2d: %s\n", line_no, line_buffer);
for (i = 0; i < last_pos + 9; i++)
fprintf (stderr, " ");
fprintf (stderr, "^ %s\n", error_msg);
error_flag = 1;
};
static void Bell_Field (i)
int i;
{
ring_my_bell = i;
};
static void Default_Field (i)
int i;
{
default_plays = i;
};
static void Helpfile_Field (s)
char *s;
{
help_file_name = strdup (s);
};
static void Load_Field (s)
char *s;
{
autoload_file = strdup (s);
};
static void Log_Field (s)
char *s;
{
char error_buf [80];
char *filename;
if (s[0] == '+') {
filename = s + 1;
logfile = fopen (filename, "a");
} else {
filename = s;
logfile = fopen (filename, "w");
};
if (logfile == NULL) {
sprintf (error_buf, "Error opening %s: %s", filename,
sys_errlist[errno]);
Field_Error (error_buf);
};
};
static void Name_Field (s)
char *s;
{
local_player_name = strdup (s);
};
static void Position_Field (i)
int i;
{
local_player = i;
};
static void Port_Field (i)
int i;
{
network_port = i;
};
static void Prompt_Field (i)
int i;
{
prompt_dummy = i;
};
static void Replay_Field (s)
char *s;
{
autoload_file = strdup (s);
autosave_file = strdup (s);
};
static void Scoring_Field (i)
int i;
{
scoring_mode = i;
};
static void Server_Field (s)
char *s;
{
if (!strcasecmp(s, "ME"))
server_mode = 1;
else {
server_mode = 0;
server_name = strdup (s);
};
};
static int Read_Field_Line ()
/* Reads a line from initialization file init_file and copies it into
line_buffer. Returns 1 if data is returned, or 0 if the end of file
is reached. Skips comment lines. Strips trailing blanks from the
end of the line.
*/
{
int ch;
do {
line_length = 0;
ch = getc (init_file);
while ((ch != EOF) && (ch != '\n')) {
if (line_length < MAX_LENGTH)
line_buffer [line_length++] = ch;
ch = getc(init_file);
};
if (ch == EOF)
return (0);
line_no++;
while (line_buffer[line_length-1] == ' ')
line_length--;
} while ((line_length == 0) || (line_buffer[0] == '#'));
current_char = 0;
line_buffer[line_length] = '\0';
return (1);
};
static int Read_Keyword (buf, buflen)
char *buf; int buflen;
/* Reads a whitespace delimited sequence of characters from the current
input line into the buffer. Returns the number of characters
transferred.
*/
{
int i;
i = 0;
while ((current_char < line_length) &&
isspace (line_buffer[current_char]))
current_char++;
last_pos = current_char;
while ((current_char < line_length) &&
!isspace(line_buffer[current_char])) {
if (i < buflen-1)
buf[i++] = line_buffer[current_char++];
else
current_char++;
};
buf[i] = '\0';
return (i);
};
static int Lookup_Keyword (lookup_string, keyword)
char *lookup_string, *keyword;
/* Assumes that lookup_string is a comma-delimited sequence of keywords.
Looks for the keyword in lookup_string which matches the given keyword.
If the keyword is found, then returns its index in lookup_string,
i.e., Lookup_Keyword ("OFF,ON", "OFF") = 0,
Lookup_Keyword ("OFF,ON", "ON") = 1.
If the keyword is not found, then returns -1.
*/
{
int i, n;
i = 0;
n = strlen (keyword);
while (lookup_string != NULL) {
if (!strncasecmp(lookup_string, keyword, n)) {
if ((lookup_string[n] == '\0') ||
(lookup_string[n] == ','))
return (i);
};
i += 1;
lookup_string = index (lookup_string, ',');
if (lookup_string != NULL) lookup_string++;
};
return (-1);
};
static int all_digits (s)
char *s;
{
while (*s)
if (!isdigit(*(s++)))
return (0);
return (1);
};
void Read_Initialization_File ()
{
char *home_dir, filename_buf[128];
char name [20], value [80], message_buf[80];
int i, j;
init_file = fopen (".okbridgerc", "r");
home_dir = getenv ("HOME");
if ((init_file == NULL) && (home_dir != NULL)) {
sprintf (filename_buf, "%s/.okbridgerc", home_dir);
init_file = fopen (filename_buf, "r");
};
if (init_file == NULL) {
/* couldn't find an initialization file. */
return;
};
error_flag = 0;
while (Read_Field_Line()) {
Read_Keyword (name, 20);
i = 0;
while ((Fields[i].field_name != NULL) &&
strcmp(Fields[i].field_name, name))
i++;
if (Fields[i].field_name == NULL)
Field_Error ("Error in field name");
else {
Read_Keyword (value, 80);
if (current_char < line_length)
Field_Error ("Extra data at end of line");
if (Fields[i].parameter_type[0] == '*')
Fields[i].handler (value);
else if (Fields[i].parameter_type[0] == '#') {
if (all_digits(value))
Fields[i].handler (atoi(value));
else
Field_Error ("Expected a positive integer");
} else {
j = Lookup_Keyword (Fields[i].parameter_type, value);
if (j < 0) {
sprintf (message_buf, "Expected keyword: %s",
Fields[i].parameter_type);
Field_Error (message_buf);
} else
Fields[i].handler (j);
};
};
};
fclose (init_file);
if (error_flag) {
fprintf (stderr, "\n%s -- %s\n",
"Errors in .okbridgerc initialization file",
"Program terminating");
exit (1);
};
};