/*
* 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;
}