
/* $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/
#ident "$Header: out.c 1.1 90/01/19 $@(#)out.c	1.1 89/12/01"
#include <stdio.h>
#include "xsld.h"
#include <malloc.h>

extern char *gettxt();

struct mo_q {
  MODULE q_mo;
  struct mo_q *q_next;
};

static struct mo_q *q_start, *q_end;

static q_append(mo)
  MODULE mo;
{
  struct mo_q *new = (struct mo_q *)malloc(sizeof(struct mo_q));
  if (new == 0){
    fprintf(stderr, gettxt("xsld:28","Out of memory (out.c)\n"));
    fatal();
  }
  new->q_mo = mo;
  new->q_next = 0;
  
  if (q_end == 0){
    q_start = q_end = new;
  } else {
    q_end->q_next = new;
    q_end = new;
  }
}

void
gen_out_files(do_output)
  bool do_output;
{
  FILE *fm, *fc, *fd;
  register MODULE i, j, k;
  char *name;
  register int set_nr = 1;
  
  if (do_output){
    if ((fm = fopen(outmsg, "w")) == NULL){
      perror(outmsg);
      return;
    }

    fprintf(fm, "$quote \"\n");
  
    for (i = mo_scan_first() ; !is_null_mo(i) ; i = mo_scan_next()){
      if (mo_used(i) && mo_func(i) != 0){
        if (is_null_lib(mo_lib(i))){
          name = mo_name(i);
          fprintf(fm, "$ MODULE %s\n", name);
        } else {
          name = lib_name(mo_lib(i));
          fprintf(fm, "$ MODULE %s(%s)\n", mo_name(i), name);
        }
        if ((fd = fopen(name, "r")) == NULL){
          perror(name);
          continue;
        }
        if (fseek(fd, mo_msg_start(i), 0) != 0){
          fprintf(stderr, gettxt("xsld:29","Seek error in %s\n"), name);
          fclose(fd);
          continue;
        }
        fprintf(fm, "$set %d\n", set_nr);
        mo_set_new(i, set_nr++);
        copy_len(fm, fd, mo_msg_end(i) - mo_msg_start(i));
        fclose(fd);
      }
    }
  
    fclose(fm);
  } else
    unlink(outmsg);
  
  /* 
   * Generate desc_file if requested
   */
  if (desc_file != 0){
    FILE *fd;
    
    if ((fd = fopen(desc_file, "w")) == NULL)
      perror(desc_file);
    else {
      desc_init(fd);
      fclose(fd);
    }
  }
  if (do_output){    
    if ((fc = fopen(outC, "w")) == NULL){
      perror(outC);
      return;
    }
    fprintf(fc, "_string_init()\n{\n");
  
    /*
     * Perform a topological sort on the used modules according to
     * the constraints coming from 'init' symbols (i.e. global unsized characters
     * arrays which must be initialized prior to any use in any other module)
     * Algorithm from Tremblay-Sorenson "An introduction to data structures
     * with applictions" (Mac Graw-Hill, 1976, pp 433-442)
     */
    mo_modules_set();
  
    for (i = mo_scan_first() ; !is_null_mo(i) ; i = mo_scan_next()){
      if (!mo_used(i) || mo_func(i) == 0)
        continue;
      if (mo_pred_count(i) == 0)
        q_append(i);
    }
    
    while (q_start != 0){
      struct mo_q *aux;
      SUCCLIST succ;

      mo_modules_new(mo_modules() - 1);
      i = q_start->q_mo;
      aux = q_start;
      q_start = q_start->q_next;
      free((char *)aux);
      fprintf(fc, "\t%s(%d);\n", mo_func(i), mo_set(i));
      mo_used_new(i, FALSE);
      if (q_start == 0)
        q_end = 0;
      for (succ = mo_succ_first(i) ; !is_null_succ(succ) ; succ =mo_succ_next(i)){
        mo_pred_count_new(succ_mo(succ), mo_pred_count(succ_mo(succ)) - 1);
        if (mo_pred_count(succ_mo(succ)) == 0)
          q_append(succ_mo(succ));
      }
    }
    fprintf(fc, "}\n");
    fclose(fc);
  
    if (mo_modules() > 0){
      fprintf(stdout, gettxt("xsld:30","Unresolvable symbols/modules cycles:\n"));
      for (i = mo_scan_first() ; !is_null_mo(i) ; i = mo_scan_next()){
        if (!mo_used(i) || mo_func(i) == 0)
          continue;
        mo_pred_count_new(i, 0);
        mo_tag_new(i, FALSE);
      }
      for (i = mo_scan_first() ; !is_null_mo(i) ; i = mo_scan_next()){
        SUCCLIST succ;
        if (!mo_used(i) || mo_func(i) == 0)
          continue;
        for (succ = mo_succ_first(i) ;!is_null_succ(succ);succ=mo_succ_next(i)){
          if (mo_pred_count(succ_mo(succ)) == 0){
            mo_pred_count_new(succ_mo(succ), (int)i);
            mo_succ_sym_new(succ_mo(succ), succ_sym(succ));
          }
        }
      }
      for (i = mo_scan_first() ; !is_null_mo(i) ; i = mo_scan_next()){
        if (!mo_used(i) || mo_func(i) == 0)
          continue;
        if (mo_pred_count(i) != 0)
          break;
      }
      while (!mo_tag(i)){
        mo_tag_new(i, TRUE);
        i = (MODULE)mo_pred_count(i);
      }
      j = NULL_MODULE;
      while (!is_null_mo((MODULE)mo_pred_count(i))){
        k = j;
        j = i;
        i = (MODULE)mo_pred_count(j);
        mo_pred_count_new(j, (int)k);
      }
      mo_pred_count_new(i, (int)j);
      while (mo_tag(i)){
        fprintf(stdout, gettxt("xsld:31","%s is used in "), sym_name(mo_succ_sym(i)));
        mo_print(i);
        fprintf(stdout, gettxt("xsld:32"," and defined in "));
        mo_print(mo_defines(mo_succ_sym(i)));
        fprintf(stdout, "\n");
        mo_tag_new(i, FALSE);
        i = (MODULE)mo_pred_count(i);
      }
    }
  } else
    unlink(outC);
}
