/* $Id: cim.c,v 1.18 1997/01/26 14:30:21 cim Exp $ */

/* Copyright (C) 1987-1998 Sverre Hvammen Johansen,
 * Department of Informatics, University of Oslo.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

/* Main for kompilatoren. */

#include <stdio.h>
#include "const.h"
#include "name.h"
#include "filelist.h"
#include "newstr.h"
#include "cimcomp.h"
#include "error.h"
#include "lex.h"
#include "mellbuilder.h"
#include "checker.h"
#include "gen.h"
#include "trans.h"

#if STDC_HEADERS || HAVE_STRING_H
#include <string.h>
#else /* not STDC_HEADERS and not HAVE_STRING_H */
#include <strings.h>
#endif /* not STDC_HEADERS and not HAVE_STRING_H */

#if HAVE_UNISTD_H
#include <unistd.h>
#endif

#if STDC_HEADERS
#include <stdlib.h>
#endif

#if HAVE_SIGNAL_H
#include <signal.h>
#endif

#include "getopt.h"

struct SENT *mainSent;

FILE *ccode;

char *extcodename;
char *mifcodename;

static char *outputname = "";
static char *exekname;
static char *sourcename;
static char *listname;
static char *ccodename;
static char *ocodename;
static char *shlname;

static char *ccomp;

static char *ccompargs = "";
static char *linkargs = "";
static char *systemlibdir = LIBDIR;
static char *tmpdir;
char *includedir = INCLUDEDIR;

int option_write_tokens;
int option_write_mif;
int option_nowarning;
int option_atr;
int option_line;
int option_reuse_timestamp;
int option_verbose;
int option_init_poolsize;
int option_dyn_poolsize;
int option_max_poolsize;
int option_bl_in_dir_line;

static int option_static;
static int option_pic;
static int option_checkdiff;
static int option_nolink;
static int option_nosim;
static int option_nocc;
static int option_checkdif;
static int option_notempdel;
static int option_noexecdel;
static int option_quiet;
static int option_sscheck;
#ifdef DEBUG
static int option_lex,
static int option_gen_test;
static int option_declarations;
static int option_expressions;
static int option_msymbols;
static int option_input;
#endif

#ifdef DEBUG
static int s_out;
#endif
char separat_comp;		/* Sier om kj|ringen er en separat
				 * kompilering eller ikke */

char *progname;

/******************************************************************************
                                                                     XMALLOC */

char *
xmalloc (size)
     unsigned int size;
{
  char *ptr = malloc (size);
  if (! ptr)
    {
      fprintf (stderr, "%s: virtual memory exhausted\n", progname);
      exit (1);
    }
  return ptr;
}

/******************************************************************************
                                                               TRAP-ROUTINES */
#if HAVE_SIGFPE
static RETSIGTYPE
float_trap ()
{
  lerror (25);
}
#endif

#if HAVE_SIGSEGV
static RETSIGTYPE
seg_trap ()
{
  lerror (26);
}
#endif

#if HAVE_SIGILL
static RETSIGTYPE
illegal_trap ()
{
  lerror (28);
}
#endif

#if HAVE_SIGTRAP
static RETSIGTYPE
trace_trap ()
{
  lerror (29);
}
#endif

#if HAVE_SIGBUS
static RETSIGTYPE
bus_trap ()
{
  lerror (27);
}
#endif

#if HAVE_SIGSYS
static RETSIGTYPE
sys_trap ()
{
  lerror (30);
}
#endif

static init_trap_routines()
{
#if HAVE_SIGFPE
  signal (SIGFPE, float_trap);
#endif
#if HAVE_SIGSEGV
  signal (SIGSEGV, seg_trap);
#endif
#if HAVE_SIGILL
  signal (SIGILL, illegal_trap);
#endif
#if HAVE_SIGTRAP
  signal (SIGTRAP, trace_trap);
#endif
#if HAVE_SIGSYS
  signal (SIGSYS, sys_trap);
#endif
#if HAVE_SIGBUS
  signal (SIGBUS, bus_trap);
#endif
}

/******************************************************************************
                                                                 GET_ALL_ENV */

#if HAVE_GETENV
extern char *getenv ();
static xgetenv (name, var)
     char *name;
     char **var;
{
  char *value;
  value = getenv (name);
  if (value != NULL)
    *var = newstrcat1 (value);
}
#endif

static get_all_env()
{
#if HAVE_GETENV
  xgetenv ("CIMLIBDIR", &systemlibdir);
  xgetenv ("CIMINCLUDEDIR", &includedir);
  xgetenv ("TMPDIR", &tmpdir);
  xgetenv ("CIMTMPDIR", &tmpdir);
#endif
}

/******************************************************************************
                                                                     SIMCOMP */
static simcomp ()
{
  mbuilderInit();

  if (initLex (sourcename)) return (TRUE);
  if (option_write_tokens)
    {
      scan_and_write_tokens ();
      return (FALSE);
    }
#ifdef DEBUG
  if (option_declarations || option_expressions
      || option_msymbols || option_input || option_lex)
    {
      s_out = dup (stdout->_file);
      if (freopen (listname, "w", stdout) == NULL)
	{
	  perror (newstrcat3 (progname, ": ", listname));
	  return (TRUE);
	}
    }
#endif
  if ((ccode = fopen (ccodename, "w")) == NULL)
    {
      perror (newstrcat3 (progname, ": ", ccodename));
      return (TRUE);
    }
  if (!option_quiet)
    fprintf (stderr, "Compiling %s:\n", sourcename);

  /* PASS 1 */

  initExtspec ();
  init_parser ();
  initDecl ();
  yyparse ();

  /* PASS 2 AV KOMPILATOREN */

  if (anterror == 0)
    {
      mbuilderReinit();
      ebuilderInit();
      sbuilderInit();
      mainSent= sbuild();
      reinit ();
      expCheckerInit ();
      genInit ();
      sentCheck (mainSent, TRUE);
      if (anterror == 0)
	{
	  sentTrans (mainSent);
	  sentGen (mainSent);
	}
      if (separat_comp && (anterror == 0 || option_atr))
	write_all_ext ();
#ifdef DEBUG
      if (option_declarations)
	dump ();
#endif
    }
  fclose (ccode);
#ifdef DEBUG
  if (option_declarations || option_expressions
      || option_msymbols || option_input || option_lex)
    {
      fclose (stdout);
      fdopen (s_out, "w");
      dup2 (s_out, fileno (stdout));
    }
#endif
  if (anterror != 0)
    return (TRUE);
  else
    return (FALSE);
}

/******************************************************************************
                                                               STRINGTOUPPER */

static char *
stringtoupper (s)
     char *s;
{
  char *st;
  for (st = s; *st != '\0'; st++)
    if (*st >= 'a' && *st <= 'z')
      *st = *st - (char) 32;
  return (s);
}

/******************************************************************************
                                                                    BASENAME */
static char *
basename (str) char *str;
{
  int i,j;
  for (i = strlen (str) - 2; i >= 0; i--)
    if (!strncmp (&str[i], "/", 1))
      {
	str= &str[i + 1];
	break;
      }
  str= newstrcat1 (str);
  i= strlen (str);
  if (i > 4 && !(strcmp (&str[i - 4], ".sim")
		 && strcmp (&str[i - 4], ".SIM")
		 && strcmp (&str[i - 4], ".cim")
		 && strcmp (&str[i - 4], ".CIM")))
    str[i - 4] = '\0';
  
  return str;
}

/******************************************************************************
                                                                  PRINT_HELP */

static int print_help(status)int status;
{
  fprintf(stderr,"Usage: %s"
	  " [-a] [--atr]"
	  " [-b flags] [--cflags=flags]"
	  "\n      "
	  " [-B flags] [--ldflags=flags]"
          " [-c] [--suppress-linking]"
	  "\n      "
	  " [-d] [--compare]"
	  " [-D NAME] [--define=NAME]"
	  " [-e] [--static]" 
	  "\n      "
	  " [-E] [--preprocess]" 
	  " [-F] [--write-mif]"
	  " [-g] [--debug]"
	  "\n      "
	  " [-G] [--gcc]"
	  " [-I DIR] [--includedir=DIR]"
	  " [-h] [--help]"
	  "\n      "
	  " [-H] [--no-lines]"
	  " [-l LIBRARY] [--library=LIBRARY]"
	  "\n      "
	  " [-L DIR] [--library-dir=DIR]"
	  " [-m [N]] [--memory-pool-size[=N]]"
	  "\n      "
	  " [-M N] [--max-memory-pool-size=N]"
	  " [-N FILE] [--input=FILE]"
	  "\n      "
	  " [-o FILE] [--output=FILE]"
	  " [-O] [-ON]"
	  " [--optimize] [--optimize=N]"
	  "\n      "
	  " [-p] [--pic]"
	  " [-P] [--only-link]"
	  " [-q] [--quiet]"
	  "\n      "
	  " [-R] [--preserve-timestamp]"
	  " [--silent]"
	  " [-s] [--no-simula-compile]"
	  "\n      "
	  " [-S] [--only-simula-compile]"
	  " [-t] [--dont-remove-temporaries]"
	  "\n      "
	  " [-U NAME] [--undefine=NAME]"
	  " [-v] [--verbose]"
	  " [-V] [--version]"
	  "\n      "
	  " [-w] [--no-warn]"
	  " simula-file [file...]\n", progname);
  exit(status);
}

/******************************************************************************
                                                                PARSEOPTIONS */
static parseoptions (argc, argv)
     int argc;
     char *argv[];
{
  int c;
  int index;
  while (1)
    {
      int option_index = 0;
      static struct option long_options[] =
	{
	  {"atr", 0, 0, 'a'},
	  {"cflags=", 1, 0, 'b'},
	  {"ldflags", 1, 0, 'B'},
	  {"suppress-linking", 0, 0, 'c'},
	  {"c-compiler", 1, 0, 'C'},
	  {"compare", 0, 0, 'd'},
	  {"define", 1, 0, 'D'},
	  {"static", 0, 0, 'e'},
	  {"preprocess", 0, 0, 'E'},
	  {"write-mif", 0, 0, 'F'},
	  {"debug", 0, 0, 'g'},
	  {"gcc", 0, 0, 'G'},
	  {"include-dir", 1, 0, 'I'},
	  {"help", 0, 0, 'h'},
	  {"no-lines", 0, 0, 'H'},
	  {"library", 1, 0, 'l'},
	  {"library-dir", 2, 0, 'L'},
	  {"memory-pool-size", 2, 0, 'm'},
	  {"max-memory-pool-size", 1, 0, 'M'},
	  {"input", 1, 0, 'N'},
	  {"output", 1, 0, 'o'},
	  {"optimize", 2, 0, 'O'},
	  {"pic", 0, 0, 'p'},
	  {"only-link", 0, 0, 'P'},
	  {"quiet", 0, 0, 'q'},
	  {"silent", 0, 0, 'q'},
	  {"preserve-timestamp", 0, 0, 'R'},
	  {"no-simula-compile", 0, 0, 's'},
	  {"only-simula-compile", 0, 0, 'S'},
	  {"dont-remove-temporaries", 0, 0, 't'},
	  {"undefine", 1, 0, 'U'},
	  {"verbose", 0, 0, 'v'},
	  {"version", 0, 0, 'V'},
	  {"no-warn", 0, 0, 'w'},
#ifdef DEBUG
	  {"dd", 0, &option_declarations, 1},
	  {"de", 0, &option_expressions, 1},
	  {"dm", 0, &option_msymbols, 1},
	  {"di", 0, &option_input, 1},
	  {"dl", 0, &option_lex, 1},
	  {"dg", 0, &option_gen, 1},
#endif
	  {"oc", 1, 0, 'b'},
	  {"ol", 1, 0, 'B'},
	  {0, 0, 0, 0}
	};

      c = getopt_long_only (argc, argv, "ab:B:cC:edD:EFgGI:hHl:L::m::M:o:O::pP"
			    "qRsStTU:vVw", long_options, &option_index);

      if (c == EOF) break;

      switch (c)
	{
     	case 0:
     	  /* If this option set a flag, do nothing else now.   */
     	  break;
     	case 'a':
	  option_atr = TRUE;
	  option_checkdiff = TRUE;
	  option_reuse_timestamp = TRUE;
	  break;
	case 'b':
	  ccompargs = newstrcat3 (ccompargs, optarg, " ");
	  break;
	case 'B':
	  linkargs = newstrcat3 (linkargs, optarg, " ");
	  break;
	case 'c':
	  if (option_nolink || option_nocc)
	    {
	      fprintf (stderr, "%s: Option -c: Specified twise or "
		       "in combination with -S or -C\n", progname);
	      print_help (1);
	    }
	  option_nolink = TRUE;
	  break;
	case 'C':
	  ccomp = newstrcat1 (optarg);
	  break;
	case 'd':
	  option_checkdiff = TRUE;
	  option_reuse_timestamp = TRUE;
	  break;
	case 'D':
	  defineName (tag (stringtoupper (optarg)), TRUE);
	  break;
	case 'e':
	  option_static = TRUE;
	  break;
	case 'E':
	  option_write_tokens = TRUE;
	  break;
	case 'F':
	  option_write_mif = TRUE;
	  break;
	case 'g':
	  break;
	case 'G':
	  ccomp = "gcc -g -O2";
	  break;
	case 'h':
	  print_help(0);
	  break;
	case 'H':
	  option_line = TRUE;
	  break;
	case 'I':
	  includedir = newstrcat1 (optarg);
	  break;
	case 'l':
	  new_lib (optarg);
	  break;
	case 'L':
	  insert_name_in_dirlist (optarg);
	  break;
	case 'm':
	  if (optarg)
	    {
	      sscanf (optarg, "%d", &option_init_poolsize);
	      option_init_poolsize *= 1024;
	    } else
	      {
		option_dyn_poolsize = TRUE;
	      }
	  break;
	case 'M':
	  sscanf (optarg, "%d", &option_max_poolsize);
	  option_max_poolsize *= 1024;
	  break;
	case 'N':
	  if (sourcename != NULL)
	    {
	      fprintf (stderr, "%s: More than one simula-file "
		       "are specified\n", progname);
	      print_help (1);
	    };
	  sourcename = newstrcat1 (optarg);
	  break;
	case 'o':
	  outputname = newstrcat1 (optarg);
	  break;
	case 'O':
	  if (!optarg) optarg="";
	  ccompargs = newstrcat4 (ccompargs, "-O", optarg, " ");
	  break;
	case 'p':
	  option_pic = TRUE;
	  break;
	case 'P':
	  if (option_nolink || option_nocc || option_nosim)
	    {
	      fprintf (stderr, "%s: Option -C: Specified twise or "
		       "in combination with -s, -c or -S\n", progname);
	      print_help (1);
	    }
	  option_nocc = option_nosim = TRUE;
	  break;
	case 'q':
	  option_quiet = TRUE;
	  option_verbose = FALSE;
	  break;
	case 'R':
	  option_reuse_timestamp = TRUE;
	  break;
	case 's':
	  if (option_nocc || option_nosim)
	    {
	      fprintf (stderr, "%s: Option -s: Specified twise or in "
		       "combination with -S or -C\n", progname);
	      print_help (1);
	    }
	  option_nosim = TRUE;
	  break;
	case 'S':
	  if (option_nolink || option_nocc || option_nosim)
	    {
	      fprintf (stderr, "%s: Option -S: Specified twise or "
		       "in combination with -s, -c or -C\n", progname);
	      print_help (1);
	    }
	  option_nolink = option_nocc = TRUE;
	  break;
	case 't':
	  option_notempdel = TRUE;
	  break;
	case 'u':
	  option_bl_in_dir_line = TRUE;
	  break;
	case 'U':
	  defineName (tag (stringtoupper (optarg)), FALSE);
	  break;
	case 'v':
	  option_verbose = TRUE;
          option_quiet = FALSE;
	  break;
	case 'V':
	  printf ("%s-%s\n", PACKAGE_VERSION, SYSTEM_TYPE);
	  exit (0);
	  break;
	case 'w':
	  option_nowarning = TRUE;
	  break;
	case '?':
	  return (TRUE);
	  break;
	}
    }
  for (index = optind; index < argc; index++)
    {
      int l = strlen (argv[index]);
      if (l >= 6 && !strcmp (&argv[index][l - 6], "-atr.a"))
	{
	  insert_name_in_archlist (argv[index]);
	  insert_name_in_linklist (transform_name (argv[index], "-atr.a", ".a"), FALSE);
	} else
      if (l >= 2 && !strcmp (&argv[index][l - 2], ".a"))
	{
	  insert_name_in_archlist (transform_name (argv[index], ".a", "-atr.a"));
	  insert_name_in_linklist (argv[index], FALSE);
	}
      else if (l >= 2 && !strcmp (&argv[index][l - 2], ".o"))
	{
	  insert_name_in_linklist (argv[index], FALSE);
	}
      else if (l >= 2 && argv[index][l - 2] == '.')
	{
	  fprintf (stderr, "%s: Illegal extension\n", progname);
	  print_help (1);
	}
      else
	{
	  if (sourcename != NULL)
	    {
	      fprintf (stderr, "%s: More than one simula-files "
		       "are specified\n", progname);
	      print_help (1);
	    };
	  if (l > 4 && !(strcmp (&argv[index][l - 4], ".sim")
			 && strcmp (&argv[index][l - 4], ".SIM")
			 && strcmp (&argv[index][l - 4], ".cim")
			 && strcmp (&argv[index][l - 4], ".CIM")))
	    sourcename = newstrcat1 (argv[index]);
	  else
	    sourcename = newstrcat2 (argv[index], ".sim");
	}
    }

  if (sourcename == NULL)
    {
      fprintf (stderr, "%s: No simula-file is specified\n", progname);
      print_help (1);
    };

  exekname= basename (sourcename);
  listname= newstrcat2 (exekname, ".L");
  extcodename= newstrcat2 (exekname, ".atr");
  mifcodename= newstrcat2 (exekname, ".mif");
  ccodename= newstrcat2 (exekname, ".c");
  ocodename= newstrcat2 (exekname, ".o");
  shlname= newstrcat3 ("./", exekname, ".shl");

  if (!strcmp (outputname, ""))
    outputname = exekname;
  else
    exekname = outputname;

  if (strncmp (exekname, "/", 1))
    exekname = newstrcat2 ("./", exekname);

  return (FALSE);
}

/******************************************************************************
                                                                        MAIN */

main (argc, argv, envp)
     int argc;
     char *argv[];
     char *envp[];
{
  char *archname;
  char *kom;
  char differ=TRUE;

  progname = argv[0];

  initNewstr ();
  initFilelist ();

  ccomp = newstrcat3 (SCC, " ", SCFLAGS);

  init_trap_routines();

  get_all_env();
  
  insert_name_in_dirlist (systemlibdir);

  initName ();

  if (parseoptions (argc, argv))
    return (1);

  new_lib ("cim");

  if (option_verbose)
    {
      fprintf 
	(stderr, 
	 "Cim Compiler (version: %s configuration name: %s).\n"
	 "Copyright 1989-1998 by Sverre Hvammen Johansen, Stein Krogdahl,"
	 "Terje Mjøs and Free Software Foundation, Inc.\n"
	 "Cim comes with ABSOLUTELY NO WARRANTY.\n"
	 "This is free software, and you are welcome to redistribute it\n"
	 "under the GNU General Public License; version 2.\n", 
	 PACKAGE_VERSION, SYSTEM_TYPE);
    }

  if(option_atr)
    system (newstrcat6 ("cp -f ", extcodename, " ", extcodename, 
			 ".old", " 2>/dev/null"));

  if(option_checkdiff)
    {
      rename (ccodename, newstrcat2 (ccodename, ".old")); 
    }

  if (!option_nosim && simcomp ())
    {
      unlink (ccodename);

      if(option_checkdiff)
	{
	  rename (ccodename, newstrcat2 (ccodename, ".old")); 
	}
      return (1);
    }

  if (option_write_tokens)
    return (0);

  if(option_atr)
    {
      char status;
      unlink (ccodename);

      status = system (newstrcat5 ("cmp -s ", extcodename, " ", 
				  extcodename, ".old 2>/dev/null"));
      unlink (newstrcat2 (extcodename, ".old"));
      if (status)
	{
	  if (option_verbose)
	    fprintf (stderr, "Atr file differ\n");
	  return (1);
	} else return (0);
    }

  if (!option_nosim)
    {
      FILE *shlfile;

      if ((shlfile = fopen (shlname, "w")) == NULL)
	{
	  perror (newstrcat3 (progname, ": ", shlname));
	  return (1);
	}

      fprintf (shlfile, 
	       "#! /bin/sh\n"
	       "\n"
	       "CC='%s'\n"
	       "CFLAGS='%s'\n"
	       "CFLAGS_ADD=\n"
	       "LDFLAGS='%s'\n"
	       "LDFLAGS_ADD=\n"
	       "wl='%s'\n"
	       "link_static_flag=\"%s\"\n"
	       "pic_flag=\"%s\"\n"
	       "\n"
	       "prev=\n"
	       "for option\n"
	       "do\n"
	       "  if test -n \"$prev\"; then\n"
	       "    eval \"$prev=\\$option\"\n"
	       "    prev=\n"
	       "    if test -n \"$CFLAGS_ADD\"; then\n"
	       "      CFLAGS=\"$CFLAGS $option\"\n"
	       "      CFLAGS_ADD=\n"
	       "    fi\n"
	       "    if test -n \"$LDFLAGS_ADD\"; then\n"
	       "      LDFLAGS=\"$LDFLAGS $option\"\n"
	       "      LDFLAGS_ADD=\n"
	       "    fi\n"
	       "    continue\n"
	       "  fi\n"
	       "\n"
	       "  case \"$option\" in\n"
	       "  -*=*) optarg=`echo \"$option\" | "
	       "sed 's/[-_a-zA-Z0-9]*=//'` ;;\n"
	       "  *) optarg= ;;\n"
	       "  esac\n"
	       "\n"
	       "  case \"$option\" in\n"
	       "  -c | --suppress-linking | -suppress-linking)\n"
	       "    option_nolink=yes ;;\n"
	       "  -e | --static | -static)\n"
	       "  LDFLAGS=\"$LDFLAGS $link_static_flag\" ;;\n"
	       "  -G | --gcc | -gcc)\n"
	       "    CC='gcc -g -O2'; static_flag='-static'; \n"
	       "    pic_flag=' -fPIC' ;;\n"
	       "  -q | --quiet | --silent | -quiet | -silent)\n"
	       "    option_quiet=yes ; option_verbose= ;;\n"
	       "  -v | --verbose | -verbose) "
	       "    option_quiet= ; option_verbose=yes ;;\n"
	       "  -p | --pic | -pic)\n"
	       "  CFLAGS=\"$CFLAGS $pic_flag\" ;;\n"
	       "  -P | --only-link | -only-link)\n"
	       "    option_nocc=yes ;;\n"
	       "  -t | --dont-remove-temporaries | -dont-remove-temporaries)\n"
	       "    option_notempdel=yes ;;\n"
	       "  -s | --no-simula-compile | -no-simula-compile)\n"
	       "    option_notempdel=yes ;;\n"
	       "  -S | --only-simula-compile | -only-simula-compile)\n"
	       "    option_nolink=yes; option_nocc=yes ;;\n"
	       "  -d | --compare | -compare) "
	       "    option_checkdiff=yes; option_notempdel=yes ;;\n"
	       "\n"
	       "  -b | --cflags | -cflags)\n"
	       "    prev=CFLAGS_ADD ;;\n"
	       "  -B | --ldflags | -ldflags)\n"
	       "    prev=LDFLAGS_ADD ;;\n"
	       "  -C | --c-compiler | -c-compiler)\n"
	       "    prev=CC ;;\n"
	       "  -b=* | --cflags=* | -cflags=*)\n"
	       "    CFLAGS=\"$CFLAGS $optarg\" ;;\n"
	       "  -B=* | --ldflags=* | -ldflags=*)\n"
	       "    LDFLAGS=\"$LDFLAGS $optarg\" ;;\n"
	       "  -C=* | --c-compiler=* | -c-compiler=*)\n"
	       "    CC=\"$optarg\" ;;\n"
	       /*	       "  *) { echo \"n.shl: $option: invalid option\" 1>&2; "
	       "exit 1 };;\n"*/
	       "  esac\n"
	       "done\n"
	       "\n"
	       "differ=yes\n"
	       "if test -z \"$option_nocc\"; then\n"
	       "  if test -n \"$option_checkdiff\"; then\n"
	       "    cmp -s %s %s.old &&\n"
	       "      differ=\n"
	       "    rm -f %s.old\n"
	       "  fi\n"
	       "\n"
	       "  if test -n \"$differ\"; then\n"
	       "    if test -z \"$option_quiet\"; then\n"
	       "      echo $CC $CFLAGS -c %s\n"
	       "    fi\n"
	       "    $CC $CFLAGS -c %s || exit 1\n"
	       "  else\n"
	       "    if test -z\"$option_quiet\"; then\n"
	       "      echo touch %s\n"
	       "    fi\n"
	       "    touch %s\n"
	       "  fi\n"
	       "  if test -z \"$option_notempdel\"; then\n"
	       "    rm -f %s\n"
	       "  fi\n"
	       "fi\n"
	       "\n",
	       ccomp, "", SLDFLAGS,
	       WL_FLAG, LINK_STATIC_FLAG, PIC_FLAG,
	       ccodename, ccodename,
	       ccodename,
	       ccodename, ccodename,
	       ocodename, ocodename,
	       ccodename);

      if (!separat_comp)
	{
	  more_modules ();
	  fprintf (shlfile,
		   "if test -z \"$option_nolink\"; then\n"
		   "  if test -z \"$option_quiet\"; then\n"
		   "    echo $CC $LDFLAGS -o %s %s %s\n"
		   "  fi\n"
		   "\n"
		   "  $CC $LDFLAGS -o %s %s %s %s || exit 1\n"
		   "fi\n", 
		   outputname, ocodename, get_names_in_linklist (),
		   outputname, ocodename, get_names_in_linklist (), SLIBS);
	}
      if (!((option_nolink && !separat_comp) 
	    || option_nocc || option_notempdel))
	fprintf (shlfile, "rm -f %s\n",shlname);
      fclose (shlfile);
      system (newstrcat2 ("chmod +x ", shlname));
    }
  argv[0]= shlname;
  execve (shlname, argv, envp);
}


syntax highlighted by Code2HTML, v. 0.9.1