/*
|
* Copyright (C) 2016 The Android Open Source Project
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
#include <getopt.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <unistd.h>
|
|
/*
|
* The parameters to generate testing DTS
|
* /dts-v1/ /plugin/; <- header and plugin
|
* /{
|
* level0 { <- depth
|
* level1 {
|
* ...
|
* node0: node0 { <- node
|
* unused0 {} <- unused
|
* unused1 {}
|
* ...
|
* status="disabled";
|
* }
|
* ...
|
* };
|
* };
|
* };
|
*
|
* &node0 { <- append
|
* new_prop="foo";
|
* }
|
* ...
|
*
|
* &node0 { <- override
|
* status="okay";
|
* }
|
* ...
|
*/
|
|
static const char short_options[] = "Hpd:u:n:a:w:o:";
|
static struct option long_options[] = {
|
{ "no-header", no_argument, NULL, 'H' },
|
{ "plugin", no_argument, NULL, 'p' },
|
{ "depth", required_argument, NULL, 'd' },
|
{ "unused", required_argument, NULL, 'u' },
|
{ "node", required_argument, NULL, 'n' },
|
{ "append", required_argument, NULL, 'a' },
|
{ "override", required_argument, NULL, 'w' },
|
{ "output", required_argument, NULL, 'o' },
|
{ 0, 0, NULL, 0 }
|
};
|
|
struct gen_params {
|
int no_header; /* Doesn't add header */
|
int plugin; /* Add /plugin/ in header */
|
int depth; /* the depth of a node, 0 means generate on root node */
|
int unused_num; /* unused child nodes per node */
|
int node_num; /* the number to generate nodes */
|
int append_num; /* the number to generate appending references */
|
int override_num; /* the number to generate overriding references */
|
};
|
|
|
static void output_header(FILE *fp, int is_plugin) {
|
fprintf(fp, "/dts-v1/;\n");
|
if (is_plugin) {
|
fprintf(fp, "/plugin/;\n");
|
}
|
fprintf(fp, "\n");
|
}
|
|
static void output_root_begin(FILE *fp, int depth) {
|
fprintf(fp, "/ {\n");
|
|
int i;
|
for (i = 0; i < depth; i++) {
|
fprintf(fp, "level%d {\n", i);
|
}
|
}
|
|
static void output_root_end(FILE *fp, int depth) {
|
int i;
|
for (i = 0; i < depth; i++) {
|
fprintf(fp, "};\n");
|
}
|
|
fprintf(fp, "};\n\n");
|
}
|
|
static void output_unused_nodes(FILE *fp, int count) {
|
int i;
|
for (i = 0; i < count; i++) {
|
fprintf(fp, "unused%d {};\n", i);
|
}
|
}
|
|
static void output_prop_str(FILE *fp, const char *prop, const char *value) {
|
/* TODO: should escape value */
|
fprintf(fp, "%s=\"%s\";\n", prop, value);
|
}
|
|
static void output_nodes(FILE *fp, int count, const char *prop, const char *value) {
|
int i;
|
for (i = 0; i < count; i++) {
|
fprintf(fp, "node%d: node%d {\n", i, i);
|
output_prop_str(fp, prop, value);
|
fprintf(fp, "};\n\n");
|
}
|
}
|
|
static void output_ref_nodes(FILE *fp, int start_id, int count,
|
const char *prop, const char *value) {
|
int i;
|
for (i = start_id; i < start_id + count; i++) {
|
fprintf(fp, "&node%d {\n", i);
|
output_prop_str(fp, prop, value);
|
fprintf(fp, "};\n\n");
|
}
|
}
|
|
static int gen_dts(FILE *fp, const struct gen_params *params) {
|
if (!params->no_header) {
|
output_header(fp, params->plugin);
|
}
|
|
if (params->node_num > 0) {
|
output_root_begin(fp, params->depth);
|
output_unused_nodes(fp, params->unused_num);
|
output_nodes(fp, params->node_num, "status", "disabled");
|
output_root_end(fp, params->depth);
|
}
|
|
int start_id = 0;
|
output_ref_nodes(fp, start_id, params->append_num, "new_prop", "bar");
|
start_id += params->append_num;
|
output_ref_nodes(fp, start_id, params->override_num, "status", "okay");
|
|
return 0;
|
}
|
|
int main(int argc, char *argv[]) {
|
const char *filename = NULL;
|
struct gen_params params;
|
memset(¶ms, 0, sizeof(struct gen_params));
|
|
while (1) {
|
int option_index = 0;
|
int c = getopt_long(argc, argv, short_options, long_options, &option_index);
|
if (c == -1) {
|
break;
|
}
|
switch (c) {
|
case 'H':
|
params.no_header = 1;
|
break;
|
case 'p':
|
params.plugin = 1;
|
break;
|
case 'd':
|
params.depth = atoi(optarg);
|
break;
|
case 'u':
|
params.unused_num = atoi(optarg);
|
break;
|
case 'n':
|
params.node_num = atoi(optarg);
|
break;
|
case 'a':
|
params.append_num = atoi(optarg);
|
break;
|
case 'w':
|
params.override_num = atoi(optarg);
|
break;
|
case 'o':
|
filename = optarg;
|
break;
|
case '?':
|
break;
|
}
|
}
|
|
FILE *fp = NULL;
|
if (filename) {
|
fp = fopen(filename, "wt");
|
if (fp == NULL) {
|
fprintf(stderr, "Can not create file: %s\n", filename);
|
return -1;
|
}
|
}
|
|
gen_dts(fp ? fp : stdout, ¶ms);
|
|
if (fp) {
|
fclose(fp);
|
}
|
|
return 0;
|
}
|