blob: b0c4d37a5955b00da6c84a807b8d5dbd048bfa2c [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* All Rights Reserved.
*/
#include "libxfs.h"
#include "command.h"
#include "type.h"
#include "faddr.h"
#include "fprint.h"
#include "field.h"
#include "io.h"
#include "print.h"
#include "bit.h"
#include "flist.h"
#include "strvec.h"
#include "output.h"
#include "sig.h"
#include "write.h"
static void print_allfields(const struct field *fields);
static int print_f(int argc, char **argv);
static void print_flist_1(struct flist *flist, char **pfx, int parentoff);
static void print_somefields(const struct field *fields, int argc,
char **argv);
static const cmdinfo_t print_cmd =
{ "print", "p", print_f, 0, -1, 0, N_("[value]..."),
N_("print field values"), NULL };
static void
print_allfields(
const field_t *fields)
{
flist_t *flist;
#ifdef DEBUG
int i;
#endif
flist = flist_make("");
flist->fld = fields;
#ifndef DEBUG
(void)flist_parse(fields, flist, iocur_top->data, 0);
#else
i = flist_parse(fields, flist, iocur_top->data, 0);
ASSERT(i == 1);
#endif
flist_print(flist);
print_flist(flist);
flist_free(flist);
}
static int
print_f(
int argc,
char **argv)
{
pfunc_t pf;
if (cur_typ == NULL) {
dbprintf(_("no current type\n"));
return 0;
}
pf = cur_typ->pfunc;
if (pf == NULL) {
dbprintf(_("no print function for type %s\n"), cur_typ->name);
return 0;
}
argc--;
argv++;
(*pf)(DB_READ, cur_typ->fields, argc, argv);
return 0;
}
void
print_flist(
flist_t *flist)
{
char **pfx;
pfx = new_strvec(0);
print_flist_1(flist, pfx, 0);
free_strvec(pfx);
}
static void
print_flist_1(
flist_t *flist,
char **ppfx,
int parentoff)
{
char buf[16];
const field_t *f;
const ftattr_t *fa;
flist_t *fl;
int low;
int count;
int neednl;
char **pfx;
for (fl = flist; fl && !seenint(); fl = fl->sibling) {
pfx = copy_strvec(ppfx);
if (fl->name[0])
add_strvec(&pfx, fl->name);
if (fl->flags & FL_OKLOW) {
add_strvec(&pfx, "[");
snprintf(buf, sizeof(buf), "%d", fl->low);
add_strvec(&pfx, buf);
if (fl->low != fl->high) {
add_strvec(&pfx, "-");
snprintf(buf, sizeof(buf), "%d", fl->high);
add_strvec(&pfx, buf);
}
add_strvec(&pfx, "]");
}
if (fl->child) {
if (fl->name[0])
add_strvec(&pfx, ".");
print_flist_1(fl->child, pfx, fl->offset);
} else {
f = fl->fld;
fa = &ftattrtab[f->ftyp];
ASSERT(fa->ftyp == f->ftyp);
print_strvec(pfx);
dbprintf(" = ");
if (fl->flags & FL_OKLOW)
low = fl->low;
else
low = 0;
count = fcount(f, iocur_top->data, parentoff);
if (fl->flags & FL_OKHIGH)
count = min(count, fl->high - low + 1);
if (fa->prfunc) {
int fsz;
int bitlen;
/* Don't read an array off the end of the buffer */
fsz = fsize(f, iocur_top->data, parentoff, 0);
bitlen = iocur_top->len * NBBY;
if ((f->flags & FLD_ARRAY) &&
fl->offset + (count * fsz) > bitlen) {
count = (bitlen - fl->offset) / fsz;
}
neednl = fa->prfunc(iocur_top->data, fl->offset,
count, fa->fmtstr, fsz, fa->arg, low,
(f->flags & FLD_ARRAY) != 0);
if (neednl)
dbprintf("\n");
} else if (fa->arg & FTARG_OKEMPTY) {
dbprintf(_("(empty)\n"));
} else {
dbprintf(_("Unrecognized metadata or type mismatch\n"));
}
}
free_strvec(pfx);
}
}
void
print_init(void)
{
add_command(&print_cmd);
}
void
print_sarray(
void *obj,
int bit,
int count,
int size,
int base,
int array,
const field_t *flds,
int skipnms)
{
int bitoff;
const field_t *f;
const ftattr_t *fa;
int first;
int i;
ASSERT(bitoffs(bit) == 0);
if (skipnms == 0) {
for (f = flds, first = 1; f->name; f++) {
if (f->flags & FLD_SKIPALL)
continue;
dbprintf("%c%s", first ? '[' : ',', f->name);
first = 0;
}
dbprintf("] ");
}
for (i = 0, bitoff = bit;
i < count && !seenint();
i++, bitoff += size) {
if (array)
dbprintf("\n%d:", i + base);
for (f = flds, first = 1; f->name; f++) {
if (f->flags & FLD_SKIPALL)
continue;
fa = &ftattrtab[f->ftyp];
ASSERT(fa->ftyp == f->ftyp);
dbprintf("%c", first ? '[' : ',');
first = 0;
if (fa->prfunc)
fa->prfunc(obj,
bitoff +
bitoffset(f, obj, bitoff, i + base),
fcount(f, obj, bitoff), fa->fmtstr,
fsize(f, obj, bitoff, i + base),
fa->arg, (f->flags & FLD_ABASE1) != 0,
f->flags & FLD_ARRAY);
else {
ASSERT(fa->arg & FTARG_OKEMPTY);
dbprintf(_("(empty)"));
}
}
dbprintf("]");
if (i < count - 1)
dbprintf(" ");
}
}
static void
print_somefields(
const field_t *fields,
int argc,
char **argv)
{
const ftattr_t *fa;
flist_t *fl;
flist_t *lfl;
flist_t *nfl;
fl = lfl = NULL;
while (argc > 0) {
nfl = flist_scan(*argv);
if (!nfl) {
if (fl)
flist_free(fl);
return;
}
if (lfl)
lfl->sibling = nfl;
else
fl = nfl;
lfl = nfl;
argc--;
argv++;
}
if (fields->name[0] == '\0') {
fa = &ftattrtab[fields->ftyp];
ASSERT(fa->ftyp == fields->ftyp);
fields = fa->subfld;
}
if (!flist_parse(fields, fl, iocur_top->data, 0)) {
flist_free(fl);
return;
}
flist_print(fl);
print_flist(fl);
flist_free(fl);
}
/*ARGSUSED*/
void
print_string(
const field_t *fields,
int argc,
char **argv)
{
char *cp;
if (argc != 0)
dbprintf(_("no arguments allowed\n"));
dbprintf("\"");
for (cp = iocur_top->data;
cp < (char *)iocur_top->data + iocur_top->len && *cp &&
!seenint();
cp++)
dbprintf("%c", *cp);
dbprintf("\"\n");
}
void
print_struct(
const field_t *fields,
int argc,
char **argv)
{
if (argc == 0)
print_allfields(fields);
else
print_somefields(fields, argc, argv);
}