/*
 * builder.c
 * some pieces that are common to building gates and links.
 * [eichin:19880330.1726EST]
 */

#include <msimdecl.h>


Wire makewire(nam, initval)
     char *nam;
     Event_data initval;
{
  Wire retwire = getblock();
  Timeline futline = getblock();
  Timeline futptr = futline;

  add_event(futline, initval, 1);
  START(futptr);
  
  add_item(retwire, WIRE, SYMNAME, symname, nam);
  add_chain(retwire, WIRE, DEPENDS, deps);
  add_item(retwire, WIRE, NOW, now, futptr);
  INC(futptr);
  add_item(retwire, WIRE, THEN, then, futptr);
  add_item(retwire, WIRE, FUTURE, future, futline);
  add_chain(retwire, WIRE, PAST, past);
  add_chain(retwire, WIRE, CONTENTION, contention);
  return(retwire);
}

add_depends(towire, func, wires)
     Wire towire;
     int (*func)();
     Wirelist wires;
{
  Deps deplist;
  Generics newdep = getblock();
  
  add_item(newdep, GENERIC, GENFUNC, genfunc, func); /* .func, arg actually */
  INC(wires);
  while(wires->tag.CTL != END)	/* useup will break out... */
    {
      ASSERT(wires->tag.WIRELIST = WIRE);
      add_item(newdep, GENERIC, GENWIRE, genwire, (wires->data.WIRELIST.wire));
      /*       useup(wires,break); */
      INC(wires);		/* we actually ALLOW dup inputs... */
    }
  
  find_item(towire, WIRE, DEPENDS);
  deplist = towire->data.DEPS.generics;

  add_item(deplist, DEPS, DEPSLIST, generics, newdep);
}

/*
 * make_wirelist_n
 * these should seriously be made into real macros, none of this
 * foolish nested procedure call stuff. That is what the rest of the
 * universe is designed to avoid. However, we want to finish this
 * soon! Anyhow, this should be done with varargs anyhow... made into
 * a user interface.
 * [eichin:19880401.0601EST]
 */
Wirelist make_wirelist_1(w1)
     Wire w1;
{
  Wirelist retlist = getblock();

  add_item(retlist, WIRELIST, WIRE, wire, w1);
  return(retlist);
}

Wirelist make_wirelist_2(w1, w2)
     Wire w1, w2;
{
  Wirelist retlist = make_wirelist_1(w1);
  add_item(retlist, WIRELIST, WIRE, wire, w2);
  return(retlist);
}

Wirelist make_wirelist_3(w1, w2, w3)
     Wire w1, w2, w3;
{
  Wirelist retlist = make_wirelist_2(w1, w2);
  add_item(retlist, WIRELIST, WIRE, wire, w3);
  return(retlist);
}

/*
 * Serious Sugar here... Crunch Crunch!
 * [eichin:19880510.0548EST]
 */

Wire new_to_wirelist(master, name)
     Wirelist master;
     char *name;
{
  Wire tnam = makewire(name, UNDEFINED);
  add_item(master, WIRELIST, WIRE, wire, tnam);
  return(tnam);
}

/* open the file, set up wff */
initialize_file(master, argc, argv)
     Wirelist master;
     int argc;
     char *argv[];
{
  WFile *wff=(WFile *)malloc(sizeof(WFile));
  FILE *inf;
  int c;
  extern int optind;
  extern char *optarg;

  while((c = getopt(argc, argv, "i:o:dt:")) != EOF)
    {
      switch(c){
      case 'i':			/* -i infile */
	{
	  if(strcmp(optarg,"-"))
	    {
	      inf = fopen(optarg, "r");
	      if(!inf)
		{
		  fprintf(stderr, "%s: Error opening Input file <%s>\n",
			  argv[0], optarg);
		  exit(1);
		}
	    }
	  else
	    {
	      inf = stdin;
	    }
	  wff->filedesc = inf;
	  wff->next = 1;
	  add_item(master, WIRELIST, WFILE, wfile, wff);
	  break;
	}
      case 'o':			/* -o outfile */
	{
	  if(!freopen(optarg, "w", stdout))
	    {
	      fprintf(stderr, "%s: Error opening output file <%s>\n",
		      argv[0], optarg);
	      exit(1);
	    }
	  break;
	}
      case 'd':			/* -d for debugging */
	{
	  extern int debug;
	  debug++;
	  break;
	}
      case 't':			/* -t time-to-start */
	{
	  extern int globaltime;
	  globaltime = atoi(optarg);
	}
      }
    }
}

