/* catg.c version 1.3; B D McKay, Jan 2013 */

#define USAGE "catg [-xv] [infile]..."

#define HELPTEXT \
"  Copy files to stdout with all but the first header removed.\n\
\n\
     -x  Don't write a header.\n\
         In the absence of -x, a header is written if\n\
         there is one in the first input file.\n\
\n\
     -v  Summarize to stderr.\n"

#include "gtools.h"

/***********************************************************************/

static FILE*
openfile_head(char *filename, char **header)
/* Open the file for reading and return a FILE*.  If open fails, or
   the header is malformed, write a message and return NULL.  Set
   *header to point to the header string (statically allocated).
   A filename of NULL or "-" means stdin. */
{
    int c,i;
    char *actname;
    FILE *f;
    DYNALLSTAT(char,head,head_sz);

    if (filename == NULL || strcmp(filename,"-") == 0)
    {
        f = stdin;
        actname = "stdin";
    }
    else 
    {
        f = fopen(filename,"r");
        actname = filename;
    }

    if (f == NULL)
    {
        fprintf(stderr,">E catg: can't open file %s\n",actname);
        return NULL;
    }

    DYNALLOC1(char,head,head_sz,100,"catg");

    c = getc(f);
    if (c == '>')
    {
        i = 0;
        head[i++] = (char)c;

        c = getc(f);
        if (c != '>')
        {
            fprintf(stderr,">E catg: bad header in %s\n",actname);
            fclose(f);
            return NULL;
        }
        head[i++] = (char)c;

        do
        {
            c = getc(f);
            if (c == EOF)
            {
                fprintf(stderr,">E catg: bad header in %s\n",actname);
                fclose(f);
                return NULL;
            }

            if (i >= head_sz-1)
                DYNREALLOC(char,head,head_sz,head_sz+100,"catg");
            head[i++] = (char)c;
        }
        while (c != '<' || head[i-2] != '<');

        head[i] = '\0';
    }
    else
    {
        ungetc(c,f);
        head[0] = '\0';
    }

    *header = head;

    return f;
}

/***********************************************************************/

int
main(int argc, char *argv[])
{
    char *infilename,*head;
    FILE *infile;
    int nfiles,i,j;
    char *arg,sw;
    boolean vswitch,xswitch;
    boolean badargs;
    char buff[1024];
    size_t nr;
    DYNALLSTAT(char*,filename,filename_sz);

    HELP; PUTVERSION;

    DYNALLOC1(char*,filename,filename_sz,200,"catg");

    xswitch = vswitch = FALSE;

    nfiles = 0;
    badargs = FALSE;
    for (j = 1; !badargs && j < argc; ++j)
    {
        arg = argv[j];
        if (arg[0] == '-' && arg[1] != '\0')
        {
            ++arg;
            while (*arg != '\0')
            {
                sw = *arg++;
                     SWBOOLEAN('v',vswitch)
                else SWBOOLEAN('x',xswitch)
                else badargs = TRUE;
            }
        }
        else
        {
            if (nfiles >= filename_sz)
                DYNREALLOC(char*,filename,filename_sz,
                                      filename_sz+200,"catg");
            filename[nfiles++] = arg;
        }
    }

    if (badargs)
    {
        fprintf(stderr,">E Usage: %s\n",USAGE);
        GETHELP;
        exit(1);
    }

    for (i = 0; i < (nfiles == 0 ? 1 : nfiles); ++i)
    {
        infilename = (nfiles == 0 ? NULL : filename[i]);
        infile = openfile_head(infilename,&head);
        if (infile == NULL) ABORT("catg");

        if (i == 0 && !xswitch) fprintf(stdout,"%s",head);

        while ((nr = fread(buff,1,1024,infile)) > 0)
        {
            fwrite(buff,1,nr,stdout);
            if (ferror(stdout))
            {
                fprintf(stderr,">E catg: error in writing to stdout\n");
                ABORT("catg");
            }
        }
        if (ferror(infile))
        {
            fprintf(stderr,">E catg: error in reading from %s\n",
                    infilename == NULL ? "stdin" : infilename);
            ABORT("catg");
        }
        fclose(infile);
    }

    if (vswitch)  { }

    exit(0);
}
