/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
* or http://www.opensolaris.org/os/licensing.
* 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) 1994, by Sun Microsytems, Inc.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef DEBUG
#define NDEBUG 1
#endif
#include "tnf_trace.h"
#include "tnf_types.h"
#include "tnf_args.h"
#include <string.h>
#include <assert.h>
/*
* tnf_probe_get_num_args: returns the number of arguments at probe site
* probe_p. This includes the first 2 args (tag and time delta) in the return
* value.
*/
int
tnf_probe_get_num_args(tnf_probe_control_t *probe_p)
{
int count = 0;
tnf_tag_data_t ***tag_p;
tag_p = probe_p->slot_types;
while (*tag_p) {
count++;
tag_p++;
}
return (count);
}
/*
* tnf_probe_get_arg_indexed: returns a pointer into the buffer where
* argument i is stored. Returns NULL on error. Argument numbering is
* zero based i.e. to get the 3rd argument, the input value should be 2.
*/
/* ALIGN_ROUNDUP: y has to be one less than a power of 2 eg. 3, 7, 15, etc. */
#define ALIGN_ROUNDUP(x, y) (((x) + (y)) & ~(y))
void *
tnf_probe_get_arg_indexed(tnf_probe_control_t *probe_p, int index, void *buffer)
{
int count = 0;
size_t align;
size_t elem_size = 0;
tnf_tag_data_t ***tag_ppp;
tnf_tag_data_t *tag_p;
unsigned long offset = 0;
tag_ppp = probe_p->slot_types;
if (!tag_ppp)
return (NULL);
while (count <= index) {
/* error checking. REMIND: Do we need it ? */
if (!(*tag_ppp))
return (NULL);
tag_p = **tag_ppp;
if (!tag_p)
return (NULL);
offset = offset + elem_size;
align = tag_p->tag_align - 1;
assert(align != 0);
offset = ALIGN_ROUNDUP(offset, align);
/* get size of current element */
elem_size = tag_p->tag_ref_size;
tag_ppp++;
count++;
}
return ((void *)((char *)buffer + offset));
}
/*
* tnf_probe_get_type_indexed: returns the type of the ith argument.
* returns TNF_UNKNOWN on error. Argument numbering is zero based
* i.e. to get the 3rd argument, the input value should be 2.
*/
tnf_arg_kind_t
tnf_probe_get_type_indexed(tnf_probe_control_t *probe_p, int index)
{
tnf_tag_data_t ***tag_ppp;
tnf_tag_data_t *tag_p;
tag_ppp = probe_p->slot_types + index;
if (!tag_ppp)
return (TNF_UNKNOWN);
if (!(*tag_ppp))
return (TNF_UNKNOWN);
tag_p = **tag_ppp;
if (!tag_p)
return (TNF_UNKNOWN);
return (tag_p->tag_kind);
}
/*
* tnf_probe_get_value: returns the start of the value string that is
* associated with the input attribute. The number of characters in the
* value is also returned as the final argument. The size return value
* indicates the length of the string that is valid. Returns NULL on no
* match or error.
*/
const char *
tnf_probe_get_value(tnf_probe_control_t *probe_p, char *attribute,
ulong_t *size)
{
const char *attr_start, *attr_end, *str_end;
const char *val_start;
int separator;
uint_t attr_len;
size_t input_len;
input_len = strlen(attribute);
attr_start = probe_p->attrs;
assert(attr_start);
str_end = attr_start + strlen(attr_start);
separator = ATTR_SEPARATOR;
while (attr_start < str_end) {
attr_end = strchr(attr_start, separator);
if (!attr_end) {
/* last attribute */
attr_end = str_end;
}
/* LINTED - result <= string length */
attr_len = attr_end - attr_start;
/* skip over leading white space */
while (*attr_start && ((*attr_start == ' ') ||
(*attr_start == '\t'))) {
attr_start++;
}
/* search for match on attribute */
if (strncmp(attr_start, attribute, input_len) == 0) {
/* make sure next char is a space or semicolon */
val_start = attr_start + input_len;
if (*val_start == ATTR_SEPARATOR) {
*size = 0;
return (val_start);
} else if (*val_start == VAL_SEPARATOR) {
/* +1 for val separator */
*size = attr_len - (input_len + 1);
return (val_start + 1);
}
/* a false match - just continue */
}
/* skip to next attribute */
attr_start = attr_end + 1;
}
/* no match */
return (NULL);
}
/* used by in-process argument reader */
char *
tnf_probe_get_chars(void *slot)
{
tnf_reference_t ref;
char *str_p;
ref = *((tnf_reference_t *)slot);
assert(TNF_REF32_IS_FWD(ref));
str_p = (char *)slot + TNF_REF32_VALUE(ref);
str_p += ARRAY_HDR_SIZE;
return (str_p);
}