1 /*
2  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005, 2008.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
17  *                                                                   USA
18  */
19 
20 %option noyywrap nounput noinput never-interactive
21 
22 %x BYTESTRING
23 %x PROPNODENAME
24 
25 PROPNODECHAR	[a-zA-Z0-9,._+*#?@-]
26 PATHCHAR	({PROPNODECHAR}|[/])
27 LABEL		[a-zA-Z_][a-zA-Z0-9_]*
28 STRING		\"([^\\"]|\\.)*\"
29 WS		[[:space:]]
30 COMMENT		"/*"([^*]|\*+[^*/])*\*+"/"
31 LINECOMMENT	"//".*\n
32 GAP		({WS}|{COMMENT}|{LINECOMMENT})*
33 
34 %{
35 #include <string.h>
36 #include <stdlib.h>
37 #include <stdarg.h>
38 
39 #include <errno.h>
40 #include <assert.h>
41 #include <fnmatch.h>
42 
43 #include "srcpos.h"
44 #include "util.h"
45 
46 static int v1_tagged; /* = 0 */
47 static int cbase = 16;
48 static int saw_hyphen; /* = 0 */
49 static unsigned long long last_val;
50 static char *last_name; /* = NULL */
51 
52 static const struct {
53 	const char *pattern;
54 	int obase, width;
55 } guess_table[] = {
56 	{ "*-frequency", 10, 0 },
57 	{ "num-*", 10, 0 },
58 	{ "#*-cells", 10, 0 },
59 	{ "*cache-line-size", 10, 0 },
60 	{ "*cache-block-size", 10, 0 },
61 	{ "*cache-size", 10, 0 },
62 	{ "*cache-sets", 10, 0 },
63 	{ "cell-index", 10, 0 },
64 	{ "bank-width", 10, 0 },
65 	{ "*-fifo-size", 10, 0 },
66 	{ "*-frame-size", 10, 0 },
67 	{ "*-channel", 10, 0 },
68 	{ "current-speed", 10, 0 },
69 	{ "phy-map", 16, 8 },
70 	{ "dcr-reg", 16, 3 },
71 	{ "reg", 16, 8 },
72 	{ "ranges", 16, 8},
73 };
74 %}
75 
76 %%
77 <*>"/include/"{GAP}{STRING}	ECHO;
78 
79 <*>\"([^\\"]|\\.)*\"	ECHO;
80 
81 <*>"/dts-v1/"	{
82 			die("Input dts file is already version 1\n");
83 		}
84 
85 <*>"/memreserve/"	{
86 			if (!v1_tagged) {
87 				fprintf(yyout, "/dts-v1/;\n\n");
88 				v1_tagged = 1;
89 			}
90 
91 			ECHO;
92 			BEGIN(INITIAL);
93 		}
94 
95 <*>{LABEL}:		ECHO;
96 
97 <INITIAL>[bodh]# {
98 			if (*yytext == 'b')
99 				cbase = 2;
100 			else if (*yytext == 'o')
101 				cbase = 8;
102 			else if (*yytext == 'd')
103 				cbase = 10;
104 			else
105 				cbase = 16;
106 		}
107 
108 <INITIAL>[0-9a-fA-F]+	{
109 			unsigned long long val;
110 			int obase = 16, width = 0;
111 			int i;
112 
113 			val = strtoull(yytext, NULL, cbase);
114 
115 			if (saw_hyphen)
116 				val = val - last_val + 1;
117 
118 			if (last_name) {
119 				for (i = 0; i < ARRAY_SIZE(guess_table); i++)
120 					if (fnmatch(guess_table[i].pattern,
121 					    last_name, 0) == 0) {
122 						obase = guess_table[i].obase;
123 						width = guess_table[i].width;
124 					}
125 			} else {
126 				obase = 16;
127 				width = 16;
128 			}
129 
130 			if (cbase != 16)
131 				obase = cbase;
132 
133 			switch (obase) {
134 			case 2:
135 			case 16:
136 				fprintf(yyout, "0x%0*llx", width, val);
137 				break;
138 			case 8:
139 				fprintf(yyout, "0%0*llo", width, val);
140 				break;
141 			case 10:
142 				fprintf(yyout, "%*llu", width, val);
143 				break;
144 			}
145 
146 			cbase = 16;
147 			last_val = val;
148 			saw_hyphen = 0;
149 		}
150 
151 \&{LABEL}		ECHO;
152 
153 "&{/"{PATHCHAR}+\}	ECHO;
154 
155 <INITIAL>"&/"{PATHCHAR}+ fprintf(yyout, "&{/%s}", yytext + 2);
156 
157 <BYTESTRING>[0-9a-fA-F]{2} ECHO;
158 
159 <BYTESTRING>"]"	{
160 			ECHO;
161 			BEGIN(INITIAL);
162 		}
163 
164 <PROPNODENAME>{PROPNODECHAR}+ {
165 			ECHO;
166 			last_name = xstrdup(yytext);
167 			BEGIN(INITIAL);
168 		}
169 
170 <*>{GAP}	ECHO;
171 
172 <*>-		{	/* Hack to convert old style memreserves */
173 			saw_hyphen = 1;
174 			fprintf(yyout, " ");
175 		}
176 
177 <*>.		{
178 			if (!v1_tagged) {
179 				fprintf(yyout, "/dts-v1/;\n\n");
180 				v1_tagged = 1;
181 			}
182 
183 			ECHO;
184 			if (yytext[0] == '[') {
185 				BEGIN(BYTESTRING);
186 			}
187 			if ((yytext[0] == '{')
188 			    || (yytext[0] == ';')) {
189 				BEGIN(PROPNODENAME);
190 			}
191 		}
192 
193 %%
194 /* Usage related data. */
195 static const char usage_synopsis[] = "convert-dtsv0 [options] <v0 dts file>...";
196 static const char usage_short_opts[] = "" USAGE_COMMON_SHORT_OPTS;
197 static struct option const usage_long_opts[] = {
198 	USAGE_COMMON_LONG_OPTS
199 };
200 static const char * const usage_opts_help[] = {
201 	USAGE_COMMON_OPTS_HELP
202 };
203 
204 static void convert_file(const char *fname)
205 {
206 	const char suffix[] = "v1";
207 	int len = strlen(fname);
208 	char *newname;
209 
210 	newname = xmalloc(len + sizeof(suffix));
211 	memcpy(newname, fname, len);
212 	memcpy(newname + len, suffix, sizeof(suffix));
213 
214 	yyin = fopen(fname, "r");
215 	if (!yyin)
216 		die("Couldn't open input file %s: %s\n",
217 		    fname, strerror(errno));
218 
219 	yyout = fopen(newname, "w");
220 	if (!yyout)
221 		die("Couldn't open output file %s: %s\n",
222 		    newname, strerror(errno));
223 
224 	while(yylex())
225 		;
226 
227 	free(newname);
228 }
229 
230 int main(int argc, char *argv[])
231 {
232 	int opt;
233 	int i;
234 
235 	while ((opt = util_getopt_long()) != EOF) {
236 		switch (opt) {
237 		case_USAGE_COMMON_FLAGS
238 		}
239 	}
240 	if (argc < 2)
241 		usage("missing filename");
242 
243 	for (i = 1; i < argc; i++) {
244 		fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]);
245 		convert_file(argv[i]);
246 	}
247 
248 	exit(0);
249 }
250