(root)/
gcc-13.2.0/
gcc/
ada/
adadecode.c
       1  /****************************************************************************
       2   *                                                                          *
       3   *                         GNAT COMPILER COMPONENTS                         *
       4   *                                                                          *
       5   *                            A D A D E C O D E                             *
       6   *                                                                          *
       7   *                          C Implementation File                           *
       8   *                                                                          *
       9   *           Copyright (C) 2001-2023, Free Software Foundation, Inc.        *
      10   *                                                                          *
      11   * GNAT is free software;  you can  redistribute it  and/or modify it under *
      12   * terms of the  GNU General Public License as published  by the Free Soft- *
      13   * ware  Foundation;  either version 3,  or (at your option) any later ver- *
      14   * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
      15   * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
      16   * or FITNESS FOR A PARTICULAR PURPOSE.                                     *
      17   *                                                                          *
      18   * As a special exception under Section 7 of GPL version 3, you are granted *
      19   * additional permissions described in the GCC Runtime Library Exception,   *
      20   * version 3.1, as published by the Free Software Foundation.               *
      21   *                                                                          *
      22   * You should have received a copy of the GNU General Public License and    *
      23   * a copy of the GCC Runtime Library Exception along with this program;     *
      24   * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
      25   * <http://www.gnu.org/licenses/>.                                          *
      26   *                                                                          *
      27   * GNAT was originally developed  by the GNAT team at  New York University. *
      28   * Extensive contributions were provided by Ada Core Technologies Inc.      *
      29   *                                                                          *
      30   ****************************************************************************/
      31  
      32  #include "runtime.h"
      33  #include <string.h>
      34  #include <stdio.h>
      35  #include <ctype.h>
      36  
      37  #include "adaint.h"  /* for a macro version of xstrdup.  */
      38  
      39  #ifndef ISDIGIT
      40  #define ISDIGIT(c) isdigit(c)
      41  #endif
      42  
      43  #ifndef PARMS
      44  #define PARMS(ARGS) ARGS
      45  #endif
      46  
      47  #include "adadecode.h"
      48  
      49  static void add_verbose (const char *, char *);
      50  static int has_prefix (const char *, const char *);
      51  static int has_suffix (const char *, const char *);
      52  
      53  /* This is a safe version of strcpy that can be used with overlapped
      54     pointers. Does nothing if s2 <= s1.  */
      55  static void ostrcpy (char *s1, char *s2);
      56  
      57  /* Set to nonzero if we have written any verbose info.  */
      58  static int verbose_info;
      59  
      60  /* Add TEXT to end of ADA_NAME, putting a leading " (" or ", ", depending
      61     on VERBOSE_INFO.  */
      62  
      63  static void add_verbose (const char *text, char *ada_name)
      64  {
      65    strcat (ada_name, verbose_info ? ", " : " (");
      66    strcat (ada_name, text);
      67  
      68    verbose_info = 1;
      69  }
      70  
      71  /* Returns 1 if NAME starts with PREFIX.  */
      72  
      73  static int
      74  has_prefix (const char *name, const char *prefix)
      75  {
      76    return strncmp (name, prefix, strlen (prefix)) == 0;
      77  }
      78  
      79  /* Returns 1 if NAME ends with SUFFIX.  */
      80  
      81  static int
      82  has_suffix (const char *name, const char *suffix)
      83  {
      84    int nlen = strlen (name);
      85    int slen = strlen (suffix);
      86  
      87    return nlen > slen && strncmp (name + nlen - slen, suffix, slen) == 0;
      88  }
      89  
      90  /* Safe overlapped pointers version of strcpy.  */
      91  
      92  static void
      93  ostrcpy (char *s1, char *s2)
      94  {
      95    if (s2 > s1)
      96      {
      97        while (*s2) *s1++ = *s2++;
      98        *s1 = '\0';
      99      }
     100  }
     101  
     102  /* This function will return the Ada name from the encoded form.
     103     The Ada coding is done in exp_dbug.ads and this is the inverse function.
     104     see exp_dbug.ads for full encoding rules, a short description is added
     105     below. Right now only objects and routines are handled. Ada types are
     106     stripped of their encodings.
     107  
     108     CODED_NAME is the encoded entity name.
     109  
     110     ADA_NAME is a pointer to a buffer, it will receive the Ada name. A safe
     111     size for this buffer is: strlen (coded_name) * 2 + 60. (60 is for the
     112     verbose information).
     113  
     114     VERBOSE is nonzero if more information about the entity is to be
     115     added at the end of the Ada name and surrounded by ( and ).
     116  
     117       Coded name           Ada name                verbose info
     118    ---------------------------------------------------------------------
     119    _ada_xyz                xyz                     library level
     120    x__y__z                 x.y.z
     121    x__yTKB                 x.y                     task body
     122    x__yB                   x.y                     task body
     123    x__yX                   x.y                     body nested
     124    x__yXb                  x.y                     body nested
     125    xTK__y                  x.y                     in task
     126    x__y$2                  x.y                     overloaded
     127    x__y__3                 x.y                     overloaded
     128    x__Oabs                 "abs"
     129    x__Oand                 "and"
     130    x__Omod                 "mod"
     131    x__Onot                 "not"
     132    x__Oor                  "or"
     133    x__Orem                 "rem"
     134    x__Oxor                 "xor"
     135    x__Oeq                  "="
     136    x__One                  "/="
     137    x__Olt                  "<"
     138    x__Ole                  "<="
     139    x__Ogt                  ">"
     140    x__Oge                  ">="
     141    x__Oadd                 "+"
     142    x__Osubtract            "-"
     143    x__Oconcat              "&"
     144    x__Omultiply            "*"
     145    x__Odivide              "/"
     146    x__Oexpon               "**"     */
     147  
     148  void
     149  __gnat_decode (const char *coded_name, char *ada_name, int verbose)
     150  {
     151    int lib_subprog = 0;
     152    int overloaded = 0;
     153    int task_body = 0;
     154    int in_task = 0;
     155    int body_nested = 0;
     156  
     157    /* Deal with empty input early.  This allows assuming non-null length
     158       later on, simplifying coding.  In principle, it should be our callers
     159       business not to call here for empty inputs.  It is easy enough to
     160       allow it, however, and might allow simplifications upstream so is not
     161       a bad thing per se.  We need a guard in any case.  */
     162  
     163    if (*coded_name == '\0')
     164      {
     165        *ada_name = '\0';
     166        return;
     167      }
     168  
     169    /* Check for library level subprogram.  */
     170    else if (has_prefix (coded_name, "_ada_"))
     171      {
     172        strcpy (ada_name, coded_name + 5);
     173        lib_subprog = 1;
     174      }
     175    else
     176      strcpy (ada_name, coded_name);
     177  
     178    /* Check for the first triple underscore in the name. This indicates
     179       that the name represents a type with encodings; in this case, we
     180       need to strip the encodings.  */
     181    {
     182      char *encodings;
     183  
     184      if ((encodings = (char *) strstr (ada_name, "___")) != NULL)
     185        {
     186  	*encodings = '\0';
     187        }
     188    }
     189  
     190    /* Check for task body.  */
     191    if (has_suffix (ada_name, "TKB"))
     192      {
     193        ada_name[strlen (ada_name) - 3] = '\0';
     194        task_body = 1;
     195      }
     196  
     197    if (has_suffix (ada_name, "B"))
     198      {
     199        ada_name[strlen (ada_name) - 1] = '\0';
     200        task_body = 1;
     201      }
     202  
     203    /* Check for body-nested entity: X[bn] */
     204    if (has_suffix (ada_name, "X"))
     205      {
     206        ada_name[strlen (ada_name) - 1] = '\0';
     207        body_nested = 1;
     208      }
     209  
     210    if (has_suffix (ada_name, "Xb"))
     211      {
     212        ada_name[strlen (ada_name) - 2] = '\0';
     213        body_nested = 1;
     214      }
     215  
     216    if (has_suffix (ada_name, "Xn"))
     217      {
     218        ada_name[strlen (ada_name) - 2] = '\0';
     219        body_nested = 1;
     220      }
     221  
     222    /* Change instance of TK__ (object declared inside a task) to __.  */
     223    {
     224      char *tktoken;
     225  
     226      while ((tktoken = (char *) strstr (ada_name, "TK__")) != NULL)
     227        {
     228  	ostrcpy (tktoken, tktoken + 2);
     229  	in_task = 1;
     230        }
     231    }
     232  
     233    /* Check for overloading: name terminated by $nn or __nn.  */
     234    {
     235      int len = strlen (ada_name);
     236      int n_digits = 0;
     237  
     238      if (len > 1)
     239        while (ISDIGIT ((int) ada_name[(int) len - 1 - n_digits]))
     240  	n_digits++;
     241  
     242      /* Check if we have $ or __ before digits.  */
     243      if (ada_name[len - 1 - n_digits] == '$')
     244        {
     245  	ada_name[len - 1 - n_digits] = '\0';
     246  	overloaded = 1;
     247        }
     248      else if (ada_name[len - 1 - n_digits] == '_'
     249  	     && ada_name[len - 1 - n_digits - 1] == '_')
     250        {
     251  	ada_name[len - 1 - n_digits - 1] = '\0';
     252  	overloaded = 1;
     253        }
     254    }
     255  
     256    /* Check for nested subprogram ending in .nnnn and strip suffix. */
     257    {
     258      int last = strlen (ada_name) - 1;
     259  
     260      while (ISDIGIT (ada_name[last]) && last > 0)
     261        {
     262          last--;
     263        }
     264  
     265      if (ada_name[last] == '.')
     266        {
     267          ada_name[last] = (char) 0;
     268        }
     269    }
     270  
     271    /* Change all "__" to ".". */
     272    {
     273      int len = strlen (ada_name);
     274      int k = 0;
     275  
     276      while (k < len)
     277        {
     278  	if (ada_name[k] == '_' && ada_name[k+1] == '_')
     279  	  {
     280  	    ada_name[k] = '.';
     281  	    ostrcpy (ada_name + k + 1, ada_name + k + 2);
     282  	    len = len - 1;
     283  	  }
     284  	k++;
     285        }
     286    }
     287  
     288    /* Checks for operator name.  */
     289    {
     290      const char *trans_table[][2]
     291        = {{"Oabs", "\"abs\""},  {"Oand", "\"and\""},    {"Omod", "\"mod\""},
     292  	 {"Onot", "\"not\""},  {"Oor", "\"or\""},      {"Orem", "\"rem\""},
     293  	 {"Oxor", "\"xor\""},  {"Oeq", "\"=\""},       {"One", "\"/=\""},
     294  	 {"Olt", "\"<\""},     {"Ole", "\"<=\""},      {"Ogt", "\">\""},
     295  	 {"Oge", "\">=\""},    {"Oadd", "\"+\""},      {"Osubtract", "\"-\""},
     296  	 {"Oconcat", "\"&\""}, {"Omultiply", "\"*\""}, {"Odivide", "\"/\""},
     297  	 {"Oexpon", "\"**\""}, {NULL, NULL} };
     298      int k = 0;
     299  
     300      while (1)
     301        {
     302  	char *optoken;
     303  
     304  	if ((optoken = (char *) strstr (ada_name, trans_table[k][0])) != NULL)
     305  	  {
     306  	    int codedlen = strlen (trans_table[k][0]);
     307  	    int oplen = strlen (trans_table[k][1]);
     308  
     309  	    if (codedlen > oplen)
     310  	      /* We shrink the space.  */
     311  	      ostrcpy (optoken, optoken + codedlen - oplen);
     312  	    else if (oplen > codedlen)
     313  	      {
     314  		/* We need more space.  */
     315  		int len = strlen (ada_name);
     316  		int space = oplen - codedlen;
     317  		int num_to_move = &ada_name[len] - optoken;
     318  		int t;
     319  
     320  		for (t = 0; t < num_to_move; t++)
     321  		  ada_name[len + space - t - 1] = ada_name[len - t - 1];
     322  	      }
     323  
     324  	    /* Write symbol in the space.  */
     325  	    memcpy (optoken, trans_table[k][1], oplen);
     326  	  }
     327  	else
     328  	  k++;
     329  
     330  	/* Check for table's ending.  */
     331  	if (trans_table[k][0] == NULL)
     332  	  break;
     333        }
     334    }
     335  
     336    /* If verbose mode is on, we add some information to the Ada name.  */
     337    if (verbose)
     338      {
     339        if (overloaded)
     340  	add_verbose ("overloaded", ada_name);
     341  
     342        if (lib_subprog)
     343  	add_verbose ("library level", ada_name);
     344  
     345        if (body_nested)
     346  	add_verbose ("body nested", ada_name);
     347  
     348        if (in_task)
     349  	add_verbose ("in task", ada_name);
     350  
     351        if (task_body)
     352  	add_verbose ("task body", ada_name);
     353  
     354        if (verbose_info == 1)
     355  	strcat (ada_name, ")");
     356      }
     357  }
     358  
     359  #ifdef __cplusplus
     360  extern "C" {
     361  #endif
     362  
     363  void
     364  get_encoding (const char *coded_name, char *encoding)
     365  {
     366    char * dest_index = encoding;
     367    const char *p;
     368    int found = 0;
     369    int count = 0;
     370  
     371    /* The heuristics is the following: we assume that the first triple
     372       underscore in an encoded name indicates the beginning of the
     373       first encoding, and that subsequent triple underscores indicate
     374       the next encodings. We assume that the encodings are always at the
     375       end of encoded names.  */
     376  
     377    for (p = coded_name; *p != '\0'; p++)
     378      {
     379        if (*p != '_')
     380  	count = 0;
     381        else
     382  	if (++count == 3)
     383  	  {
     384  	    count = 0;
     385  
     386  	    if (found)
     387  	      {
     388  		dest_index = dest_index - 2;
     389  		*dest_index++ = ':';
     390  	      }
     391  
     392  	    p++;
     393  	    found = 1;
     394  	  }
     395  
     396        if (found)
     397  	*dest_index++ = *p;
     398      }
     399  
     400    *dest_index = '\0';
     401  }
     402  
     403  #ifdef __cplusplus
     404  }
     405  #endif