// (c) 1993-2007 Electronic Arts Inc.

const char *SPIT_history[] =
{
"------------------------------------------------------------------",
"                                                                  ",
"                           Unslash v1.03                          ",
"                                                                  ",
"            Copyright (c) 1993 Electronic Arts Canada Inc         ",
"                                                                  ",
"                        by FrANK G. Barchard                      ",
"                                                                  ",
"                     Main program - Feb 02, 1999                  ",
"                                                                  ",
"------------------------------------------------------------------",
"                                                                  ",
" Version Date   SE History:                                       ",
" ------- ------ -- --------                                       ",
"    1.00 931124 FB Initial version, by based txt                  ",
"    1.01 950512 FB understand \' is not end quote                 ",
"    1.02 981117 FB use stdgimex to do renaming/temp files         ",
"    1.03 990202 FB unslash on last line                           ",
"                                                                  ",
"------------------------------------------------------------------",
"\0"
};

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

#include    "spit.h"

const char TextVersion[]="1.03 (Samba) 2007.12.4";
#define TOOL_VERSION 103
#define TOOL_NAME "unslash"

int OPTtype;
int OPTnamelower;

#define BUFSIZE 4096

static int bufpos=0;
static char bufc[BUFSIZE];
static int inslash=0;
static int inquote=0;
static int incomment=0;
static int slashcount=0;

static void SPIT_flushc(GSTREAM *out)
{
    if (OPTwrite)
        gwrite(out,bufc,bufpos);
    SPIT_flush();
    bufpos = 0;
}

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

static void SPIT_flushslash(GSTREAM *out)
{
    if (inslash)
    {
        SPIT_putc(' ',out);
        SPIT_putc('*',out);
        SPIT_putc('/',out);
        ++slashcount;
        inslash = 0;
    }
}

static void SPIT_putcr(GSTREAM *out,int type)
{
    SPIT_flushslash(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,amiga,3do style lf */
            SPIT_putc(10,out);
            break;
    }
}


static int unslash(GSTREAM *in,GSTREAM *out, int type)
{
    int done=0;
    int lastch=0;
    int ch=0;
    unsigned char buf[4];
    int numberoflines=0;

    while (!done)
    {
        if (gtell(in)>=glen(in))
        {
            done = 1;
        }
        else
        {
            lastch = ch;
            gread(in,buf,1);
            ch=(int)buf[0];

            switch(ch)
            {
                case '"':
                    if (!inslash && !incomment)
                    {
                        if (!inquote)
                            inquote = '"';
                        else if (inquote=='"' && lastch!='\\')
                            inquote = 0;
                    }
                    SPIT_putc(ch,out);
                    break;

                case '\047':
                    if (!inslash && !incomment)
                    {
                        if (!inquote)
                            inquote = '\047';
                        else if (inquote=='\047' && lastch!='\\')
                            inquote = 0;
                    }
                    SPIT_putc(ch,out);
                    break;

                case '\\':
                    SPIT_putc(ch,out);
                    if (lastch=='\\')
                        ch = 0;
                    break;

                case '*':
                    if (lastch=='/')
                    {
                        if (!inquote && !inslash)
                        {
                            ++incomment;    /* can be nested */
                            SPIT_putc(ch,out);
                            ch = 0;
                            break;
                        }
                    }
                    SPIT_putc(ch,out);
                    break;

                case '/':
                    if (inslash)    /* avoid nested comments trouble */
                        ch = '\\';
                    else
                    {
                        if (lastch=='*')
                        {
                            if (!inquote && !inslash && incomment)
                            {
                                --incomment;
                                SPIT_putc(ch,out);
                                ch = 0;
                                break;
                            }
                        }
                        else if (lastch=='/')
                        {
                            if (!inquote && !incomment && !inslash)
                            {
                                ch = '*';
                                ++inslash;
                                SPIT_putc(ch,out);
                                ch = 0;
                                break;
                            }
                        }
                    }
                    SPIT_putc(ch,out);
                    break;

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

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

                default:
                    SPIT_putc(ch,out);
                case 'z'&31:
                    break;
            }
        }
    }
    SPIT_flushslash(out);
    SPIT_flushc(out);

    return(numberoflines);
}


static 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));
        }
    }
}



/*
;
; ABSTRACT
;
; unslash - convert C++ comments to C style
;
; SUMMARY
;
; unslash -options [files]
;     -t0       __WATCOMC__ type crlf
;     -t1       Mac type cr
;     -t2       Unix type lf
;     -nologo   disable banner
;     -v1       prints source file name and errors
;     -v0       no console output
;     -v2       status line for each file (default)
;     -v3       additional info
;     -w0       don't output file
;     -w1       output to file (default)
;     @file     response file, containing a list of options and files
;     =file     specify a output file ie unslash source=dest
;
; DESCRIPTION
;
; Unslash converts C or C++ source files that contain // style
; comments, to standard C style comments.  This is useful
; for porting to C compilers such as MIPS, that don't support
; the // comments.  Unslash is intelligent about strings and comments
; that contain // and avoids creating nested comments.
;
; RETURNS
;
; no return code
;
; SEE ALSO
;
; txt, copyr, tabs
;
; SAMPLE OUTPUT
;
; >unslash *.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)
{
#if defined(__WATCOMC__) || defined(_MSC_VER)
    OPTtype = 0;   /* crlf */
#else
#ifdef applec
    OPTtype = 1;   /* cr */
#else
    OPTtype = 2;   /* lf */
#endif
#endif
    OPTnamelower = 1;
    OPTbanner = 0;
}

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

    switch (utype)
    {
        case 2:
            puts("    -t cr type (0 PC,1 Mac,2 Unix)");
            puts("    -w write file                -v verbose");
            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,TextVersion,(float)SPIT_VERSION/100.0f);
            puts("SUMMARY: Unslash replaces C++ //'s with C /* */'s");
          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("    -t0       __WATCOMC__ type crlf");
            puts("    -t1       Mac type cr");
            puts("    -t2       Unix type lf");
            puts("    -nologo   disable banner");
            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)");

        default:
            break;
    }
}

char *SPIT_opt(const char* optptr)
{
    switch (*optptr|(char)' ')
    {
        case 't':
            return(SPIT_getopt( &OPTtype,optptr+1, "cr type", 0, 2));
            break;

        case 'n':
            return(SPIT_getopt( &OPTnamelower,optptr+1, "name to lower case", 0, 1));
            break;

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

int main(int argc, char* argv[])
{
    int more;
    int i;
    int j;
    int numberoflines;
    GSTREAM *infile;
    GSTREAM *outfile=0;

    /* Command line options. */
    SPIT_init(SPIT_reset, SPIT_usage, SPIT_opt, SPIT_history);
    do
    {
        more = SPIT_parse(argc, argv, TOOL_NAME, TOOL_VERSION);

        for (i=0; i<SPITargnum; ++i)
        {
            inslash=0;
            inquote=0;
            incomment=0;
            slashcount=0;

            if (OPTnamelower)
            {
               for (j=0; SPITsargv[i][j]; ++j)
                    SPITsargv[i][j] = (char) tolower(SPITsargv[i][j]);
            }

            SPIT_openstr(SPITsargv[i]);
            SPIT_flush();

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

                if (OPTwrite)
                    outfile = gwopen(SPITdargv[i]);

                if (!outfile)
                {
                    if (OPTverbose>=2)
                        printf("unslash - COULD NOT OPEN FILE FOR WRITE '%s'\n",SPITdargv[i]);
                    gclose(infile);
                }
                else
                {
                    if (OPTverbose>=3)
                    {   printf("Translating, ");
                        SPIT_flush();
                    }

                    numberoflines = unslash(infile,outfile,OPTtype);

                    gclose(infile);
                    if (OPTwrite)
                    {
                        gclose(outfile);
#ifdef applec
                        fsetfileinfo(SPITdargv[i],'MPS ','TEXT');
#endif
                    }

                    if (OPTverbose>=3)
                    {   printf("%d lines, %d slashes, done.\n",numberoflines,slashcount);
                        SPIT_flush();
                    }
                }
            }
        }
        if (OPTverbose==1)
            puts("");
    } while (more>0);

    return(0);
}

