📄 !best001.c
字号:
/*==========================================================================
*
* !BEST001.C Tuesday, April 12, 1994
*
* con_ str_ fil_ counter counter_reg dos_shell
* supplementary source file 1 for The BESTLibrary
*
* Authored independently by George Vanous
*
*==========================================================================*/
/* ------------------------------------------------------------------------ */
/* ---------------------------- INCLUDE FILES --------------------------- */
#include <dir.h>
#include <alloc.h>
#include <errno.h>
#include <stdlib.h>
#include <process.h>
#include "!bestlib.h"
/* ------------------------------------------------------------------------ */
/* ------------------------------ MESSAGES ------------------------------ */
#define MSG01 "\nThis is your first time using %s\nI, %s, hope you enjoy this program\n\n"
#define MSG02 "\n%s has been used %d time"
#define MSG03 "\nThere is %ld bytes of free RAM now available to %s\n"
#define MSG04 "\nThis copy of %s is registered to %s\n"
#define MSG05 "\nThis is the master copy of %s\nIt is registered to its author, %s\n"
#define ERR01 "\n!!! ERROR !!! I cannot find the data file %s\n"
/* ------------------------------------------------------------------------ */
/*----------------------------------------------------------------------------
* Shell to DOS.
*
* RETURNS:
* = pointer to an error message
* = NULL if no error message
*/
char *dos_shell(void)
{
int error;
char *commandpath, *textstring;
struct ffblk ffblk;
if ((commandpath = getenv("COMSPEC")) == NULL &&
(commandpath = searchpath("COMMAND.COM")) == NULL) {
if ((error = findfirst(commandpath = "COMMAND.COM", &ffblk, 0)) == NULL &&
(error = findfirst(commandpath = "C:\COMMAND.COM", &ffblk, 0)) == NULL &&
(error = findfirst(commandpath = "C:\DOS\COMMAND.COM", &ffblk, 0)) == NULL &&
(error = findfirst(commandpath = "C:\BIN\COMMAND.COM", &ffblk, 0)) == NULL) {
textstring = "Cannot find file COMMAND.COM -- initialize COMSPEC=[path]COMMAND.COM";
return( textstring );
}
}
video_set(TEXT);
error = spawnl(P_WAIT, commandpath, commandpath, NULL);
if (error == -1) {
switch(errno) {
case EINVAL : textstring = "Bad argument passed to COMMAND.COM"; break;
case E2BIG : textstring = "Too many arguments passed to COMMAND.COM"; break;
case ENOEXEC: textstring = "Internal error -- exitting strongly suggested"; break;
case ENOMEM : textstring = "Out of memory -- cannot shell to DOS"; break;
case ENOENT : textstring = "Cannot find file COMMAND.COM -- initialize COMSPEC=[path]COMMAND.COM";
}
}
else if (!error) textstring = NULL;
return( textstring );
}
/*----------------------------------------------------------------------------
* Read, print, and increment the number of program executions.
* Print a comment, depending on the current execution number.
* Print the amount of available memory.
*
* "filename" - name of the text data file to read the number of program
* executions from (this number must be the first byte)
* - writes the incremented number of executions back to the file
* "title" - name of the program
* "author" - name of the author of the program
* "msgs" - one comment will be randomly chosen from this array of
* messages
* "msg_num" - number of messages present
*
* RETURNS:
* = file handle of the opened data file
*/
FILE *fil_count(char *filename, char *title, char *author, char *msgs[], word msg_num)
{
word counter; // usage counter
FILE *f; // file handle
DASHES; // print one line of dashes
if ((f = fopen(filename, "r+b")) == NULL) {
fprintf(stderr, ERR01, filename); // file could not be opened
exit(1); // abort with ERRORLEVEL 1
}
/* the first byte of the file is the usage counter -- get it */
fread(&counter, sizeof(counter), 1, f);
/* increment the counter and print the correct message */
if (counter++ == 0)
printf(MSG01, title, author); // print "first time used" message
else {
printf(MSG02, title, counter); // print number of program uses
if (counter != 1) // if uses do not equal 1 then
printf("s"); // pluralise
}
DOUBLESPACE;
/* write the incremented counter back to the file */
rewind(f); // go to beginning of file
fwrite(&counter, sizeof(counter), 1, f);
// the "fseek" is REQUIRED for the next "fread" to work???
fseek(f, 0L, SEEK_CUR);
printf(msgs[random(msg_num)], title);
printf(MSG03, coreleft(), title); // print amount of available memory
return( f ); // return file handle
}
/*----------------------------------------------------------------------------
* Read, print, and increment the number of program executions.
* Print to whom this program is registered.
* Print the amount of available memory.
*
* "filename" - name of the text data file to read the number of program
* executions from (this number must be the first byte)
* - writes the incremented number of executions back to the file
* "title" - name of the program
* "author" - name of the author of the program
* "registree" - name of the person to whom this program is registered
*
* RETURNS:
* = file handle of the opened data file
*/
FILE *fil_count_reg(char *filename, char *title, char *author, char *registree)
{
word counter; // usage counter
FILE *f; // file handle
DASHES; // print one line of dashes
if ((f = fopen(filename, "r+b")) == NULL) {
fprintf(stderr, ERR01, filename); // file could not be opened
exit(1); // abort with ERRORLEVEL 1
}
/* the first byte of the file is the usage counter -- get it */
fread(&counter, sizeof(counter), 1, f);
/* increment the counter and print the correct message */
if (counter++ == 0)
printf(MSG01, title, author); // print "first time used" message
else {
printf(MSG02, title, counter); // print number of program uses
if (counter != 1) // if uses do not equal 1 then
printf("s"); // pluralise
}
DOUBLESPACE;
/* write the incremented counter back to the file */
rewind(f); // go to beginning of file
fwrite(&counter, sizeof(counter), 1, f);
// the "fseek" is REQUIRED for the next "fread" to work???
fseek(f, 0L, SEEK_CUR);
if (!str_cmp(author, registree)) // if this is registered to author then
printf(MSG05, title, author); // print master copy message
else // else
printf(MSG04, title, registree); // print to whom this is registered
printf(MSG03, coreleft(), title); // print amount of available memory
return( f ); // return file handle
}
/*----------------------------------------------------------------------------
* Return the length of a file, in bytes.
*
* "f" - file handle of file to return length of
*
* RETURNS:
* = length of file in bytes
*/
long fil_len(FILE *f)
{
long curpos, length;
curpos = ftell(f); // save current position
fseek(f, 0L, SEEK_END); // go to EOF
length = ftell(f); // get EOF position relative to start
fseek(f, curpos, SEEK_SET); // go back to original position
return( length ); // return length of file, in bytes
}
/*----------------------------------------------------------------------------
* Read the next string from the current file position.
*
* "size" - initial size of text input buffer
* "f" - file handle of file to read from
*
* RETURNS:
* = pointer to next string (file pointer is set to byte just beyond word)
* = NULL if no string was found (file pointer is set to EOF)
*/
char *fil_next_str(word *size, FILE *f)
{
char ch, // temporary character-holder
*text; // text input buffer
word index = 0, // index into text input buffer
size_org; // original initial size of buffer
text = (char *) malloc(size_org = *size);
/* ignore initial whitespaces */
for (ch = getc(f); !is_letternum(ch) && ch != QUOTE; ch = getc(f)) {
if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
}
/* read in next string */
if (ch == QUOTE) {
do {
if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
while (index+2 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
text[index++] = ch; // store next valid character
ch = getc(f); // get next character
} while (ch != QUOTE // loop until next character is a '"'
&& ch != CR && ch != LF); // or until it is a CR or LF
if (ch == QUOTE) // if the last character was a '"'
text[index++] = ch; // store it
}
else {
for ( ; is_letternum(ch); ch = getc(f) ) {
if (index+1 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
text[index++] = ch; // store next valid character
}
}
text[index] = NULL; // end string with NULL-terminator
return( text ); // return next string
}
/*----------------------------------------------------------------------------
* Read the next word from the current file position.
*
* "size" - initial size of text input buffer
* "f" - file handle of file to read from
*
* RETURNS:
* = pointer to next word (file pointer is set to byte just beyond word)
* = NULL if no word was found (file pointer is set to EOF)
*/
char *fil_next_word(word *size, FILE *f)
{
char ch, // temporary character-holder
*text; // text input buffer
word index = 0, // index into text input buffer
size_org; // original initial size of buffer
text = (char *) malloc(size_org = *size);
/* ignore initial whitespaces */
for (ch = getc(f); !is_letter(ch); ch = getc(f) ) {
if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
}
/* read in next word */
for ( ; is_letter(ch); ch = getc(f)) {
if (index+1 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
text[index++] = ch; // store valid alphabet character
}
text[index] = NULL; // end string with NULL-terminator
return( text ); // return next word
}
/*----------------------------------------------------------------------------
* Read from the current file position upto the first occurrence of a string.
*
* "str" - string to read up to
* "size" - initial size of text input buffer
* "f" - file handle of file to read from
*
* RETURNS:
* = pointer to contents of file read in (file pointer is set to byte just
* beyond match
* = NULL if no match was found (file pointer is set to EOF)
*/
char *fil_read_to(char *str, word *size, FILE *f)
{
char ch, // temporary character holder
*text; // text input buffer
int index_str; // index into string-to-read-to
// must be integer because: fseek(f, -index_str, SEEK_CUR); (-ve seek)
word index = 0, // index into text input buffer
size_org; // original initial size of buffer
text = (char *) malloc(size_org = *size);
while (TRUE)
{
while ( (text[index++] = getc(f)) != str[0] ) {
if (text[index-1] == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
if (index+1 >= *size) // allocate more memory if required
text = (char *) realloc(text, *size += size_org);
}
if (str_len(str) == 1) {
text[1] = NULL; // end string with NULL-terminator
return( text ); // return pointer to text input holder
}
else {
for (index_str = 0; (ch = getc(f)) == str[++index_str]; );
if (index_str == str_len(str)) { // if we found the string
fseek(f, -1, SEEK_CUR); // rewind to byte just after match
if (index+index_str > *size) // allocate more memory if required
text = (char *) realloc(text, *size = index_str+index);
str_copy(text + index, str+1);
return( text ); // return pointer to text input holder
}
else if (ch == EOF) { // if we hit end of file
free(text); // no match was found (free up memory)
return( NULL ); // return NULL
}
}
fseek(f, -index_str, SEEK_CUR); // false alarm -- rewind
}
}
/*----------------------------------------------------------------------------
* Read from the current file position upto the first occurrence of a string.
* All comments (beginning with a ';'), blank lines, and extra spaces are
* stripped to conserve memory.
*
* "str" - string to read up to
* "size" - initial size of text input buffer
* "f" - file handle of file to read from
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -