/****************************************************/
/*          LISTING 4. SEMDOS.C                     */
/* Semantically parse a file of full DOS pathanames */
/* Use the DFA state machine and the state table    */
/*		defined in dostbl2.h                */
/* Print out each component after parsing           */
/* Parsing rule:                                    */
/*      [DRIVE] [\] [PATH]* FILENAME [EXT] e        */
/*  where   DRIVE    :=  a:                         */
/*          ROOT     :=  \                          */
/*          PATH     :=  ax* \                      */
/*          FILENAME :=  ax* [.]                    */
/*          EXT      :=  x[x][x]                    */
/*          e        :=  '\n' (terminator)          */
/*                                                  */
/*  Copyright August 29, 1991 by Alan Cline	    */
/*      Carolla Development, Dublin, Ohio           */
/****************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "dfa.h"
#include "dostbl2.h"


#define TESTFILE    "testfile.dat"
#define DELIMSTR	":.\\"
#define MAXFNAME	10
#define MAXEXT		 4

// Global storage to test parsing
char drive;
char pathname[MAXBUFLEN];
char fname[MAXFNAME];
char ext[MAXEXT];

void main(void)
{
    DFA_CLASS semdos_dfa;
    FILE *fp;               // ptr to test file
    short retval = OK;

    // Open the file of test names to parse
    fp = fopen(TESTFILE, READ_TEXT);

    while (!feof(fp) && retval != ERR) {
        retval = OK;

	// Init each component variable
	drive = EMPTY;
	memset(pathname, 0, MAXBUFLEN);
	memset(fname, 0, MAXFNAME);
	memset(ext, 0, MAXEXT);

	// Initialize the DFA and begin parsing
	// Pass dfa, state table, override-tokenizer,
	//      input file, delimeters
	InitStateMachine(&semdos_dfa, &semdos_stt,
		NULL, fp, DELIMSTR);

	retval = StateMachine(&semdos_dfa);
    }

    // End test run; close file and quit
    fclose(fp);
    return;
}

/************************************************/
/* Application-specific routines for tokenizing */
/************************************************/


char *get_token(
    DFA_CLASS *o)
{
    o->wp = &(o->workbuf[0]);
    memset(o->workbuf, 0, MAXBUFLEN);
    while (!feof(INFILE)) {
        o->cp = getc(INFILE);
	*(o->wp) = (char) o->cp;
	o->wp++;
	if (strchr(o->delim, o->cp) != NULL) {
	    break;
	}

	// Force EOR and DOT to front of buffer
	if (o->cp == (int) EOR) {
            if (o->wp != o->workbuf+1) {
	        ungetc(o->cp, INFILE);
		o->wp--;
	    }
	    break;
	}
    }		// end of while loop

    *(o->wp) = '\0';
    return(o->workbuf);
}


/*********************************/
/* Application-specific routines */
/*********************************/

short isfbase(char *, short);

// Test DRIVE:= a:
short isdrive(
    char *token)
{
    return((token[1] == GS) &&
            isalpha((int) token[0]));
}

// Test EXT := x[x][x]
short isext(
    char *token)
{
    short len, k;
    short retval = GOOD;

    len = strlen(token);
    for (k=0; k < len; k++) {
        if (!isalnum((int) token[k]))
	    retval = BAD;
    }
    return(retval);
}

// Test for filebase := ax*
short isfbase(
    char *token,
    short len)
{
    short k;
    short retval = BAD;

    if ((len <= 9) && (isalpha((int) token[0]))) {
        for (k=0; k < len; k++) {
	    if (!isalnum((int) token[k]))
	        break;
        }
        if (k == len)
	    retval = GOOD;
    }
    return(retval);
}

// Test FNAME:= ax* [.]
short isfname(
    char *token)
{
    short len;

    len = (LASTBYTE(token) == DOT) ?
            strlen(token) - 1 : strlen(token);

    return(isfbase(token, len));
}

// Test PATH:= ax* \
short ispath(
    char *token)
{
    short retval = BAD;

    if (LASTBYTE(token) == FS) {
        retval = isfbase(token, strlen(token) - 1);
    }

    return(retval);
}

// Test root character:= '\'
short isroot(
    char *token)
{
    return(*token == '\\');
}


/****************************************/
/* Application-specific action routines */
/****************************************/

// Save the drive letter tokenized;
short appendpath(
    char *token)
{
    strncat(pathname, token, strlen(token));
    return(1);
}

// Print out each component of the parsed pathname
short cleanup(
   char *token)
{
    IGNORE(token);
    printf("File: %s\n\tDrive: %c\n",
            fname, drive);
    printf("\tPath: %s\n\tExtension: %s\n",
            pathname, ext);
	return(1);
}


// Save the drive letter
short savedrive(
    char *token)
{
    IGNORE(token);
    drive = (toupper((int) token[0]));
    return(1);
}


// Save the file extension
short saveext(
    char *token)
{
    strcpy(ext, token);
    return(1);
}


// Save the filename
short savefname(
    char *token)
{
    strcpy(fname, token);
    return(1);
}


