KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > kawa > util > PreProcess


1 // Copyright (c) 2005 Per M.A. Bothner
2
// This is free software; for terms and warranty disclaimer see COPYING.
3

4 package gnu.kawa.util;
5 import java.io.*;
6 import java.util.*;
7
8 /** Help class to pre-process Java source. */
9
10 public class PreProcess
11 {
12   // JAVA5:
13
// Hashtable<String,Boolean> keywords = new Hashtable<String,Boolean>();
14
Hashtable keywords = new Hashtable();
15
16   String JavaDoc filename;
17   int lineno;
18
19   void error(String JavaDoc msg)
20   {
21     System.err.println(filename+':'+lineno+": "+msg);
22     System.exit(-1);
23   }
24
25   public void filter (String JavaDoc filename) throws Throwable JavaDoc
26   {
27     this.filename = filename;
28     boolean changed = false;
29     BufferedInputStream in
30       = new BufferedInputStream(new FileInputStream(filename));
31     
32     byte[] buf = new byte[2000];
33     int len = 0;;
34     int lineStart = 0;
35     int dataStart = -1;
36     int cmdLine= 0;
37     lineno = 1;
38     // If non-negative, comment out at this indentation.
39
int commentAt = -1;
40     int curIndent = 0;
41     int nesting = 0;
42     // If currently skipping, the nesting level of the controlling
43
// conditional. Otherwise, 0.
44
int skipNesting = 0;
45     String JavaDoc cmd = null;
46     int changedLine = 0; // -1: comment added or moved; +1 comment removed
47
for (;;)
48       {
49     int c = in.read();
50     if (c < 0)
51       break;
52     if (len + 10 >= buf.length) // Allow a little extra for look-ahead.
53
{
54         byte[] nbuf = new byte[2 * len];
55         System.arraycopy(buf, 0, nbuf, 0, len);
56         buf = nbuf;
57       }
58     if (c == '\n' && len > 0 && buf[len-1] == '\r')
59       {
60         buf[len++] = (byte) c;
61         continue;
62       }
63     if (commentAt >= 0 && dataStart < 0 && changedLine <= 0
64         && c != '\r' && c != '\n'
65         && (commentAt == curIndent
66         || (c != ' ' && c != '\t')))
67       {
68         boolean doComment;
69         if (c == '/')
70           {
71         // This is a little tricky. We want to comment out regular
72
// comments, because they might continue over multiple lines,
73
// or because they might be documentation comments (which
74
// we want to comment out so javadoc doesn't see them).
75
// However, we don't want to comment out directives.
76
in.mark(100);
77         int d = in.read();
78         if (d == '/')
79           doComment = false;
80         else if (d == '*')
81           {
82             do { d = in.read(); } while (d == ' ' || d == '\t');
83             doComment = d != '#';
84           }
85         else
86           doComment = true;
87         in.reset();
88           }
89         else
90           doComment = true;
91         if (doComment)
92           {
93         buf[len++] = '/';
94         buf[len++] = '/';
95         buf[len++] = ' ';
96         changedLine = 1;
97                 changed = true;
98           }
99       }
100     if (c != ' ' && c != '\t' && dataStart < 0)
101       {
102         // First non-space character.
103
dataStart = len;
104         if (nesting > 0 && commentAt != curIndent && c == '/')
105           {
106         c = in.read();
107         if (c < 0)
108           break;
109         else if (c != '/')
110           buf[len++] = '/';
111         else
112           {
113             c = in.read();
114             if (c < 0)
115               break;
116             changedLine = -1;
117                     changed = true;
118             if (c == ' ')
119                       {
120                         c = in.read();
121                         if (c == ' ' || c == '\t')
122                           dataStart = -1;
123                       }
124           }
125           }
126       }
127     buf[len] = (byte) c;
128     len++;
129     if (c == '\r' || c == '\n')
130       {
131         int firstNonSpace = -1;
132         int lastNonSpace = 0;
133         for (int i = lineStart; i < len-1; i++)
134           {
135         if (buf[i] != ' ' && buf[i] != '\t')
136           {
137             lastNonSpace = i;
138             if (firstNonSpace < 0)
139               firstNonSpace = i;
140           }
141           }
142         if (lastNonSpace - firstNonSpace >= 4
143         && buf[firstNonSpace] == '/'
144         && buf[firstNonSpace+1] == '*'
145         && buf[lastNonSpace-1] == '*'
146         && buf[lastNonSpace] == '/')
147           {
148         firstNonSpace += 2;
149         while (firstNonSpace < lastNonSpace
150                && buf[firstNonSpace] == ' ')
151           firstNonSpace++;
152         lastNonSpace -= 2;
153         while (lastNonSpace > firstNonSpace
154                && buf[lastNonSpace] == ' ')
155           lastNonSpace--;
156         if (buf[firstNonSpace] == '#')
157           {
158             String JavaDoc cmnt = new String JavaDoc(buf, firstNonSpace,
159                          lastNonSpace - firstNonSpace + 1,
160                          "ISO-8859-1");
161             int sp = cmnt.indexOf(' ');
162             String JavaDoc rest;
163             Object JavaDoc binding;
164             cmdLine = lineno;
165             if (sp > 0)
166               {
167             cmd = cmnt.substring(0, sp);
168             rest = cmnt.substring(sp).trim();
169             binding = keywords.get(rest);
170               }
171             else
172               {
173             cmd = cmnt;
174             rest = "";
175             binding = null;
176               }
177             if ("#ifdef".equals(cmd) || "#ifndef".equals(cmd))
178               {
179             if (binding == null)
180               {
181                 System.err.println(filename+":"+lineno
182                            +": warning - undefined keyword: "+rest);
183                 binding = Boolean.FALSE;
184               }
185             nesting++;
186                         if (skipNesting > 0)
187                           commentAt = curIndent;
188                         else if ((cmd.charAt(3) == 'n')
189                                  != (binding == Boolean.FALSE))
190                           {
191                             commentAt = curIndent;
192                             skipNesting = nesting;
193                           }
194               }
195             else if ("#else".equals(cmd))
196               {
197             if (nesting == 0)
198               error("unexpected "+cmd);
199                         else if (nesting == skipNesting)
200                           {
201                             commentAt = -1;
202                             skipNesting = 0;
203                           }
204                         else
205                           {
206                             commentAt = curIndent;
207                             if (skipNesting == 0)
208                               skipNesting = nesting;
209                           }
210               }
211             else if ("#endif".equals(cmd))
212               {
213             if (nesting == 0)
214               error("unexpected "+cmd);
215                         if (nesting == skipNesting)
216                           {
217                             skipNesting = 0;
218                             commentAt = -1;
219                           }
220                         else if (skipNesting > 0)
221                           commentAt = curIndent;
222             nesting--;
223               }
224             else
225               error("unknown command: "+cmnt);
226           }
227           }
228         lineStart = len;
229         dataStart = -1;
230         curIndent = 0;
231         lineno++;
232         changedLine = 0;
233       }
234     else if (dataStart < 0)
235       curIndent = c == '\t' ? (curIndent + 8) & ~7 : curIndent + 1;
236       }
237     if (nesting != 0)
238       {
239     lineno = cmdLine;
240     error("unterminated "+cmd);
241       }
242     if (changed)
243       {
244     FileOutputStream out = new FileOutputStream(filename);
245     out.write(buf, 0, len);
246     out.close();
247     System.err.println("Pre-processed "+filename);
248       }
249   }
250
251   public static void main (String JavaDoc[] args)
252   {
253     PreProcess pp = new PreProcess();
254  
255     pp.keywords.put("true", Boolean.TRUE);
256     pp.keywords.put("false", Boolean.FALSE);
257
258     for (int i = 0; i < args.length; i++)
259       {
260     String JavaDoc arg = args[i];
261     if (arg.charAt(0) == '+')
262       pp.keywords.put(arg.substring(1), Boolean.TRUE);
263     else if (arg.charAt(0) == '-')
264       {
265         int eq = arg.indexOf('=');
266         if (eq > 1)
267           {
268         String JavaDoc keyword
269           = arg.substring(arg.charAt(1) == '-' ? 2 :1, eq);
270         String JavaDoc value = arg.substring(eq+1);
271         Boolean JavaDoc b = Boolean.FALSE;
272         if (value.equalsIgnoreCase("true"))
273           b = Boolean.TRUE;
274         else if (! value.equalsIgnoreCase("false"))
275           {
276             System.err.println("invalid value "+value+" for "+keyword);
277             System.exit(-1);
278           }
279         pp.keywords.put(keyword, b);
280           }
281         else
282           pp.keywords.put(arg.substring(1), Boolean.FALSE);
283       }
284     else
285       {
286         try
287           {
288         pp.filter(arg);
289           }
290         catch (Throwable JavaDoc ex)
291           {
292         System.err.println("caught "+ex);
293         ex.printStackTrace();
294         System.exit(-1);
295           }
296       }
297       }
298   }
299 }
300
Popular Tags