/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
*/
#include <sys/sysmacros.h>
#include <strings.h>
#include <stdlib.h>
#include <alloca.h>
#include <assert.h>
#include <errno.h>
#include <ctype.h>
#include <sys/procfs_isa.h>
#include <limits.h>
#include <dt_ident.h>
#include <dt_parser.h>
#include <dt_provider.h>
#include <dt_strtab.h>
#include <dt_impl.h>
/*
* Common code for cooking an identifier that uses a typed signature list (we
* use this for associative arrays and functions). If the argument list is
* of the same length and types, then return the return type. Otherwise
* print an appropriate compiler error message and abort the compile.
*/
static void
{
if (isp->dis_varargs >= 0) {
} else if (isp->dis_optargs >= 0) {
} else {
}
if (mismatch) {
}
else
if (!compat) {
"%s%s%s %s #%d is incompatible with "
"prototype:\n\tprototype: %s\n\t%9s: %s\n",
sizeof (n1)),
}
}
}
/*
* Cook an associative array identifier. If this is the first time we are
* cooking this array, create its signature based on the argument list.
* Otherwise validate the argument list against the existing signature.
*/
static void
{
char n[DT_TYPE_NAMELEN];
int i;
isp->dis_auxinfo = 0;
}
/*
* If this identifier has not been explicitly declared earlier,
* set the identifier's base type to be our special type <DYN>.
* If this ident is an aggregation, it will remain as is. If
* this ident is an associative array, it will be reassigned
* based on the result type of the first assignment statement.
*/
}
"used as %s index: key #%d\n",
dt_node_type_name(args, n, sizeof (n)),
}
}
if (argc != 0)
} else {
}
}
/*
* Cook a function call. If this is the first time we are cooking this
* identifier, create its type signature based on predefined prototype stored
* in di_iarg. We then validate the argument list against this signature.
*/
static void
{
int i = 0;
}
i++;
break;
}
}
/*
* We first allocate a new ident signature structure with the
* appropriate number of argument entries, and then look up
*/
isp->dis_auxinfo = 0;
}
}
} else {
}
/*
* For each comma-delimited parameter in the prototype string,
* we look up the corresponding type and store its CTF data in
* the corresponding location in dis_args[]. We also recognize
* the special type string "@" to indicate that the specified
* parameter may be a D expression of *any* type (represented
* as a dis_args[] element with ctfp = NULL, type == CTF_ERR).
* If a varargs "..." is present, we record the argument index
* in dis_varargs for the benefit of dt_idcook_sign(), above.
* If the type of an argument is enclosed in square brackets
* (e.g. "[int]"), the argument is considered optional: the
* argument may be absent, but if it is present, it must be of
* the specified type. Note that varargs may not optional,
* optional arguments may not follow varargs, and non-optional
* arguments may not follow optional arguments.
*/
p1++; /* skip leading whitespace */
else
*p2++ = '\0';
if (*p1 == '.')
isp->dis_varargs = i;
continue;
}
"may not follow variable arg#%d\n",
}
isp->dis_optargs = i;
p1++;
"follow optional arg#%d\n", i + 1,
}
}
}
}
}
/*
* Cook a reference to the dynamically typed args[] array. We verify that the
* reference is using a single integer constant, and then construct a new ident
* representing the appropriate type or translation specifically for this node.
*/
static void
{
if (argc != 1) {
}
"prototype:\n\tprototype: %s\n\t argument: %s\n",
}
}
"%s[ ] may not be referenced because probe description %s "
}
}
/*
* Look up the native and translated argument types for the probe.
* If no translation is needed, these will be the same underlying node.
* If translation is needed, look up the appropriate translator. Once
* we have the appropriate node, create a new dt_ident_t for this node,
* assign it the appropriate attributes, and set the type of 'dnp'.
*/
}
}
if (dt_xlator_dynamic(dxp))
/*
* Propagate relevant members from the translator's internal
* dt_ident_t. This code must be kept in sync with the state
* that is initialized for idents in dt_xlator_create().
*/
B_FALSE);
} else {
}
}
static void
{
char n[DT_TYPE_NAMELEN];
if (argc != 1) {
}
"prototype:\n\tprototype: %s\n\t argument: %s\n",
}
}
}
}
/*ARGSUSED*/
static void
{
"failed to resolve type %s for identifier %s: %s\n",
}
}
}
/*ARGSUSED*/
static void
{
}
static void
{
else
}
static void
{
}
static void
{
}
static void
{
}
else
}
/*ARGSUSED*/
static void
{
/* do nothing */
}
static void
{
}
static size_t
{
}
/*ARGSUSED*/
static size_t
{
return (0);
}
};
};
};
};
};
};
};
};
static void
{
}
}
{
size = sizeof (dt_idhash_t) +
return (NULL);
return (dhp);
}
/*
* Destroy an entire identifier hash. This must be done using two passes with
* an inlined version of dt_ident_destroy() to avoid referencing freed memory.
* In the first pass di_dtor() is called for all identifiers; then the second
* pass frees the actual dt_ident_t's. These must be done separately because
* a di_dtor() may operate on data structures which contain references to other
* identifiers inside of this hash itself (e.g. a global inline definition
* which contains a parse tree that refers to another global variable).
*/
void
{
ulong_t i;
}
}
}
}
}
void
{
ulong_t i;
/*
* Right now we're hard coding which types need to be
* reset, but ideally this would be done dynamically.
*/
}
}
}
{
return (idp);
}
return (NULL);
}
int
{
return (-1); /* no more id's are free to allocate */
return (0);
}
{
}
const char *
{
}
{
ulong_t h;
return (NULL);
return (idp);
}
void
{
ulong_t h;
}
void
{
break;
else
}
}
static int
{
else
}
int
{
ulong_t i, j, n;
int rv;
}
for (i = 0; i < n; i++) {
return (rv);
}
return (0);
}
{
return (idp);
}
return (NULL);
}
void
{
}
void
{
}
{
char *s = NULL;
free(s);
return (NULL);
}
return (idp);
}
/*
* Destroy an individual identifier. This code must be kept in sync with the
* dt_idhash_destroy() function below, which separates out the call to di_dtor.
*/
void
{
}
void
{
}
{
int argc = 0;
argc++;
}
void
{
}
{
break; /* can't resolve any further yet */
case DT_NODE_VAR:
case DT_NODE_SYM:
case DT_NODE_FUNC:
case DT_NODE_AGG:
case DT_NODE_INLINE:
case DT_NODE_PROBE:
continue;
}
if (dt_node_is_dynamic(dnp))
else
break;
}
return (idp);
}
{
}
int
{
}
const char *
{
switch (kind) {
case DT_IDENT_ARRAY: return ("associative array");
case DT_IDENT_SCALAR: return ("scalar");
case DT_IDENT_PTR: return ("pointer");
case DT_IDENT_FUNC: return ("function");
case DT_IDENT_AGG: return ("aggregation");
case DT_IDENT_AGGFUNC: return ("aggregating function");
case DT_IDENT_ACTFUNC: return ("tracing function");
case DT_IDENT_XLSOU: return ("translated data");
case DT_IDENT_XLPTR: return ("pointer to translated data");
case DT_IDENT_SYMBOL: return ("external symbol reference");
case DT_IDENT_ENUM: return ("enumerator");
case DT_IDENT_PRAGAT: return ("#pragma attributes");
case DT_IDENT_PRAGBN: return ("#pragma binding");
case DT_IDENT_PROBE: return ("probe definition");
default: return ("<?>");
}
}