Add MigrationTools
[mirror_edk2.git] / Tools / Source / MigrationTools / org / tianocore / migration / SourceFileReplacer.java
1 package org.tianocore.migration;
2
3 import java.io.*;
4 import java.util.*;
5 import java.util.regex.Matcher;
6 import java.util.regex.Pattern;
7
8 public class SourceFileReplacer {
9 SourceFileReplacer(String path, ModuleInfo moduleinfo, Database database, UI fp) {
10 modulepath = path;
11 mi = moduleinfo;
12 db = database;
13 ui = fp;
14 }
15 private String modulepath;
16 private ModuleInfo mi;
17 private Database db;
18 private UI ui;
19 private boolean showdetails = false;
20
21 private class r8tor9 {
22 r8tor9(String r8, String r9) {
23 r8thing = r8;
24 r9thing = r9;
25 }
26 public String r8thing;
27 public String r9thing;
28 }
29
30 // these sets are used only for printing log of the changes in current file
31 private Set<r8tor9> filefunc = new HashSet<r8tor9>();
32 private Set<r8tor9> filemacro = new HashSet<r8tor9>();
33 private Set<r8tor9> fileguid = new HashSet<r8tor9>();
34 private Set<r8tor9> fileppi = new HashSet<r8tor9>();
35 private Set<r8tor9> fileprotocol = new HashSet<r8tor9>();
36 private Set<String> filer8only = new HashSet<String>();
37
38 private String r8only = "EfiLibInstallDriverBinding " +
39 "EfiLibInstallAllDriverProtocols " +
40 "EfiLibCompareLanguage " +
41 "BufToHexString " +
42 "EfiStrTrim " +
43 "EfiValueToHexStr " +
44 "HexStringToBuf " +
45 "IsHexDigit " +
46 "NibbleToHexChar " +
47 "GetHob " +
48 "GetHobListSize " +
49 "GetHobVersion " +
50 "GetHobBootMode " +
51 "GetCpuHobInfo " +
52 "GetDxeCoreHobInfo " +
53 "GetNextFirmwareVolumeHob " +
54 "GetNextGuidHob " +
55 "GetPalEntryHobInfo " +
56 "GetIoPortSpaceAddressHobInfo ";
57
58 public void flush() throws Exception {
59 PrintWriter outfile;
60 String temp = null;
61 if (ui.yesOrNo("Change Source Code is to be doing . See details ?")) {
62 showdetails = true;
63 }
64 File tempdir = new File(modulepath + File.separator + "result" + File.separator);
65 if (!tempdir.exists()) tempdir.mkdir();
66 String[] list = new File(modulepath + File.separator + "temp").list(); //what I change is the non-local .h commented-out files
67 for (int i = 0 ; i < list.length ; i++) {
68 if (list[i].contains(".c")) {
69 ui.println("\nModifying file : " + list[i]);
70 outfile = new PrintWriter(new BufferedWriter(new FileWriter(modulepath + File.separator + "result" + File.separator + list[i])));
71 outfile.append(sourcefilereplace(modulepath + File.separator + "temp" + File.separator + list[i]));
72 outfile.flush();
73 outfile.close();
74 } else {
75 if (list[i].contains(".h")) {
76 temp = list[i];
77 } else if (list[i].contains(".C")) {
78 temp = list[i].replaceFirst(".C", ".c");
79 } else if (list[i].contains(".H")) {
80 temp = list[i].replaceFirst(".H", ".h");
81 } else {
82 continue;
83 }
84 ui.println("\nCopying file : " + temp);
85 outfile = new PrintWriter(new BufferedWriter(new FileWriter(modulepath + File.separator + "result" + File.separator + temp)));
86 outfile.append(sourcefiletostring(modulepath + File.separator + "temp" + File.separator + list[i]));
87 outfile.flush();
88 outfile.close();
89 }
90 }
91
92 if (!mi.hashr8only.isEmpty()) {
93 addr8only();
94 }
95 }
96
97 private void addr8only() throws Exception {
98 String paragraph = null;
99 String line = sourcefiletostring(Database.defaultpath + File.separator + "R8Lib.c");
100 PrintWriter outfile1 = new PrintWriter(new BufferedWriter(new FileWriter(modulepath + File.separator + "result" + File.separator + "R8Lib.c")));
101 PrintWriter outfile2 = new PrintWriter(new BufferedWriter(new FileWriter(modulepath + File.separator + "result" + File.separator + "R8Lib.h")));
102 //outfile1.append("#include \"R8Lib.h\"\n\n");
103 //outfile2.append("#include \"R8Lib.h\"\n\n");
104 Pattern ptnr8only = Pattern.compile("////#?(\\w*)?.*?R8_(\\w*).*?////~", Pattern.DOTALL);
105 Matcher mtrr8only = ptnr8only.matcher(line);
106 Matcher mtrr8onlyhead;
107 while (mtrr8only.find()) {
108 if (mi.hashr8only.contains(mtrr8only.group(2))) {
109 paragraph = mtrr8only.group();
110 outfile1.append(paragraph + "\n\n");
111 if (mtrr8only.group(1).length() != 0) {
112 mi.hashrequiredr9libs.add(mtrr8only.group(1));
113 }
114 //generate R8lib.h
115 while ((mtrr8onlyhead = Func.ptnbrace.matcher(paragraph)).find()) {
116 paragraph = mtrr8onlyhead.replaceAll(";");
117 }
118 outfile2.append(paragraph + "\n\n");
119 }
120 }
121 outfile1.flush();
122 outfile1.close();
123 outfile2.flush();
124 outfile2.close();
125 }
126
127 private String sourcefiletostring(String filename) throws Exception {
128 BufferedReader rd = new BufferedReader(new FileReader(filename));
129 StringBuffer wholefile = new StringBuffer();
130 String line;
131 while ((line = rd.readLine()) != null) {
132 wholefile.append(line + "\n");
133 }
134 return wholefile.toString();
135 }
136
137 // Caution : if there is @ in file , it will be replaced with \n , so is you use Doxygen ... God Bless you!
138 private String sourcefilereplace(String filename) throws Exception {
139 BufferedReader rd = new BufferedReader(new FileReader(filename));
140 StringBuffer wholefile = new StringBuffer();
141 String line;
142 String r8thing;
143 String r9thing;
144 r8tor9 temp;
145 boolean addr8 = false;
146
147 Pattern pat = Pattern.compile("g?(BS|RT)(\\s*->\\s*)([a-zA-Z_]\\w*)", Pattern.MULTILINE); // ! only two level () bracket allowed !
148 //Pattern ptnpei = Pattern.compile("\\(\\*\\*?PeiServices\\)[.-][>]?\\s*(\\w*[#$]*)(\\s*\\(([^\\(\\)]*(\\([^\\(\\)]*\\))?[^\\(\\)]*)*\\))", Pattern.MULTILINE);
149
150 while ((line = rd.readLine()) != null) {
151 wholefile.append(line + "\n");
152 }
153 line = wholefile.toString();
154
155 // replace BS -> gBS , RT -> gRT
156 Matcher mat = pat.matcher(line);
157 if (mat.find()) { // add a library here
158 ui.println("Converting all BS->gBS,RT->gRT");
159 line = mat.replaceAll("g$1$2$3"); //unknown correctiveness
160 }
161 mat.reset();
162 while (mat.find()) {
163 if (mat.group(1).matches("BS")) {
164 mi.hashrequiredr9libs.add("UefiBootServicesTableLib");
165 }
166 if (mat.group(1).matches("RT")) {
167 mi.hashrequiredr9libs.add("UefiRuntimeServicesTableLib");
168 }
169 }
170 /*
171 // remove EFI_DRIVER_ENTRY_POINT
172 Pattern patentrypoint = Pattern.compile("EFI_DRIVER_ENTRY_POINT[^\\}]*\\}");
173 Matcher matentrypoint = patentrypoint.matcher(line);
174 if (matentrypoint.find()) {
175 ui.println("Deleting Entry_Point");
176 line = matentrypoint.replaceAll("");
177 }
178 */
179 // start replacing names
180 Iterator<String> it;
181 // Converting non-locla function
182 it = mi.hashnonlocalfunc.iterator();
183 while (it.hasNext()) {
184 r8thing = it.next();
185 if (r8thing.matches("EfiInitializeDriverLib")) { //s
186 mi.hashrequiredr9libs.add("UefiBootServicesTableLib"); //p
187 mi.hashrequiredr9libs.add("UefiRuntimeServicesTableLib"); //e
188 } else if (r8thing.matches("DxeInitializeDriverLib")) { //c
189 mi.hashrequiredr9libs.add("UefiBootServicesTableLib"); //i
190 mi.hashrequiredr9libs.add("UefiRuntimeServicesTableLib"); //a
191 mi.hashrequiredr9libs.add("DxeServicesTableLib"); //l
192 } else { //
193 mi.hashrequiredr9libs.add(db.getR9Lib(r8thing)); // add a library here
194 }
195
196 if ((r9thing = db.getR9Func(r8thing)) != null) {
197 if (!r8thing.equals(r9thing)) {
198 if (line.contains(r8thing)) {
199 line = line.replaceAll(r8thing, r9thing);
200 filefunc.add(new r8tor9(r8thing, r9thing));
201 Iterator<r8tor9> rt = filefunc.iterator();
202 while (rt.hasNext()) {
203 temp = rt.next();
204 if (r8only.contains(temp.r8thing)) {
205 mi.localmodulesources.add("R8Lib.h");
206 mi.localmodulesources.add("R8Lib.c");
207 mi.localmoduleheaders.add("R8Lib.h");
208 filer8only.add(r8thing);
209 mi.hashr8only.add(r8thing);
210 addr8 = true;
211 }
212 }
213 }
214 }
215 }
216 } //is any of the guids changed?
217 if (addr8 == true) {
218 line = line.replaceFirst("\\*/\n", "\\*/\n#include \"R8Lib.h\"\n");
219 }
220
221 // Converting macro
222 it = mi.hashnonlocalmacro.iterator();
223 while (it.hasNext()) { //macros are all assumed MdePkg currently
224 r8thing = it.next();
225 //mi.hashrequiredr9libs.add(db.getR9Lib(r8thing));
226 if ((r9thing = db.getR9Macro(r8thing)) != null) {
227 if (line.contains(r8thing)) {
228 line = line.replaceAll(r8thing, r9thing);
229 filemacro.add(new r8tor9(r8thing, r9thing));
230 }
231 }
232 }
233
234 // Converting guid
235 replaceGuid(line, mi.guid, "guid", fileguid);
236 replaceGuid(line, mi.ppi, "ppi", fileppi);
237 replaceGuid(line, mi.protocol, "protocol", fileprotocol);
238
239 // Converting Pei
240 // First , find all (**PeiServices)-> or (*PeiServices). with arg "PeiServices" , change name and add #%
241 Pattern ptnpei = Pattern.compile("\\(\\*\\*?PeiServices\\)[.-][>]?\\s*(\\w*)(\\s*\\(\\s*PeiServices\\s*,\\s*)", Pattern.MULTILINE);
242 if (mi.moduletype.contains("PEIM")) {
243 Matcher mtrpei = ptnpei.matcher(line);
244 while (mtrpei.find()) { // ! add a library here !
245 line = mtrpei.replaceAll("PeiServices$1#%$2");
246 mi.hashrequiredr9libs.add("PeiServicesLib");
247 }
248 mtrpei.reset();
249 if (line.contains("PeiServicesCopyMem")) {
250 line = line.replaceAll("PeiServicesCopyMem#%", "CopyMem");
251 mi.hashrequiredr9libs.add("BaseMemoryLib");
252 }
253 if (line.contains("PeiServicesSetMem")) {
254 line = line.replaceAll("PeiServicesSetMem#%", "SetMem");
255 mi.hashrequiredr9libs.add("BaseMemoryLib");
256 }
257
258 // Second , find all #% to drop the arg "PeiServices"
259 Pattern ptnpeiarg = Pattern.compile("#%+(\\s*\\(+\\s*)PeiServices\\s*,\\s*", Pattern.MULTILINE);
260 Matcher mtrpeiarg = ptnpeiarg.matcher(line);
261 while (mtrpeiarg.find()) {
262 line = mtrpeiarg.replaceAll("$1");
263 }
264 }
265
266 Matcher mtrmac;
267 mtrmac = Pattern.compile("EFI_IDIV_ROUND\\((.*), (.*)\\)").matcher(line);
268 if (mtrmac.find()) {
269 line = mtrmac.replaceAll("\\($1 \\/ $2 \\+ \\(\\(\\(2 \\* \\($1 \\% $2\\)\\) \\< $2\\) \\? 0 \\: 1\\)\\)");
270 }
271 mtrmac = Pattern.compile("EFI_MIN\\((.*), (.*)\\)").matcher(line);
272 if (mtrmac.find()) {
273 line = mtrmac.replaceAll("\\(\\($1 \\< $2\\) \\? $1 \\: $2\\)");
274 }
275 mtrmac = Pattern.compile("EFI_MAX\\((.*), (.*)\\)").matcher(line);
276 if (mtrmac.find()) {
277 line = mtrmac.replaceAll("\\(\\($1 \\> $2\\) \\? $1 \\: $2\\)");
278 }
279 mtrmac = Pattern.compile("EFI_UINTN_ALIGNED\\((.*)\\)").matcher(line);
280 if (mtrmac.find()) {
281 line = mtrmac.replaceAll("\\(\\(\\(UINTN\\) $1\\) \\& \\(sizeof \\(UINTN\\) \\- 1\\)\\)");
282 }
283 if (line.contains("EFI_UINTN_ALIGN_MASK")) {
284 line = line.replaceAll("EFI_UINTN_ALIGN_MASK", "(sizeof (UINTN) - 1)");
285 }
286
287 show(filefunc, "function");
288 show(filemacro, "macro");
289 show(fileguid, "guid");
290 show(fileppi, "ppi");
291 show(fileprotocol, "protocol");
292 if (!filer8only.isEmpty()) {
293 ui.println("Converting r8only : " + filer8only);
294 }
295
296 filefunc.clear();
297 filemacro.clear();
298 fileguid.clear();
299 fileppi.clear();
300 fileprotocol.clear();
301 filer8only.clear();
302
303 return line;
304 }
305
306 private void show(Set<r8tor9> hash, String sh) {
307 Iterator<r8tor9> it = hash.iterator();
308 r8tor9 temp;
309 if (showdetails) {
310 if (!hash.isEmpty()) {
311 ui.print("Converting " + sh + " : ");
312 while (it.hasNext()) {
313 temp = it.next();
314 ui.print("[" + temp.r8thing + "->" + temp.r9thing + "] ");
315 }
316 ui.println("");
317 }
318 }
319 }
320
321 private void replaceGuid(String line, Set<String> hash, String kind, Set<r8tor9> filehash) {
322 Iterator<String> it;
323 String r8thing;
324 String r9thing;
325 it = hash.iterator();
326 while (it.hasNext()) {
327 r8thing = it.next();
328 if ((r9thing = db.getR9Guidname(r8thing)) != null) {
329 if (!r8thing.equals(r9thing)) {
330 if (line.contains(r8thing)) {
331 line = line.replaceAll(r8thing, r9thing);
332 filehash.add(new r8tor9(r8thing, r9thing));
333 }
334 }
335 }
336 }
337 }
338 }