1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
TP-Link_Archer-XR500v/EN7526G_3.18Kernel_SDK/apps/public/linux-atm/qgen/second.c
2024-07-22 01:58:46 -03:00

330 lines
8.3 KiB
C
Executable File

/* second.c - Phase II, table generation */
/* Written 1995-2000 by Werner Almesberger, EPFL-LRC/ICA */
#include <stdlib.h>
#include "common.h"
#include "qgen.h"
#include "file.h"
int sym_tables = 0,symbols = 0;
static int unique;
static void dump_required(FIELD *start,FIELD *leader,int group)
{
FIELD *walk;
for (walk = start; walk; walk = walk->next) {
if (walk->structure) {
dump_required(walk->my_block,leader,group);
continue;
}
if (walk->brk) break;
if (!walk->value) {
if (!leader->has_required) {
to_c("static int required_%d[] = {\n",group);
leader->has_required = 1;
}
to_c(" %d, /* %s */\n",walk->field,walk->id);
}
else if (walk->value->type == vt_length)
dump_required(walk->value->block,leader,group);
}
if (leader == start && leader && leader->has_required)
to_c(" -1\n};\n\n");
}
static void find_required(FIELD *start)
{
FIELD *walk;
TAG *scan;
for (walk = start; walk; walk = walk->next) {
if (walk->structure) {
find_required(walk->my_block);
continue;
}
if (walk->value)
switch (walk->value->type) {
case vt_id:
break;
case vt_case:
case vt_multi:
for (scan = walk->value->tags; scan; scan = scan->next)
if (scan->block) {
scan->block->has_required = 0;
dump_required(scan->block,scan->block,scan->group);
find_required(scan->block);
}
break;
case vt_length:
find_required(walk->value->block);
break;
default:
abort();
}
}
}
static void groups(FIELD *start,int group)
{
FIELD *walk;
TAG *scan;
for (walk = start; walk; walk = walk->next) {
if (walk->structure) {
groups(walk->my_block,group);
continue;
}
if (walk->value)
switch (walk->value->type) {
case vt_id:
break;
case vt_case:
case vt_multi:
for (scan = walk->value->tags; scan; scan = scan->next) {
int start_field,length,offset;
if (scan->block && scan->block->structure &&
scan->block->structure->instances < 0) {
start_field = scan->block->structure->first_field;
length = scan->block->structure->fields;
offset = scan->block->my_block->field-
scan->block->structure->first_field;
}
else {
start_field = -1;
length = offset = 0;
}
if (scan->id) to_test(" \"%s\",\n",scan->id);
if (scan->block && scan->block->has_required)
if (scan->block->id)
to_c(" { %d, required_%d, %d, %d, %d }, "
"/* %s */\n",group,scan->group,start_field,
length,offset,scan->block->id);
else to_c(" { %d, required_%d, %d, %d, %d },\n",
group,scan->group,start_field,length,offset);
else to_c(" { %d, NULL, %d, %d, %d },\n",group,
start_field,length,offset);
groups(scan->block,scan->group);
}
break;
case vt_length:
groups(walk->value->block,group);
break;
default:
abort();
}
}
}
static void values(FIELD *start)
{
FIELD *walk;
TAG *scan;
VALUE_LIST *tag;
for (walk = start; walk; walk = walk->next) {
if (walk->structure) {
values(walk->my_block);
}
if (walk->value)
switch (walk->value->type) {
case vt_id:
break;
case vt_case:
if (*walk->id != '_') {
to_c("static int values_%d[] = { /* %s */\n",
walk->field,walk->id);
for (scan = walk->value->tags; scan; scan = scan->next)
{
to_c(" %s, %d,\n",scan->value,scan->group);
for (tag = scan->more; tag; tag = tag->next)
to_c(" %s, %d,\n",tag->value,scan->group);
if (scan->deflt) to_c(" -2, %d,\n",scan->group);
/* could also skip while entry, but maybe we'll
want to use the tags later */
}
to_c(" -1, -1\n};\n\n");
}
/* fall through */
case vt_multi:
for (scan = walk->value->tags; scan; scan = scan->next)
values(scan->block);
break;
case vt_length:
values(walk->value->block);
break;
default:
abort();
}
}
}
static void fields(FIELD *start,int group)
{
FIELD *walk;
TAG *scan;
VALUE_LIST *tag;
for (walk = start; walk; walk = walk->next) {
if (walk->structure) {
fields(walk->my_block,group);
continue;
}
if (*walk->id != '_') {
if (walk->value && walk->value->type == vt_case)
to_c(" { %d, %d, %d, values_%d, %d }, /* %s */\n",group,
walk->pos,walk->size,walk->field,walk->var_len,walk->id);
else to_c(" { %d, %d, %d, NULL, %d }, /* %s */\n",group,
walk->pos,walk->size,walk->var_len,walk->id);
}
if (walk->value)
switch (walk->value->type) {
case vt_id:
break;
case vt_case:
case vt_multi:
for (scan = walk->value->tags; scan; scan = scan->next)
fields(scan->block,scan->group);
to_test("static int unique_%d[] = { /* %s */\n",unique++,
walk->id);
for (scan = walk->value->tags; scan; scan = scan->next) {
to_test(" %s,\n",scan->value);
for (tag = scan->more; tag; tag = tag->next)
to_test(" %s,\n",tag->value);
}
to_test(" -1\n};\n\n");
break;
case vt_length:
fields(walk->value->block,group);
break;
default:
abort();
}
}
}
static void symbolic_names(FIELD *start)
{
FIELD *walk;
NAME *name;
TAG *scan;
VALUE_LIST *tag;
for (walk = start; walk; walk = walk->next) {
if (walk->structure) {
symbolic_names(walk->my_block);
continue;
}
if (walk->name_list ? walk->name_list->id == -1 : !!walk->value) {
if (walk->name_list) {
to_dump("static SYM_NAME dump_sym_%d[] = { /* %s */\n",
walk->seq,walk->name_list->list_name);
sym_tables++;
walk->name_list->id = walk->seq;
for (name = walk->name_list->list; name; name = name->next) {
to_dump(" { %s, \"%s\" },\n",name->value,name->name);
symbols++;
}
}
else {
to_dump("static SYM_NAME dump_sym_%d[] = {\n",walk->seq);
sym_tables++;
switch (walk->value->type) {
case vt_id:
to_dump(" { %s, \"%s\" },\n",walk->value->id,
walk->value->id);
symbols++;
break;
case vt_case:
case vt_multi:
for (scan = walk->value->tags; scan; scan = scan->next)
{
to_dump(" { %s, \"%s\" },\n",scan->value,
scan->value);
symbols++;
for (tag = scan->more; tag; tag = tag->next) {
to_dump(" { %s, \"%s\" },\n",tag->value,
tag->value);
symbols++;
}
}
break;
case vt_length:
break;
default:
abort();
}
}
to_dump(" { 0, NULL }\n};\n\n");
}
if (walk->value)
switch (walk->value->type) {
case vt_id:
break;
case vt_case:
case vt_multi:
for (scan = walk->value->tags; scan; scan = scan->next)
symbolic_names(scan->block);
break;
case vt_length:
symbolic_names(walk->value->block);
break;
default:
abort();
}
}
}
void second(FIELD *def)
{
int i;
def->has_required = 0;
to_c("\n/*\n");
to_c(" * If a group contains required fields, these are listed in the\n");
to_c(" * following arrays. Each list ends with -1. The variable names\n");
to_c(" * end with the group number.\n */\n\n");
dump_required(def,def,0);
find_required(def);
to_c("\n/*\n * Various information about groups.\n */\n\n");
to_c("typedef struct {\n int parent;\n int *required;\n");
to_c(" int start;\n int length;\n int offset;\n} GROUP;\n\n");
to_c("static GROUP groups[] = {\n");
if (def->has_required) to_c(" { -1, required_0 },\n");
else to_c(" { -1, NULL },\n");
to_test("static const char *groups[] = {\n");
groups(def,0);
to_test(" NULL\n};\n\n");
to_c("};\n\n\n");
to_c("/*\n * Named case selectors only have a limited set of valid\n");
to_c(" * values. They are listed in the following arrays, each followed\n");
to_c(" * by the number of the group it enables.\n */\n\n");
values(def);
to_c("\n/*\n * Various information about fields.\n */\n\n");
to_c("typedef struct {\n int parent;\n int pos,size;\n");
to_c(" int *values;\n int actual;\n} FIELD;\n\n");
to_c("static FIELD fields[] = {\n");
fields(def,0);
to_c("};\n\n");
to_test("static int *unique[] = {\n");
for (i = 0; i < unique; i++) to_test(" unique_%d,\n",i);
to_test(" NULL\n};\n\n");
if (dump) {
to_dump("typedef struct {\n unsigned long value;\n");
to_dump(" const char *name;\n} SYM_NAME;\n\n");
symbolic_names(def);
}
}