plugin-script.c

     
   1  //! @file plugin-script.c
   2  //! @author J. Marcel van der Veer
   3  
   4  //! @section Copyright
   5  //!
   6  //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
   7  //! Copyright 2001-2024 J. Marcel van der Veer [algol68g@xs4all.nl].
   8  
   9  //! @section License
  10  //!
  11  //! This program is free software; you can redistribute it and/or modify it 
  12  //! under the terms of the GNU General Public License as published by the 
  13  //! Free Software Foundation; either version 3 of the License, or 
  14  //! (at your option) any later version.
  15  //!
  16  //! This program is distributed in the hope that it will be useful, but 
  17  //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  18  //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
  19  //! more details. You should have received a copy of the GNU General Public 
  20  //! License along with this program. If not, see [http://www.gnu.org/licenses/].
  21  
  22  //! @section Synopsis
  23  //!
  24  //! Plugin script builder routines.
  25  
  26  #include "a68g.h"
  27  #include "a68g-prelude.h"
  28  #include "a68g-optimiser.h"
  29  #include "a68g-options.h"
  30  
  31  #if defined (BUILD_A68_COMPILER)
  32  
  33  //! @brief Build shell script from program.
  34  
  35  void build_script (void)
  36  {
  37  #if !defined (BUILD_A68_COMPILER)
  38    return;
  39  #endif
  40    BUFFER cmd;
  41    BUFCLR (cmd);
  42    announce_phase ("script builder");
  43    ABEND (OPTION_OPT_LEVEL (&A68_JOB) == 0, ERROR_ACTION, __func__);
  44  // Flatten the source file.
  45    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s.%s", HIDDEN_TEMP_FILE_NAME, FILE_SOURCE_NAME (&A68_JOB)) >= 0);
  46    FILE_T source = open (cmd, O_WRONLY | O_CREAT | O_TRUNC, A68_PROTECTION);
  47    ABEND (source == -1, ERROR_ACTION, cmd);
  48    for (LINE_T *sl = TOP_LINE (&A68_JOB); sl != NO_LINE; FORWARD (sl)) {
  49      if (strlen (STRING (sl)) == 0 || (STRING (sl))[strlen (STRING (sl)) - 1] != NEWLINE_CHAR) {
  50        ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s\n%d\n%s\n", FILENAME (sl), NUMBER (sl), STRING (sl)) >= 0);
  51      } else {
  52        ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s\n%d\n%s", FILENAME (sl), NUMBER (sl), STRING (sl)) >= 0);
  53      }
  54      WRITE (source, cmd);
  55    }
  56    ASSERT (close (source) == 0);
  57  // Compress source and dynamic library.
  58    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "cp %s %s.%s", FILE_PLUGIN_NAME (&A68_JOB), HIDDEN_TEMP_FILE_NAME, FILE_PLUGIN_NAME (&A68_JOB)) >= 0);
  59    int ret = system (cmd);
  60    ABEND (ret != 0, ERROR_ACTION, cmd);
  61    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "tar czf %s.%s.tgz %s.%s %s.%s", HIDDEN_TEMP_FILE_NAME, FILE_GENERIC_NAME (&A68_JOB), HIDDEN_TEMP_FILE_NAME, FILE_SOURCE_NAME (&A68_JOB), HIDDEN_TEMP_FILE_NAME, FILE_PLUGIN_NAME (&A68_JOB)) >= 0);
  62    ret = system (cmd);
  63    ABEND (ret != 0, ERROR_ACTION, cmd);
  64  // Compose script.
  65    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s.%s", HIDDEN_TEMP_FILE_NAME, FILE_SCRIPT_NAME (&A68_JOB)) >= 0);
  66    FILE_T script = open (cmd, O_WRONLY | O_CREAT | O_TRUNC, A68_PROTECTION);
  67    ABEND (script == -1, ERROR_ACTION, cmd);
  68    char *strop = "";
  69    if (OPTION_STROPPING (&A68_JOB) == QUOTE_STROPPING) {
  70      strop = "--run-quote-script";
  71    } else {
  72      strop = "--run-script";
  73    }
  74    ASSERT (a68_bufprt (A68 (output_line), SNPRINTF_SIZE, "#! %s/a68g %s\n", BINDIR, strop) >= 0);
  75    WRITE (script, A68 (output_line));
  76    ASSERT (a68_bufprt (A68 (output_line), SNPRINTF_SIZE, "%s\n%s --verify \"%s\"\n", FILE_GENERIC_NAME (&A68_JOB), optimisation_option (), PACKAGE_STRING) >= 0);
  77    WRITE (script, A68 (output_line));
  78    ASSERT (close (script) == 0);
  79    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "cat %s.%s %s.%s.tgz > %s", HIDDEN_TEMP_FILE_NAME, FILE_SCRIPT_NAME (&A68_JOB), HIDDEN_TEMP_FILE_NAME, FILE_GENERIC_NAME (&A68_JOB), FILE_SCRIPT_NAME (&A68_JOB)) >= 0);
  80    ret = system (cmd);
  81    ABEND (ret != 0, ERROR_ACTION, cmd);
  82    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s", FILE_SCRIPT_NAME (&A68_JOB)) >= 0);
  83    ret = chmod (cmd, (__mode_t) (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH));  // -rwx-r-xr-x
  84    ABEND (ret != 0, ERROR_ACTION, cmd);
  85    ABEND (ret != 0, ERROR_ACTION, cmd);
  86  // Clean up.
  87    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s.%s.tgz", HIDDEN_TEMP_FILE_NAME, FILE_GENERIC_NAME (&A68_JOB)) >= 0);
  88    ret = remove (cmd);
  89    ABEND (ret != 0, ERROR_ACTION, cmd);
  90    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s.%s", HIDDEN_TEMP_FILE_NAME, FILE_SOURCE_NAME (&A68_JOB)) >= 0);
  91    ret = remove (cmd);
  92    ABEND (ret != 0, ERROR_ACTION, cmd);
  93    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s.%s", HIDDEN_TEMP_FILE_NAME, FILE_PLUGIN_NAME (&A68_JOB)) >= 0);
  94    ret = remove (cmd);
  95    ABEND (ret != 0, ERROR_ACTION, cmd);
  96    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s.%s", HIDDEN_TEMP_FILE_NAME, FILE_SCRIPT_NAME (&A68_JOB)) >= 0);
  97    ret = remove (cmd);
  98    ABEND (ret != 0, ERROR_ACTION, cmd);
  99  }
 100  
 101  //! @brief Load program from shell script .
 102  
 103  void load_script (void)
 104  {
 105  #if !defined (BUILD_A68_COMPILER)
 106    return;
 107  #endif
 108    BUFFER cmd; char ch;
 109    BUFCLR (cmd);
 110    announce_phase ("script loader");
 111  // Decompress the archive.
 112    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "sed '1,3d' < %s | tar xzf -", FILE_INITIAL_NAME (&A68_JOB)) >= 0);
 113    ABEND (system (cmd) != 0, ERROR_ACTION, cmd);
 114  // Reread the header.
 115    FILE_T script = open (FILE_INITIAL_NAME (&A68_JOB), O_RDONLY);
 116    ABEND (script == -1, ERROR_ACTION, cmd);
 117  // Skip the #! a68g line.
 118    ASSERT (io_read (script, &ch, 1) == 1);
 119    while (ch != NEWLINE_CHAR) {
 120      ASSERT (io_read (script, &ch, 1) == 1);
 121    }
 122  // Read the generic filename.
 123    A68 (input_line)[0] = NULL_CHAR;
 124    int k = 0;
 125    ASSERT (io_read (script, &ch, 1) == 1);
 126    while (ch != NEWLINE_CHAR) {
 127      A68 (input_line)[k++] = ch;
 128      ASSERT (io_read (script, &ch, 1) == 1);
 129    }
 130    A68 (input_line)[k] = NULL_CHAR;
 131    ASSERT (a68_bufprt (cmd, SNPRINTF_SIZE, "%s.%s", HIDDEN_TEMP_FILE_NAME, A68 (input_line)) >= 0);
 132    FILE_INITIAL_NAME (&A68_JOB) = new_string (cmd, NO_TEXT);
 133  // Read options.
 134    A68 (input_line)[0] = NULL_CHAR;
 135    k = 0;
 136    ASSERT (io_read (script, &ch, 1) == 1);
 137    while (ch != NEWLINE_CHAR) {
 138      A68 (input_line)[k++] = ch;
 139      ASSERT (io_read (script, &ch, 1) == 1);
 140    }
 141    isolate_options (A68 (input_line), NO_LINE);
 142    (void) set_options (OPTION_LIST (&A68_JOB), A68_FALSE);
 143    ASSERT (close (script) == 0);
 144  }
 145  
 146  //! @brief Rewrite source for shell script .
 147  
 148  void rewrite_script_source (void)
 149  {
 150  // Rebuild the source file.
 151    ASSERT (remove (FILE_SOURCE_NAME (&A68_JOB)) == 0);
 152    FILE_T source = open (FILE_SOURCE_NAME (&A68_JOB), O_WRONLY | O_CREAT | O_TRUNC, A68_PROTECTION);
 153    ABEND (source == -1, ERROR_ACTION, FILE_SOURCE_NAME (&A68_JOB));
 154    for (LINE_T *ref_l = TOP_LINE (&A68_JOB); ref_l != NO_LINE; FORWARD (ref_l)) {
 155      WRITE (source, STRING (ref_l));
 156      if (strlen (STRING (ref_l)) == 0 || (STRING (ref_l))[strlen (STRING (ref_l) - 1)] != NEWLINE_CHAR) {
 157        WRITE (source, NEWLINE_STRING);
 158      }
 159    }
 160  // Wrap it up.
 161    ASSERT (close (source) == 0);
 162  }
 163  
 164  #endif