1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
/*
* ext_dump.c - Helper functions for dumping to the external interface
*
* Written 2001,2002 by Werner Almsberger
* Copyright 2001,2002 Bivio Networks, Network Robots
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "util.h"
#include "data.h"
#include "param.h"
#include "tree.h"
#include "ext.h"
/*
* Known restriction: we callback for prm_pragma, although prm_pragma is
* supposed to be ignored. This may yield bad surprises for functions that
* assume that they'll only be called for the parameters they explicitly list
* as exceptions.
*/
static void print_pragma(FILE *file,PARAM *params)
{
const DATA_LIST *pragma;
if (!prm_present(params,&prm_pragma)) return;
fprintf(file," pragma");
for (pragma = prm_data(params,&prm_pragma).u.list; pragma;
pragma = pragma->next)
fprintf(file," %s",pragma->ref->u.string);
}
static const PARAM_DSC **combine_tables(const PARAM_DSC **a,const PARAM_DSC **b)
{
const PARAM_DSC **walk,**new,**p;
int n;
n = 0;
if (a)
for (walk = a; *walk; walk++) n++;
if (b)
for (walk = b; *walk; walk++) n++;
new = p = alloc(sizeof(PARAM_DSC *)*(n+1));
while ((a && *a) || (b && *b)) {
if (a && *a && (!b || !*b || strcmp((*a)->id,(*b)->id) < 0))
*p++ = *a++;
else *p++ = *b++;
}
*p = NULL;
return new;
}
/*
* We use the indirection via class_fn to implement pseudo_prm_parent and
* pseudo_prm_qdisc transparently.
*/
static PARAM_DSC pseudo_prm_parent ={
.id = "parent",
};
static PARAM_DSC pseudo_prm_qdisc = {
.id = "qdisc",
};
struct class_fn_args {
void (*fn)(FILE *file,const PARAM_DSC *param,const CLASS *class);
const CLASS *class;
};
static void class_fn(FILE *file,const PARAM_DSC *param,void *arg)
{
struct class_fn_args *class_fn_args = arg;
const CLASS *class = class_fn_args->class;
if (param == &pseudo_prm_parent && class->parent.class) {
fprintf(file," parent %u",(unsigned) class->parent.class->number);
return;
}
if (param == &pseudo_prm_qdisc && class->qdisc) {
fprintf(file," qdisc %u",(unsigned) class->qdisc->number);
return;
}
if (class_fn_args->fn) class_fn_args->fn(file,param,class);
}
void ext_dump_class(FILE *file,const CLASS *class,const PARAM_DSC **special,
void (*fn)(FILE *file,const PARAM_DSC *param,const CLASS *class))
{
const PARAM_DSC *default_special[] = {
&pseudo_prm_parent,
&pseudo_prm_qdisc,
&prm_pragma,
NULL
};
const QDISC *qdisc = class->parent.qdisc;
const PARAM_DSC **table;
struct class_fn_args class_fn_args;
fprintf(file,"class %u =",(unsigned) class->number);
table = combine_tables(default_special,special);
class_fn_args.fn = fn;
class_fn_args.class = class;
param_print(file,qdisc->dsc->qdisc_param,qdisc->dsc->class_param,
qdisc->dsc->class_param,table,class_fn,&class_fn_args);
free(table);
print_pragma(file,class->params);
fprintf(file,"\n");
}
void do_ext_dump_qdisc(FILE *file,const QDISC *qdisc,const QDISC_DSC *dsc,
const PARAM_DSC **special,void (*fn)(FILE *file,const PARAM_DSC *param,
const QDISC *qdisc))
{
const PARAM_DSC *default_special[] = {
&prm_pragma,
NULL
};
const PARAM_DSC **table;
fprintf(file,"qdisc %u = %s",(unsigned) qdisc->number,dsc->name);
table = combine_tables(default_special,special);
param_print(file,dsc->qdisc_param,dsc->class_param,dsc->qdisc_param,table,
(void (*)(FILE *file,const PARAM_DSC *param,void *user)) fn,
(void *) qdisc);
free(table);
print_pragma(file,qdisc->params);
fprintf(file,"\n");
}
void ext_dump_qdisc(FILE *file,const QDISC *qdisc,const PARAM_DSC **special,
void (*fn)(FILE *file,const PARAM_DSC *param,const QDISC *qdisc))
{
do_ext_dump_qdisc(file,qdisc,qdisc->dsc,special,fn);
}
|