/*
 * cmdr.c
 *
 * Perform expansions on the command line arguments
 *
 *  1998 Straylight/Edgeware
 */

/*----- Licensing note ----------------------------------------------------*
 *
 * This file is part of Straylight's core utilities (coreutils).
 *
 * Coreutils is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * Coreutils is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with coreutils.  If not, write to the Free Software Foundation,
 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*----- Header files ------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "swis.h"
#include "swiv.h"

#include "alloc.h"
#include "cmdr.h"
#include "gf.h"
#include "glob.h"

/*----- Type definitions --------------------------------------------------*/

typedef struct cmdr_ctx {
  char **av;				/* Pointer to @argv@ array */
  size_t sz;				/* Size currently allocated */
  size_t i;				/* Next available @argv@ index */
} cmdr_ctx;

/*----- Main code ---------------------------------------------------------*/

/* --- @cmdr_add@ --- *
 *
 * Arguments:	@const char *p@ = pointer to an expanded item
 *		@void *ctx@ = pointer to my context
 *
 * Returns:	---
 *
 * Use:		Adds a globbed filename to the output buffer.
 */

static void cmdr_add(const char *p, void *ctx)
{
  cmdr_ctx *cx = ctx;

  if (cx->i == cx->sz) {
    cx->sz += 1024;
    cx->av = xrealloc(cx->av, cx->sz * sizeof(cx->av[0]));
  }
  cx->av[cx->i++] = xstrdup(p);
}

/* --- @cmdreplace@ --- *
 *
 * Arguments:	@int *argc@ = pointer to argument count
 *		@char ***argv@ = address of pointer to arg list
 *
 * Returns:	---
 *
 * Use:		Mangles the argument list until it's nice.
 */

void cmdreplace(int *argc, char ***argv)
{
  cmdr_ctx cx;
  char **iav = *argv;
  int iac = 0;

  /* --- Initialise the context --- */

  cx.sz = 256;
  cx.av = xmalloc(cx.sz * sizeof(cx.av[0]));
  cx.i = 0;

  /* --- Copy over @argv[0]@ because it's special --- */

  cx.av[cx.i++] = iav[iac++];

  /* --- Copy over everything else --- */

  while (iav[iac]) {
    if (glob(iav[iac], cmdr_add, &cx) == 0) {
      if (cx.i == cx.sz) {
        cx.sz += 1024;
        cx.av = xrealloc(cx.av, cx.sz * sizeof(cx.av[0]));
      }
      cx.av[cx.i++] = iav[iac];
    }
    iac++;
  }

  /* --- Copy over the terminator --- */

  if (cx.i == cx.sz) {
    cx.sz += 1024;
    cx.av = xrealloc(cx.av, cx.sz * sizeof(cx.av[0]));
  }
  cx.av[cx.i] = 0;

  /* --- Return appropriate values to the caller --- */

  *argc = cx.i;
  *argv = cx.av;
}

/*----- That's all, folks -------------------------------------------------*/
