/* Copyright (C) 1993,1994 by the author(s).
 
 This software is published in the hope that it will be useful, but
 WITHOUT ANY WARRANTY for any part of this software to work correctly
 or as described in the manuals. See the ShapeTools Public License
 for details.

 Permission is granted to use, copy, modify, or distribute any part of
 this software but only under the conditions described in the ShapeTools 
 Public License. A copy of this license is supposed to have been given
 to you along with ShapeTools in a file named LICENSE. Among other
 things, this copyright notice and the Public License must be
 preserved on all copies.
*/
/*
 * ShapeTools/shape program - main.c
 *
 * Author: Axel Mahler (Axel.Mahler@cs.tu-berlin.de)
 *
 * $Header: main.c[8.0] Sat Jul 31 19:15:40 1993 axel@cs.tu-berlin.de frozen $
 */
#ifndef lint
static char *AtFSid = "$Header: main.c[8.0] Sat Jul 31 19:15:40 1993 axel@cs.tu-berlin.de frozen $";
#endif

#include "shape.h"

#define MAXCMDTARGETS 32

extern FILE *temp;

EXPORT char rbfile[MYMAXNAMLEN];
EXPORT char prev_dir[MYMAXNAMLEN];
EXPORT int  main_gen = AF_BUSYVERS;
EXPORT int  main_rev = AF_BUSYVERS;
EXPORT char *suffs;
EXPORT char shapeflags[2048];

LOCAL  char *filenames[] = {"Shapefile", "shapefile", "Makefile", "makefile"};
LOCAL  char *stdmacros[] = { "ASFLAGS=","AS=as", "SHELL=/bin/sh",
			"RFLAGS=","FFLAGS=","FC=f77","M2FLAGS=",
			"M2C=m2c","PFLAGS=","PC=pc","CFLAGS=",
			"CC=cc","LDFLAGS=","LD=ld","LFLAGS=",
			"LEX=lex","YFLAGS=","YACC=yacc",
			"MAKE=shape $(MAKEFLAGS)", "SHAPE=shape $(MAKEFLAGS)",
			"$=$$", "SHAPEFLAGS=$(MAKEFLAGS)",
			"SELECTED_AtFS=", "SELECTED_FS=",
			"RESTORED_OBJS=",
		        "@=$@", "?=$?", "<=$<", "*=$*",
			"+=$+", (char *)NULL};

EXPORT struct linked_list *shapefiles = (struct linked_list *) NIL;
     /* list of names of files from command line via the -f option */
LOCAL struct linked_list *shfiles;

EXPORT char *cmdtargets[MAXCMDTARGETS];
     /* list of target form the	command line */

EXPORT char *cmd_line_vars[MAXCMDLINEVARS];
     /* variant names activated from command line */

EXPORT int rec_do_depth;

EXPORT char *newarg[64];
EXPORT int newargc;

LOCAL  Bool synterrflg = FALSE;
EXPORT Bool Oldsuffs = FALSE;
EXPORT Bool Newsuffs = FALSE;

EXPORT void cleanup () {
  cleanup_links(link_reg);
  af_cleanup();
}

#ifdef DEBUG_MALLOC
LOCAL unsigned long tl_data_start = 0, histid0, histid1, histid2;
LOCAL FILE *leak_log = NULL;

LOCAL init_trace_leak () {
  tl_data_start = malloc_size(&histid0);
  histid1 = histid0;
  leak_log = fopen ("Shape_Leak.log", "w");
  fprintf (leak_log, "Memory usage profile for %s\n", stProgramName);
  fprintf (leak_log, "==================================\n");
  fprintf (leak_log, "Initial amount of allocated memory: %d bytes.\n",
	   tl_data_start);
}

EXPORT void dssize (location, aux) char *location, *aux; {
  static unsigned long oldmbytes;
  unsigned long cursize = malloc_size (&histid2);

  fprintf (leak_log, "%s%s%s - %d bytes allocated (gained %d).\n", 
	   location, (aux && *aux) ? " " : "", 
	   (aux && *aux) ? aux : "", cursize, cursize - oldmbytes);
  fflush (leak_log);
}
#endif
  

EXPORT int main(argc, argv)
     int argc;
     char **argv;
     
{
  int newac = 0;
  Bool cmd_line_macro_def = FALSE;
  char **newav;
  sb_ptr	strbuf = sbnew(128);
  register int i, k = 0;
  char *xxx, *cp;
  char atfsdir[PATH_MAX];

#ifdef DEBUG_MALLOC
  init_trace_leak ();
#endif

  if (strbuf == 0)
    errexit(10, "sbnew");
  
  rebuildflg = FALSE;
  bpoolflg = TRUE;
  rec_do_depth = 1;
  if ((curvpath[0] = malloc(PATH_MAX + 2)) == NIL)
    errexit(10,"malloc");
  getcwd(curvpath[0], PATH_MAX + 2);
  catch_sigs(); 
  
  *shapeflags = '\0';
  
  for (i = 0; i < MAXCMDLINEVARS; i++) {
    cmd_line_vars[i] = (char *)NULL;
  }
  
  stProgramName = (cp = strrchr (argv[0], '/')) ? ++cp : argv[0];
  /* make prog-name available to entire program */
  
  if (argc != 1) {
    if(stParseArgs (argc, argv, &newac, &newav, odesc)) {
      stShortUsage(stProgramName, odesc, "");
      exit(1);
    }
  }
  
  if (!echoflg) {
    strcpy(prev_dir,curvpath[0]);
    
    strcpy(atfsdir,curvpath[0]);
    strcat(atfsdir,"/AtFS");
    
    if(af_access(af_afpath(atfsdir),af_afname(atfsdir),af_aftype(atfsdir),AF_CLASS_SOURCE) != 0) {
      strcpy(atfsdir,curvpath[0]);
      strcat(atfsdir,"/AFS");
      if(af_access(af_afpath(atfsdir),af_afname(atfsdir),af_aftype(atfsdir),
		   AF_CLASS_SOURCE) != 0) {
	warning(4,NIL);
      }
    }
  }
  
  if((xxx = strrchr (prev_dir,'/')) != NIL)
    *xxx = '\0';
  init_ruletab();
  
  newargc = newac;
  for(i = 1; i < newac; i++)
    newarg[i] = newav[i];
  
  for (i = 0; stdmacros[i]; i++) {
    char *macbuf = check_strdup (stdmacros[i]);
    char *val;

    val = strchr (macbuf, '=');
    *val++ = '\0';
    define_macro (macbuf, val, DYNAMIC);
    if (macbuf) free (macbuf);
  }
  {
    char buf[16];

    (void) sprintf (buf, "%d", getpid());
    define_macro ("SHAPEPID", buf, DYNAMIC | FROM_CMDLINE);
    define_macro ("SHAPEVERSION", stStrtok (version ()), 
		  DYNAMIC | FROM_CMDLINE);
    define_macro ("LOGNAME", atUserName (af_afuser (getuid ())), 
		  DYNAMIC | FROM_CMDLINE);
  }
  
  sbfree(strbuf);
  
  add_stdrules();

  /* make command line macros known */
  for (i = 1; i < newac; i++) {
    if (strchr(newav[i],'=')) {
      char *macbuf = check_strdup (newav[i]);
      char *val;
      int mactype;

      cmd_line_macro_def = TRUE;
      val = strchr (macbuf, '=');
      switch (*(val-1)) {
      case '+':
	mactype = APPEND;
	*(val-1) = '\0';
	break;
      case ':':
	mactype = ONCE;
	*(val-1) = '\0';
	break;
      default:
	mactype = DYNAMIC;
	break;
      }
      *val++ = '\0';
      define_macro (macbuf, val, mactype | FROM_CMDLINE);
      if (macbuf) free (macbuf);
    }
    else {
      if ((cmdtargets[k] = malloc((unsigned) (strlen(newav[i]) + sizeof(char)))) == NIL)
	errexit(10,"malloc");
      strcpy(cmdtargets[k++],newav[i]);
      cmdtargets[k] = NIL;
    }
  }

  if  (!rebuildflg) {
    if (fileflg) {
      shfiles = shapefiles;
      while(shfiles != (struct linked_list *) NIL) {
	int open_ok = 0;
	
	open_ok += parse_file (shfiles->string);
	shfiles = shfiles->nextstring;
	
	if (parse_errors) {
	  errexit (15, NIL);
	}
	if (!open_ok) {
	  errexit (11, NIL);
	}
      }
    }
    else {
      int open_ok = 0;
      for ( i = 0; i <= 3; i++) {
	if ((open_ok = parse_file (filenames[i])))
	  break;
      }
      if (parse_errors) errexit (15, NIL);
    }
  }
  
  else {
    if (parse_file (rbfile)) {
      if (parse_errors) errexit (15, NIL);
    }
    else {
      errexit (8, rbfile);
    }
  }

  if (!echoflg || Var_flag) {
    fclose(temp);
  }

  commit_definitions (); /* make parsed definitions seen */
  
  define_macro ("MAKEFLAGS", shapeflags, DYNAMIC);
  
  if (echoflg && !Var_flag) {
    echo_macro(echomac);
    exit(0);
  }
  
  if(rebuildflg && cmd_line_macro_def)
    warning(3, NIL);
  
  if (synterrflg == TRUE)
    errexit(15,NIL);
  
  ruleend();
  
  adjust_stdrules(suffs);
  
  if(envflg)
    get_env_vals();
  if(environment_vars != NIL)
    free(environment_vars);
  
  for (i = 0; cmd_line_vars[i] && (i < MAXCMDLINEVARS); i++) {
    if (!is_varname (cmd_line_vars[i])) {
      char *msg = malloc (strlen (cmd_line_vars[i]) + 
			  strlen (" is not a variant name") + sizeof (char));
      if (msg == (char *)NULL)
	errexit (10, "malloc");
      
      strcpy (msg, cmd_line_vars[i]+1);
      strcat (msg, " is not a variant name");
      warning (99, msg);
      free (msg);
    }
  }
  
  if(echoflg) {
    echo_macro(echomac);
    exit(0);
  }
  
  if (printflg) {
    dump (stdout);  /* dumping macros */
    ruledump (stdout); /* dumping targets, dependents & commands, resp. */
    exit (0);
  }

#ifdef DEBUG_MALLOC
  dssize ("Before", "produce");
#endif

  produce();

#ifdef DEBUG_MALLOC
  dssize ("After", "produce");
#endif
  
  if (debugflg) {
    dump(stdout);  /* dumping macros */
    ruledump(stdout); /* dumping targets, dependents & commands, resp. */
  }
  
  cleanup ();
  exit(0);
}
	
EXPORT void get_env_vals() {
  register char *p, *name, *enventry;
  if(environment_vars == NIL)
    return;
  p = environment_vars;
  while ((*p == ' ') || (*p == '\t'))
    p++;
  while((name = get_next_item(p)))
    {
      if (strcmp(p,"") == 0)
	break;
      p = strchr(p,'\0');
      p++;
      while ((*p == ' ') || (*p == '\t'))
	p++;
      if ((enventry = getenv(name)) != NIL)
	{
	  define_macro (name, enventry, DYNAMIC);
	}
    }
}
