Metropoli BBS
VIEWER: get_lang.c MODE: TEXT (ASCII)
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                                                                          */
/*      ------------         Bit-Bucket Software, Co.                       */
/*      \ 10001101 /         Writers and Distributors of                    */
/*       \ 011110 /          Freely Available<tm> Software.                 */
/*        \ 1011 /                                                          */
/*         ------                                                           */
/*                                                                          */
/*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
/*                                                                          */
/*               This module was written by Vince Perriello                 */
/*                                                                          */
/*             BinkleyTerm Language Compiler Raw Input Module               */
/*                                                                          */
/*                                                                          */
/*    For complete  details  of the licensing restrictions, please refer    */
/*    to the License  agreement,  which  is published in its entirety in    */
/*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
/*                                                                          */
/*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
/*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
/*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
/*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
/*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
/*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
/*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
/*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
/*                                                                          */
/*                                                                          */
/* You can contact Bit Bucket Software Co. at any one of the following      */
/* addresses:                                                               */
/*                                                                          */
/* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
/* P.O. Box 460398                AlterNet 7:42/1491                        */
/* Aurora, CO 80046               BBS-Net  86:2030/1                        */
/*                                Internet f491.n343.z1.fidonet.org         */
/*                                                                          */
/* Please feel free to contact us at any time to share your comments about  */
/* our software and/or licensing policies.                                  */
/*                                                                          */
/*--------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __TURBOC__
#include <mem.h>
#else
#ifdef _MSC_VER_
#include <memory.h>
#else
#include <string.h>
#endif
#endif

#define DOS16

#ifdef OS_2
#define OS_IDENT "OS2"
#undef DOS16
#endif

#ifdef _WIN32
#define OS_IDENT "WNT"
#undef DOS16
#endif

#ifdef DOS16
#define OS_IDENT "DOS"
#endif

#include "language.h"

int parse_escapes (char *);

/*
 *  get_language - read in BinkleyTerm language source
 *
 * Read lines into table, ignoring blanks and comments
 * Store into a contiguous block of memory with the individual
 *     members being referenced by an array of pointers
 * Store number of lines read into pointer_size
 * Store amount of memory used into memory_size
 *
 */

int 
get_language (char *name_of_file)
{
	int len;					/* length of current string  */
	int count_from_file;		/* no. of strings in file    */
	int file_version;			/* version of file           */
	char *p, *q;				/* miscellaneous pointers    */
	char *storage;				/* where we're storing now   */
	char **load_pointers;		/* pointer to pointer array  */
	char linebuf[255];			/* biggest line we'll allow  */
	FILE *fpt;					/* stream pointer            */
	int internal_count;			/* How many strings we got   */
	int total_size;				/* How big it all is         */
	int error;					/* Internal error value      */
	int PrdctCode;				/* Product Code              */
	char *PrdctNm;
	char *PrdctPtr = PrdctMem;
	char *n;
	char *LangStart;
	unsigned int ansival;		/* Scanned ANSI keymap value */

	internal_count = 0;			/* zero out internal counter */
	count_from_file = 0;		/* zero out internal counter */
	total_size = 0;				/* Initialize storage size   */
	error = 0;					/* Initialize error value    */

	load_pointers = pointers;	/* Start at the beginning    */
	storage = memory;			/* A very good place to start*/

	/*
     * Open the file now. Then read in the appropriate table. First line of
     * the file contains the number of lines we want Second line through end:
     * ignore if it starts with a ; and store only up to ;
     *
     */

	fpt = fopen (name_of_file, "r");	/* Open the file             */
	if (fpt == NULL)					/* Were we successful?       */
	{
		(void) fprintf (stderr, "Can not open input file %s\n", name_of_file);
		return (-1);					/* Return failure to caller  */
	}

	while (fgets (linebuf, 254, fpt) != NULL)	/* read a line in            */
	{
		p = q = linebuf;				/* set up for scan           */

/*
 * This label is only hit when a ? line is seen.
 *
 * The format of a ? line is:
 *
 *        ?xxx ....
 *
 * where xxx is a 3-character platform identifier. For DOS systems,
 * the identifier is DOS and for OS/2 it is OS2. The text following
 * ?xxx is the same format as any other language file line.
 *
 * When we see a ?, we compare the following string to the ID of our
 * current platform. If it matches, we point p and q at the text following
 * the expression, and (I'm sorry) jump back. If it doesn't match, we throw
 * the line away.
 */

re_cycle:

		switch (*p)
		{

		case '?':

			if (strncmp (++p, OS_IDENT, 3) == 0)
			{
				q = p += 3;
				goto re_cycle;
			}
			break;

		case ';':							/* Comment                   */
		case 'C':							/* Comment                   */

			break;

		case 'L':							/* Language Line             */

			LangStart = ++p;
			(void) parse_escapes (p);
			if ((len = strlen (p)) == 0)	/* Is anything there?        */
				continue;					/* No -- ignore.             */

			if (!count_from_file)
			{
				(void) sscanf (LangStart, "%d %d", &count_from_file, &file_version);
				if (count_from_file <= pointer_size)
					continue;

				(void) fprintf (stderr,
					"Messages in file = %d, Pointer array size = %d\n",
					count_from_file, pointer_size);
				error = -2;
				break;
			}

			++len;							/* Allow for the terminator  */
			if (((total_size += len) < memory_size)	/* Make sure it fits */
				&& (internal_count < pointer_size))
			{
				(void) memcpy (storage, LangStart, len);	/* Copy it   */
				*load_pointers++ = storage;	/* Point to start of string  */
				storage += len;				/* Move pointer into memory  */
			}

			++internal_count;				/* bump count */
			break;

		case 'A':							/* ANSI key output map       */

			(void) sscanf (++p, "%4x", &ansival);
			if (*(p += 4) != ' ')
				break;
			if (*++p == ' ')
				break;
			for (q = p; *q != '\0' && *q != ' '; q++)
				;
			*q = '\0';

			q = AnsiMem + AnsiHdr.PoolSize;
			len = parse_escapes (p);
			*((unsigned int *) q) = ansival;
			q += sizeof (unsigned int);

			*q++ = (char) len;
			strncpy (q, p, len);
			AnsiHdr.ElemCnt++;
			AnsiHdr.PoolSize = (int) ((q += len) - AnsiMem);
			break;

		case 'P':							/* Product Code              */
											/* Format: nnn ProductName   */
			PrdctCode = (int) strtol (++p, &PrdctNm, 10);
			while (' ' == *PrdctNm)
				++PrdctNm;
			n = PrdctNm + strlen (PrdctNm) - 1;
			while ((PrdctNm <= n) && ((*n == ' ') || (*n == '\n')))
				*n-- = '\0';

			if (PrdctCode == -1)
			{
				strcpy (PrdctMem, PrdctNm);
				PrdctPtr = PrdctMem + strlen (PrdctMem) + 1;
				PrdctHdr.PoolSize += strlen (PrdctNm) + 1;
			}
			else if ((0 <= PrdctCode) && (MAX_PRDCTS > PrdctCode))
			{
				switch (strlen (PrdctNm))
				{
				case 0:
					PrdctTbl[PrdctCode] = PrdctMem;
					break;
				default:
					PrdctTbl[PrdctCode] = PrdctPtr;
					strcpy (PrdctPtr, PrdctNm);
					PrdctPtr += strlen (PrdctNm) + 1;
					PrdctHdr.PoolSize += strlen (PrdctNm) + 1;
					break;
				}					/* end of switch (strlen (PrdctNm))   */
			}						/* end of if (...)                    */
			break;

		case 'T':					/* Terminal Mode                      */
									/* Format: KeyVal KeyXlate            */
			{
				int ScanCode, FncIdx;

				(void) sscanf (++p, "%4x %4x", &ScanCode, &FncIdx);
				TrmnlAccelTbl[TrmnlAccelCnt].ScanCode = (short) ScanCode;
				TrmnlAccelTbl[TrmnlAccelCnt].FncIdx = (short) FncIdx;
				++TrmnlAccelCnt;
			}
			break;

		case 'U':					/* Unattended Mode                    */
									/* Format: KeyVal KeyXlate            */
			{
				int ScanCode, FncIdx;

				(void) sscanf (++p, "%4x %4x", &ScanCode, &FncIdx);
				UnattendedAccelTbl[UnattendedAccelCnt].ScanCode = (short) ScanCode;
				UnattendedAccelTbl[UnattendedAccelCnt].FncIdx = (short) FncIdx;
				++UnattendedAccelCnt;
			}
			break;

		default:
			break;
		}							/* end of switch (...)                */
	}								/* end of while (...)                 */
	/*
     * Close the file. Make sure the counts match and that memory size was
     * not exceeded. If so, we have a winner! If not, snort and puke.
     *
     */

	(void) fclose (fpt);

	if (internal_count > pointer_size)		/* Enough pointers?          */
	{
		(void) fprintf (stderr,
			"%d messages read exceeds pointer array size of %d\n",
			internal_count, pointer_size);
		error = -3;
	}

	if (total_size > memory_size)			/* Did we fit?               */
	{
		(void) fprintf (stderr,
			"Required memory of %d bytes exceeds %d bytes available\n",
			total_size, memory_size);
		error = -4;
	}

	if (count_from_file != internal_count)
	{
		(void) fprintf (stderr,
			"Count of %d lines does not match %d lines actually read\n",
			count_from_file, internal_count);
		error = -5;
	}

	if (!error)
	{
		pointer_size = internal_count;		/* Store final usage counts  */
		memory_size = total_size;
		*load_pointers = NULL;				/* Terminate pointer table   */
	}

	return (error);
}

int 
parse_escapes (char *string)
{
	char c;
	char *p, *q;
	int escape_on = 0;

	p = q = string;

	while ((c = *p++) != '\0')
	{
		switch (c)
		{
		case ';':
			if (escape_on)
			{
				*q++ = ';';
				--escape_on;
				break;
			}
			/* Otherwise drop into newline code */

		case '\n':
			*q = *p = '\0';
			break;

		case '\\':
			if (escape_on)
			{
				*q++ = '\\';
				--escape_on;
			}
			else
				++escape_on;
			break;

		case 'n':
			if (escape_on)
			{
				*q++ = '\n';
				--escape_on;
			}
			else
				*q++ = c;
			break;

		case 'r':
			if (escape_on)
			{
				*q++ = '\r';
				--escape_on;
			}
			else
				*q++ = c;
			break;

		case 'b':
			if (escape_on)
			{
				*q++ = ' ';
				--escape_on;
			}
			else
				*q++ = c;
			break;

		case 'X':
		case 'x':
			if (escape_on)
			{
				*q++ = (char) strtol (p, &p, 16);
				--escape_on;
			}
			else
				*q++ = c;
			break;

		case '0':
			if (escape_on)
			{
				*q++ = (char) strtol (p, &p, 8);
				--escape_on;
			}
			else
				*q++ = c;
			break;

		case 's':
			if (escape_on)
			{
				*q++ = ' ';
				--escape_on;
			}
			else
				*q++ = c;
			break;

		default:
			*q++ = c;
			escape_on = 0;
			break;
		}
	}
	return (int) (q - string);
}
[ RETURN TO DIRECTORY ]