/* C declarator syntax glue.
   Copyright (C) 2019 Free Software Foundation, Inc.

   This file is part of libctf.

   libctf 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.

   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; see the file COPYING.  If not see
   <http://www.gnu.org/licenses/>.  */

/* CTF Declaration Stack

   In order to implement ctf_type_name(), we must convert a type graph back
   into a C type declaration.  Unfortunately, a type graph represents a storage
   class ordering of the type whereas a type declaration must obey the C rules
   for operator precedence, and the two orderings are frequently in conflict.
   For example, consider these CTF type graphs and their C declarations:

   CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER  : int (*)()
   CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER     : int (*)[]

   In each case, parentheses are used to raise operator * to higher lexical
   precedence, so the string form of the C declaration cannot be constructed by
   walking the type graph links and forming the string from left to right.

   The functions in this file build a set of stacks from the type graph nodes
   corresponding to the C operator precedence levels in the appropriate order.
   The code in ctf_type_name() can then iterate over the levels and nodes in
   lexical precedence order and construct the final C declaration string.  */

#include <ctf-impl.h>
#include <string.h>

void
ctf_decl_init (ctf_decl_t *cd)
{
  int i;

  memset (cd, 0, sizeof (ctf_decl_t));

  for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
    cd->cd_order[i] = CTF_PREC_BASE - 1;

  cd->cd_qualp = CTF_PREC_BASE;
  cd->cd_ordp = CTF_PREC_BASE;
}

void
ctf_decl_fini (ctf_decl_t *cd)
{
  ctf_decl_node_t *cdp, *ndp;
  int i;

  for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++)
    {
      for (cdp = ctf_list_next (&cd->cd_nodes[i]); cdp != NULL; cdp = ndp)
	{
	  ndp = ctf_list_next (cdp);
	  ctf_free (cdp);
	}
    }
}

void
ctf_decl_push (ctf_decl_t *cd, ctf_file_t *fp, ctf_id_t type)
{
  ctf_decl_node_t *cdp;
  ctf_decl_prec_t prec;
  uint32_t kind, n = 1;
  int is_qual = 0;

  const ctf_type_t *tp;
  ctf_arinfo_t ar;

  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
    {
      cd->cd_err = fp->ctf_errno;
      return;
    }

  switch (kind = LCTF_INFO_KIND (fp, tp->ctt_info))
    {
    case CTF_K_ARRAY:
      (void) ctf_array_info (fp, type, &ar);
      ctf_decl_push (cd, fp, ar.ctr_contents);
      n = ar.ctr_nelems;
      prec = CTF_PREC_ARRAY;
      break;

    case CTF_K_TYPEDEF:
      if (ctf_strptr (fp, tp->ctt_name)[0] == '\0')
	{
	  ctf_decl_push (cd, fp, tp->ctt_type);
	  return;
	}
      prec = CTF_PREC_BASE;
      break;

    case CTF_K_FUNCTION:
      ctf_decl_push (cd, fp, tp->ctt_type);
      prec = CTF_PREC_FUNCTION;
      break;

    case CTF_K_POINTER:
      ctf_decl_push (cd, fp, tp->ctt_type);
      prec = CTF_PREC_POINTER;
      break;

    case CTF_K_SLICE:
      ctf_decl_push (cd, fp, ctf_type_reference (fp, type));
      prec = CTF_PREC_BASE;
      break;

    case CTF_K_VOLATILE:
    case CTF_K_CONST:
    case CTF_K_RESTRICT:
      ctf_decl_push (cd, fp, tp->ctt_type);
      prec = cd->cd_qualp;
      is_qual++;
      break;

    default:
      prec = CTF_PREC_BASE;
    }

  if ((cdp = ctf_alloc (sizeof (ctf_decl_node_t))) == NULL)
    {
      cd->cd_err = EAGAIN;
      return;
    }

  cdp->cd_type = type;
  cdp->cd_kind = kind;
  cdp->cd_n = n;

  if (ctf_list_next (&cd->cd_nodes[prec]) == NULL)
    cd->cd_order[prec] = cd->cd_ordp++;

  /* Reset cd_qualp to the highest precedence level that we've seen so
     far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER).  */

  if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY)
    cd->cd_qualp = prec;

  /* C array declarators are ordered inside out so prepend them.  Also by
     convention qualifiers of base types precede the type specifier (e.g.
     const int vs. int const) even though the two forms are equivalent.  */

  if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE))
    ctf_list_prepend (&cd->cd_nodes[prec], cdp);
  else
    ctf_list_append (&cd->cd_nodes[prec], cdp);
}

_libctf_printflike_ (2, 3)
void ctf_decl_sprintf (ctf_decl_t *cd, const char *format, ...)
{
  va_list ap;
  char *str;
  int n;

  if (cd->cd_enomem)
    return;

  va_start (ap, format);
  n = vasprintf (&str, format, ap);
  va_end (ap);

  if (n > 0)
      cd->cd_buf = ctf_str_append (cd->cd_buf, str);

  /* Sticky error condition.  */
  if (n < 0)
    {
      free (cd->cd_buf);
      cd->cd_buf = NULL;
      cd->cd_enomem = 1;
    }

  free (str);
}

char *ctf_decl_buf (ctf_decl_t *cd)
{
  return cd->cd_buf;
}
