1
/*******************************************************************************
2
* Copyright (c) 2007 Red Hat Inc..
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* Red Hat Incorporated - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.linuxtools.cdt.libhover.texinfoparsers;
12
import java.io.BufferedReader;
13
import java.io.BufferedWriter;
15
import java.io.FileReader;
16
import java.io.FileWriter;
17
import java.io.FilenameFilter;
18
import java.io.IOException;
19
import java.util.ArrayList;
20
import java.util.HashMap;
21
import java.util.List;
23
import java.util.regex.Matcher;
24
import java.util.regex.Pattern;
26
//This file contains a texinfo parser that can be
27
//run to create the Autotools glibc.xml file.
28
//Usage is as follows:
29
//1. compile this file using javac
30
//2. run this file using java, passing the
31
//arguments: dir_to_automake_texi_files output_xml_file_name
33
public class ParseAutomakeTexinfo {
35
static final boolean DEBUG = false;
37
static final String ATcmd = "(@\\w*)";
39
// Currently in automake docs, the macro section starts with
40
// a subsection as below and a table which contains macros which
41
// are item and itemx entries.
42
static final String MacrosStart = "@subsection\\sPublic\\smacros";
43
static final String OldMacrosStart = "@section\\sAutoconf\\smacros.*";
44
static final Pattern MacroSection1 = Pattern.compile(MacrosStart);
45
static final Pattern MacroSection2 = Pattern.compile(OldMacrosStart);
47
static final String Defmac = "@item";
48
static final String Defmacx = "@itemx";
51
static final String MacroName = "(\\w*)";
52
static final int MacroNameIndex = 1;
55
static final String Parms = "(\\((.*)\\))";
56
static final int ParmsIndex = 2;
58
static final String rest = ".*";
60
static final String WhiteSpace = "\\s*";
62
static final Pattern MacroPattern
63
= Pattern.compile("^" + Defmac + WhiteSpace +
64
MacroName + WhiteSpace +
66
rest, Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);
68
static final Pattern MacroPattern2
69
= Pattern.compile("^" + Defmac + WhiteSpace + MacroName + rest,
70
Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);
72
static final Pattern MacroPatternx
73
= Pattern.compile("^" + Defmacx + WhiteSpace +
74
MacroName + WhiteSpace +
76
rest, Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);
78
static final Pattern MacroPatternx2
79
= Pattern.compile("^" + Defmacx + WhiteSpace + MacroName + rest,
80
Pattern.MULTILINE + Pattern.CASE_INSENSITIVE);
82
static final Pattern ParmBracketPattern = Pattern.compile("\\((.*)\\)");
83
static final Pattern IndexPattern = Pattern.compile("@\\w*index.*");
84
static final Pattern IndexPattern2 = Pattern.compile("@\\w*index\\{[a-zA-Z0-9_@\\{\\}]*\\}");
85
static final Pattern ExamplePattern = Pattern.compile("@example");
86
static final Pattern EndExamplePattern = Pattern.compile("@end\\s+example");
87
static final Pattern EnumeratePattern = Pattern.compile("@enumerate");
88
static final Pattern EndEnumeratePattern = Pattern.compile("@end\\s+enumerate");
89
static final Pattern VerbatimPattern = Pattern.compile("@verbatim");
90
static final Pattern ItemPattern = Pattern.compile("@item");
91
static final Pattern NoIndentPattern = Pattern.compile("@noindent");
92
static final Pattern BRPattern = Pattern.compile("<br>");
93
static final Pattern EOLPattern = Pattern.compile("<eol>");
94
static final Pattern EndVerbatimPattern = Pattern.compile("@end\\s+verbatim");
95
static final Pattern TableSampItemPattern = Pattern.compile("(@table\\s*@samp.*)@item\\s*([a-zA-Z_0-9+\\-<>/ ]*)<eol>(.*@end\\s*table)", Pattern.DOTALL);
96
static final Pattern TableAsisItemPattern = Pattern.compile("(@table\\s*@asis.*)@item\\s*([a-zA-Z_0-9+\\-,<>/ ]*)<eol>(.*@end\\s*table)", Pattern.DOTALL);
97
static final Pattern TableSampPattern = Pattern.compile("@table\\s*@samp", Pattern.MULTILINE);
98
static final Pattern TableAsisPattern = Pattern.compile("@table\\s*@asis", Pattern.MULTILINE);
99
static final Pattern EndTablePattern = Pattern.compile("@end\\s+table");
100
static final Pattern DotsPattern = Pattern.compile("@dots\\{\\}");
101
static final Pattern ItemizeMinusPattern= Pattern.compile("@itemize\\s+@minus" + "(.*)" + "@end\\s+itemize", Pattern.MULTILINE);
102
static final Pattern ItemizeBulletPattern= Pattern.compile("@itemize\\s+@bullet" + "(.*)" + "@end\\s+itemize", Pattern.MULTILINE);
103
static final Pattern XrefPattern = Pattern.compile("@xref\\{[^\\}]*\\}", Pattern.MULTILINE);
104
static final Pattern CommandPattern = Pattern.compile("@command\\{([^\\}]*)\\}");
105
static final Pattern KbdPattern = Pattern.compile("@kbd\\{([^\\}]*)\\}");
106
static final Pattern RPattern = Pattern.compile("@r\\{([^\\}]*)\\}");
107
static final Pattern FilePattern = Pattern.compile("@file\\{([^\\}]*)\\}");
108
static final Pattern VarPattern = Pattern.compile("@var\\{([^\\}]*)\\}");
109
static final Pattern OVarPattern = Pattern.compile("@ovar\\{([^\\}]*)\\}");
110
static final Pattern DVarPattern = Pattern.compile("@dvar\\{([^\\},\\,]*),([^\\}]*)\\}");
111
static final Pattern CodePattern = Pattern.compile("@code\\{([^\\}]*)\\}");
112
static final Pattern EmphPattern = Pattern.compile("@emph\\{([^\\}]*)\\}");
113
static final Pattern SampPattern = Pattern.compile("@samp\\{([^\\}]*)\\}");
114
static final Pattern OptionPattern = Pattern.compile("@option\\{([^\\}]*)\\}");
115
static final Pattern UrefPattern = Pattern.compile("@uref\\{([^,]*),\\s+([^\\}]*)\\}");
116
static final Pattern TagPattern = Pattern.compile("@\\w*\\{([^\\}]*)\\}");
117
static final Pattern AmpersandPattern = Pattern.compile("&");
118
static final Pattern LeftAnglePattern = Pattern.compile("<");
119
static final Pattern RightAnglePattern = Pattern.compile(">");
122
private static Map macroMap;
124
static class MacroParms {
126
MacroParms nextParms = null;
128
public MacroParms(String[] parms) {
133
static class MacroDef {
135
MacroParms Parameters;
139
static class TPElement {
148
TPElement[] TPElements;
149
Object[] IncludeList;
152
private static String killTagsParms(String tt) {
155
mm = ParmBracketPattern.matcher(tt);
156
tt= mm.replaceAll("$1");
158
mm = OVarPattern.matcher(tt);
159
tt = mm.replaceAll("[$1]");
161
mm = DVarPattern.matcher(tt);
162
tt = mm.replaceAll("[$1=$2]");
164
mm = VarPattern.matcher(tt);
165
tt = mm.replaceAll("$1");
167
mm = RPattern.matcher(tt);
168
tt = mm.replaceAll("$1");
170
mm = DotsPattern.matcher(tt);
171
tt = mm.replaceAll("...");
177
private static String killTags(String tt) {
182
mm = XrefPattern.matcher(tt);
184
tt = mm.replaceAll("");
189
mm = IndexPattern.matcher(tt);
191
tt = mm.replaceAll("");
196
mm = IndexPattern2.matcher(tt);
198
tt = mm.replaceAll("");
203
mm = NoIndentPattern.matcher(tt);
205
tt = mm.replaceAll("");
210
mm = VarPattern.matcher(tt);
212
tt = mm.replaceAll("<VAR>$1</VAR>");
217
mm = DotsPattern.matcher(tt);
219
tt = mm.replaceAll("<small>...</small>");
224
mm = CommandPattern.matcher(tt);
226
tt = mm.replaceAll("<CODE>$1</CODE>");
231
mm = CodePattern.matcher(tt);
233
tt = mm.replaceAll("<CODE>$1</CODE>");
238
mm = UrefPattern.matcher(tt);
240
tt = mm.replaceAll("<A HREF=\"$1>$2</A>");
245
mm = KbdPattern.matcher(tt);
247
tt = mm.replaceAll("<KBD>$1</KBD>");
252
mm = EmphPattern.matcher(tt);
254
tt = mm.replaceAll("<EM>$1</EM>");
259
mm = FilePattern.matcher(tt);
261
tt = mm.replaceAll("<TT>$1</TT>");
267
mm = VerbatimPattern.matcher(tt);
269
tt = mm.replaceAll("<CODE>");
274
mm = EndVerbatimPattern.matcher(tt);
276
tt = mm.replaceAll("</CODE>");
281
mm = SampPattern.matcher(tt);
283
tt = mm.replaceAll("<samp>$1</samp>");
288
mm = OptionPattern.matcher(tt);
290
tt = mm.replaceAll("<samp>$1</samp>");
295
mm = ExamplePattern.matcher(tt);
297
tt = mm.replaceAll("<TABLE><tr><td> </td><td class=example><pre>");
302
mm = EndExamplePattern.matcher(tt);
304
tt = mm.replaceAll("</pre></td></tr></table>");
309
mm = EnumeratePattern.matcher(tt);
311
tt = mm.replaceAll("<OL>");
316
mm = EndEnumeratePattern.matcher(tt);
318
tt = mm.replaceAll("</OL>");
323
mm = TableSampItemPattern.matcher(tt);
326
System.out.println("group 1 is " + mm.group(1));
327
System.out.println("group 2 is " + mm.group(2));
328
System.out.println("group 3 is " + mm.group(3));
330
tt = mm.replaceAll("$1<DT>'<SAMP>$2</SAMP>'\n<DD>$3");
335
mm = TableAsisItemPattern.matcher(tt);
337
tt = mm.replaceAll("$1<DT>$2\n<DD>$3");
342
mm = TableSampPattern.matcher(tt);
344
tt = mm.replaceAll("<DL>\n");
349
mm = TableAsisPattern.matcher(tt);
351
tt = mm.replaceAll("<DL>\n");
356
mm = EndTablePattern.matcher(tt);
358
tt = mm.replaceAll("</DL>");
361
//FIXME: if there ever is a @itemize @bullet within a
362
// @itemize @minus or vice-versa, the following
363
// logic will get it wrong.
366
mm = ItemizeMinusPattern.matcher(tt);
368
tt = mm.replaceAll("<UL>$1</UL>");
373
mm = ItemizeBulletPattern.matcher(tt);
375
tt = mm.replaceAll("<OL>$1</OL>");
380
mm = ItemPattern.matcher(tt);
382
tt = mm.replaceAll("<LI>");
387
mm = TagPattern.matcher(tt);
389
tt = mm.replaceAll("$1");
392
mm = AmpersandPattern.matcher(tt);
393
tt = mm.replaceAll("&");
395
mm = LeftAnglePattern.matcher(tt);
396
tt = mm.replaceAll("<");
398
mm = RightAnglePattern.matcher(tt);
399
tt = mm.replaceAll(">");
401
// Clean up the eol markers we used to mark end of line for items
402
mm = EOLPattern.matcher(tt);
403
tt = mm.replaceAll("");
408
private static MacroDef BuildMacroDef(Matcher m) {
409
MacroDef md = new MacroDef();
411
md.MacroName = m.group(MacroNameIndex);
413
if (null != m.group(ParmsIndex)) {
414
String tt = killTagsParms(m.group(ParmsIndex));
415
String[] parms = tt.split(",\\s");
416
md.Parameters = new MacroParms(parms);
421
private static MacroParms AddMacroDefxParms(MacroParms mp, Matcher mx) {
422
if (null != mx.group(ParmsIndex)) {
423
String tt = killTagsParms(mx.group(ParmsIndex));
424
String[] parms = tt.split(",\\s");
425
MacroParms mpnew = new MacroParms(parms);
426
mp.nextParms = mpnew;
432
private static MacroDef HandleMacroDef(BufferedReader is, String s) throws IOException {
435
Matcher m = MacroPattern.matcher(s);
438
fd = BuildMacroDef(m);
440
else { // assume the line got split and retry
442
String il = is.readLine();
443
m = MacroPattern.matcher(s + il);
444
if (m.matches()) fd = BuildMacroDef(m);
447
m = MacroPattern2.matcher(s);
450
fd.MacroName = m.group(MacroNameIndex);
451
fd.Parameters = new MacroParms(new String[0]);
457
// Look for @defmacx which are alternate prototypes for the macro
459
String il = is.readLine();
461
Matcher mx = MacroPatternx.matcher(il);
462
Matcher mx2 = MacroPatternx2.matcher(il);
463
MacroParms mp = fd.Parameters;
464
while (mx.matches() || mx2.matches()) {
466
mp = AddMacroDefxParms(mp, mx);
468
MacroParms mpnew = new MacroParms(new String[0]);
469
mp.nextParms = mpnew;
475
mx = MacroPatternx.matcher(il);
476
mx2 = MacroPatternx2.matcher(il);
482
if (macroMap.get(fd.MacroName) != null)
484
macroMap.put(fd.MacroName, fd);
490
private static void WriteString(BufferedWriter os, String s) throws IOException {
491
// System.out.println(s);
492
os.write(s+"\n", 0, 1+s.length());
495
private static void CreateHeader(BufferedWriter os) throws IOException {
496
WriteString(os, "<!-- This file automatically generated by ParseAutomakeTexinfo utility -->");
497
WriteString(os, "<!-- cvs -d:pserver:anonymous@sources.redhat.com:/cvs/eclipse \\ -->");
498
WriteString(os, "<!-- co autotools/ParseTexinfo -->");
499
WriteString(os, "<!DOCTYPE macros [");
501
WriteString(os, " <!ELEMENT macros (macro)*>");
503
WriteString(os, " <!ELEMENT macro (prototype*,synopsis)>");
504
WriteString(os, " <!ATTLIST macro");
505
WriteString(os, " id ID #REQUIRED");
506
WriteString(os, " >");
508
WriteString(os, " <!ELEMENT synopsis (#PCDATA)*>");
510
WriteString(os, " <!ELEMENT prototype (parameter+)?>");
512
WriteString(os, " <!ELEMENT parameter (#PCDATA)*>");
513
WriteString(os, " <!ATTLIST parameter");
514
WriteString(os, " content CDATA #REQUIRED");
515
WriteString(os, " >");
517
WriteString(os, "]>");
523
private static void CreateTrailer(BufferedWriter os) throws IOException {
524
WriteString(os, "</macros>");
527
private static void WriteSynopsis(BufferedWriter os, String Synopsis, boolean indent) throws IOException {
528
String ss = Synopsis;
529
String[] tt = ss.split("\\s");
531
String spaces = indent ? " " : " ";
532
WriteString(os, spaces + "<synopsis>");
533
if (null != Synopsis) {
534
for (int pp = 0; pp < tt.length; pp++) {
535
if (tt[pp].equals("<br>")) {
536
WriteString(os, spaces + aa + "</P><P>\n");
540
if ((aa.length() + tt[pp].length()) > 64) {
541
WriteString(os, spaces + aa);
544
aa = aa + " " + tt[pp];
548
if (aa.length() > 0) WriteString(os, " " + aa);
549
WriteString(os, spaces + "</synopsis>");
552
private static void HandleDefmacro(BufferedWriter os, BufferedReader is, String s) throws IOException {
555
List FDefs = new ArrayList();
557
while (null != (il = is.readLine())) {
558
if (il.startsWith(Defmac)) {
559
if (null != (md = HandleMacroDef(is, il))) FDefs.add(md);
561
else if (il.startsWith("@comment") ||
562
il.startsWith("@c ")) { // comment -- ignore it
564
else if (il.startsWith("@subsection") ||
565
il.startsWith("@section")) {
566
for (int kk = 0; kk < FDefs.size(); kk++) {
567
md = (MacroDef)FDefs.get(kk);
569
WriteString(os, " <macro id=\"" + md.MacroName + "\">");
571
MacroParms mp = md.Parameters;
573
WriteString(os, " <prototype>");
574
String[] parms = mp.parms;
575
for (int i = 0; i < parms.length; i++) {
576
WriteString(os, " <parameter content=\"" + parms[i] + "\"/>");
578
WriteString(os, " </prototype>");
580
} while (mp != null);
582
if (null != md.Synopsis) WriteSynopsis(os, md.Synopsis, false);
584
WriteString(os, " </macro>");
590
md.Synopsis = ((md.Synopsis == null) ? "" : md.Synopsis + " " ) + ((il.length() == 0) ? "<br><br>" :
591
il.startsWith("@item") ? killTags(il) + "<eol>" : killTags(il));
598
private static class OnlyTexi implements FilenameFilter {
599
public boolean accept(File dir, String s) {
600
return (s.endsWith(".texi")) ? true : false;
604
public static void BuildXMLFromTexinfo(String srcdir, String dstdir) {
606
macroMap = new HashMap();
607
BufferedWriter os = new BufferedWriter(new FileWriter(dstdir));
610
// CreateLicense(os);
612
WriteString(os, "<macros>");
615
String[] dir = new java.io.File(srcdir).list(new OnlyTexi());
616
for (int i = 0; i < dir.length; i++) {
617
String qFile = srcdir.endsWith("/")
619
: srcdir + "/" + dir[i];
622
BufferedReader is = new BufferedReader(new FileReader(qFile));
625
while (null != (il = is.readLine())) {
626
Matcher mm1 = MacroSection1.matcher(il);
627
Matcher mm2 = MacroSection2.matcher(il);
628
if (mm1.matches() || mm2.matches()) {
629
HandleDefmacro(os, is, il);
634
catch (IOException e) {
635
System.out.println("Input File IOException: " + e);
640
catch (NullPointerException e) {
641
System.out.println("NullPointerException: " + e);
649
catch (IOException e) {
650
System.out.println("Output File IOException: " + e);
655
public static void main(String[] args) {
656
// arg[0] is input directory containing .texi documents to read
657
// arg[1] is output xml file to create
658
BuildXMLFromTexinfo(args[0], args[1]);