// (c) 1993-2006 Criterion Software Limited and its licensors. All Rights Reserved

const char *SPIT_history[] =
{
"------------------------------------------------------------------",
"                                                                  ",
"                           Zerofile v1.60                         ",
"                                                                  ",
"                        by FrANK G. Barchard                      ",
"                                                                  ",
"                     Main program - Oct 25, 2004                  ",
"                                                                  ",
"------------------------------------------------------------------",
"                                                                  ",
" Version Date   SE History:                                       ",
" ------- ----   -- --------                                       ",
"    1.00 041025 FB Initial version by based on txt & padfile      ",
"                                                                  ",
"------------------------------------------------------------------",
"\0"
};

/****************************************************************/
/*  Spit Setup                                                  */
/****************************************************************/

#include    "spit.h"

const char ZerofileVersion[]="1.00 (Hakone) 2004.10.25";
#define TOOL_VERSION 100
#define TOOL_NAME "zerofile"

int *OPTxlate;
int OPTxlatereverse;
int OPTnewlinetype;
int OPTnocr;
int OPTstats;
int OPTsmart;
int OPTtolower;
int OPTunsmart;
int OPTopera;
int OPTgcc;  // add new line to end of file for gcc on unix
int unweb;  /* auto option */

#define BUFSIZE 256


static int bufpos=0;
static char bufc[BUFSIZE];
static char buft[BUFSIZE];

#define ID(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))

struct
{
    char *ext;
    int type;
    int creator;
} filetypes[]=
{
    "ZEROFILE",  ID('T','E','X','T'), ID('M','P','S',' '),
    "ZEROFILE",  ID('T','E','X','T'), ID('M','P','S',' '),
    "C",    ID('T','E','X','T'), ID('M','P','S',' '),
    "H",    ID('T','E','X','T'), ID('M','P','S',' '),
    "INC",  ID('T','E','X','T'), ID('M','P','S',' '),
    "ASM",  ID('T','E','X','T'), ID('M','P','S',' '),
    "VSM",  ID('T','E','X','T'), ID('M','P','S',' '),
    "DSM",  ID('T','E','X','T'), ID('M','P','S',' '),
    "DEF",  ID('T','E','X','T'), ID('M','P','S',' '),
    "I",    ID('T','E','X','T'), ID('M','P','S',' '),
    "S",    ID('T','E','X','T'), ID('M','P','S',' '),
    "RC",   ID('T','E','X','T'), ID('M','P','S',' '),
    "MAP",  ID('T','E','X','T'), ID('M','P','S',' '),
    "ERR",  ID('T','E','X','T'), ID('M','P','S',' '),
    "JAVA", ID('T','E','X','T'), ID('M','P','S',' '),
    "PY",   ID('T','E','X','T'), ID('M','P','S',' '),
    "CS",   ID('T','E','X','T'), ID('M','P','S',' '),
    "CPP",  ID('T','E','X','T'), ID('M','P','S',' '),
    "C++",  ID('T','E','X','T'), ID('M','P','S',' '),
    "CC",   ID('T','E','X','T'), ID('M','P','S',' '),
    "CXX",  ID('T','E','X','T'), ID('M','P','S',' '),
    "MAK",  ID('T','E','X','T'), ID('M','P','S',' '),
    "BAT",  ID('T','E','X','T'), ID('M','P','S',' '),
    "SCR",  ID('T','E','X','T'), ID('M','P','S',' '),
    "RSP",  ID('T','E','X','T'), ID('M','P','S',' '),
    "LNK",  ID('T','E','X','T'), ID('M','P','S',' '),
    "BIF",  ID('T','E','X','T'), ID('M','P','S',' '),
    "LOG",  ID('T','E','X','T'), ID('M','P','S',' '),
    "PS",   ID('T','E','X','T'), ID('M','P','S',' '),
    "ASC",  ID('T','E','X','T'), ID('M','P','S',' '),
    "HTM",  ID('T','E','X','T'), ID('M','P','S',' '),
    "HTML", ID('T','E','X','T'), ID('M','P','S',' '),
    "XML",  ID('T','E','X','T'), ID('M','P','S',' '),
    "DOF",  ID('T','E','X','T'), ID('M','P','S',' '),
    "HRC",  ID('T','E','X','T'), ID('M','P','S',' '),
    "TOG",  ID('T','E','X','T'), ID('M','P','S',' '),
    "ABS",  ID('T','E','X','T'), ID('M','P','S',' '),
    "LST",  ID('T','E','X','T'), ID('M','P','S',' '),
    "TCL",  ID('T','C','L','T'), ID('M','P','S',' '),
    "ION",  ID('T','E','X','T'), ID('M','P','S',' '),
    "SHA",  ID('T','E','X','T'), ID('M','P','S',' '),
#ifndef __unix__
    "A",    ID('T','E','X','T'), ID('M','P','S',' '),
#endif

    "SEA",  ID('A','P','P','L'), ID('M','P','S',' '),
    "ICON", ID('I','C','O','N'), ID('S','P','o','T'),
    "ICO",  ID('I','C','O','N'), ID('S','P','o','T'),
    "ANIM", ID('3','D','O','a'), ID('S','P','o','T'),
    "BMP",  ID('.','B','M','P'), ID('S','P','o','T'),
    "BLT",  ID('.','B','L','T'), ID('S','P','o','T'),
    "BOB",  ID('B','O','B',' '), ID('B','A','B','L'),
    "CEL",  ID('3','D','O','c'), ID('S','P','o','T'),
    "C65",  ID('.','C','6','5'), ID('S','P','o','T'),
    "CMP",  ID('.','C','M','P'), ID('S','P','o','T'),
    "CUT",  ID('.','C','U','T'), ID('B','A','B','L'),
    "EPS",  ID('E','P','S','F'), ID('8','B','I','M'),
    "EPI",  ID('E','P','S','F'), ID('8','B','I','M'),
    "EPSF", ID('E','P','S','F'), ID('8','B','I','M'),
    "EPSI", ID('E','P','S','F'), ID('8','B','I','M'),
    "FLI",  ID('F','L','I','C'), ID('B','A','B','L'),
    "FLC",  ID('F','L','I','C'), ID('B','A','B','L'),
    "GIF",  ID('G','I','F','f'), ID('8','B','I','M'),
    "IMG",  ID('3','D','O','i'), ID('3','D','O','e'),
    "IMAG", ID('3','D','O','i'), ID('3','D','O','e'),
    "JPG",  ID('J','P','E','G'), ID('8','B','I','M'),
    "JFIF", ID('J','P','E','G'), ID('8','B','I','M'),
    "LBM",  ID('I','L','B','M'), ID('S','P','o','T'),
    "IFF",  ID('I','L','B','M'), ID('S','P','o','T'),
    "BBM",  ID('I','L','B','M'), ID('S','P','o','T'),
    "ILBM", ID('I','L','B','M'), ID('S','P','o','T'),
    "MOOV", ID('M','o','o','V'), ID('B','A','B','L'),
    "MOV",  ID('M','o','o','V'), ID('B','A','B','L'),
    "MSP",  ID('.','M','S','P'), ID('B','A','B','L'),
    "MVI",  ID('.','M','V','I'), ID('S','P','o','T'),
    "NEO",  ID('.','N','E','O'), ID('B','A','B','L'),
    "PAL",  ID('8','B','C','T'), ID('8','B','I','M'),
    "PCD",  ID('P','I','C','T'), ID('p','p','x','i'),
    "PCX",  ID('.','P','C','X'), ID('S','P','o','T'),
    "PI1",  ID('D','E','G','A'), ID('B','A','B','L'),
    "PIC",  ID('.','S','I','M'), ID('S','P','o','T'),
    "PICT", ID('P','I','C','T'), ID('S','P','o','T'),
    "PIQT", ID('P','I','C','T'), ID('T','V','O','D'),
    "PNTG", ID('P','N','T','G'), ID('M','P','N','T'),
    "PPM",  ID('P','P','M',' '), ID('8','B','I','M'),
    "PBM",  ID('P','P','M',' '), ID('8','B','I','M'),
    "PGM",  ID('P','P','M',' '), ID('8','B','I','M'),
    "PNM",  ID('P','P','M',' '), ID('8','B','I','M'),
    "PSD",  ID('8','B','I','M'), ID('8','B','I','M'),
    "PXR",  ID('P','X','A','R'), ID('8','B','I','M'),
    "QDV",  ID('.','Q','D','V'), ID('B','A','B','L'),
    "RAST", ID('.','S','U','N'), ID('B','A','B','L'),
    "RGB",  ID('R','R','G','B'), ID('B','A','B','L'),
    "RAW",  ID('.','H','S','I'), ID('S','P','o','T'),
    "RLE",  ID('R','L','E','C'), ID('B','A','B','L'),
    "SANM", ID('3','D','O','s'), ID('3','D','O','e'),
    "SCAN", ID('S','C','A','N'), ID('B','A','B','L'),
    "SCT",  ID('.','.','C','T'), ID('8','B','I','M'),
    "SCR",  ID('.','S','C','R'), ID('S','P','o','T'),
    "SGI",  ID('.','S','G','I'), ID('B','A','B','L'),
    "TGA",  ID('T','P','I','C'), ID('S','P','o','T'),
    "TIF",  ID('T','I','F','F'), ID('8','B','I','M'),
    "TIFF", ID('T','I','F','F'), ID('8','B','I','M'),
    "TIM",  ID('.','T','I','M'), ID('S','P','o','T'),
    "VDAN", ID('V','D','A','N'), ID('V','D','3','2'),
    "VGA",  ID('.','V','G','A'), ID('S','P','o','T'),
    "VSH",  ID('.','V','S','H'), ID('S','P','o','T'),
    "YUV",  ID('A','B','E','K'), ID('B','A','B','L'),
    "3SP",  ID('.','3','S','P'), ID('S','P','o','T'),
    "3SH",  ID('.','3','S','H'), ID('S','P','o','T'),
    "PSH",  ID('.','P','S','H'), ID('S','P','o','T'),
    "FSH",  ID('.','F','S','H'), ID('S','P','o','T'),
    "TGV",  ID('.','t','g','v'), ID('S','P','o','T'),
    "AVI",  ID('.','a','v','i'), ID('S','P','o','T'),
    "PYC",  ID('.','p','y','c'), ID('S','P','o','T'),
 (char *)0, ID( 0 , 0 , 0 , 0 ), ID( 0 , 0 , 0 , 0 ),
};

/* Translation tables */

/* Convert DOS ASCII to Windows */
int Xdostowindows[256] =
{
    0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  /*   0: */
   16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  /*  16: */
   32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  /*  32: */
   48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  /*  48: */
   64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  /*  64: */
   80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  /*  80: */
   96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,  /*  96: */
  112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,  /* 112: */
  199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238, 236, 196, 197,  /* 128: */
  201, 230, 198, 244, 246, 242, 251, 249, 255, 214, 220, 162, 163, 165,  -1, 131,  /* 144: */
  225, 237, 243, 250, 241, 209, 170,  -1, 191,  -1, 172, 189, 188, 161, 171, 187,  /* 160: */
   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  /* 176: */
   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  /* 192: */
   -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  /* 208: */
   -1, 223,  -1,  -1,  -1,  -1, 181,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  /* 224: */
   -1, 177, 178,  -1,  -1,  -1, 247,  -1, 176, 130, 183,  -1,  -1,  -1,  -1,  -1   /* 240: */
};

/* Convert to lowercase */

int Xtolower[256] =
{
    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
    0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
    0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
    0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
    0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
    0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
    0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
    0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
    0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f,
    0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
    0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
    0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
    0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
    0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
    0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
    0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
    0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
    0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
    0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,
    0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
    0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
    0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
    0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,
    0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
    0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,
    0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
    0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
    0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
};

void SPIT_flushc(GSTREAM *out)
{
    if (!strnicmp(bufc,"comments=",9))
        unweb = 1;

    if (unweb)
    {
        int i;
        int j=0;
        int c;
        static int lastc=0;

        i = 0;
        if (bufc[i]==lastc)
            ++i;

        while (i<bufpos)
        {
            switch (bufc[i])
            {
                case '%':
                    sscanf(bufc+i+1, "%02x", &c);
                    buft[j++] = (char) c;
                    i += 3-1;
                    break;

                case '+':
                    buft[j++] = (char) ' ';
                    break;

                case 10:
                case 13:
                    break;

                default:
                    lastc = bufc[i];
                    buft[j++] = (char) lastc;
                    break;
            }
            ++i;
        }
        memcpy(bufc,buft,j);
        bufpos = j;
    }

    if (OPTwrite && out)
        gwrite(out,bufc,bufpos);
    bufpos = 0;
}

void SPIT_putc(int c,GSTREAM *out)
{
    bufc[bufpos++] = (char) c;
    if (bufpos>=BUFSIZE)
        SPIT_flushc(out);
}

void SPIT_putcr(GSTREAM *out,int type)
{
    if (OPTopera)
        SPIT_putc(32,out);
    switch(type)
    {
        case 0: /* PC style cr/lf */
            SPIT_putc(13,out);
            SPIT_putc(10,out);
            break;

        case 1: /* Mac style cr */
            SPIT_putc(13,out);
            break;

        default: /* Unix style lf */
            SPIT_putc(10,out);
            break;
    }
    SPIT_flushc(out);
}

/* Table-based character translation. */
int xlate(int cin, int *table, int reverse)
{
    int cout=0;

    if (reverse)
    {
        int     i;

        /* If translation is reversed then search the table (first */
        /* check for identity translation). */
        if (table[cin] == cin)
        {
            cout = cin;
        }
        else
        {
            for (i = 0; i < 256; ++i)
            {
                if (table[i] == cin)
                {
                    cout = i;
                    break;
                }
            }
        }
    }
    else
    {
        cout = table[cin];
    }

    /* If character wasn't found then warn user and return the */
    /* input character. */
    if (cout < 0)
    {
        if (OPTverbose>=4)
        {
            printf("Untranslatable character \'%c\' (0x%02x, %dd)\n", cin, cin, cin);
        }

        cout = cin;
    }

    return(cout);
}

int zerofile(GSTREAM *in,GSTREAM *out, int type, int nocr)
{
    bool done=false;
    int lastch=0;
    int lastnl=0;
    int ch=0;
    unsigned char buf[4];
    int numberoflines=0;

    while (!done)
    {
        lastch = ch;
        ch = EOF;
        if (gread(in,buf,1))
            ch = buf[0];

        switch(ch)
        {
            case EOF:
                done = true;
                break;

            case 13:
                if (nocr)   /* completely ignore CRs */
                {
                    ch = 0;
                }
                else
                {
                    int p;
                    int numread;

                    p = (int) gtell(in);
                    numread = gread(in,buf+1,3);

                    if (!(numread==3 && buf[1]==(char)0 && buf[2]==(char)13 && buf[3]==(char)10)) // if not cr00crlf
                        gseek(in,p);

                    if (lastch==10)     /* lfCR */
                    {
                        ch = 0;
                    }
                    else if (!(lastch==13 && buf[1]==(char)10))   /* !crCRlf */
                    {
                        SPIT_putcr(out,type);
                        ++numberoflines;
                        ++lastnl;
                    }
                }
                break;

            case 10:
                if (lastch==13) /* crLF */
                {
                    ch = 0;
                }
                else
                {
                    SPIT_putcr(out,type);
                    ++numberoflines;
                    ++lastnl;
                }
                break;

            default:
                lastnl = 0;
                if (OPTxlate)
                    ch = xlate(ch, OPTxlate, OPTxlatereverse);
                if (OPTunsmart)
                {
                    if (ch==0x91 || ch==0x92)
                        ch = '\'';
                }
                SPIT_putc(ch,out);
            case 'z'&31:
                break;
        }
    }
    if (OPTgcc && lastnl<2) // gcc wants one blank line
        SPIT_putcr(out,type);

    SPIT_flushc(out);

    return(numberoflines);
}

/* copy file with no translation */

int zerofilecopy(GSTREAM *in,GSTREAM *out)
{
    int ch=0;
    int len=0;
    unsigned char buf[4];

    while (ch!=EOF)
    {
        ch = EOF;
        if (gread(in,buf,1))
            ch = buf[0];

        if (ch!=EOF)
        {
            SPIT_putc(ch,out);
            ++len;
        }
    }
    SPIT_flushc(out);
    return(len);
}

void SPIT_openstr(const char *fname)
{
    char statbuf[SPITMAXLINE];

    if (OPTverbose)
    {
        if (OPTverbose>=4)
            printf("%s: ",fname);
        else
        {
            if (OPTverbose>=3)
                printf("%s: ",SPIT_getname( statbuf,fname));
            else
                printf("%s ",SPIT_getname( statbuf,fname));
        }
    }
}

int findtype(const char *fname)
{
    int i;
    int type=0;
    char *ext;
    char buf[512];

    ext = strrchr(SPIT_getname(buf,fname),'.');
    if (ext)
    {
        ++ext;
        for (i=0; filetypes[i].ext; ++i)
        {
            if (!stricmp(ext,filetypes[i].ext))
            {
                type = i;
            }
        }
    }

    return(type);
}

/* Do translation if */
/*   recognised zerofile file extension */
/*   or unrecognised extension, 1 file only, and dest==source */

int checkdotranslation(char *inname,char *outname,int SPITargnum,int smart)
{
    int i;
    int doit=1;

    if (smart)
    {
        doit = 0;
        i = findtype(inname);

        if (i)
        {
            if (filetypes[i].type == ID('T','E','X','T'))
                doit = 1;
        }
        else
        {
            char buf[512];
            if (!strrchr(SPIT_getname(buf,inname),'.'))
                if (smart==2)
                    doit = 1;

            if (!strcmp(inname, outname) && SPITargnum==1)
                doit = 1;
        }
    }

    return(doit);
}

/*
;
; ABSTRACT
;
; zerofile - convert zerofile file CR styles
;
; SUMMARY
;
; zerofile -options [files]
;     @file     response file, containing a list of options and files
;     =file     specify a output file ie zerofile source=dest
;     -pc       PC type crlf (also -ibm,-pc,-dos or -crlf)
;     -mac      Mac type cr (also -mpw,-ppc or -cr)
;     -unix     Unix type lf (also -sgi, -linux or -lf)
;     -opera    Opera likes you to a add a space at end of line
;     -gcc      GCC Unix likes you to a add a NL at end of file
;     -t0       PC type crlf
;     -t1       Mac type cr
;     -t2       SGI type lf
;     -nologo   disable banner
;     -i0       disable info/stats
;     -i1       enable info/stats
;     -tolower  lower case filenames
;     -r        recurse subdirectories
;     -s0       disable smartness - translate all files
;     -s1       smart translate only known file types based on extension
;     -s2       smart + translate extensionless(default)
;     -unsmart  replace smart quotes with single quotes
;     -v0       no console output
;     -v1       prints source file name and errors
;     -v2       status line for each file (default)
;     -v3       additional info
;     -w0       don't output file
;     -w1       output to file (default)
;     -xl       translate to lower case
;
; DESCRIPTION
;
; ZEROFILE converts zerofilefile formats between PC, Unix and Mac.
; The input file type is automatically detected.  The output type
; is specified by the -t option, which defaults to the type native
; to the machine ZEROFILE is running on.  Normally, only the filenames
; need to be specified.  Files are converted and written over the
; original files.  Options can be used to write files with different
; names or to different directories.  ZEROFILE can also be used to view
; zerofile files on the console, using the -w1 option.
;
; The -x option is used to specify character translations.
;
; RETURNS
;
; no return code
;
; SEE ALSO
;
; xd -t, tabs, type, Spit
;
; SAMPLE OUTPUT
;
; >zerofile *.h
;
; HUFF.H: Translating, 163 lines, done.
; FILLMAC.H: Translating, 97 lines, done.
; MACPS.H: Translating, 16 lines, done.
; FILL.H: Translating, 102 lines, done.
; FILLCUR.H: Translating, 18 lines, done.
; CEL2SHPI.H: Translating, 2 lines, done.
; FILLSMGR.H: Translating, 14 lines, done.
; SPIT.H: Translating, 169 lines, done.
; XI.H: Translating, 29 lines, done.
; IMG2SHPI.H: Translating, 17 lines, done.
; MACHINE.H: Translating, 470 lines, done.
; VSH2SHPI.H: Translating, 10 lines, done.
; SHP2CELI.H: Translating, 21 lines, done.
; EMM.H: Translating, 14 lines, done.
; AZM.H: Translating, 1043 lines, done.
; LUMPY.H: Translating, 70 lines, done.
;
; END ABSTRACT
;
*/

/****************************************************************/
/*  SPIT Routines                                               */
/****************************************************************/

void SPIT_reset(void)
{
    OPTxlate = NULL;
    OPTxlatereverse = 0;
    OPTstats = 0;
    OPTsmart = 2;
    OPTnocr = 0;
/*    OPTverbose = -1; */

#if defined(__WATCOMC__) || defined(_MSC_VER)
    OPTnewlinetype = 0;   /* crlf */
#elif defined(applec) || defined(powerc) || defined (__powerc)
    OPTnewlinetype = 1;   /* cr */
#else
    OPTnewlinetype = 2;   /* lf */
#endif
    OPTtolower = 0;
    OPTopera = 0;
    OPTgcc = 0;
    OPTbanner = 0;
    OPTunsmart = 0;
    unweb = 0;

}

void SPIT_usage(const char *prgname,const char *envname,const char *urlname, int utype)
{
    printf("Zerofile v%s by FrANK Barchard, EAC\n",ZerofileVersion);
    if (utype)
        printf("USAGE: %s -options [files]\n", prgname);

    switch (utype)
    {
        case 2:
            puts("   -pc convert to pc zerofile     -unix convert to unix (SGI)");
            puts("  -mac convert to mac zerofile   -opera add a space at end of line");
            puts("  -gcc add nl to end of zerofile -unsmart replace smart quotes with single quotes");
            puts("    -i info/stats          -tolower lower case file names");
            puts("    -t type (0 PC,1 Mac,2 SGI,3 Opera) -s smart translate on extension");
            puts("    -w write file                -v verbose");
            puts("    -x translate characters      -r recurse subdirectories");
            puts("     @ response file              = output file");
          printf("type '%s -h' for more help\n", prgname);
          printf("type '%s -help' for web page (%s)\n", prgname,urlname);
            break;

        case 3:
            puts("");
          printf("VERSION: %s v%s, Spit v%.2f\n",SPIT_MACHINE,ZerofileVersion,(float)SPIT_VERSION/100.0f);
            puts("SUMMARY: Zerofile convert zerofile file cr/lf styles for PC,MAC & SGI");
          printf("         SPIT environment variable is %s\n",envname);
            puts("");
            puts("    @file     response file, containing a list of options and files");
          printf("    =file     specify a output file ie %s source=dest\n", prgname);
            puts("    -pc       PC type crlf (also -ibm,-pc,-dos or -crlf)");
            puts("    -mac      Mac type cr (also -mpw,-ppc or -cr)");
            puts("    -unix     Unix type lf (also -sgi, -linux or -lf)");
            puts("    -opera    Opera likes you to a add a space at end of line");
            puts("    -gcc      GCC Unix likes you to a add a NL at end of file");
            puts("    -t0       PC type crlf");
            puts("    -t1       Mac type cr");
            puts("    -t2       SGI type lf");
            puts("    -nologo   disable banner");
            puts("    -i0       disable info/stats");
            puts("    -i1       enable info/stats");
            puts("    -tolower  lower case filenames");
            puts("    -r        recurse subdirectories");
            puts("    -s0       disable smartness - translate all files");
            puts("    -s1       smart translate only known file types based on extension");
            puts("    -s2       smart + translate extensionless(default)");
            puts("    -unsmart  replace smart quotes with single quotes");
            puts("    -v0       no console output");
            puts("    -v1       prints source file name and errors");
            puts("    -v2       status line for each file (default)");
            puts("    -v3       additional info");
            puts("    -w0       don't output file");
            puts("    -w1       output to file (default)");
            puts("    -xl       translate to lower case");
            //puts("    -xdw      translate DOS ASCII to Windows");
            //puts("    -xwd      translate Windows ASCII to DOS");

        default:
            break;
    }
}

char *SPIT_opt(const char *optptr)
{
    int i;
    const char *d=NULL;
    char optbuf[SPITMAXLINE];

    for (i=0; (unsigned char)optptr[i]>(unsigned char)' ' && i<SPITMAXLINE; ++i)
        optbuf[i] = (char) tolower(optptr[i]);
    optbuf[i] = 0;

    if (!stricmp(optbuf,"pc") || !stricmp(optbuf,"ibm") || !stricmp(optbuf,"dos") || !stricmp(optbuf,"pc") || !stricmp(optbuf,"crlf"))
    {
        OPTnewlinetype = 0;
        d = (char *)optptr+i;
    }
    else if (!stricmp(optbuf,"mac") || !stricmp(optbuf,"mpw") || !stricmp(optbuf,"ppc") || !stricmp(optbuf,"cr"))
    {
        OPTnewlinetype = 1;
        d = (char *)optptr+i;
    }
    else if (!stricmp(optbuf,"sgi") || !stricmp(optbuf,"linux") || !stricmp(optbuf,"unix") || !stricmp(optbuf,"lf"))
    {
        OPTnewlinetype = 2;
        d = (char *)optptr+i;
    }
    else if (!stricmp(optbuf,"nocr"))
    {
        d = SPIT_getopt( &OPTnocr,optptr+4, "Kill CRs", 0, 1);
    }

    if (!d)
    {
        switch (*optptr|(char)' ')
        {
            case 'i':
                d = SPIT_getopt( &OPTstats,optptr+1, "info", 0, 1);
                break;

            case 'g':
                if (!strnicmp(optptr,"gcc",3))
                    d = SPIT_getopt( &OPTgcc,optptr+3, "gcc nl at end of zerofile", 0, 1);
                break;


            case 's':
                d = SPIT_getopt( &OPTsmart,optptr+1, "smart", 0, 2);
                break;

            case 't':
                if (!strnicmp(optptr, "tolower", 7))
                {
                    d = SPIT_getopt( &OPTtolower,optptr+7, "name to lower case", 0, 1);
                }
                else
                {
                    d = SPIT_getopt( &OPTnewlinetype,optptr+1, "cr type", 0, 3);
                }
                break;

            case 'l':
            case 'n':
                d = SPIT_getopt( &OPTtolower,optptr+1, "name to lower case", 0, 1);
                break;

            case 'o':
                if (!strnicmp(optptr,"opera",5))
                    d = SPIT_getopt( &OPTopera,optptr+5, "opera add space at eol", 0, 1);
                break;

            case 'u':
                if (!strnicmp(optptr, "unsmart", 7))
                {
                    d = SPIT_getopt( &OPTunsmart,optptr+7, "convert smart quotes to single quotes", 0, 1);
                }
                break;

            /* Translation options */
            case 'x':
                if ((optptr[1]|(char)' ') == 'l')
                {
                    /* Convert DOS ASCII to Windows */
                    OPTxlate = Xtolower;
                    OPTxlatereverse = 0;
                    d = (char *)optptr+2;
                }
                else if (((optptr[1]|(char)' ') == 'd') &&
                    ((optptr[2]|(char)' ') == 'w'))
                {
                    /* Convert DOS ASCII to Windows */
                    OPTxlate = Xdostowindows;
                    OPTxlatereverse = 0;
                    d = (char *)optptr+3;
                }
                else if (((optptr[1]|(char)' ') == 'w') &&
                         ((optptr[2]|(char)' ') == 'd'))
                {
                    /* Convert Windows ASCII to DOS */
                    OPTxlate = Xdostowindows;
                    OPTxlatereverse = 1;
                    d = (char *)optptr+3;
                }
                break;

            default: ;
        }
    }
    return((char *)d);
}

int main(int argc,char **argv)
{
    int more;
    int i;
    int ok;
    int numberoflines;
    int numberofbytes;
    int totalnumberoflines;
    int totalnumberofbytes;
    char *transtype;
    GSTREAM *infile=0;
    GSTREAM *outfile=0;

    SPIT_init(SPIT_reset, SPIT_usage, SPIT_opt, SPIT_history);
    do
    {
        more = SPIT_parse(argc, argv, TOOL_NAME, TOOL_VERSION);

        switch (OPTnewlinetype)
        {
            default:;
            case 0: transtype = "PC";    break;
            case 1: transtype = "Mac";   break;
            case 2: transtype = "Unix";  break;
        }

        totalnumberoflines = 0;
        totalnumberofbytes = 0;
        for (i=0; i<SPITargnum; ++i)
        {
            SPIT_openstr(SPITsargv[i]);
            SPIT_flush();

            infile = gopen(SPITsargv[i]);
            if (!infile)
            {
                if (OPTverbose>=2)
                    printf("zerofile - COULD NOT OPEN FILE FOR READ '%s'\n",SPITsargv[i]);
            }
            else
            {
                char outname[SPITMAXLINE];

                ok = 1;
                if (OPTwrite)
                {
                    if (OPTtolower)
                        strlwr(SPITdargv[i]);

                    SPIT_tempname(outname,SPITdargv[i]);
                    remove(outname);

                    outfile = gwopen(outname);
                    if (!outfile)
                    {
                        if (OPTverbose>=2)
                            printf("zerofile - COULD NOT OPEN FILE FOR WRITE '%s'\n",outname);
                        gclose(infile);
                        ok = 0;
                    }
                }
                else
                    outfile = 0;

                if (ok)
                {
                    numberoflines = 0;
                    numberofbytes = 0;
                    if (checkdotranslation(SPITsargv[i],SPITdargv[i],SPITargnum,OPTsmart))
                    {
                        if (OPTverbose>=3)
                        {   printf("Translating to %s",transtype);
                            if (OPTopera)
                                printf(" Opera");
                            if (OPTgcc)
                                printf(" gcc");
                            SPIT_flush();
                        }

                        numberoflines = zerofile(infile,outfile,OPTnewlinetype,OPTnocr);
                    }
                    else
                    {
                        if (OPTverbose>=3)
                        {   printf("Copying");
                            SPIT_flush();
                        }
                        numberofbytes = zerofilecopy(infile,outfile);
                    }

                    totalnumberoflines += numberoflines;
                    totalnumberofbytes += numberofbytes;


                    gclose(infile);
                    if (OPTwrite && outfile)
                    {
                        gclose(outfile);
#if defined(applec) || defined(powerc) || defined (__powerc)
                        {
                            int type;

                            type = findtype(SPITsargv[i]);
                            fsetfileinfo(SPITdargv[i],filetypes[type].creator,filetypes[type].type);
                        }
#endif
                        remove(SPITdargv[i]);
                        rename(outname,SPITdargv[i]);

#if defined(__unix__)
                        if (OPTnewlinetype == 2)  /* unix script? */
                        {
                            int type;
                            char *ext;
                            char buf[512];

                            /* if not extension, assume its a unix script or executable and make it executable */

                            ext = strrchr(SPIT_getname(buf,SPITsargv[i]),'.');
                            if (!ext || !strcmp(ext,".tcl") || !strcmp(ext,".py"))
                            {
                                if (OPTverbose>=3)
                                    printf(" script");
                                sprintf(buf,"chmod +x %s",SPITdargv[i]);
                                system(buf);
                            }
                        }
#endif
                    }

                    if (OPTverbose>=3)
                    {
                        printf(", ");
                        if (numberofbytes)
                           printf("%ld bytes, done.\n",numberofbytes);
                        else
                           printf("%d lines, done.\n",numberoflines);
                        SPIT_flush();
                    }
                    if (OPTverbose>=5)
                        printf("renamed %s to %s\n",outname,SPITdargv[i]);
                }
            }
        }
        if (OPTverbose>=3 && OPTstats)
        {   printf("total %d files, %d zerofile lines, %d binary bytes\n",SPITargnum,totalnumberoflines,totalnumberofbytes);
            SPIT_flush();
        }
        if (OPTverbose==1)
            puts("");
    } while (more > 0);
    SPIT_restore();

    return(0);
}

