/*--------------------------------------------------------------------------*/ /* */ /* */ /* ------------ Bit-Bucket Software, Co. */ /* \ 10001101 / Writers and Distributors of */ /* \ 011110 / Freely Available 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 #include #include #ifdef __TURBOC__ #include #else #ifdef _MSC_VER_ #include #else #include #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); }