/* ---------------------------------------------------------------------- */
/*                   Copyright (C) 1992 by Natrlich!                     */
/*                      This file is copyrighted!                         */
/*                Refer to the documentation for details.                 */
/* ---------------------------------------------------------------------- */
#define LIBRARIAN 1
#include "defines.h"
#include "nasm.h"
#include <stdio.h>
#include <string.h>
#include "debug.h"
#include "object.h"
#include "lib.h"
#if STATISTICS
#include <time.h>
#endif
#include OSBIND
#include NMALLOC_H

char          *currfile,
              outfile[ 256];
static char   *infile[ MAXFILES],
              linkfile[ 256],
#if OS == TOS
_usage[] =
"Usage: nlib65 [-{tw}][-{aducev}][-b batch] <-l library> <object files>\n",
#else
_usage[] =
"Usage: nlib65 [-w][-{aducev}][-b batch] <-l library> <object files>\n",
# if PORTED
portnoy[] =
{
#  if INCOMPATIBLE
   'W','a','r','n','i','n','g',':',' ','O','b','j','e','c','t',' ',
   'f','i','l','e',' ',
   'i','n','c','o','m','p','a','t','i','b','i','l','t','y','.',' ',
#  endif
   'P','o','r','t','e','d',' ','b','y',' ','t','h','e',' ',
   'v','a','l','i','a','n','t',' ',PORTER,'\n',0
},
# endif
#endif
notice[] =
{
   'N','l','i','b','6','5',' ',' ','v',VERSION+'0','.',
   LIBREVISION/10+'0',LIBREVISION%10+'0',' ',
   'b','y',' ',AUTHOR,' ',' ','C','o','p','y','r','i','g','h','t',' ',
   '(','c',')',' ','1','9','9','2',' ',ORGANIZATION,'\r','\n',0
};

int           operation,
              verbose,
              laber,
#if OS == TOS
              tossable,
#endif
              emptyfile,
              what_the_fuck,        /* cited from "Everybody wants some" */
              fdout,
              nfiles,
#if STATISTICS              
              tok_remain,
#endif
              maxerrors = 20;

extern int  freshflag,
            errors;


void main( argc, argv)
int   argc;
char  **argv;
{
#if STATISTICS
   clock_t        t_start, t_finish, t_result, t_tmp;
#endif
   int            i = 0;

   ENTER("main");
#if STATISTICS
   t_start = clock();
#endif

#if DEBUG
   if( argc > 1)
      printf("Argc=%d  argv[1]=\"%s\"\n", argc, argv[1]);
#endif

   while( ++i < argc)
      if( *argv[i] == '-')
         switch( Xtolower( argv[i][1]))
         {

            case 'l' :
               if( ++i == argc)
            default  :
                  goto usage;
               strcpy( outfile, argv[i]);
               break;

            case 'a' :
               operation = OP_ADD;
               break;

            case 'u' :
               operation = OP_UPDATE;
               break;

            case 'd' :
               operation = OP_DELETE;
               break;

            case 'c' :
               operation = OP_CREATE;  /* not for the faint of heart */
               break;

            case 'e' :
               operation = OP_EXTRACT;
               break;

            case 'v' :
               verbose   = argv[i][2];
               operation = OP_LIST;
               break;

#if OS == TOS
            case 't' :
               tossable = ! tossable;
               break;
#endif

#ifdef __DATE__
            case ':' :
               fputs( __DATE__, stderr);
# ifdef __TIME__
               fprintf( stderr, " %s", __TIME__);
# endif                              
               putc( '\n', stderr);
               break;
#endif               
            case 'w' :
               what_the_fuck = 1;
               break;

            case '_' :
               laber = 1;
               break;

            case 'b' :
            {
               register char  c;
               FILE           *fp, *fopen();
               static char    x[256];

               if( ++i == argc)
                  goto usage;
               strcpy( linkfile, argv[i]);
               complete( linkfile, ".bth", 0);
               if( ! (fp = fopen( linkfile, "r")))
                  nferror("Opening the linkfile failed");
               do
                  switch( c = getc( fp))
                  {
                     case '#'  :
                        while( (c = getc( fp)) != '\n' && c != EOF);
                        break;

                     default   :
                     {
                        register int   i = 0;

                        do
                           x[i++] = c;
                        while( (c = getc( fp)) != ' '  && c != '\t' &&
                               c != '\r' && c != '\n' && c != EOF && i < 255);
                        x[i++] = 0;
                        infile[ nfiles++] = strcpy( (char *) nmalloc( (long) i), x);
                     }
                     case ' '  :
                     case '\t' :
                     case '\r' :
                     case '\n' :
                     case EOF  : ;
                  }
               while( c != EOF);
               fclose( fp);
            }
         }
      else
         infile[nfiles++] = argv[i];

   if( (! infile[0] && operation < OP_LIST) || ! outfile[0])
      goto usage;

#if OS == MSDOS
   _fmode = O_BINARY;
#endif
   Cconws( notice);
#if ! VERSION
   Cconws("unfinished - unstable - unsupported -- untested. Don't use it!\r\n");
   version0();
#endif
#if PORTED
   Cconws( portnoy);
#endif
   complete( currfile = outfile, ".l65", 0);
   pro_init();

   if( operation == OP_CREATE)
   {
      if( (i = (int) Fopen( outfile, OPEN_W)) >= 0)
      {
         Fclose( i);
         nwarning("Killed an old real existing library");
      }
      goto doit;
   }
   if( ! lload( currfile = outfile))
      if( operation == OP_ADD)
      {
doit:
         if( (i = (int) Fkreate( currfile, 0x664)) < 0)
            ngferror( i, "Couldn't create library file");
         Fclose( i);
         emptyfile = 1;
      }
      else
         nferror("Library not found");

   if( operation == OP_LIST)
   {
      if( nfiles)
         nwarning("Object files ignored");
      list( verbose);
   }
   else
      for( i = 0; i != nfiles; i++)
      {
         IMESS("Libbing now \"%s\"", (unsigned long) infile[i], 4);
         switch( operation)
         {
            case OP_UPDATE :
               delete( infile[ i], 1);
            case OP_CREATE :
            case OP_ADD    :
               oload( currfile = infile[i]);
               sym_lib();
               file_lib( currfile);
               wrapup();
               break;

            case OP_EXTRACT :
               extract( infile[ i]);
               break;

            case OP_DELETE  :
               delete( infile[ i], 0);
         }
      }
   pro_exit();

   if( ! errors || what_the_fuck)
   {
      extern word  gindex, findex;

      if( ! (findex && gindex))
         nferror("Library would be empty");
      if( (fdout = (int) Fopen( currfile = outfile, OPEN_W)) < 0)
         nferror("Can't open library file");
      write_results( fdout);     /* clobbers internal structures !! */
   }

   MESS("OK JUST ABOUT DONE");
#if STATISTICS
   t_finish = clock();
   if( t_start > t_finish)
      t_tmp = t_start - t_finish;
   else
      t_tmp = t_finish - t_start;
   t_result = (t_finish - t_start) / (int) CLK_TCK;
   finalstats(1);
   printf("Link took %ld.%lds\n", t_result,
                           (t_tmp - (t_result * (int) CLK_TCK)) >> 1 );
   stats();
#endif
   ALEAVE();
   nexit( 0);

usage:
   fputs( _usage, ESTREAM);
   fputs( "\
\t-a         : add to library\n\
\t-u         : update libraray\n\
\t-d         : delete from library\n\
\t-c         : create library from scratch\n\
\t-e         : extract from library\n\
\t-v         : verbose\n\
\t-w         : write output file anyway (W.T.F.)\n\
\t-_         : talkative\n\
\t-b  <batch>: take input files from batchfile\n\
\t-l  <lib>  : library to use\n", ESTREAM);
#if OS == TOS
        fputs( "\
\t-t         : wait for keypress before exit\n", ESTREAM);
#endif
   ALEAVE();
   nexit( 1);
}


