xref: /titanic_44/usr/src/cmd/print/printmgr/com/sun/admin/pm/client/helptools/parseMain.java (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 import java.io.*;
23 import java.util.*;
24 import java.lang.*;
25 
26 
27 class ResourceWriter {
28 
29     BufferedWriter theWriter = null;
30     String theTag = null;
31 
32     static final String NL = new String("\n");
33     static final String LOCALIZE = new String("// LOCALIZE");
34     static final String NOLOCALIZE = new String("// DO NOT LOCALIZE");
35     static final String INDENT = new String("    ");
36     static final String INDENT_2 = new String(INDENT + INDENT);
37     static final String COMMENTBLOCK_START = new String("/*");
38     static final String COMMENTBLOCK_END = new String(" */");
39     static final String COMMENTLINE_START = new String(" * ");
40 
ResourceWriter(BufferedWriter w)41     public ResourceWriter(BufferedWriter w) {
42         theWriter = w;
43     }
44 
close()45     public void close() throws IOException {
46         theWriter.flush();
47         theWriter.close();
48     }
49 
writenl(String s)50     protected void writenl(String s) throws IOException {
51         theWriter.write(s, 0, s.length());
52         theWriter.newLine();
53     }
54 
write(String s)55     protected void write(String s) throws IOException {
56         theWriter.write(s, 0, s.length());
57     }
58 
fileheader()59     public void fileheader() throws IOException {
60         writenl("/* ");
61 	writenl(" * GENERATED CODE");
62         writenl(" *");
63         writenl(" * Copyright 1999 Sun Microsystems, Inc.");
64         writenl(" * All rights reserved.");
65 	writenl(" *");
66         writenl(" */");
67 	writenl("");
68         writenl("package com.sun.admin.pm.client;");
69         writenl("import java.util.*;");
70     }
71 
classheader(String className)72     public void classheader(String className) throws IOException {
73         writenl("public class " + className +
74                 " extends ListResourceBundle {");
75         writenl(INDENT +
76                 "static final Object[][] pmHelpBundlecontents = {");
77     }
78 
footer()79     public void footer() throws IOException {
80         writenl(INDENT + "};");
81         writenl(INDENT + "public Object[][] getContents() {");
82         writenl(INDENT_2 + "return pmHelpBundlecontents;");
83         writenl(INDENT + "}");
84         writenl("}");
85     }
86 
87 
setTag(String tag)88     public void setTag(String tag) throws IOException {
89         theTag = new String(tag);
90     }
91 
tag(String tag)92     public void tag(String tag) throws IOException {
93         if (tag != null) {
94             writenl(NL + INDENT_2 + NOLOCALIZE);
95             writenl(INDENT_2 +
96 		"{\"" + theTag + ".tag\", \"" + tag + "\"},");
97         }
98     }
99 
title(String title)100     public void title(String title) throws IOException {
101         if (title != null) {
102             writenl(NL + INDENT_2 + LOCALIZE);
103             writenl(INDENT_2 +
104 		"{\"" + theTag + ".title\", \"" + title + "\"},");
105         }
106     }
107 
seealso(String seealso)108     public void seealso(String seealso) throws IOException {
109         if (seealso != null) {
110             writenl(NL + INDENT_2 + NOLOCALIZE);
111             writenl(INDENT_2 +
112 		"{\"" + theTag + ".seealso\", \"" + seealso + "\"},");
113         }
114     }
115 
keywords(String keywords)116     public void keywords(String keywords) throws IOException {
117         if (keywords != null) {
118             writenl(NL + INDENT_2 + LOCALIZE);
119             writenl(INDENT_2 +
120 		"{\"" + theTag + ".keywords\", \"" + keywords + "\"},");
121         }
122     }
123 
content(Vector content)124     public void content(Vector content) throws IOException {
125         if (content == null)
126             return;
127 
128         writenl(NL + INDENT_2 + LOCALIZE);
129         writenl(INDENT_2 + "{\"" + theTag + ".content\",");
130 
131         Enumeration e = content.elements();
132         while (e.hasMoreElements()) {
133             String s = (String) e.nextElement();
134             if (s.length() == 0) {
135                 if (e.hasMoreElements())
136                     continue;
137                 else {
138                     writenl(INDENT_2 + "  \"\"\n        },");
139                     break;
140                 }
141             }
142             String endOfLine = (e.hasMoreElements() ?
143                 " +" :
144                 "\n        },");
145             writenl(INDENT_2 + "  \"" + s + " \"" + endOfLine);
146         }
147     }
148 
delimiter()149     public void delimiter() throws IOException {
150         writenl(NL);
151     }
152 
commentStart()153     public void commentStart() throws IOException {
154 	writenl(COMMENTBLOCK_START);
155     }
156 
commentEnd()157     public void commentEnd() throws IOException {
158 	writenl(COMMENTBLOCK_END);
159     }
160 
comment(String s)161     public void comment(String s) throws IOException {
162 	writenl(COMMENTLINE_START + s);
163     }
164 }
165 
166 
167 
168 
169 class Article {
170     String theTitle;
171     String theKeywords;
172     String theSeeAlso;
173     Vector theContent;
174     String theTag;
175 
176     Reader r;
177 
read(Reader theReader)178     public void read(Reader theReader) {
179         r = theReader;
180 
181         Tag theTag = null;
182 
183         try {
184             while (true) {
185                 theTag = readNextTag();
186                 Debug.message("Article read: " + theTag);
187 
188                 if (theTag instanceof CommentTag) {
189                     Debug.message("Comment ignored");
190                 } else if (theTag instanceof TitleTag) {
191                     theTitle = theTag.content;
192                 } else if (theTag instanceof ContentTag) {
193                     theContent = theTag.contentVector;
194                 } else if (theTag instanceof SeeAlsoTag) {
195                     theSeeAlso = theTag.content;
196                 } else if (theTag instanceof KeywordsTag) {
197                     theKeywords = theTag.content;
198                 } else {
199                     Debug.message("Unknown tag: " + theTag);
200                 }
201             }
202         } catch (IOException x) {
203             Debug.message("Article read caught " + x);
204         }
205 
206 
207     }
208 
209 
localread()210     int localread() throws IOException {
211         int ch = r.read();
212         if (ch == -1) {
213             Debug.message("localread: eof");
214             throw new IOException();
215         }
216         // Debug.message("localread: " + ch);
217         return ch;
218     }
219 
220 
221     /*
222      * read the word within tagOpen/tagClose pair
223      */
readTagName()224     String readTagName() throws IOException {
225         String rv = null;
226         int ch;
227         StringBuffer b = new StringBuffer();
228 
229         while (true)
230             if (localread() == HelpSyntax.tagOpen)
231                 break;
232 
233         Debug.message("readTagName: got a tagOpen");
234 
235         while (true) {
236             ch = localread();
237             if (ch == HelpSyntax.tagClose)
238                 break;
239             else
240                 b.append((char) ch);
241         }
242 
243         Debug.message("readTagName: " + (new String(b)).trim());
244         return (new String(b)).trim();
245     }
246 
247 
readNextTag()248     Tag readNextTag() throws IOException {
249         Tag rv = null;
250         int ch;
251         StringBuffer b;
252 
253         String tag = readTagName();
254         Debug.message("readNextTag name: " + tag);
255 
256         if (tag.equalsIgnoreCase(HelpSyntax.tagTitle)) {
257             rv = new TitleTag();
258             rv.read(r);
259         } else if (tag.equalsIgnoreCase(HelpSyntax.tagKeywords)) {
260             rv = new KeywordsTag();
261             rv.read(r);
262         } else if (tag.equalsIgnoreCase(HelpSyntax.tagSeeAlso)) {
263             rv = new SeeAlsoTag();
264             rv.read(r);
265         } else if (tag.equalsIgnoreCase(HelpSyntax.tagContent)) {
266             rv = new ContentTag();
267             rv.readMultipleLines(r);
268         } else {
269             Debug.message("Bad tag: " + tag);
270         }
271         return rv;
272     }
273 
274 
toString()275     public String toString() {
276         return new String("Title <" + theTitle +
277                           "> Keywords <" + theKeywords +
278                           "> See-Also <" + theSeeAlso +
279                           "> Content <" + theContent + ">");
280     }
281 }
282 
283 
284 class HelpSyntax {
285     public final static int tagOpen = '<';
286     public final static int tagClose = '>';
287     public final static String startComment = "!-";
288     public final static String endComment = "--";
289     public final static String tagContent = "CONTENT";
290     public final static String tagTitle = "TITLE";
291     public final static String tagSeeAlso = "SEEALSO";
292     public final static String tagKeywords = "KEYWORDS";
293 }
294 
295 class ParseException extends Exception {
296 }
297 
298 class BadTagException extends ParseException {
299 }
300 
301 class SyntaxErrorException extends ParseException {
302 }
303 
304 abstract class Tag {
305     String content;
306     Vector contentVector;
307     protected String name;
308     protected boolean escapeQuotes = false;
309 
Tag(String s)310     public Tag(String s) {
311         content = s;
312     }
313 
Tag()314     public Tag() {
315         this(null);
316     }
317 
toString()318     public String toString() {
319         return new String(this.getClass().getName() + ": " + content);
320     }
321 
322     // respect line spacing, stuff contentVector
readMultipleLines(Reader r)323     public void readMultipleLines(Reader r) throws IOException {
324         int ch;
325         StringBuffer b = new StringBuffer();
326         Vector v = new Vector();
327         boolean spaced = false;
328 
329         while (true) {
330             ch = r.read();
331             if (ch == -1)
332                 break;
333 
334             if (ch == '\n') {
335                 v.addElement(new String(b));
336                 b = new StringBuffer();
337                 continue;
338             }
339 
340             if (Character.isWhitespace((char) ch)) {
341                 if (spaced == false) {
342                     b.append(" ");
343                     spaced = true;
344                 }
345                 continue;
346             }
347 
348             if (escapeQuotes && ch == '\"') {
349                 b.append("\\\"");
350                 continue;
351             }
352 
353             spaced = false;
354             if (ch == HelpSyntax.tagOpen) {
355                 boolean localspaced = false;
356                 boolean localopen = true;
357                 Debug.message("Tag: got a tagOpen");
358 
359                 StringBuffer tmp = new StringBuffer();
360                 while ((ch = r.read()) != HelpSyntax.tagClose) {
361                     if (Character.isWhitespace((char) ch)) {
362                         if (localspaced == false) {
363                             tmp.append(" ");
364                             localspaced = true;
365                         }
366                         continue;
367                     }
368                     tmp.append((char) ch);
369                 }
370 
371                 String t = new String(tmp);
372 
373                 if ((t.trim()).equalsIgnoreCase("/" + this.name)) {
374                     Debug.message("Tag: close tag = " + t);
375                     break;
376                 } else {
377                     Debug.message("Tag: ignoring bad close tag = " + t);
378                     b.append((char) HelpSyntax.tagOpen);
379                     b.append(t);
380                     b.append((char) HelpSyntax.tagClose);
381                 }
382             } else {
383                 b.append((char)ch);
384             }
385         }
386         contentVector = v;
387         Debug.message("Tag: contentVector = " + contentVector);
388     }
389 
390     // catenate input lines, eliminating whitespace
read(Reader r)391     public void read(Reader r) throws IOException {
392         int ch;
393         StringBuffer b = new StringBuffer();
394         boolean spaced = false;
395 
396         while (true) {
397             ch = r.read();
398             if (ch == -1)
399                 break;
400 
401             if (Character.isWhitespace((char) ch)) {
402                 if (spaced == false) {
403                     b.append(" ");
404                     spaced = true;
405                 }
406                 continue;
407             }
408 
409             if (escapeQuotes && ch == '\"') {
410                 b.append("\\\"");
411                 continue;
412             }
413 
414             spaced = false;
415             if (ch == HelpSyntax.tagOpen) {
416                 boolean localspaced = false;
417                 boolean localopen = true;
418                 Debug.message("Tag: got a tagOpen");
419 
420                 StringBuffer tmp = new StringBuffer();
421                 while ((ch = r.read()) != HelpSyntax.tagClose) {
422                     if (Character.isWhitespace((char) ch)) {
423                         if (localspaced == false) {
424                             tmp.append(" ");
425                             localspaced = true;
426                         }
427                         continue;
428                     }
429                     tmp.append((char) ch);
430                 }
431 
432                 String t = new String(tmp);
433 
434                 if ((t.trim()).equalsIgnoreCase("/" + this.name)) {
435                     Debug.message("Tag: close tag = " + t);
436                     break;
437                 } else {
438                     Debug.message("Tag: ignoring bad close tag = " + t);
439                     b.append((char) HelpSyntax.tagOpen);
440                     b.append(t);
441                     b.append((char) HelpSyntax.tagClose);
442                 }
443             } else {
444                 b.append((char)ch);
445             }
446         }
447         content = (new String(b)).trim();
448         Debug.message("Tag: content = " + content);
449     }
450 }
451 
452 class TitleTag extends Tag {
TitleTag()453     public TitleTag() {
454         name = HelpSyntax.tagTitle;
455     }
456 }
457 
458 class SeeAlsoTag extends Tag {
SeeAlsoTag()459     public SeeAlsoTag() {
460         name = HelpSyntax.tagSeeAlso;
461     }
462 }
463 
464 class ContentTag extends Tag {
ContentTag()465     public ContentTag() {
466         name = HelpSyntax.tagContent;
467         escapeQuotes = true;
468     }
469 }
470 
471 class CommentTag extends Tag {
CommentTag()472     public CommentTag() {
473         name = null;
474     }
475 }
476 
477 class KeywordsTag extends Tag {
KeywordsTag()478     public KeywordsTag() {
479         name = HelpSyntax.tagKeywords;
480         escapeQuotes = true;
481     }
482 }
483 
484 
485 
486 class parseMain {
487 
488     static String outputFileName = "pmHelpResources.java";
489     static String commentFileName = "comments.txt";
490     static int firstFile = 0;
491 
492     // returns -1 if error, 0 otherwise
parseArgs(String[] args)493     protected static int parseArgs(String[] args) {
494         int rv = 0;
495 	int i;
496 
497         for (i = 0; i < args.length; ++i) {
498             if (args[i].compareTo("-d") == 0) {
499 		if (args[i].length() > 2) {
500 		    outputFileName = args[i].substring(2);
501 		} else {
502 		    outputFileName = args[++i];
503 		}
504 	    } else if (args[i].compareTo("-c") == 0) {
505 		if (args[i].length() > 2) {
506 		    commentFileName = args[i].substring(2);
507 		} else {
508 		    commentFileName = args[++i];
509 		}
510 	    } else if (args[i].compareTo("-v") == 0) {
511 		Debug.setDebugLevel(Debug.WARNING);
512 	    } else
513 		break;	// unknown arg ==> list of files starts
514 
515         }
516 
517 	firstFile = i;
518 
519 	/*
520 	 * System.out.println("outputFileName = " + outputFileName +
521 	 *		   " commentFileName = " + commentFileName  +
522 	 *		   " firstFile = " + firstFile);
523 	 */
524 
525         return rv;
526     }
527 
528 
main(String args[])529     public static void main(String args[]) {
530         FileReader f = null;
531         FileWriter fw = null;
532         String filename = null;
533 
534         Debug.setDebugLevel(Debug.ERROR);
535 
536         // validate command line
537         if (args.length == 0) {
538             System.err.println("At least one filename required.");
539             System.exit(-1);
540         }
541 
542         if (parseArgs(args) < 0)
543             System.exit(-1);
544 
545 
546         outputFileName = outputFileName.trim();
547 
548         Debug.warning("Writing to " + outputFileName);
549 
550         try {
551 
552             // create output file
553             fw = new FileWriter(outputFileName);
554             BufferedWriter w = new BufferedWriter(fw);
555             ResourceWriter rw = new ResourceWriter(w);
556 
557 	    // imports and package statement
558             rw.fileheader();
559 
560 	    // comment block
561             File commentFile = new File(commentFileName);
562 	    if (commentFile.exists()) {
563                 rw.delimiter();
564 		rw.commentStart();
565 		BufferedReader comments =
566 			new BufferedReader(new FileReader(commentFileName));
567 		String commentLine;
568 		while ((commentLine = comments.readLine()) != null)
569 		    rw.comment(commentLine);
570 		comments.close();
571 		rw.commentEnd();
572                 rw.delimiter();
573 	    } else {
574 		Debug.error("Comment file " + commentFileName +
575 								" not found.");
576 	    }
577 
578 	    // create class name w/o extension or leading path
579 	    File cf = new File(outputFileName);
580 	    String className = cf.getName();
581 
582             // class name is output filename w/o extension
583             int dotIndex = className.indexOf(".");
584             if (dotIndex < 0)
585                 dotIndex = className.length();
586 
587             className = className.substring(0, dotIndex);
588 
589 	    // class definition
590             rw.classheader(className);
591 
592             // iterate over input files
593             for (int i = firstFile; i < args.length; ++i) {
594                 filename = args[i];
595                 Debug.warning("Reading file " + filename);
596 
597                 try {
598                     f = new FileReader(filename);
599                 } catch (Exception x) {
600                     Debug.fatal(x.toString());
601                     return;
602                 }
603 
604                 BufferedReader r = new BufferedReader(f);
605 
606                 Article a = new Article();
607                 a.read(r);
608                 // System.out.println(a);
609 
610                 // process the Article
611 
612                 String tagName = filenameToTag(filename);
613                 Debug.warning("Creating tag " + tagName);
614 
615                 // HTML syntax checking on content
616                 if (!validHTMLSyntax(a.theContent))
617                     throw new IOException(
618                         "Bad HTML syntax in article " + tagName);
619 
620 
621                 rw.setTag(tagName);
622                 rw.tag(tagName);
623                 rw.seealso(a.theSeeAlso);
624                 rw.title(a.theTitle);
625                 rw.keywords(a.theKeywords);
626                 rw.content(a.theContent);
627                 rw.delimiter();
628             }
629 
630             rw.footer();
631             rw.close();
632             w.close();
633         } catch (IOException x) {
634             Debug.fatal(x.toString());
635 
636             // try to unlink the broken output file
637             boolean unlink = true;
638 
639             try {
640                 fw.close();
641             } catch (IOException xx) {
642                 Debug.error(xx.toString());
643                 unlink = false;
644             }
645 
646             if (unlink) {
647                 File theFile = new File(outputFileName);
648 
649                 Debug.warning("Deleting file " + outputFileName);
650 
651                 if (theFile.exists())
652                     theFile.delete();
653             }
654 
655             System.exit(-2);
656         }
657     }
658 
659 
660     // return true if no syntax errors found
validHTMLSyntax(String s)661     static boolean validHTMLSyntax(String s) {
662 
663         if (s == null)
664             return true;
665 
666         // check only for <b>..</b> pairs
667 
668         String src = s.toLowerCase();   // html tags are case-neutral
669 
670         int i;
671 
672         int opens = 0;
673         for (i = src.indexOf("<b>");
674              i != -1;
675              i = src.indexOf("<b>", i + 1))
676             ++opens;
677 
678         int closes = 0;
679         for (i = src.indexOf("</b>");
680             i != -1;
681             i = src.indexOf("</b>", i + 1))
682             ++closes;
683 
684         // System.out.println("syntax: " + opens + " " + closes);
685 
686         return opens == closes;
687 
688     }
689 
690     // return true if no syntax errors found
validHTMLSyntax(Vector v)691     static boolean validHTMLSyntax(Vector v) {
692         String s = new String();
693         Enumeration e = v.elements();
694         while (e.hasMoreElements())
695             s = s + (String) e.nextElement();
696         return validHTMLSyntax(s);
697     }
698 
699     /*
700      * extract the tag name from a filename, possibly containing
701      * a fully qualified path as well as a complex extension.
702      */
filenameToTag(String filename)703     static String filenameToTag(String filename) {
704 
705         // the help tag is the filename exclusive of path or extensions
706 
707         File f = new File(filename);
708         String s = f.getName();
709         int period = s.indexOf('.');
710         // System.out.println("filename: " + s);
711         if (period < 0)
712             period = filename.length();
713         // System.out.println("period = " + period);
714         return s.substring(0, period);
715     }
716 
717 
718 }
719 
720 class Debug {
721 
722     /**
723      * Log a highest-priority message.
724      * @param String s The message to be logged.
725      */
fatal(String s)726     static public void fatal(String s) {
727         printIf(s, FATAL);
728     }
729 
730     /**
731      * Log a highest-priority message.
732      * @param String s The message to be logged.
733      */
error(String s)734     static public void error(String s) {
735         printIf(s, ERROR);
736     }
737 
738     /**
739      * Log a highest-priority message.
740      * @param String s The message to be logged.
741      */
warning(String s)742     static public void warning(String s) {
743         printIf(s, WARNING);
744     }
745 
746     /**
747      * Log a highest-priority message.
748      * @param String s The message to be logged.
749      */
message(String s)750     static public void message(String s) {
751         printIf(s, MESSAGE);
752     }
753 
754     /**
755      * Log a highest-priority message.
756      * @param String s The message to be logged.
757      */
setDebugLevel(int lvl)758     static public void setDebugLevel(int lvl) {
759         if (lvl < ALL || lvl > NONE)
760             return;
761 
762         globalDebugLevel = lvl;
763     }
764 
printIf(String s, int lvl)765     private static void printIf(String s, int lvl) {
766         if (lvl < globalDebugLevel)
767             return;
768         DebugPrint(s);
769     }
770 
771     // here is where we could hide syslog or file destination...
DebugPrint(String s)772     private static void DebugPrint(String s) {
773         System.out.println(s);         // for now
774     }
775 
776 
777     /**
778      * Verbosity level to suppress all messages.
779      */
780     static public final int NONE = 5;
781 
782     /**
783      * Verbosity level to log only highest-priority messages.
784      */
785     static public final int FATAL = 4;
786 
787     /**
788      * Verbosity level to log  high- and highest-priority messages.
789      */
790     static public final int ERROR = 3;
791 
792     /**
793      * Verbosity level to log medium-, high-, and
794      * highest-priority messages.
795      */
796     static public final int WARNING = 2;
797 
798     /**
799      * Verbosity level to log low-, medium-, high-, and
800      *  highest-priority messages.
801      */
802     static public final int MESSAGE = 1;
803 
804     /**
805      * Verbosity level to log all messages.
806      */
807     static public final int ALL = 0;
808 
809     private static int globalDebugLevel = ERROR;
810 
811 }
812