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(&params, 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, &params);
204 
205   if (fp) {
206     fclose(fp);
207   }
208 
209   return 0;
210 }
211