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

                   Beebug C Library Facility
                   -------------------------

Author : David Allison
Issue  : 1.0
Date   : 13 August 1987

(C) 1987 Beebug Limited

This is the main driver module for the facility.

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

# include <h.stdio>
# include <h.ctype>
# include <h.string>
# include <h.stdlib>
# include "c.libdef"


struct 
   {
   char *comm ;
   int token ;
   char *description ;
   } commands [] = {
                   { "LIST",LIST,"List contents of library" },
                   { "INSERT",INSERT,"Insert module into library" },
                   { "EXIT",EXIT,"Exit, committing changes"} ,
                   { "USE",USE,"Establish working library"},
                   { "CREATE",CREATE,"Create new library"},
                   { "DELETE",DELETE,"Delete module from library"},
                   { "QUIT",QUIT,"Quit from facility"},
                   { "COMMIT",COMMIT,"Commit changes to disk"},
                   { "NEW",NEW,"Establish new working library"},
                   { "EXTRACT",EXTRACT,"Extract module into file"},
                   { "HELP",HELP,"This command"}
                   } ;

# define MAX_COMMAND 50

char command_line[MAX_COMMAND], filename[100] ;
FILE *fp,*new_fp ;
int offset, modified ;
char header[] = "Beebug C Librarian V1.1\n" ;

extern char buffer [] ;   /* in c.dirops */

unsigned short get_byte(void)
   {
   return getc(fp) &0xff ;
   }

void read_symbol_name(void)
   {
   char *ch = buffer ;

   while ((*ch++ = get_byte()) != '\n') ;
   *--ch = '\0' ;
   }

void read_offset(void)
   {
   offset = bget(fp) &0xff ;
   offset += ((bget(fp) &0xff)*256) ;
   }

void read_symbol(void)
   {
   read_symbol_name() ;
   read_offset() ;
   }

int skip_header(void)
   {
   char *ch = header ;

   while (*ch == get_byte())
      if (*ch++ == '\n')
         return TRUE ;
   return FALSE ;
   }


void upper_case (char *string)
   {
   while (*string)
      {
      *string = toupper (*string) ;
      string++ ;
      }
   }

char *get_string (char *buf, char *prompt)
   {
   char *result ;

   if ((result=strtok(buf," ")) != NULL)
      return result ;
   fflush (stdin) ;
   printf ("%s:",prompt) ;
   gets (command_line) ;
   return get_string (command_line,prompt) ;
   }



int get_command(void)
   {
   char command[255] ;
   int loop, command_count, command_num ;

   for (;;)
      {
      memset (command_line,0,MAX_COMMAND) ; /* reset command buffer */
      osbyte (200,1,0xfe) ;          /* disable escape key */
      printf ("LIBRARY> ") ;         /* display prompt */
      fflush (stdin) ;
      gets (command_line) ;         /* get command */
      osbyte (200,0,0xfe) ;    /* reenable escape */
      if (command_line[0] == '\0')        /* return pressed */
         continue ;
      if (command_line[0] == '*')         /* star command */
         {
         system (command_line) ;
         continue ;
         }
      strcpy (command,strtok (command_line," .")) ; /* get first word */
      upper_case (command) ;
      command_count = 0 ;
      for (loop = 0 ; loop < NUM_COMMANDS ; loop ++)
         if (strncmp (commands[loop].comm,command,strlen(command)) == 0)
            {
            command_count ++ ;     /* increment command count */
            command_num = loop ;   /* save command */
            }
      if (command_count > 1)
         fprintf (stderr,"Ambiguous command\n") ;    /* more than one */
      else
         if (command_count == 0)
            fprintf (stderr,"Bad command\n") ;       /* bad command */
         else   
            return commands[command_num].token ;     /* command ok */
      }
   }



int check_valid (void)
   {
   if (filename[0] == '\0')
      {
      fprintf (stderr,"No working library\n") ;
      return FALSE ;
      }
   return TRUE ;
   }


void handle_command(int command) 
   {
   switch (command)
      {
      case CREATE      : create_library() ;
                         break ;
      case USE         : use_library() ;
                         break ;
      case LIST        : list_directory() ;
                         break ;
      case INSERT      : insert_module() ;
                         break ;
      case DELETE      : delete_module() ;
                         break ;
      case COMMIT      : if (modified)
                            {
                            commit_changes() ;
                            fp = fopen (filename,"r") ;
                            free_tree() ;
                            skip_header() ;
                            print_lib_id() ;
                            read_directory() ;
                            }
                         break ;
      case NEW         : new_library() ;
                         break ;
      case EXTRACT     : extract_module() ;
                         break ;
      case HELP        : give_help() ;
      }
   }

  
void print_lib_id (void)
   {
   char ch ;

   while (ch=get_byte())       /* library id text */
      putchar (ch) ;
   putchar ('\n') ;
   while (ch=get_byte())       /* copyright info */
      putchar (ch) ;
   putchar ('\n') ;
   }


void use_library (void)
   {
   if (filename[0] != '\0')
      {
      fprintf (stderr,"Already using a library\n") ;
      return ;
      }
   strcpy (filename,get_string (NULL,"Name of library to use")) ;
   upper_case (filename) ;
   if ((fp=fopen(filename,"r")) == NULL)
      {
      fprintf (stderr,"Library %s not found\n",filename) ;
      filename[0] = '\0' ;
      return ;
      }
   if (skip_header() == FALSE)
      {
      fprintf (stderr,"Bad library\n") ;
      close_library() ; ;
      filename[0] = '\0' ;
      return ;
      }
   print_lib_id() ;
   read_directory() ;
   }

void put_header (char *ch, FILE *file)
   {
   while (*ch)
      {
      if (*ch == '\n')
         bput (file,'\r') ;
      else 
         bput (file,*ch) ;
      ch ++ ;
      }
   }


void create_library (void)
   {
   char library_id[255] ;

   if (filename[0] != '\0')
      {
      fprintf (stderr,"There is a library in use\n") ;
      return ;
      }
   strcpy (filename,get_string(NULL,"Name of library to create")) ;
   upper_case (filename) ;
   fp = fopen (filename,"w") ;
   put_header (header,fp) ;
   fflush (stdin) ;
   printf ("Enter the library identification text:") ;
   gets (library_id) ;
   fprintf (fp,"%s",library_id) ;
   fputc (0,fp) ;
   printf ("Enter copyright text:") ;
   gets (library_id) ;
   fprintf (fp,"%s",library_id) ;
   fputc (0,fp) ;
   fputc (0xff,fp) ;
   fclose(fp) ;
   fp = fopen (filename,"r") ;
   skip_header() ;
   print_lib_id() ;
   read_directory() ;
   }

void ask_commit (void)
   {
   char answer[10] ;

   printf ("Commit changes ? ") ;
   scanf ("%s",answer) ;
   if (toupper(answer[0]) == 'Y')
     commit_changes() ;
   else
      close_library() ;
   }

void new_library(void)                        /* establish new library */
   {
   if (modified)
      ask_commit() ;
   else
      close_library() ;
   filename[0] = '\0' ;
   free_tree () ;
   modified = FALSE ;
   init_tree() ;
   }

void give_help(void)
  {
  int loop = 0;

  printf ("\nThe commands available are:\n\n") ;
  for (; loop < NUM_COMMANDS; loop++)
     printf ("%-8s %s\n",commands[loop].comm,commands[loop].description) ;
  putchar ('\n') ;
  }

void close_library (void)
  {
  fclose (fp) ;
  }

void main(void)
   {
   int command ;

   printf ("\nBeebug C Library Facility\nVersion 1.0\n") ;
   printf ("Author : David Allison\n") ;
   printf ("(C) 1987 Beebug Limited\n\n") ;
   atexit (close_library) ;       /* close library on exit */
   filename[0] ='\0' ;            /* no working library yet */
   modified = FALSE ;             /* no modifications yet */
   init_tree() ;                  /* initialise the binary tree */
   for (;;)
      {
      command = get_command() ;                  /* get a command */
      if (command == EXIT || command == QUIT)    /* EXIT or QUIT? */
         break ;
      handle_command (command) ;                 /* execute command */
      }
   if (modified)
      if (command == QUIT)
         ask_commit() ;
      else commit_changes() ;               /* commit changes on EXIT */
   else
      close_library() ;
   }

/* c'est fini */
