/* ---------------------------------------------------------------------
   (c) ED 2000-2002
   Project      : CLIB
   Function     : Lecture des options de la ligne de commande
   Module       : OPT
   File         : OPT.C
   Created      : 12-11-2000
   Modified     : 01-06-2004
   --------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
   Log

   0.0 - 12-11-2000 Created
   1.0 - 12-11-2000 Initial version
   1.1 - 13-11-2000 OPT_scan() parameter 'firstarg' added.
   1.2 - 13-07-2002 LCLint
   1.3 - 01-06-2004  .errno devient .err

   --------------------------------------------------------------------- */
#ifdef __cplusplus
#error This source file is not C++ but rather C. Please use a C-compiler
#endif

#include "ed/inc/opt.h"
#include "ed/inc/sys.h"
#include "ed/inc/sysalloc.h"

/* ---------------------------------------------------------------------
   Public data
   --------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
   Private constants
   --------------------------------------------------------------------- */
#define MODULE "OPT"
#define VER "1.3"
#define ID "OPT Module \"C\" (c) ED 2000-2004"

/* ---------------------------------------------------------------------
   Private structures
   --------------------------------------------------------------------- */
typedef struct
{
   char const *sopt;
   fOPT_CB *pf;
   void *pUser;
}
sOPTION;

typedef struct
{
   eOPT_ERR err;
   sOPTION *aopt;
   size_t nmax;
   size_t ncur;
   fOPT_ERR_CB *pfErr;
   void *pUserErr;
}
sPRIVATE;

/* ---------------------------------------------------------------------
   Private data
   --------------------------------------------------------------------- */

/* =====================================================================
   Private functions
   ===================================================================== */

/* ---------------------------------------------------------------------
   define()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   E :
   S :
   --------------------------------------------------------------------- */
static eOPT_ERR define (sPRIVATE * const pPrivate
                        ,const char *sOption
                        ,fOPT_CB * pf
                        ,void *pUser
)
{
   eOPT_ERR ret = -1;
   ASSERT (pPrivate != NULL);
   /*  function code */
   {
      sOPTION *const p = &pPrivate->aopt[pPrivate->ncur];
      p->sopt = sOption;
      p->pf = pf;
      p->pUser = pUser;
   }

   pPrivate->ncur++;
   ASSERT (pPrivate->ncur <= pPrivate->nmax);

   ret = 0;

   return ret;
}

/* ---------------------------------------------------------------------
   scan()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   E :
   S :
   --------------------------------------------------------------------- */
static eOPT_ERR scan (sPRIVATE * const pPrivate
                      ,size_t const firstarg
                      ,size_t const argc
                      ,char const *args[]
)
{
   eOPT_ERR ret = -1;
   ASSERT (pPrivate != NULL);
   /*  function code */

   {
      size_t i;

      for (i = firstarg; i < argc; i++)
      {
         size_t j;
         char const *p = NULL;
         int found = 0;

         for (j = 0; j < pPrivate->ncur; j++)
         {
            sOPTION const *const pOpt = &pPrivate->aopt[j];

            p = strstr (args[i], pOpt->sopt);

            if (p != NULL)
            {
               if (pOpt->pf != NULL)
               {
                  /* LCLint */
                  ret = (*pOpt->pf) (pOpt->pUser, p);
               }
               found = 1;
            }

         }

         if (!found && pPrivate->pfErr != NULL)
         {
            /* LCLint */
            ret = (*pPrivate->pfErr) (pPrivate->pUserErr, args[i]);
         }

      }
   }

   return ret;
}

/* =====================================================================
   Public functions
   ===================================================================== */

/* ---------------------------------------------------------------------
   OPT_sver()
   ---------------------------------------------------------------------
   Returns the "Version" string
   ---------------------------------------------------------------------
   E :
   S : ASCIIZ string pointer
   --------------------------------------------------------------------- */
const char *OPT_sver (void)
{
   return VER;
}

/* ---------------------------------------------------------------------
   OPT_sid()
   ---------------------------------------------------------------------
   Returns the "Identification" string
   ---------------------------------------------------------------------
   E :
   S : ASCIIZ string pointer
   --------------------------------------------------------------------- */
const char *OPT_sid (void)
{
   return ID;
}

/* ---------------------------------------------------------------------
   OPT_init()
   ---------------------------------------------------------------------
   Creates and initializes the C-object
   ---------------------------------------------------------------------
   E : Max number of options
   E : callback "Erreur"
   E : Contexte utilisateur
   S : Data pointer
   --------------------------------------------------------------------- */
sOPT *OPT_init (size_t const nopt, fOPT_ERR_CB * const pf, void *const pUser)
{
   sOPT *pOpt = NULL;

   pOpt = malloc (sizeof *pOpt);

   if (pOpt != NULL)
   {

      sPRIVATE *pPrivate = NULL;

      CLR (pOpt, sOPT);

      pPrivate = malloc (sizeof *pPrivate);

      if (pPrivate != NULL)
      {

         CLR (pPrivate, sPRIVATE);

         pOpt->pPrivate = pPrivate;

         /* creation code ... */
         /* initializes the pointers to NULL */

         {
            sOPTION *const p = malloc (sizeof *p * nopt);

            if (p != NULL)
            {
               size_t i;

               for (i = 0; i < nopt; i++)
               {
                  CLR (p + i, sOPTION);
               }

               pPrivate->aopt = p;
               pPrivate->nmax = nopt;
               pPrivate->ncur = 0;

               pPrivate->pfErr = pf;
               pPrivate->pUserErr = pUser;

               pPrivate->err = OPT_ERR_OK;
            }
            else
            {
               OPT_end (pOpt);
               pOpt = NULL;
            }

         }

         pOpt->err = pPrivate->err;

      }
      else
      {
         OPT_end (pOpt);
         pOpt = NULL;
      }
   }
   return pOpt;
}

/* ---------------------------------------------------------------------
   OPT_end()
   ---------------------------------------------------------------------
   Suppresses the C-object
   ---------------------------------------------------------------------
   E : Data pointer
   S :
   --------------------------------------------------------------------- */
void OPT_end (sOPT * const pOpt)
{
   if (pOpt != NULL)
   {
      if (pOpt->pPrivate != NULL)
      {
         sPRIVATE *pPrivate = pOpt->pPrivate;

         /* suppress code ... */

         if (pPrivate->aopt)
         {
            free (pPrivate->aopt);
            pPrivate->aopt = NULL;
         }
         free (pPrivate);
         pOpt->pPrivate = NULL;
      }
      free (pOpt);
   }
}

/* ---------------------------------------------------------------------
   OPT_errno()
   ---------------------------------------------------------------------
   Returns the current error code
   ---------------------------------------------------------------------
   E : Data pointer
   S :
   --------------------------------------------------------------------- */
eOPT_ERR OPT_errno (sOPT const *const pOpt)
{
   eOPT_ERR ret = -1;

   if (pOpt != NULL)
   {
      ret = pOpt->err;
   }

   return ret;
}

/* ---------------------------------------------------------------------
   OPT_define()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   E : Data pointer
   E : Option string
   E : Function to be called
   E : User context
   E : Help string
   S :
   --------------------------------------------------------------------- */
eOPT_ERR OPT_define (sOPT * const pOpt
                     ,const char *const sOption
                     ,fOPT_CB * const pf
                     ,void *const pUser
)
{
   eOPT_ERR ret = -1;

   if (pOpt != NULL)
   {
      sPRIVATE *pPrivate = pOpt->pPrivate;

      if (pPrivate != NULL)
      {
         /*  function code */
         if (sOption != NULL)
         {
            if (pPrivate->ncur < pPrivate->nmax)
            {
               ret = define (pPrivate, sOption, pf, pUser);

               if (ret != 0)
               {
                  pOpt->err = pPrivate->err;
               }
            }
            else
            {
               pOpt->err = OPT_ERR_FULL;
            }
         }
         else
         {
            pOpt->err = OPT_ERR_PARAMETER;
         }
      }
   }
   return ret;
}

/* ---------------------------------------------------------------------
   OPT_scan()
   ---------------------------------------------------------------------
   Scans the options and eventually call the setup functions
   ---------------------------------------------------------------------
   E :
   S : Data pointer
   --------------------------------------------------------------------- */
eOPT_ERR OPT_scan (sOPT * const pOpt
                   ,int const firstarg
                   ,int const argc
                   ,char const **const args)
{
   eOPT_ERR ret = -1;

   if (pOpt != NULL)
   {
      sPRIVATE *pPrivate = pOpt->pPrivate;

      if (pPrivate != NULL)
      {
         /*  function code */

         ret = scan (pPrivate, (size_t) firstarg, (size_t) argc, args);

         if (ret != 0)
         {
            pOpt->err = pPrivate->err;
         }
      }
   }
   return ret;
}

/* File generated by 'NEW.EXE' Ver 1.25 (c) ED 1998-2000 */
