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

const char *SPIT_history[] =
{
"------------------------------------------------------------------",
"                                                                  ",
"                            Touch v1.01                           ",
"                                                                  ",
"                        by FrANK G. Barchard                      ",
"                                                                  ",
"                     Main program - Aug 22, 2006                  ",
"                                                                  ",
"------------------------------------------------------------------",
"                                                                  ",
" Version Date   SE History:                                       ",
" ------- ----   -- --------                                       ",
"    1.00 051101 FB Initial version based on makepad               ",
"    1.01 060822 FB Converted to spit to support wildcards         ",
"                                                                  ",
"------------------------------------------------------------------",
"\0"
};

/****************************************************************/
/*  Spit Setup                                                  */
/****************************************************************/
#include <windows.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>

#include "spit.h"
#include "stdgimex.h"
#include "ranger.h"

const char TextVersion[]="1.08a (Samba) 2007.12.4";
#define TOOL_VERSION 108
#define TOOL_NAME "touch"

char OPTreturn[SPITMAXLINE];


// SetFileToCurrentTime - sets last write time to current system time
// Return value - TRUE if successful, FALSE otherwise
// hFile  - must be a valid file handle

BOOL SetFileToCurrentTime(HANDLE hFile)
{
    FILETIME ft;
    SYSTEMTIME st;
    BOOL f;

    GetSystemTime(&st);              // gets current time
    SystemTimeToFileTime(&st, &ft);  // converts to file time format
    f = SetFileTime(hFile,           // sets last-write time for file
        (LPFILETIME) NULL, (LPFILETIME) NULL, &ft);

    return f;
}

int TouchFile(const char *filename)
{
    int Error = 1;

    HANDLE hFile = CreateFile(filename,    // create filename
             FILE_WRITE_ATTRIBUTES,        // open for writing attributes
             0,                            // do not share
             NULL,                         // no security
             OPEN_EXISTING,                // open existing file
             FILE_ATTRIBUTE_NORMAL |       // normal file
             FILE_FLAG_OVERLAPPED,         // asynchronous I/O
             NULL);                        // no attr. template

    if ((int)hFile>=0)
    {
        SetFileToCurrentTime(hFile);
        CloseHandle(hFile);
        Error = 0;
    }
    return Error;
}

/*
;
; ABSTRACT
;
; touch - a tool to set the time stamp on files to the current time/date
;
; SUMMARY
;
; touch -options [files]
;     @file          response file, containing a list of options and files
;     =file          specify a output file ie source=dest
;     -b0            disable banner
;     -v0            no console output
;     -v1            less output
;     -v2            normal output (default)
;     -v             more output
;     -w0            dont output file
;     -r             recurse subdirectories to find files
;     -r%ENV%        traverse environment variable ENV to find files
;     -time          show execution time
;     -return<expr>  return expression (default errorcount)
;                    variables available:
;                      errorcount
;                      TOOL_VERSION
;                      SPIT_VERSION
;
;
; DESCRIPTION
;
; Touch set the time stamp on files to the current time and date.
; The file contents are not affected and write access to the file contents
; is not needed.  Write access to the file attributes is needed.
;
; RETURNS
;
; error count by default (0 for no errors)
; -return value if specified
;
; SEE ALSO
;
; huff, Spit
;
; SAMPLE OUTPUT
;
; >touch *.*
;
; END ABSTRACT
;
*/

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

void SPIT_reset(void)
{
    OPTkeepopts = 1;
    OPTtime = 0;
    strcpy(OPTreturn,"");

    return;
}

char *optionhelp[]=
{
    "    @file          response file, containing a list of options and files\n",
    "    =file          specify a output file ie source=dest\n",
    "    -b0            disable banner\n",
    "    -v0            no console output\n"
    "    -v1            less output\n"
    "    -v2            normal output (default)\n"
    "    -v             more output\n",
    "    -w0            dont output file\n",
    "    -r             recurse subdirectories to find files\n"
    "    -r%ENV%        traverse environment variable ENV to find files\n",
    "    -time          show execution time\n",
    "    -return<expr>  return expression (default errorcount)\n"
    "                   variables available:\n"
    "                     errorcount\n"
    "                     TOOL_VERSION\n"
    "                     SPIT_VERSION\n",
    "\n",
    "RANGE SYNTAX:\n"
    "    [[!][<start>][..][<end>][+=<step>][,]]*\n"
    "    ie -f             all frames\n"
    "       -f5            frame 5\n"
    "       -f5..9         frames 5..9 inclusive\n"
    "       -f!10          all frames except\n"
    "       -f5,7,9        frames 5,7 and 9\n"
    "       -f10..98+=2    even frames in range between 10 and 98\n",
    "\n",
    0,
};

void SPIT_usage(const char *prgname, const char *envname, const char *urlname, int utype)
{
    char **hlp;

    if (((OPTverbose>=2 && utype==2) || OPTverbose>=4))
        printf("Touch v%s by FrANK G. Barchard\n",TextVersion);


    if (utype)
        printf("USAGE: %s -options [files]\n", prgname);

    switch (utype)
    {
        case 0:
        case 1:
            break;

        case 2:
            puts("    -time time execution         -return value");
            puts("    -v verbose                   -w write file");
            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: a tool to set the time stamp on files to the current time/date");
          printf("         SPIT environment variable is %s\n",envname);
            puts("");

            hlp = optionhelp;
            while (*hlp)
            {
                printf("%s",*hlp);
                ++hlp;
            }
            break;

         case 4:
            puts("");
            {
                hlp = optionhelp;
                while (*hlp)
                {
                    if (SPIT_strstr(*hlp,envname))
                        printf("%s",*hlp);
                    ++hlp;
                }
                puts("");
            }
            break;

        default:
            break;
    }
}

char *SPIT_opt(const char* optptr)
{
    char *d=NULL;
    switch (tolower(*optptr))
    {
        case 'r':
            if (!strnicmp(optptr,"return",6))
            {
                d = SPIT_getfield( OPTreturn,optptr+6,1,0);
            }
            break;

        default:
            break;
    }
    return(d);
}

int main(int argc, char* argv[])
{
    int more;
    int i;
    int errorcount=0;
    double totaltime;

    SPIT_init(SPIT_reset, SPIT_usage, SPIT_opt, SPIT_history);

    EXPR *expr = EXPR_open();

    totaltime = SPIT_gettime();

    do
    {
        more = SPIT_parse(argc, argv, TOOL_NAME, TOOL_VERSION);

        if (!SPIThelpgiven)
        {
            for (i=0; i<SPITargnum; ++i)
            {
                bool isopt = false;
                if (SPITsargv[i][0]=='-' || SPITsargv[i][0]=='+' || (SPITsargv[i][0]=='.' && SPITsargv[i][1]!='.' && SPITsargv[i][1]!='/' && SPITsargv[i][1]!='\\'))
                    isopt = Zop(SPITsargv[i]+1)?true:false;
                else if (SPITsargv[i][0]=='=')
                    isopt = Zop(SPITsargv[i])?true:false;

                if (!isopt)
                {
                    if (OPTverbose>=4)
                    {
                        printf("%s -> %s\n",SPITsargv[i],SPITdargv[i]);
                    }
                    else if (OPTverbose>=3)
                    {
                        char fname[SPITMAXLINE];
                        SPIT_getname(fname,SPITdargv[i]);
                        printf("%s\n",fname);
                    }
                    if (OPTwrite)
                        errorcount += TouchFile(SPITdargv[i]);
                }
            }
        }
    } while (more>0);

    int returncode = errorcount;
    if (OPTreturn[0])
    {
        RANGER *r = RANGER_open(expr,OPTreturn,0.0,1000000.0);  // min/max mostly ignored

        EXPR_set(expr,"errorcount",   errorcount);
        EXPR_set(expr,"TOOL_VERSION", TOOL_VERSION);
        EXPR_set(expr,"SPIT_VERSION", SPIT_VERSION);

        returncode = (int) RANGER_closest(r, (double) returncode, RANGER_ROUND_CLOSEST);

        RANGER_close(r);
    }
    EXPR_close(expr);

    if (OPTverbose==1)
        puts("");

    totaltime = SPIT_gettime()-totaltime;
    if (OPTtime)
    {
        if (totaltime>=3600000.0)
            printf("TIME " TOOL_NAME " %.2f ms (%.2f seconds) (%.2f minutes) (%.2f hours)",totaltime,totaltime/1000.0,totaltime/60000.0,totaltime/3600000.0);
        else if (totaltime>=60000.0)
            printf("TIME " TOOL_NAME " %.2f ms (%.2f seconds) (%.2f minutes)",totaltime,totaltime/1000.0,totaltime/60000.0);
        else if (totaltime>=1000.0)
            printf("TIME " TOOL_NAME " %.2f ms (%.2f seconds)",totaltime,totaltime/1000.0);
        else
            printf("TIME " TOOL_NAME " %.2f ms",totaltime);
    }

    SPIT_restore();

    if (galloccount)
    {
        if (OPTverbose>=2)
        {
            printf(TOOL_NAME " - WARNING MEMORY NOT FREED TO SYSTEM %d\n",galloccount);
            returncode = galloccount;
        }
    }

    return returncode;
}

