/* do not edit automatically generated by mc from mcPreprocess.  */
/* This file is part of GNU Modula-2.

GNU Modula-2 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; either version 3, or (at your option) any later
version.

GNU Modula-2 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 GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include <stdbool.h>
#   if !defined (PROC_D)
#      define PROC_D
       typedef void (*PROC_t) (void);
       typedef struct { PROC_t proc; } PROC;
#   endif

#define _mcPreprocess_C

#include "GmcPreprocess.h"
#   include "GSYSTEM.h"
#   include "GDynamicStrings.h"
#   include "Glibc.h"
#   include "Galists.h"
#   include "GM2RTS.h"
#   include "GFIO.h"
#   include "GmcPrintf.h"
#   include "GmcOptions.h"

static alists_alist listOfFiles;

/*
   preprocessModule - preprocess a file, filename, returning the new filename
                      of the preprocessed file.
                      Preprocessing will only occur if requested by the user.
                      If no preprocessing was requested then filename is returned.
                      If preprocessing occurs then a temporary file is created
                      and its name is returned.
                      All temporary files will be deleted when the compiler exits.
*/

extern "C" DynamicStrings_String mcPreprocess_preprocessModule (DynamicStrings_String filename);

/*
   makeTempFile -
*/

static DynamicStrings_String makeTempFile (DynamicStrings_String ext);

/*
   onExitDelete -
*/

static DynamicStrings_String onExitDelete (DynamicStrings_String filename);

/*
   removeFile - removes a single file, s.
*/

static void removeFile (void * a);

/*
   removeFiles -
*/

static void removeFiles (void);


/*
   makeTempFile -
*/

static DynamicStrings_String makeTempFile (DynamicStrings_String ext)
{
  return DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "/tmp/mctemp.", 12), ext);
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   onExitDelete -
*/

static DynamicStrings_String onExitDelete (DynamicStrings_String filename)
{
  alists_includeItemIntoList (listOfFiles, reinterpret_cast <void *> (DynamicStrings_Dup (filename)));
  return filename;
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}


/*
   removeFile - removes a single file, s.
*/

static void removeFile (void * a)
{
  DynamicStrings_String s;

  s = static_cast<DynamicStrings_String> (a);
  if ((libc_unlink (DynamicStrings_string (s))) != 0)
    {}  /* empty.  */
}


/*
   removeFiles -
*/

static void removeFiles (void)
{
  alists_foreachItemInListDo (listOfFiles, (alists_performOperation) {(alists_performOperation_t) removeFile});
}


/*
   preprocessModule - preprocess a file, filename, returning the new filename
                      of the preprocessed file.
                      Preprocessing will only occur if requested by the user.
                      If no preprocessing was requested then filename is returned.
                      If preprocessing occurs then a temporary file is created
                      and its name is returned.
                      All temporary files will be deleted when the compiler exits.
*/

extern "C" DynamicStrings_String mcPreprocess_preprocessModule (DynamicStrings_String filename)
{
  DynamicStrings_String tempfile;
  DynamicStrings_String command;
  DynamicStrings_String commandLine;
  unsigned int pos;

  command = mcOptions_getCppCommandLine ();
  if (DynamicStrings_EqualArray (command, (const char *) "", 0))
    {
      return filename;
    }
  else
    {
      tempfile = DynamicStrings_InitStringCharStar (reinterpret_cast <void *> (makeTempFile (DynamicStrings_InitString ((const char *) "cpp", 3))));
      commandLine = DynamicStrings_Dup (command);
      commandLine = DynamicStrings_ConCat (DynamicStrings_ConCat (DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Dup (commandLine), ' '), filename), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) " -o ", 4))), tempfile);
      if (mcOptions_getVerbose ())
        {
          mcPrintf_fprintf1 (FIO_StdOut, (const char *) "%s\\n", 4, (const unsigned char *) &commandLine, (sizeof (commandLine)-1));
        }
      if ((libc_system (DynamicStrings_string (commandLine))) != 0)
        {
          mcPrintf_fprintf1 (FIO_StdErr, (const char *) "C preprocessor failed when preprocessing %s\\n", 45, (const unsigned char *) &filename, (sizeof (filename)-1));
          libc_exit (1);
        }
      commandLine = DynamicStrings_KillString (commandLine);
      return onExitDelete (tempfile);
    }
  /* static analysis guarentees a RETURN statement will be used before here.  */
  __builtin_unreachable ();
}

extern "C" void _M2_mcPreprocess_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
{
  listOfFiles = alists_initList ();
  if (! (M2RTS_InstallTerminationProcedure ((PROC ) {(PROC_t) removeFiles})))
    {
      M2RTS_HALT (-1);
      __builtin_unreachable ();
    }
}

extern "C" void _M2_mcPreprocess_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
{
}