home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / gnatbl.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  15KB  |  527 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                         GNAT COMPILER COMPONENTS                         */
  4. /*                                                                          */
  5. /*                               G N A T B L                                */
  6. /*                                                                          */
  7. /*                          C Implementation File                           */
  8. /*                                                                          */
  9. /*                             $Revision: 1.47 $                            */
  10. /*                                                                          */
  11. /*           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          */
  12. /*                                                                          */
  13. /* GNAT is free software;  you can  redistribute it  and/or modify it under */
  14. /* terms of the  GNU General Public License as published  by the Free Soft- */
  15. /* ware  Foundation;  either version 2,  or (at your option) any later ver- */
  16. /* sion.  GNAT is distributed in the hope that it will be useful, but WITH- */
  17. /* OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY */
  18. /* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License */
  19. /* for  more details.  You should have  received  a copy of the GNU General */
  20. /* Public License  distributed with GNAT;  see file COPYING.  If not, write */
  21. /* to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  22. /*                                                                          */
  23. /****************************************************************************/
  24.  
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include "config.h"  /* this may define MSDOS */
  29. #include <stdlib.h>
  30. #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
  31. #include <process.h>
  32. #endif
  33. #include <string.h>
  34. #include "a-adaint.h"
  35.  
  36. /* These can be set by command line arguments */
  37. char *binder_path = 0;
  38. char *linker_path = 0;
  39. char *exec_file_name = 0;
  40. #define BIND_ARG_MAX 512
  41. char *bind_args[BIND_ARG_MAX];
  42. int  bind_arg_index = -1;
  43. #ifdef MSDOS
  44. char *coff2exe_path = 0;
  45. char *coff2exe_args[] = {(char *) 0, (char *) 0};
  46. char *del_command = 0;
  47. #endif
  48. int  verbose      = 0;
  49. int  o_present    = 0;
  50. int  g_present    = 0;
  51.  
  52. int  link_arg_max = -1;
  53. char **link_args = (char **) 0;
  54. int  link_arg_index = -1;
  55. int  numerics_present = 0;  /* indicates presence of ada numerics packages */
  56. int  tasking_present = 0;   /* indicates needs for gthreads library */
  57. #ifdef WINNT
  58. int  windows_present = 0;  /* indicates a windows application */
  59. #endif
  60.  
  61. char *gcc_B_arg = 0;
  62. #ifndef DIR_SEPARATOR
  63. #if defined (__EMX__)
  64. #define DIR_SEPARATOR '\\'
  65. #else
  66. #define DIR_SEPARATOR '/'
  67. #endif
  68. #endif
  69.  
  70. extern char *rindex ();
  71.  
  72. static void proc_bind_file (char *aliname);
  73. static int linkonly = 0;
  74.  
  75. static void
  76. addarg (char *str)
  77. {
  78.   int i;
  79.  
  80.   if (++link_arg_index >= link_arg_max) {
  81.     char **new_link_args
  82.       = (char **) calloc (link_arg_max + 1000, sizeof (char *));
  83.     for (i = 0; i <= link_arg_max; i++)
  84.       new_link_args [i] = link_args [i];
  85.     if (link_args) free (link_args);
  86.     link_arg_max += 1000;
  87.     link_args = new_link_args;
  88.   }
  89.  
  90.   link_args [link_arg_index] = str;
  91. }
  92.  
  93.  
  94. static void
  95. process_args (int *p_argc, char *argv [])
  96. {
  97.   int i, j;
  98.  
  99.   for (i = 1; i < *p_argc; i++) {
  100.  
  101.     /* -I is passed on to gnatbind */
  102.     if (! strncmp( argv[i], "-I", 2))
  103.     {
  104.       bind_arg_index += 1;
  105.       if (bind_arg_index >= BIND_ARG_MAX)
  106.       {
  107.          fprintf (stderr, "Too many arguments to gnatbind\n");
  108.          exit (-1);
  109.       }
  110.       bind_args[bind_arg_index] = argv[i];
  111.     }
  112.     /* -B is passed on to gcc */
  113.     if (! strncmp (argv [i], "-B", 2)) {
  114.        gcc_B_arg = argv[i];
  115.     }
  116.     /* -v turns on verbose option here and is passed on to gcc */
  117.  
  118.     if (! strcmp (argv [i], "-v"))
  119.       verbose = 1;
  120.  
  121.     if (! strcmp (argv [i], "-o"))
  122.     {
  123.       o_present = 1;
  124.       exec_file_name = argv [i + 1];
  125.     }
  126.  
  127.     if (! strcmp (argv [i], "-g"))
  128.       g_present = 1;
  129.  
  130.     if (! strcmp (argv [i], "-gnatbind")) {
  131.  
  132.       /* Explicit naming of binder.  Grab the value then remove the
  133.      two arguments from the argument list. */
  134.  
  135.       if ( i + 1 >= *p_argc ) {
  136.     fprintf (stderr, "Missing argument for -gnatbind\n");
  137.     exit (1);
  138.       }
  139.  
  140.       binder_path = locate_exec (argv [i + 1], ".");
  141.       if (!binder_path) {
  142.         fprintf (stderr, "Could not locate binder: %s\n", argv [i + 1]);
  143.         exit (1);
  144.       }
  145.       for (j = i + 2; j < *p_argc; j++)
  146.         argv [j - 2] = argv [j];
  147.       (*p_argc) -= 2;
  148.       i--;
  149.  
  150.     }
  151.  
  152.     else if (! strcmp (argv [i], "-linkonly")) {
  153.  
  154.       /* Don't call the binder. Set the flag and then remove the
  155.      argument from the argument list. */
  156.  
  157.       linkonly = 1;
  158.       for (j = i + 1; j < *p_argc; j++)
  159.     argv [j - 1] = argv [j];
  160.       (*p_argc) -= 1;
  161.       i--;
  162.     }
  163.  
  164.     else if (! strcmp (argv [i], "-gnatlink")) {
  165.  
  166.       /* Explicit naming of binder.  Grab the value then remove the
  167.      two arguments from the argument list. */
  168.  
  169.       if ( i + 1 >= *p_argc ) {
  170.     fprintf (stderr, "Missing argument for -gnatlink\n");
  171.     exit (1);
  172.       }
  173.       linker_path = locate_exec (argv [i + 1], ".");
  174.       if (!linker_path) {
  175.     fprintf (stderr, "Could not locate linker: %s\n", argv [i + 1]);
  176.     exit (1);
  177.       }
  178.       for (j = i + 2; j < *p_argc; j++)
  179.     argv [j - 2] = argv [j];
  180.       (*p_argc) -= 2;
  181.       i--;
  182.     }
  183.   }
  184. }
  185.  
  186. main (int argc, char *argv [])
  187. {
  188.   int i,j;
  189.   int done_an_ali = 0;
  190.   int file_name_index;
  191.   int retcode;
  192.   char *pathval = getenv ("PATH");
  193.   char *spawn_args [5];
  194.   int  spawn_index = 0;
  195.   char *bind_src_file_name;
  196.   char *bind_obj_file_name;
  197.   int   bind_file_name_len;
  198.  
  199. #if defined (__EMX__) || defined(MSDOS) || defined(WINNT)
  200.   char *tmppathval = malloc (strlen (pathval) + 3);
  201.   strcpy (tmppathval, ".;");
  202.   pathval = strcat (tmppathval, pathval);
  203. #endif
  204. #if defined(__amigaos__)
  205.   /* Provide a default PATH if none was not found.  Perhaps this should be
  206.      done for all machines using a value derived from $(bindir) in the
  207.      Makefile? */
  208.   if (!pathval)
  209.     pathval = "/ade/bin";
  210. #endif
  211.  
  212.   process_args (&argc , argv);
  213.  
  214.   if (argc == 1) {
  215.     fprintf (stdout,
  216.     "Usage: %s 'name'.ali\n", argv[0]);
  217.     fprintf (stdout,
  218.     "             [-o exec_name]        -- by default it is 'name'\n");
  219.     fprintf (stdout,
  220.     "             [-v]                  -- verbose mode\n");
  221.     fprintf (stdout,
  222.     "             [-linkonly]           -- doesn't call the binder\n");
  223.     fprintf (stdout,
  224.     "             [-gnatbind name]      -- full name for gnatbind\n");
  225.     fprintf (stdout,
  226.     "             [-gnatlink name]      -- full name for the linker (gcc)\n");
  227.     fprintf (stdout,
  228.     "             [list of objects]     -- non Ada binaries\n");
  229.     fprintf (stdout,
  230.     "             [linker options]      -- other options for the linker\n");
  231.     exit (1);
  232.   }
  233.   if (!binder_path && !linkonly)
  234.     binder_path = locate_exec ("gnatbind", pathval);
  235.   if (!binder_path && !linkonly) {
  236.     fprintf (stderr, "Couldn't locate gnatbind\n");
  237.     exit (1);
  238.   }
  239.   if (!linker_path)
  240.     linker_path = locate_exec ("gcc", pathval);
  241.     if (!linker_path) {
  242.       fprintf (stderr, "Couldn't locate gcc\n");
  243.       exit (1);
  244.     }
  245. #ifdef MSDOS
  246.   coff2exe_path = locate_exec ("coff2exe", pathval);
  247.   if (!coff2exe_path) {
  248.     fprintf (stderr, "Couldn't locate %s\n", "coff2exe");
  249.     exit (1);
  250.   } else coff2exe_args[0] = coff2exe_path;
  251. #endif
  252.   addarg (linker_path);
  253.  
  254.   for (i = 1; i < argc; i++) {
  255.     int arg_len = strlen (argv [i]);
  256.     if (arg_len > 4 && ! strcmp (&argv [i][arg_len - 4], ".ali")) {
  257.  
  258.       if (done_an_ali) {
  259.     fprintf (stderr, "Sorry - cannot handle more than one ALI file\n");
  260.     exit (1);
  261.       }
  262.       done_an_ali = 1;
  263.  
  264.       if (is_regular_file (argv [i])) {
  265.     int pid;
  266.  
  267.     if (!linkonly) {
  268.       /* Run gnatbind */
  269.           spawn_index = 0;
  270.       spawn_args [spawn_index++] = binder_path;
  271.       spawn_args [spawn_index++] = argv[i];
  272.       for (j = 0 ; j <= bind_arg_index ; j++ )
  273.         spawn_args [spawn_index++] = bind_args [j];
  274.        spawn_args [spawn_index] = 0;
  275.  
  276.           if (verbose) {
  277.             int i;
  278.             for (i = 0; i < 2; i++)
  279.               printf ("%s ", spawn_args [i]);
  280.             putchar ('\n');
  281.           }
  282.  
  283.       retcode = portable_spawn (spawn_args);
  284.       if (retcode != 0) exit (retcode);
  285.     }
  286.  
  287.     for (file_name_index = arg_len - 4; ; file_name_index--)
  288.       if (file_name_index == 0
  289.               /* DJGPP could have either or both */
  290.           || argv [i][file_name_index - 1] == '/'
  291.           || argv [i][file_name_index - 1] == DIR_SEPARATOR)
  292.         break;
  293.     bind_file_name_len = strlen (&(argv [i][file_name_index]));
  294.     bind_src_file_name = malloc (bind_file_name_len + 1);
  295.     strcpy  (bind_src_file_name, "b_");
  296.     strncat (bind_src_file_name,
  297.          &(argv [i][file_name_index]), bind_file_name_len - 3);
  298.     strcat  (bind_src_file_name, "c");
  299.  
  300.     if (! o_present) {
  301. #if defined (__EMX__)
  302.       exec_file_name = malloc (bind_file_name_len);
  303.       strncpy (exec_file_name,
  304.            &(argv [i][file_name_index]), bind_file_name_len - 3);
  305.       strcat (exec_file_name, "exe");
  306. #else
  307.       exec_file_name = malloc (bind_file_name_len - 3);
  308.       strncpy (exec_file_name,
  309.            &(argv [i][file_name_index]), bind_file_name_len - 4);
  310.           exec_file_name [bind_file_name_len - 4] = '\0';
  311. #endif
  312.     }
  313.  
  314.     /* Compile binder output */
  315.     /* ??? should linker and compiler be separate */
  316.         spawn_index = 0;
  317.     spawn_args [spawn_index++] = linker_path;
  318.     spawn_args [spawn_index++] = "-c";
  319.         if (g_present) spawn_args [spawn_index++] = "-g";
  320.         if (gcc_B_arg) spawn_args [spawn_index++] = gcc_B_arg;
  321.     spawn_args [spawn_index++] = bind_src_file_name;
  322.     spawn_args [spawn_index] = 0;
  323.  
  324.         if (verbose) {
  325.            int i;
  326.            for (i = 0; i < spawn_index; i++)
  327.              printf ("%s ", spawn_args [i]);
  328.            putchar ('\n');
  329.         }
  330.  
  331.     retcode = portable_spawn (spawn_args);
  332.     if (retcode != 0) exit (retcode);
  333.  
  334.     bind_obj_file_name = xstrdup (bind_src_file_name);
  335.     bind_obj_file_name [strlen (bind_obj_file_name) - 1] = 'o';
  336.     addarg (bind_obj_file_name);
  337.  
  338.     proc_bind_file (bind_src_file_name);
  339.       }
  340.       else {
  341.     addarg (argv [i]);
  342.       }
  343.     }
  344. #ifdef MSDOS
  345.     else if (!strcmp (argv [i], "-o")) {
  346.  
  347.       addarg (argv [i]);
  348.       if (i < argc) i++;
  349.       {
  350.         char* ptr = strstr (argv[i], ".exe");
  351.  
  352.         arg_len = strlen (argv [i]);
  353.     coff2exe_args[1] = malloc (arg_len + 1);
  354.     strcpy (coff2exe_args[1], argv[i]);
  355.         if (ptr != NULL && strlen (ptr) == 4) {
  356.           coff2exe_args[1][arg_len-4] = 0;
  357.         }
  358.         addarg (coff2exe_args[1]);
  359.       }
  360.     }
  361. #endif
  362.     else {
  363.       addarg (argv [i]);
  364.     }
  365.   }
  366.  
  367.   if (! done_an_ali) {
  368.     fprintf (stderr, "No \".ali\" file specified\n");
  369.     exit (1);
  370.   }
  371.  
  372.   if (! o_present) {
  373.     addarg ("-o");
  374.     addarg (exec_file_name);
  375. #ifdef MSDOS
  376.     coff2exe_args[1] = exec_file_name;
  377. #endif
  378.   }
  379.  
  380. #if !(defined (__EMX__))
  381. #if !(defined (MSDOS) || defined (WINNT))
  382.   addarg ("-L" ADA_RTL_OBJ_DIR);
  383.   if (tasking_present) 
  384.     addarg ("-lgthreads");
  385. #endif
  386. #ifndef WINNT
  387.   if (numerics_present) addarg ("-lm");
  388. #endif
  389. #endif
  390. #ifdef WINNT
  391.   if (windows_present)
  392.       addarg ("-mwindows");
  393. #endif
  394.   addarg ("-lgnat");
  395.   addarg (NULL);
  396.  
  397.   if (verbose) {
  398.     int i;
  399.     for (i = 0; i < link_arg_index; i++)
  400.       printf ("%s ", link_args [i]);
  401.     putchar ('\n');
  402.   }
  403.  
  404.   retcode = portable_spawn (link_args);
  405.   if (retcode != 0) exit (retcode);
  406.  
  407.   /* Only keep the binder generated files if the debugging option was
  408.    * specified when the gnatbl was invoked since this implies that the user
  409.    * might want to break within the binder generated file.
  410.    */
  411.   if (!g_present) {
  412.     unlink (bind_src_file_name);
  413.     unlink (bind_obj_file_name);
  414.   }
  415.  
  416. #ifdef MSDOS
  417.   retcode = portable_spawn (coff2exe_args);
  418.   if (retcode != 0) exit (retcode);
  419.   if (!g_present)
  420.     {
  421.       del_command = malloc (strlen (coff2exe_args[1]) + 5);
  422.       sprintf (del_command, "del %s", coff2exe_args[1]);
  423.       retcode = system (del_command);
  424.     }
  425. #endif
  426.  
  427.   exit(0);
  428. }
  429.  
  430. static void
  431. proc_bind_file (char *bind_file_name)
  432. {
  433.   char *ptr, *tptr;
  434.   char buf [1000];
  435.   FILE *bind_file;
  436.   int aliname_len = strlen (bind_file_name);
  437.   char *start_string = "/* BEGIN Object";
  438.   int  start_string_len = strlen (start_string);
  439.   char *end_string   = "   END Object";
  440.   int  end_string_len = strlen (end_string);
  441. #ifdef WINNT
  442.   char *argfile_name, *rf;
  443.   FILE *argfile;
  444. #endif
  445.  
  446.   if ((bind_file = fopen (bind_file_name, "r")) == NULL) {
  447.     fprintf (stderr, "Failed to open binder output\n");
  448.     exit (1);
  449.   }
  450.  
  451. #ifdef WINNT
  452.   argfile_name = (char *)malloc (strlen ("-Xlinker") +
  453.                                  strlen (exec_file_name) + 6);
  454.   rf = strlen ("-Xlinker") + argfile_name + 2;
  455.   sprintf (argfile_name, "-Xlinker @%s.gp", exec_file_name);
  456.   argfile = fopen (rf, "w");
  457.   if (argfile == 0)
  458.     {
  459.       fprintf (stderr, "Error opening response file: %s\n", rf);
  460.       exit (1);
  461.     }
  462.   addarg (argfile_name);
  463. #endif
  464.  
  465.   for (;;) {
  466.     if (fgets (buf, 1000, bind_file) == NULL) {
  467.       fprintf (stderr, "Error reading binder output\n");
  468.       exit (1);
  469.     }
  470.     if (!strncmp (buf, start_string, start_string_len))
  471.       break;
  472.   }
  473.  
  474.   for (;;) {
  475.     if (fgets (buf, 1000, bind_file) == NULL) {
  476.       fprintf (stderr, "Error reading binder output\n");
  477.       exit (1);
  478.     }
  479.     if (!strncmp (buf, end_string, end_string_len))
  480.       break;
  481.  
  482.     for (ptr = buf; *ptr && *ptr != '\n'; ptr++)
  483.       ;
  484.     *ptr = '\0';
  485.  
  486. #ifdef WINNT
  487.     fprintf (argfile, "%s\n", buf);
  488. #else
  489.     addarg (xstrdup (buf));
  490. #endif
  491.  
  492.     /* If the object file "a-numaux" is present set a flag and later
  493.      * when the final arguments of the link are appended, the flag will be
  494.      * queried and "-lm" will be added to the link since this is needed by
  495.      * the numerics packages.
  496.      */
  497.     ptr = rindex (buf, '/');
  498.     if (ptr != NULL) {
  499.       ptr++;  /* skip over the separator */
  500.     }
  501.     else {
  502.       ptr = buf;
  503.     }
  504.     if ('/' != DIR_SEPARATOR) {  /* DJGPP could have either or both */
  505.       tptr = rindex (ptr, DIR_SEPARATOR);
  506.       if (tptr != NULL) {
  507.         ptr = ++tptr;  /* skip over the separator */
  508.       }
  509.     }
  510.     if (! strcmp (ptr, "a-numaux.o"))
  511.       numerics_present++;
  512.  
  513.     if (! strcmp (ptr, "s-taskin.o"))
  514.       tasking_present++;
  515.  
  516. #ifdef WINNT
  517.     if (! strcmp (ptr, "windows.o"))
  518.       windows_present++;
  519. #endif
  520.  
  521.   }
  522. #ifdef WINNT
  523.   fclose (argfile);
  524. #endif
  525.   fclose (bind_file);
  526. }
  527.