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 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 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 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 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 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 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 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 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 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