/******************************************************************************
* Module    :   File Names --- File name utilities.
*
* Author    :   John W. M. Stevens
******************************************************************************/

#include    "compiler.h"

#include    "unpost.h"
#include    "sets.h"
#include    "modflnm.h"

/*  Sets.   */
static      int     InitSets = 1;
static      SET     StandSet;
static      SET     ThrowSet;
static      SET     NoSet;
static      SET     AlphaSet;

/*  Strings for character sets. */
static      char    *Stand = "a-z0-9_.-";
static      char    *Throw = "aeiouy_-";
static      char    *Numbers = "0-9";
static      char    *Alpha = "a-z";

/*-----------------------------------------------------------------------------
| Routine   :   ChkFlNmLen() --- Check the file name length.
|
| Inputs    :   FileName    - File name.
-----------------------------------------------------------------------------*/

static
int     ChkFlNmLen(char     *FileNm)
{
    register    int     i;

    /*  Count file characters.  */
    for (i = 0;
         FileNm[i] && FileNm[i] != EXT_SEP_CHAR;
         i++)
        ;

    /*  Return True or False.   */
    return( i );
}

/*-----------------------------------------------------------------------------
| Routine   :   FlNmFilter() --- Filter a string so that only characters from
|               the set of standard file name characters are left.
|
| Inputs    :
-----------------------------------------------------------------------------*/

void    FlNmFilter(char     *FlName)
{
    auto        char    *cp;
    auto        char    *tp;
    auto        char    c;

    /*  Create character sets.  */
    if ( InitSets )
    {
        tp = Stand;
        CrtSet((unsigned char **) &tp, StandSet);
        tp = Throw;
        CrtSet((unsigned char **) &tp, ThrowSet);
        tp = Numbers;
        CrtSet((unsigned char **) &tp, NoSet);
        tp = Alpha;
        CrtSet((unsigned char **) &tp, AlphaSet);
        InitSets = 0;
    }

    /*  Convert string to lower case and strip out illegal characters.  */
    for (cp = tp = FlName; *tp; tp++)
    {
        /*  First, convert to lower case.   */
        c = (char) tolower( *tp );

        /*  Next, check for standards conformity.   */
        if (c == ' ' || c == '\t' || InSet(StandSet, (unsigned char) c))
            *cp++ = c;
    }
    *cp = '\0';
}

/*-----------------------------------------------------------------------------
| Routine   :   ModifyFlNm() --- Convert to lower case and make sure that
|               this file name conforms to MS-DOS restrictions/limitations
|               and USENET posting standards.
|
| Inputs    :   FlName  - File name.
|               Ext     - Extension.
| Outputs   :   OutName - Modified file name.
-----------------------------------------------------------------------------*/

int     ModifyFlNm(char     *FlName,
                   char     *Ext,
                   char     *OutName)
{
    register    int     i;
    auto        int     len;
    auto        int     ChopFlag;
    auto        char    *cp;
    auto        char    *tp;
    auto        char    c;
    extern      FILE    *ErrFile;

    /*  Create character sets.  */
    if ( InitSets )
    {
        tp = Stand;
        CrtSet((unsigned char **) &tp, StandSet);
        tp = Throw;
        CrtSet((unsigned char **) &tp, ThrowSet);
        tp = Numbers;
        CrtSet((unsigned char **) &tp, NoSet);
        tp = Alpha;
        CrtSet((unsigned char **) &tp, AlphaSet);
        InitSets = 0;
    }

    /*  Convert string to lower case and strip out illegal characters.  */
    for (cp = OutName, tp = FlName; *tp; tp++)
    {
        /*  First, convert to lower case.   */
        c = (char) tolower( *tp );

        /*  Next, check for standards conformity.   */
        if ( InSet(StandSet, (unsigned char) c) )
            *cp++ = c;
    }
    *cp = '\0';

    /*  If we have more than MAX_FILE characters in the file name,
    *   then shorten the file name.
    */
    if ((len = ChkFlNmLen( OutName )) > MAX_FILE)
    {
        /*  Shorten by removing vowels and separator characters.    */
        for (tp = cp = OutName, i = len;
             *tp && *tp != EXT_SEP_CHAR && i > MAX_FILE;
             tp++)
        {
            /*  If this is not a throw away character, save it back
            *   in the string.
            */
            if (! InSet(ThrowSet, (unsigned char) *tp))
            {
                *cp++ = *tp;
                continue;
            }
            else if (tp == OutName)
            {
                *cp++ = *tp;
                continue;
            }

            /*  Decrement the file name size.   */
            i--;
        }
        strcpy(cp, tp);
    }
    else
        goto ShortEnough;

    /*  If we still have more than MAX_FILE characters in the file
    *   name, chop off leading zeros in any numeric strings in the
    *   file name.
    */
    if ((len = ChkFlNmLen( OutName )) > MAX_FILE)
    {
        /*  Loop through string.    */
        for (tp = cp = OutName, i = len;
             *tp && *tp != EXT_SEP_CHAR && i > MAX_FILE;
             tp++)
        {
            /*  If this is a numeric sub-string, strip any leading
            *   zeros.
            */
            if (tp[1] && tp[1] != '.' &&
                InSet(NoSet, (unsigned char) *tp)   &&
                InSet(NoSet, (unsigned char) tp[1]) &&
                *tp == '0')
            {
                i--;
                continue;
            }

            /*  Copy character in.  */
            *cp++ = *tp;
        }
        strcpy(cp, tp);
    }
    else
        goto ShortEnough;

    /*  If we still have more than MAX_FILE characters in the file name, chop
    *   alphabetic strings short by throwing away excess characters.
    */
    while ((len = ChkFlNmLen( OutName )) > MAX_FILE)
    {
        /*  Loop through string.    */
        for (tp = cp = OutName, ChopFlag = 0, i = len;
             *tp && *tp != EXT_SEP_CHAR && i > MAX_FILE;
             tp++)
        {
            /*  Do not throw away numeric characters at this point. */
            if ( InSet(NoSet, (unsigned char) *tp) )
            {
                *cp++ = *tp;
                continue;
            }

            /*  Throw away the trailing character in an alphabetic
            *   substring.
            */
            if (*tp && tp[1] != EXT_SEP_CHAR &&
                InSet(AlphaSet, (unsigned char) *tp) &&
                InSet(AlphaSet, (unsigned char) tp[1]))
            {
                *cp++ = *tp;
                continue;
            }

            /*  Yup, we are chopping out a character.   */
            i--;
            ChopFlag = 1;
        }
        strcpy(cp, tp);

        /*  If not even one character is chopped out in a pass
        *   through the file name list, drop out and issue an
        *   error.
        */
        if (ChopFlag == 0)
        {
            fprintf(ErrFile,
                    "%s %d : Error - Could not modify file name to be ",
                    __FILE__,
                    __LINE__);
            fprintf(ErrFile,
                    "MS-DOS conformant.\n");
            return( 1 );
        }
    }

    /*  Done with file name, now fix extension. */
ShortEnough:
    for (tp = OutName;
         *tp && *tp != EXT_SEP_CHAR;
         tp++)
        ;
    if (*tp == EXT_SEP_CHAR)
    {
        /*  Were we able to identify this file? */
        if ( *Ext )
            strcpy(tp, Ext);
        else
        {
            /*  Move four characters across (including '.') and we
            *   are done.
            */
            for (i = 0, tp++;
                 *tp && *tp != EXT_SEP_CHAR && i < MAX_EXT;
                 i++, tp++)
                ;
            *tp = '\0';
        }
    }
    else
    {
        /*  No extension, so append one.    */
        strcpy(tp, Ext);
    }

    /*  Return no error.    */
    return( 0 );
}

/*-----------------------------------------------------------------------------
| Routine   :   ModExten() --- Modify the file name extension.
|
| Inputs    :   FlName  - File name.
-----------------------------------------------------------------------------*/

void    ModExten(char   *FlName,
                 char   *Exten,
                 char   *OutFlNm)
{
    auto    char    *InPtr;
    auto    char    *OutPtr;
    auto    char    *ExtPtr;

    /*  Search for the first file name extension separator character.   */
    for (InPtr = FlName, OutPtr = OutFlNm, ExtPtr = NULL;
         *InPtr;
         InPtr++, OutPtr++
        )
    {
        /*  Copy Characters.    */
        *OutPtr = *InPtr;

        /*  Check for extension separator character.    */
        if (*OutPtr == EXT_SEP_CHAR)
            ExtPtr = OutPtr;
    }
    *OutPtr = '\0';

    /*  Copy in new extension.  */
    if ( ExtPtr )
        strcpy(ExtPtr, Exten);
    else
        strcpy(OutPtr, Exten);
}


syntax highlighted by Code2HTML, v. 0.9.1