1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <getopt.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 /*
24 * The parameters to generate testing DTS
25 * /dts-v1/ /plugin/; <- header and plugin
26 * /{
27 * level0 { <- depth
28 * level1 {
29 * ...
30 * node0: node0 { <- node
31 * unused0 {} <- unused
32 * unused1 {}
33 * ...
34 * status="disabled";
35 * }
36 * ...
37 * };
38 * };
39 * };
40 *
41 * &node0 { <- append
42 * new_prop="foo";
43 * }
44 * ...
45 *
46 * &node0 { <- override
47 * status="okay";
48 * }
49 * ...
50 */
51
52 static const char short_options[] = "Hpd:u:n:a:w:o:";
53 static struct option long_options[] = {
54 { "no-header", no_argument, NULL, 'H' },
55 { "plugin", no_argument, NULL, 'p' },
56 { "depth", required_argument, NULL, 'd' },
57 { "unused", required_argument, NULL, 'u' },
58 { "node", required_argument, NULL, 'n' },
59 { "append", required_argument, NULL, 'a' },
60 { "override", required_argument, NULL, 'w' },
61 { "output", required_argument, NULL, 'o' },
62 { 0, 0, NULL, 0 }
63 };
64
65 struct gen_params {
66 int no_header; /* Doesn't add header */
67 int plugin; /* Add /plugin/ in header */
68 int depth; /* the depth of a node, 0 means generate on root node */
69 int unused_num; /* unused child nodes per node */
70 int node_num; /* the number to generate nodes */
71 int append_num; /* the number to generate appending references */
72 int override_num; /* the number to generate overriding references */
73 };
74
75
output_header(FILE * fp,int is_plugin)76 static void output_header(FILE *fp, int is_plugin) {
77 fprintf(fp, "/dts-v1/;\n");
78 if (is_plugin) {
79 fprintf(fp, "/plugin/;\n");
80 }
81 fprintf(fp, "\n");
82 }
83
output_root_begin(FILE * fp,int depth)84 static void output_root_begin(FILE *fp, int depth) {
85 fprintf(fp, "/ {\n");
86
87 int i;
88 for (i = 0; i < depth; i++) {
89 fprintf(fp, "level%d {\n", i);
90 }
91 }
92
output_root_end(FILE * fp,int depth)93 static void output_root_end(FILE *fp, int depth) {
94 int i;
95 for (i = 0; i < depth; i++) {
96 fprintf(fp, "};\n");
97 }
98
99 fprintf(fp, "};\n\n");
100 }
101
output_unused_nodes(FILE * fp,int count)102 static void output_unused_nodes(FILE *fp, int count) {
103 int i;
104 for (i = 0; i < count; i++) {
105 fprintf(fp, "unused%d {};\n", i);
106 }
107 }
108
output_prop_str(FILE * fp,const char * prop,const char * value)109 static void output_prop_str(FILE *fp, const char *prop, const char *value) {
110 /* TODO: should escape value */
111 fprintf(fp, "%s=\"%s\";\n", prop, value);
112 }
113
output_nodes(FILE * fp,int count,const char * prop,const char * value)114 static void output_nodes(FILE *fp, int count, const char *prop, const char *value) {
115 int i;
116 for (i = 0; i < count; i++) {
117 fprintf(fp, "node%d: node%d {\n", i, i);
118 output_prop_str(fp, prop, value);
119 fprintf(fp, "};\n\n");
120 }
121 }
122
output_ref_nodes(FILE * fp,int start_id,int count,const char * prop,const char * value)123 static void output_ref_nodes(FILE *fp, int start_id, int count,
124 const char *prop, const char *value) {
125 int i;
126 for (i = start_id; i < start_id + count; i++) {
127 fprintf(fp, "&node%d {\n", i);
128 output_prop_str(fp, prop, value);
129 fprintf(fp, "};\n\n");
130 }
131 }
132
gen_dts(FILE * fp,const struct gen_params * params)133 static int gen_dts(FILE *fp, const struct gen_params *params) {
134 if (!params->no_header) {
135 output_header(fp, params->plugin);
136 }
137
138 if (params->node_num > 0) {
139 output_root_begin(fp, params->depth);
140 output_unused_nodes(fp, params->unused_num);
141 output_nodes(fp, params->node_num, "status", "disabled");
142 output_root_end(fp, params->depth);
143 }
144
145 int start_id = 0;
146 output_ref_nodes(fp, start_id, params->append_num, "new_prop", "bar");
147 start_id += params->append_num;
148 output_ref_nodes(fp, start_id, params->override_num, "status", "okay");
149
150 return 0;
151 }
152
main(int argc,char * argv[])153 int main(int argc, char *argv[]) {
154 const char *filename = NULL;
155 struct gen_params params;
156 memset(¶ms, 0, sizeof(struct gen_params));
157
158 while (1) {
159 int option_index = 0;
160 int c = getopt_long(argc, argv, short_options, long_options, &option_index);
161 if (c == -1) {
162 break;
163 }
164 switch (c) {
165 case 'H':
166 params.no_header = 1;
167 break;
168 case 'p':
169 params.plugin = 1;
170 break;
171 case 'd':
172 params.depth = atoi(optarg);
173 break;
174 case 'u':
175 params.unused_num = atoi(optarg);
176 break;
177 case 'n':
178 params.node_num = atoi(optarg);
179 break;
180 case 'a':
181 params.append_num = atoi(optarg);
182 break;
183 case 'w':
184 params.override_num = atoi(optarg);
185 break;
186 case 'o':
187 filename = optarg;
188 break;
189 case '?':
190 break;
191 }
192 }
193
194 FILE *fp = NULL;
195 if (filename) {
196 fp = fopen(filename, "wt");
197 if (fp == NULL) {
198 fprintf(stderr, "Can not create file: %s\n", filename);
199 return -1;
200 }
201 }
202
203 gen_dts(fp ? fp : stdout, ¶ms);
204
205 if (fp) {
206 fclose(fp);
207 }
208
209 return 0;
210 }
211