KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > util > cpp > lib > JPP


1 /***
2  * Jonathan: an Open Distributed Processing Environment
3  *
4  * The contents of this file are subject to the JOnAS Public License Version
5  * 1.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License on the JOnAS web site. *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
10  * See the License for the specific terms governing rights and limitations under
11  * the License.
12  *
13  * The Original Code is JOnAS application server code released July 1999.
14  *
15  * The Initial Developer of the Original Code is Bull S.A.
16  * The Original Code and portions created by Bull S.A. are
17  * Copyright (C) 1999 Bull S.A. All Rights Reserved.
18  *
19  * Contributor(s): François Horn (rewrite for Jonathan).
20  * Philippe Merle (updated for OpenCCM).
21  * --------------------------------------------------------------------
22  * $Id: JPP.java,v 1.1 2004/02/05 20:29:57 rouvoy Exp $
23  */

24
25 // Changes done by Philippe Merle.
26
// * Changed original package name i.e. org.objectweb.jonathan.tools
27
// * Correction for displaying unknown included file names correctly
28
// * Replaced System.out by System.err
29
// * Include files only if possible (i.e. negTest<=0)
30
// * Updated error messages
31

32 package org.objectweb.util.cpp.lib;
33
34 import java.io.BufferedReader JavaDoc;
35 import java.io.File JavaDoc;
36 import java.io.FileInputStream JavaDoc;
37 import java.io.FilterInputStream JavaDoc;
38 import java.io.IOException JavaDoc;
39 import java.io.InputStream JavaDoc;
40 import java.io.InputStreamReader JavaDoc;
41 import java.io.OutputStream JavaDoc;
42 import java.util.Enumeration JavaDoc;
43 import java.util.StringTokenizer JavaDoc;
44 import java.util.Hashtable JavaDoc;
45 import java.util.Vector JavaDoc;
46 import java.util.Stack JavaDoc;
47
48 /**
49  * JPP as Java PreProcessor.
50  * This class allows to preprocess a jpp file included the directives
51  * <ul>
52  * <li>
53  * #include
54  * <li>
55  * #ifdef
56  * <li>
57  * #ifndef
58  * <li>
59  * #else
60  * <li>
61  * #endif
62  * </ul>
63  */

64
65 public class JPP {
66     private static final int JPP_INST_NB = 9;
67     public static final int NO_JPP_INST = -1;
68     public static final int INST_INCLUDE = 0;
69     public static final int INST_DEFINE = 1;
70     public static final int INST_IFDEF = 2;
71     public static final int INST_IFNDEF = 3;
72     public static final int INST_IF = 4;
73     public static final int INST_ELSE = 5;
74     public static final int INST_ELIF = 6;
75     public static final int INST_ENDIF = 7;
76     public static final int INST_UNDEF = 8;
77
78     public static final int BUFSIZE = 1024;
79
80     static final String JavaDoc[] INST_TOKEN =
81         { "#include","#define","#ifdef","#ifndef","#if","#else","#elif","#endif","#undef" };
82     private static final String JavaDoc JAVA_DELIM = " \t\n\r;,.{}()[]+-*/%<>=&|!?:#";
83
84     private static final String JavaDoc NULLSTRING = "";
85     private static final Object JavaDoc NULLSCOPE = new Object JavaDoc();
86     private static final Object JavaDoc IFSCOPE = new Object JavaDoc();
87     private static final Object JavaDoc ELSESCOPE = new Object JavaDoc();
88
89     Hashtable JavaDoc defined_names = new Hashtable JavaDoc();
90     int nb_defs = 0;
91    
92     private static int jppToken(String JavaDoc nm) {
93         for (int i = 0;i<JPP_INST_NB;i++) if (nm.startsWith(INST_TOKEN[i])) return i;
94         return -1;
95     }
96
97     private JPPExpandedStream jpp_fIn;
98     private OutputStream JavaDoc jpp_fOut;
99     private int errorNumber = 0;
100
101     /* *************************************************************************
102      * This included class provides an inputstream offering a readLine() method
103      * and handling #include directives.
104      ************************************************************************* */

105
106     static class JPPExpandedStream {
107         Vector JavaDoc iDirs = null;
108       
109         Stack JavaDoc fStack = null;
110         Stack JavaDoc nameStack = null;
111         Stack JavaDoc nbStack = null;
112       
113 // DataInputStream fCur = null;
114
BufferedReader JavaDoc fCur = null;
115         String JavaDoc nameCur = null;
116         int nbCur = -1;
117       
118       
119         JPPExpandedStream (String JavaDoc fileName, Vector JavaDoc includeDirs) throws java.io.IOException JavaDoc {
120             //fCur = new DataInputStream(new BufferedInputStream(new FileInputStream(fileName)));
121
fCur = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(new FileInputStream JavaDoc(fileName)));
122             iDirs = includeDirs;
123             fStack = new Stack JavaDoc();
124             nameStack = new Stack JavaDoc();
125             nbStack = new Stack JavaDoc();
126             nameCur = fileName;
127             nbCur = 0;
128         }
129       
130         String JavaDoc readLine(boolean dont_include_file) throws java.io.IOException JavaDoc {
131             String JavaDoc line = fCur.readLine();
132             nbCur++;
133          
134             if (line == null) {
135                 if (!fStack.empty()) {
136                     fCur.close();
137                     nbCur = ((Integer JavaDoc) nbStack.pop()).intValue();
138                     line = "# "+nbCur+" "+"\""+nameCur+"\""+" 2";
139                     nameCur = (String JavaDoc) nameStack.pop();
140                     fCur = (BufferedReader JavaDoc) fStack.pop();
141                 }
142             } else {
143                 if (line.startsWith("#include")) {
144                     if(dont_include_file)
145                         return "";
146                     StringTokenizer JavaDoc stLine = new StringTokenizer JavaDoc(line);
147                     stLine.nextToken();
148                     String JavaDoc fiName = stLine.nextToken();
149                     fiName = fiName.substring(1,fiName.length()-1);
150                     String JavaDoc fiNameWithPath = this.includeFileName(fiName);
151                
152                     if (fiNameWithPath == null) {
153                         System.err.println(nameCur+":"+nbCur+":1: " + fiName + ": No such file or directory");
154                         return "";
155                     }
156                     else {
157                         fStack.push(fCur);
158                         nameStack.push(nameCur);
159                         nbStack.push(new Integer JavaDoc(nbCur));
160                   
161 // fCur = new DataInputStream(new BufferedInputStream(new FileInputStream(fiNameWithPath)));
162
fCur = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(new FileInputStream JavaDoc(fiNameWithPath)));
163                         nameCur = new String JavaDoc(fiNameWithPath);
164                         line = "# "+nbCur+" "+"\""+fiNameWithPath+"\""+" 1";
165                         nbCur = 0;
166                     }
167                 }
168             }
169          
170             return(line);
171         }
172       
173         private String JavaDoc includeFileName(String JavaDoc fName) {
174             String JavaDoc fiName = null;
175             Enumeration JavaDoc dirs = iDirs.elements();
176             while (dirs.hasMoreElements()) {
177                 fiName = new String JavaDoc((String JavaDoc)dirs.nextElement()+File.separatorChar+fName);
178                 File JavaDoc f = new File JavaDoc(fiName);
179                 if (f.exists()) return fiName;
180             }
181             return(null);
182         }
183       
184         String JavaDoc getFileName() { return(nameCur); }
185         int getLineNumber() { return(nbCur); }
186         void close() throws java.io.IOException JavaDoc { fCur.close(); }
187     }
188
189     /* *************************************************************************
190      * This included class provides an inputstream offering a readLine() method.
191      ************************************************************************* */

192
193     static class JPPInputStream extends FilterInputStream JavaDoc {
194         public static final int BUFSIZE = 1024;
195         public static final String JavaDoc NULLSTRING = "";
196       
197         byte[] buffer = new byte[BUFSIZE];
198         boolean isMacFile;
199       
200         public JPPInputStream(InputStream JavaDoc iS,boolean isM) { super(iS); isMacFile = isM; }
201         public JPPInputStream(InputStream JavaDoc iS) { this(iS,false); }
202       
203         public int read() throws IOException JavaDoc {
204             return super.read();
205         }
206       
207         public String JavaDoc readLine() throws IOException JavaDoc {
208             int i = readLine(buffer);
209             if (i == -1) return null;
210             else return new String JavaDoc(buffer,0,i);
211         }
212       
213         public int readLine(byte[] buf) throws IOException JavaDoc {
214             boolean escaped = false;
215             boolean CRLFEscaped = false;
216             boolean endWhile = false;
217             int i = -1,car = 0,maxL = buf.length-1;
218          
219             while(!endWhile && i<maxL && (car = read())!= -1) {
220                 switch(car) {
221                     default :
222                         if (escaped) {
223                             buf[++i] = (byte) '\\';
224                             escaped = false;
225                         }
226                         buf[++i] = (byte) car;
227                         if (CRLFEscaped) CRLFEscaped = false;
228                         break;
229                     case '\\' :
230                         if (escaped) {
231                             buf[++i] = (byte) '\\';
232                             buf[++i] = (byte) '\\';
233                         }
234                         escaped = !escaped;
235                         if (CRLFEscaped) CRLFEscaped = false;
236                         break;
237                     case '\r' : case '\n' :
238                         if (!escaped) {
239                             if (!CRLFEscaped) endWhile = true;
240                             else CRLFEscaped = false;
241                         }
242                         else if (!CRLFEscaped) CRLFEscaped = true;
243                         else CRLFEscaped = false;
244                         break;
245                 }
246             }
247             if (i>= 0 || endWhile) return i+1; else return -1;
248         }
249     }
250    
251     /**
252      * JPP Constructor
253      *
254      * @param fileNameIn path of the jpp file
255      * @param outputStream outputStream where to send the result
256      * @param includeDirs list of the 'include' directories
257      * @param definedNames list of the defined names
258      */

259
260     public JPP(String JavaDoc fileNameIn, OutputStream JavaDoc outS, Vector JavaDoc includeDirs, Hashtable JavaDoc defNames)
261         throws java.io.IOException JavaDoc {
262         jpp_fIn = new JPPExpandedStream(fileNameIn, includeDirs);
263         jpp_fOut = outS;
264         defined_names = defNames;
265     }
266
267     public boolean preprocess() throws java.io.IOException JavaDoc {
268         String JavaDoc line = null;
269         int negTest = 0,posTest = 0;
270         Stack JavaDoc ifScope = new Stack JavaDoc();
271         Object JavaDoc curScope = NULLSCOPE;
272         ifScope.push(curScope);
273
274         while(true) {
275             line = jpp_fIn.readLine(negTest>0);
276             if (line == null) {
277                 jpp_fIn.close();
278                 return (errorNumber == 0);
279             }
280          
281             StringTokenizer JavaDoc stLine;
282             String JavaDoc nom1,nom2;
283          
284             switch(jppToken(line)) {
285                 case INST_DEFINE :
286                     if (negTest>0) break;
287                     stLine = new StringTokenizer JavaDoc(line.trim());
288                     stLine.nextToken();
289                     if (stLine.hasMoreTokens()) nom1 = stLine.nextToken();
290                     else {
291                         printErrorMsg(jpp_fIn,"Illegal empty definition of preprocessor variable",true);
292                         break;
293                     }
294                     if (stLine.hasMoreTokens()) {
295                         nom2 = stLine.nextToken();
296                         while (stLine.hasMoreTokens()) nom2 = nom2 + " " + stLine.nextToken();
297                     } else {
298                         nom2 = NULLSTRING;
299                     }
300                     if (defined_names.containsKey(nom1)) {
301                         printErrorMsg(jpp_fIn,"Redefinition of preprocessor variable "+nom1,false);
302                     } else {
303                         nb_defs++;
304                     }
305                     defined_names.put(nom1,nom2);
306                     break;
307                 case INST_UNDEF :
308                     if (negTest>0) break;
309                     stLine = new StringTokenizer JavaDoc(line);
310                     stLine.nextToken();
311                     if (stLine.hasMoreTokens()) nom1 = stLine.nextToken();
312                     else {
313                         printErrorMsg(jpp_fIn,"Illegal empty (un)definition of preprocessor variable",true);
314                         break;
315                     }
316                     if (defined_names.containsKey(nom1)) {
317                         defined_names.remove(nom1);
318                         nb_defs--;
319                     } else {
320                         printErrorMsg(jpp_fIn,"(un)definition of unknown preprocessor variable "+nom1,false);
321                     }
322                     break;
323                 case INST_IFDEF :
324                     curScope = IFSCOPE;
325                     ifScope.push(curScope);
326                     if (negTest>0) { negTest++; break; }
327                     stLine = new StringTokenizer JavaDoc(line);
328                     stLine.nextToken();
329                     if (stLine.hasMoreTokens()) nom1 = stLine.nextToken();
330                     else {
331                         printErrorMsg(jpp_fIn,"Illegal empty #ifdef test of preprocessor variable",true);
332                         break;
333                     }
334                     if (defined_names.containsKey(nom1)) posTest++; else negTest++;
335                     break;
336                 case INST_IFNDEF :
337                     curScope = IFSCOPE;
338                     ifScope.push(curScope);
339                     if (negTest>0) { negTest++; break; }
340                     stLine = new StringTokenizer JavaDoc(line);
341                     stLine.nextToken();
342                     if (stLine.hasMoreTokens()) nom1 = stLine.nextToken();
343                     else {
344                         printErrorMsg(jpp_fIn,"Illegal empty #ifndef test of preprocessor variable",true);
345                         break;
346                     }
347                     if (!defined_names.containsKey(nom1)) posTest++; else negTest++;
348                     break;
349                 case INST_IF :
350                     printErrorMsg(jpp_fIn,"Unsupported #if processor directive",true);
351                     break;
352                 case INST_ENDIF :
353                     if (curScope == NULLSCOPE) {
354                         printErrorMsg(jpp_fIn,"Unbalanced #endif processor directive",true);
355                         break;
356                     }
357                     curScope =ifScope.pop();
358                     if (negTest>0) negTest--;
359                     else if (posTest>0) posTest--;
360                     break;
361                 case INST_ELIF :
362                     printErrorMsg(jpp_fIn,"Unsupported #elif processor directive ",true);
363                     break;
364                 case INST_ELSE :
365                     if (curScope != IFSCOPE) {
366                         printErrorMsg(jpp_fIn,"Unbalanced #else processor directive ",true);
367                         break;
368                     }
369                     ifScope.pop();
370                     curScope = ELSESCOPE;
371                     ifScope.push(curScope);
372                     if (negTest>0) negTest--;
373                     else { negTest++; posTest--; }
374                     break;
375                 case NO_JPP_INST :
376                     if (negTest>0) break;
377                     if (nb_defs == 0) {
378                         jpp_fOut.write(line.getBytes());
379                         jpp_fOut.write('\n');
380                     }
381                     else {
382                         stLine = new StringTokenizer JavaDoc(line.trim(),JAVA_DELIM,true);
383                         String JavaDoc line2;
384                         if (stLine.hasMoreTokens()) {
385                             line2 = "";
386                             while (stLine.hasMoreTokens()) {
387                                 String JavaDoc tok2 = stLine.nextToken();
388                                 String JavaDoc tok3 = (String JavaDoc) defined_names.get(tok2);
389                                 if (tok3 == null) line2 = line2+tok2;
390                                 else line2 = line2+tok3;
391                             }
392                             jpp_fOut.write(line2.getBytes());
393                         }
394                         jpp_fOut.write('\n');
395                     }
396                     break;
397                 case INST_INCLUDE :
398                     printErrorMsg(jpp_fIn,"Unexpected #include directive",true);
399             }
400         }
401     }
402
403     void printErrorMsg(JPPExpandedStream jE,String JavaDoc msg,boolean isErr) {
404         System.err.println(jE.getFileName()+":"+jE.getLineNumber()+":1: "+msg);
405         if (isErr) errorNumber++;
406     }
407 }
408
Popular Tags