1 /*
2  * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 package build.tools.projectcreator;
26 
27 import java.io.File;
28 import java.io.IOException;
29 import java.io.PrintWriter;
30 import java.util.Hashtable;
31 import java.util.Iterator;
32 import java.util.Stack;
33 import java.util.Vector;
34 
35 abstract class HsArgHandler extends ArgHandler {
36     static final int STRING = 1;
37     static final int VECTOR = 2;
38     static final int HASH   = 3;
39 
nextNotKey(ArgIterator it)40     boolean nextNotKey(ArgIterator it) {
41         if (it.next()) {
42             String s = it.get();
43             return (s.length() == 0) || (s.charAt(0) != '-');
44         } else {
45             return false;
46         }
47     }
48 
empty(String key, String message)49     void empty(String key, String message) {
50         if (key != null) {
51             System.err.println("** Error: empty " + key);
52         }
53         if (message != null) {
54             System.err.println(message);
55         }
56         WinGammaPlatform.usage();
57     }
58 
getCfg(String val)59     static String getCfg(String val) {
60         int under = val.indexOf('_');
61         int len = val.length();
62         if (under != -1 && under < len - 1) {
63             return val.substring(under+1, len);
64         } else {
65             return null;
66         }
67     }
68 }
69 
70 class ArgRuleSpecific extends ArgRule {
ArgRuleSpecific(String arg, ArgHandler handler)71     ArgRuleSpecific(String arg, ArgHandler handler) {
72         super(arg, handler);
73     }
74 
match(String rulePattern, String arg)75     boolean match(String rulePattern, String arg) {
76         return rulePattern.startsWith(arg);
77     }
78 }
79 
80 
81 class SpecificHsArgHandler extends HsArgHandler {
82 
83     String message, argKey, valKey;
84     int type;
85 
handle(ArgIterator it)86     public void handle(ArgIterator it) {
87         String cfg = getCfg(it.get());
88         if (nextNotKey(it)) {
89             String val = it.get();
90             switch (type) {
91             case VECTOR:
92                 BuildConfig.addFieldVector(cfg, valKey, val);
93                 break;
94             case HASH:
95                 BuildConfig.putFieldHash(cfg, valKey, val, "1");
96                 break;
97             case STRING:
98                 BuildConfig.putField(cfg, valKey, val);
99                 break;
100             default:
101                 empty(valKey, "Unknown type: "+type);
102             }
103             it.next();
104 
105         } else {
106             empty(argKey, message);
107         }
108     }
109 
SpecificHsArgHandler(String argKey, String valKey, String message, int type)110     SpecificHsArgHandler(String argKey, String valKey, String message, int type) {
111         this.argKey = argKey;
112         this.valKey = valKey;
113         this.message = message;
114         this.type = type;
115     }
116 }
117 
118 
119 class HsArgRule extends ArgRuleSpecific {
120 
HsArgRule(String argKey, String valKey, String message, int type)121     HsArgRule(String argKey, String valKey, String message, int type) {
122         super(argKey, new SpecificHsArgHandler(argKey, valKey, message, type));
123     }
124 
125 }
126 
127 public abstract class WinGammaPlatform {
128 
fileNameStringEquality(String s1, String s2)129     public boolean fileNameStringEquality(String s1, String s2) {
130         return s1.equalsIgnoreCase(s2);
131     }
132 
usage()133     static void usage() throws IllegalArgumentException {
134         System.err.println("WinGammaPlatform platform-specific options:");
135         System.err.println("  -sourceBase <path to directory (workspace) " +
136                            "containing source files; no trailing slash>");
137         System.err.println("  -projectFileName <full pathname to which project file " +
138                            "will be written; all parent directories must " +
139                            "already exist>");
140         System.err.println("  If any of the above are specified, "+
141                            "they must all be.");
142         System.err.println("  Note: if '-altRelativeInclude' option below " +
143                            "is used, then the '-relativeAltSrcInclude' " +
144                            "option must be used to specify the alternate " +
145                            "source dir, e.g., 'src\\closed'");
146         System.err.println("  Additional, optional arguments, which can be " +
147                            "specified multiple times:");
148         System.err.println("    -absoluteInclude <string containing absolute " +
149                            "path to include directory>");
150         System.err.println("    -altRelativeInclude <string containing " +
151                            "alternate include directory relative to " +
152                            "-sourceBase>");
153         System.err.println("    -relativeInclude <string containing include " +
154                            "directory relative to -sourceBase>");
155         System.err.println("    -define <preprocessor flag to be #defined " +
156                            "(note: doesn't yet support " +
157                            "#define (flag) (value))>");
158         System.err.println("    -startAt <subdir of sourceBase>");
159         System.err.println("    -additionalFile <file not in database but " +
160                            "which should show up in project file>");
161         System.err.println("    -additionalGeneratedFile <absolute path to " +
162                            "directory containing file; no trailing slash> " +
163                            "<name of file generated later in the build process>");
164         throw new IllegalArgumentException();
165     }
166 
167 
addPerFileLine(Hashtable table, String fileName, String line)168     public void addPerFileLine(Hashtable table,
169                                String fileName,
170                                String line) {
171         Vector v = (Vector) table.get(fileName);
172         if (v != null) {
173             v.add(line);
174         } else {
175             v = new Vector();
176             v.add(line);
177             table.put(fileName, v);
178         }
179     }
180 
181     protected static class PerFileCondData {
182         public String releaseString;
183         public String debugString;
184     }
185 
addConditionalPerFileLine(Hashtable table, String fileName, String releaseLine, String debugLine)186     protected void addConditionalPerFileLine(Hashtable table,
187                                            String fileName,
188                                            String releaseLine,
189                                            String debugLine) {
190         PerFileCondData data = new PerFileCondData();
191         data.releaseString = releaseLine;
192         data.debugString = debugLine;
193         Vector v = (Vector) table.get(fileName);
194         if (v != null) {
195             v.add(data);
196         } else {
197             v = new Vector();
198             v.add(data);
199             table.put(fileName, v);
200         }
201     }
202 
203     protected static class PrelinkCommandData {
204       String description;
205       String commands;
206     }
207 
addPrelinkCommand(Hashtable table, String build, String description, String commands)208     protected void addPrelinkCommand(Hashtable table,
209                                      String build,
210                                      String description,
211                                      String commands) {
212       PrelinkCommandData data = new PrelinkCommandData();
213       data.description = description;
214       data.commands = commands;
215       table.put(build, data);
216     }
217 
findString(Vector v, String s)218     public boolean findString(Vector v, String s) {
219         for (Iterator iter = v.iterator(); iter.hasNext(); ) {
220             if (((String) iter.next()).equals(s)) {
221                 return true;
222             }
223         }
224 
225         return false;
226     }
227 
getProjectName(String fullPath, String extension)228      String getProjectName(String fullPath, String extension)
229         throws IllegalArgumentException, IOException {
230         File file = new File(fullPath).getCanonicalFile();
231         fullPath = file.getCanonicalPath();
232         String parent = file.getParent();
233 
234         if (!fullPath.endsWith(extension)) {
235             throw new IllegalArgumentException("project file name \"" +
236                                                fullPath +
237                                                "\" does not end in "+extension);
238         }
239 
240         if ((parent != null) &&
241             (!fullPath.startsWith(parent))) {
242             throw new RuntimeException(
243                 "Internal error: parent of file name \"" + parent +
244                 "\" does not match file name \"" + fullPath + "\""
245             );
246         }
247 
248         int len = parent.length();
249         if (!parent.endsWith(Util.sep)) {
250             len += Util.sep.length();
251         }
252 
253         int end = fullPath.length() - extension.length();
254 
255         if (len == end) {
256             throw new RuntimeException(
257                 "Internal error: file name was empty"
258             );
259         }
260 
261         return fullPath.substring(len, end);
262     }
263 
getProjectExt()264     protected abstract String getProjectExt();
265 
createVcproj(String[] args)266     public void createVcproj(String[] args)
267         throws IllegalArgumentException, IOException {
268 
269         parseArguments(args);
270 
271         String projectFileName = BuildConfig.getFieldString(null, "ProjectFileName");
272         String ext = getProjectExt();
273 
274         String projectName = getProjectName(projectFileName, ext);
275 
276         writeProjectFile(projectFileName, projectName, createAllConfigs(BuildConfig.getFieldString(null, "PlatformName")));
277     }
278 
writePrologue(String[] args)279     protected void writePrologue(String[] args) {
280         System.err.println("WinGammaPlatform platform-specific arguments:");
281         for (int i = 0; i < args.length; i++) {
282             System.err.print(args[i] + " ");
283         }
284         System.err.println();
285     }
286 
287 
parseArguments(String[] args)288     void parseArguments(String[] args) {
289         new ArgsParser(args,
290                        new ArgRule[]
291             {
292                 new ArgRule("-sourceBase",
293                             new HsArgHandler() {
294                                 public void handle(ArgIterator it) {
295                                    String cfg = getCfg(it.get());
296                                    if (nextNotKey(it)) {
297                                       String sb = (String) it.get();
298                                       if (sb.endsWith(Util.sep)) {
299                                          sb = sb.substring(0, sb.length() - 1);
300                                       }
301                                       BuildConfig.putField(cfg, "SourceBase", sb);
302                                       it.next();
303                                    } else {
304                                       empty("-sourceBase", null);
305                                    }
306                                 }
307                             }
308                             ),
309 
310                 new HsArgRule("-buildBase",
311                               "BuildBase",
312                               "   (Did you set the HotSpotBuildSpace environment variable?)",
313                               HsArgHandler.STRING
314                               ),
315 
316                new HsArgRule("-buildSpace",
317                               "BuildSpace",
318                               null,
319                               HsArgHandler.STRING
320                               ),
321 
322                new HsArgRule("-makeBinary",
323                               "MakeBinary",
324                               null,
325                               HsArgHandler.STRING
326                               ),
327 
328                new HsArgRule("-makeOutput",
329                               "MakeOutput",
330                               null,
331                               HsArgHandler.STRING
332                               ),
333 
334               new HsArgRule("-platformName",
335                               "PlatformName",
336                               null,
337                               HsArgHandler.STRING
338                               ),
339 
340               new HsArgRule("-projectFileName",
341                               "ProjectFileName",
342                               null,
343                               HsArgHandler.STRING
344                               ),
345 
346                 new HsArgRule("-jdkTargetRoot",
347                               "JdkTargetRoot",
348                               "   (Did you set the HotSpotJDKDist environment variable?)",
349                               HsArgHandler.STRING
350                               ),
351 
352                 new HsArgRule("-compiler",
353                               "CompilerVersion",
354                               "   (Did you set the VcVersion correctly?)",
355                               HsArgHandler.STRING
356                               ),
357 
358                 new HsArgRule("-absoluteInclude",
359                               "AbsoluteInclude",
360                               null,
361                               HsArgHandler.VECTOR
362                               ),
363 
364                 new HsArgRule("-altRelativeInclude",
365                               "AltRelativeInclude",
366                               null,
367                               HsArgHandler.VECTOR
368                               ),
369 
370                 new HsArgRule("-relativeInclude",
371                               "RelativeInclude",
372                               null,
373                               HsArgHandler.VECTOR
374                               ),
375 
376                 new HsArgRule("-absoluteSrcInclude",
377                               "AbsoluteSrcInclude",
378                               null,
379                               HsArgHandler.VECTOR
380                               ),
381 
382                 new HsArgRule("-relativeAltSrcInclude",
383                               "RelativeAltSrcInclude",
384                               null,
385                               HsArgHandler.STRING
386                               ),
387 
388                 new HsArgRule("-relativeSrcInclude",
389                               "RelativeSrcInclude",
390                               null,
391                               HsArgHandler.VECTOR
392                               ),
393 
394                 new HsArgRule("-define",
395                               "Define",
396                               null,
397                               HsArgHandler.VECTOR
398                               ),
399 
400                 new HsArgRule("-useToGeneratePch",
401                               "UseToGeneratePch",
402                               null,
403                               HsArgHandler.STRING
404                               ),
405 
406                 new ArgRuleSpecific("-perFileLine",
407                             new HsArgHandler() {
408                                 public void handle(ArgIterator it) {
409                                     String cfg = getCfg(it.get());
410                                     if (nextNotKey(it)) {
411                                         String fileName = it.get();
412                                         if (nextNotKey(it)) {
413                                             String line = it.get();
414                                             BuildConfig.putFieldHash(cfg, "PerFileLine", fileName, line);
415                                             it.next();
416                                             return;
417                                         }
418                                     }
419                                     empty(null, "** Error: wrong number of args to -perFileLine");
420                                 }
421                             }
422                             ),
423 
424                 new ArgRuleSpecific("-conditionalPerFileLine",
425                             new HsArgHandler() {
426                                 public void handle(ArgIterator it) {
427                                     String cfg = getCfg(it.get());
428                                     if (nextNotKey(it)) {
429                                         String fileName = it.get();
430                                         if (nextNotKey(it)) {
431                                             String productLine = it.get();
432                                             if (nextNotKey(it)) {
433                                                 String debugLine = it.get();
434                                                 BuildConfig.putFieldHash(cfg+"_debug", "CondPerFileLine",
435                                                                          fileName, debugLine);
436                                                 BuildConfig.putFieldHash(cfg+"_product", "CondPerFileLine",
437                                                                          fileName, productLine);
438                                                 it.next();
439                                                 return;
440                                             }
441                                         }
442                                     }
443 
444                                     empty(null, "** Error: wrong number of args to -conditionalPerFileLine");
445                                 }
446                             }
447                             ),
448 
449                 new HsArgRule("-disablePch",
450                               "DisablePch",
451                               null,
452                               HsArgHandler.HASH
453                               ),
454 
455                 new ArgRule("-startAt",
456                             new HsArgHandler() {
457                                 public void handle(ArgIterator it) {
458                                     if (BuildConfig.getField(null, "StartAt") != null) {
459                                         empty(null, "** Error: multiple -startAt");
460                                     }
461                                     if (nextNotKey(it)) {
462                                         BuildConfig.putField(null, "StartAt", it.get());
463                                         it.next();
464                                     } else {
465                                         empty("-startAt", null);
466                                     }
467                                 }
468                             }
469                             ),
470 
471                 new HsArgRule("-ignoreFile",
472                                       "IgnoreFile",
473                                       null,
474                                       HsArgHandler.HASH
475                                       ),
476 
477                 new HsArgRule("-ignorePath",
478                               "IgnorePath",
479                               null,
480                               HsArgHandler.VECTOR
481                               ),
482 
483                 new HsArgRule("-hidePath",
484                       "HidePath",
485                       null,
486                       HsArgHandler.VECTOR
487                       ),
488 
489                 new HsArgRule("-additionalFile",
490                               "AdditionalFile",
491                               null,
492                               HsArgHandler.VECTOR
493                               ),
494 
495                 new ArgRuleSpecific("-additionalGeneratedFile",
496                             new HsArgHandler() {
497                                 public void handle(ArgIterator it) {
498                                     String cfg = getCfg(it.get());
499                                     if (nextNotKey(it)) {
500                                         String dir = it.get();
501                                         if (nextNotKey(it)) {
502                                             String fileName = it.get();
503                                             BuildConfig.putFieldHash(cfg, "AdditionalGeneratedFile",
504                                                                      Util.normalize(dir + Util.sep + fileName),
505                                                                      fileName);
506                                             it.next();
507                                             return;
508                                         }
509                                     }
510                                     empty(null, "** Error: wrong number of args to -additionalGeneratedFile");
511                                 }
512                             }
513                             ),
514 
515                 new ArgRule("-prelink",
516                             new HsArgHandler() {
517                                 public void handle(ArgIterator it) {
518                                     if (nextNotKey(it)) {
519                                         if (nextNotKey(it)) {
520                                             String description = it.get();
521                                             if (nextNotKey(it)) {
522                                                 String command = it.get();
523                                                 BuildConfig.putField(null, "PrelinkDescription", description);
524                                                 BuildConfig.putField(null, "PrelinkCommand", command);
525                                                 it.next();
526                                                 return;
527                                             }
528                                         }
529                                     }
530 
531                                     empty(null,  "** Error: wrong number of args to -prelink");
532                                 }
533                             }
534                             ),
535 
536                 new ArgRule("-postbuild",
537                             new HsArgHandler() {
538                                 public void handle(ArgIterator it) {
539                                     if (nextNotKey(it)) {
540                                         if (nextNotKey(it)) {
541                                             String description = it.get();
542                                             if (nextNotKey(it)) {
543                                                 String command = it.get();
544                                                 BuildConfig.putField(null, "PostbuildDescription", description);
545                                                 BuildConfig.putField(null, "PostbuildCommand", command);
546                                                 it.next();
547                                                 return;
548                                             }
549                                         }
550                                     }
551 
552                                     empty(null,  "** Error: wrong number of args to -postbuild");
553                                 }
554                             }
555                             ),
556             },
557                                        new ArgHandler() {
558                                            public void handle(ArgIterator it) {
559 
560                                                throw new RuntimeException("Arg Parser: unrecognized option "+it.get());
561                                            }
562                                        }
563                                        );
564         if (BuildConfig.getField(null, "SourceBase") == null      ||
565             BuildConfig.getField(null, "BuildBase") == null       ||
566             BuildConfig.getField(null, "ProjectFileName") == null ||
567             BuildConfig.getField(null, "CompilerVersion") == null) {
568             usage();
569         }
570 
571         BuildConfig.putField(null, "PlatformObject", this);
572     }
573 
createAllConfigs(String platform)574     Vector createAllConfigs(String platform) {
575         Vector allConfigs = new Vector();
576 
577         allConfigs.add(new C1DebugConfig());
578         allConfigs.add(new C1FastDebugConfig());
579         allConfigs.add(new C1ProductConfig());
580 
581         allConfigs.add(new TieredDebugConfig());
582         allConfigs.add(new TieredFastDebugConfig());
583         allConfigs.add(new TieredProductConfig());
584 
585         return allConfigs;
586     }
587 
588     PrintWriter printWriter;
589 
writeProjectFile(String projectFileName, String projectName, Vector<BuildConfig> allConfigs)590     public void writeProjectFile(String projectFileName, String projectName,
591                                  Vector<BuildConfig> allConfigs) throws IOException {
592         throw new RuntimeException("use compiler version specific version");
593     }
594 
595     int indent;
596     private Stack<String> tagStack = new Stack<String>();
597 
startTagPrim(String name, String[] attrs, boolean close)598     private void startTagPrim(String name, String[] attrs, boolean close) {
599        startTagPrim(name, attrs, close, true);
600     }
601 
startTagPrim(String name, String[] attrs, boolean close, boolean newline)602     private void startTagPrim(String name, String[] attrs, boolean close,
603           boolean newline) {
604        doIndent();
605        printWriter.print("<" + name);
606        indent++;
607 
608        if (attrs != null && attrs.length > 0) {
609           for (int i = 0; i < attrs.length; i += 2) {
610              printWriter.print(" " + attrs[i] + "=\"" + attrs[i + 1] + "\"");
611              if (i < attrs.length - 2) {
612              }
613           }
614        }
615 
616        if (close) {
617           indent--;
618           printWriter.print(" />");
619        } else {
620           // TODO push tag name, and change endTag to pop and print.
621           tagStack.push(name);
622           printWriter.print(">");
623        }
624        if (newline) {
625           printWriter.println();
626        }
627     }
628 
startTag(String name, String... attrs)629     void startTag(String name, String... attrs) {
630        startTagPrim(name, attrs, false);
631     }
632 
startTagV(String name, Vector attrs)633     void startTagV(String name, Vector attrs) {
634        String s[] = new String[attrs.size()];
635        for (int i = 0; i < attrs.size(); i++) {
636           s[i] = (String) attrs.elementAt(i);
637        }
638        startTagPrim(name, s, false);
639     }
640 
endTag()641     void endTag() {
642        String name = tagStack.pop();
643        indent--;
644        doIndent();
645        printWriter.println("</" + name + ">");
646     }
647 
endTagNoIndent()648     private void endTagNoIndent() {
649        String name = tagStack.pop();
650        indent--;
651        printWriter.println("</" + name + ">");
652     }
653 
tag(String name, String... attrs)654     void tag(String name, String... attrs) {
655        startTagPrim(name, attrs, true);
656     }
657 
tagData(String name, String data)658     void tagData(String name, String data) {
659        startTagPrim(name, null, false, false);
660        printWriter.print(data);
661        endTagNoIndent();
662     }
663 
tagData(String name, String data, String... attrs)664     void tagData(String name, String data, String... attrs) {
665        startTagPrim(name, attrs, false, false);
666        printWriter.print(data);
667        endTagNoIndent();
668     }
669 
tagV(String name, Vector attrs)670     void tagV(String name, Vector attrs) {
671        String s[] = new String[attrs.size()];
672        for (int i = 0; i < attrs.size(); i++) {
673           s[i] = (String) attrs.elementAt(i);
674        }
675        startTagPrim(name, s, true);
676     }
677 
doIndent()678     void doIndent() {
679        for (int i = 0; i < indent; i++) {
680           printWriter.print("  ");
681        }
682     }
683 
684 
685 }
686