001    /*
002      Copyright (C) 2002 Julien van Malderen
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public License
015      along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
017    
018    package org.objectweb.jac.util.preparse;
019    
020    import java.io.BufferedReader;
021    import java.io.BufferedWriter;
022    import java.io.File;
023    import java.io.FileInputStream;
024    import java.io.FileOutputStream;
025    import java.io.FileReader;
026    import java.io.InputStreamReader;
027    import java.io.OutputStream;
028    import java.io.OutputStreamWriter;
029    import java.io.Writer;
030    import java.util.Iterator;
031    import java.util.Vector;
032    
033    public class Preparse
034    {
035        public static final String CFGNAME = "preparse.cfg";
036        public static final String EXTENSION = ".modified";
037    
038        Vector tokenList = new Vector();
039    
040        // if in a string
041        boolean isInString = false;
042    
043        // if in a quote
044        boolean isInQuote = false;
045       
046        // if the next char is escaped
047        boolean isEscaped = false;
048    
049        // number of opened parentheses
050        int parenthLvl = 0;
051    
052        // initial level of parenth before function ro remove call
053        int endLvl = -1;
054    
055        protected void writeToOutput(String str, Writer output)
056            throws Exception
057        {
058            output.write(str);
059        }
060    
061        /**
062         * @param line line of text
063         * @param i offset in line of text
064         * @param output
065         */
066        protected int treat(String line, int i, Writer output)
067            throws Exception
068        {
069            int lineLength = line.length();
070          
071            //System.out.println("treat: `"+line+"' offset="+i+", length="+lineLength);
072            
073            if (!isInString)
074            {
075                Iterator j = tokenList.iterator();
076                while (j.hasNext())
077                {
078                    Config token = (Config) j.next();
079                
080                    int tokenLength = token.token.length();
081                    //System.out.println("    token="+token.token+", tokenLength="+tokenLength);
082                    if ((tokenLength < lineLength - i + 1)
083                        && (line.substring(i, i + tokenLength)
084                            .equals(token.token)))
085                    {
086                        if (token.hasArguments)
087                            endLvl = parenthLvl;
088                        writeToOutput("/* a " + token.token + " was here */", output);
089                        //System.out.println("    found token "+token.token);
090                        return (i + tokenLength - 1);
091                    }
092                }
093            }
094            /*
095              System.out.println("treat: `"+line.charAt(i)+"' isEscaped="+isEscaped+
096              "; isInQuote="+isInQuote);
097            */
098            switch (line.charAt(i))
099            {
100                case '\"' :
101                    if ((!isEscaped) && (!isInQuote)) {
102                        isInString = !isInString;
103                        //System.out.println("Found \" -> "+isInString);
104                    }
105                    isEscaped = false;
106                    break;
107                case '\'':
108                    if ((!isInString) && (!isEscaped)) {
109                        isInQuote = !isInQuote;
110                        //System.out.println("Found ' -> "+isInQuote);
111                    }
112                    isEscaped = false;
113                    break;
114                case '\\':
115                    if (isInString || isInQuote) {
116                        isEscaped = true;
117                        //System.out.println("Found \\ -> "+isEscaped);
118                    }
119                    break;
120                case '(':
121                    if (!isInString) {
122                        parenthLvl++;
123                        //System.out.println("Found ( -> "+parenthLvl+"/"+endLvl);
124                    }
125                    isEscaped = false;
126                    break;
127                case ')':
128                    if (!isInString)
129                    {
130                        parenthLvl--;
131    
132                        //System.out.println("Found ) -> "+parenthLvl+"/"+endLvl);
133    
134                        if ((endLvl != -1) && (parenthLvl == endLvl))
135                        {
136                            endLvl = -1;
137                            return i;
138                        }
139                    }
140                    isEscaped = false;
141                    break;
142                default:
143                    isEscaped = false;
144                    break;
145            }
146    
147            if (endLvl == -1) {
148                output.write(line.charAt(i));
149                //System.out.println("print `"+line.charAt(i)+"'");
150            } else {
151                //System.out.println("skip  `"+line.charAt(i)+"'");
152            }
153            return i;
154        }
155    
156        int lineNumber = 0;
157    
158        public void parse(ParseInput input, Writer output)
159        {
160            String line;
161    
162            lineNumber = 0;
163            try {
164                line = input.readLine();
165                //System.out.println("read line ("+isInString+","+isInQuote+"=: "+line);
166                lineNumber++;
167                while (line != null)
168                {
169                    int lineLength = line.length();
170    
171                    for (int i = 0; i < lineLength ; i++)
172                    {
173                        if ((!isInString) &&
174                            ((line.charAt(i) == '/') && (i < lineLength - 1)))
175                        {
176                            // skipping '//' comments
177                            if (line.charAt(i + 1) == '/')
178                            {
179                                //System.out.println("Found // comment");
180                                writeToOutput(line.substring(i), output);
181                                break;
182                            }
183                      
184                            // skipping '/* */' comments
185                            else if (line.charAt(i + 1) == '*')
186                            {
187                                //System.out.println("Found /* */ comment");
188                                writeToOutput(input.skipTo(i, "*/"), output);
189                                break;
190                            }
191                            else
192                                i = treat(line, i, output);
193                        }
194                        else
195                            i = treat(line, i, output);
196                    }
197                    if (!input.isModified())
198                        output.write('\n');
199                    line = input.readLine();
200                    lineNumber++;
201                    //System.out.println("read line ("+isInString+"): "+line);
202                }
203            }
204            catch (Exception e)
205            {
206                e.printStackTrace();
207            }
208        }
209    
210        protected String[] getTokens(String str)
211            throws Exception
212        {
213            if (str == null)
214                return null;
215    
216            if (str.length() == 0)
217                return new String[] {};
218    
219            Vector result = new Vector();
220    
221            int begin = 0;
222            int end = 0;
223          
224            int strLength = str.length();
225    
226            while (begin < strLength)
227            {
228                while ((begin < strLength)
229                       && ((str.charAt(begin) == ' ') || (str.charAt(begin) == '\t')))
230                    begin++;
231    
232                end = begin;
233                while ((end < strLength)
234                       && ((str.charAt(end) != ' ') && (str.charAt(end) != '\t')))
235                    end++;
236                result.add(str.substring(begin, end));
237                begin = end + 1;
238            }
239            return (String[]) result.toArray(new String[] {});
240        }
241    
242        public void readConfigFile(String filename)
243            throws Exception
244        {
245            try {
246                BufferedReader config = 
247                    new BufferedReader(
248                        new FileReader(filename));
249    
250                String line = config.readLine();
251                while (line != null)
252                {
253                    line = line.trim();
254                    if ((line.length() > 0) && (line.charAt(0) != '#')) {
255                        String[] tokens = getTokens(line);
256                        tokenList.add(new Config(tokens[0],!tokens[1].equals("0")));
257                    }
258                    line = config.readLine();
259                }
260                config.close();
261            }
262            catch (Exception e)
263            {
264                e.printStackTrace();
265                throw new Exception ("problem with config file '"
266                                     + filename
267                                     +"' : " + e.getMessage());
268            }
269        }
270    
271    
272        public String modifName(String javaName)
273        {
274            int i = javaName.length() - 1;
275            while ((i >= 0) && (javaName.charAt(i) != '.'))
276                i--;
277            if (i == 0)
278                return javaName + Preparse.EXTENSION;
279            return javaName.substring(0, i) + Preparse.EXTENSION;
280        }
281       
282        /**
283         * Usage: java org.objectweb.jac.util.preparse.PreParse <config_file> <dest_dir> [<file> ...]
284         */
285        public static void main(String[] args)
286            throws Exception
287        {
288            Preparse parser = new Preparse();
289    
290            if (args.length == 0)
291            {
292                System.err.println("Error: a configuration file must be specified");
293                return;
294            }
295    
296            parser.readConfigFile(args[0]);
297          
298            String msg = new String();
299            for (int i = 1; i < args.length; i++)
300                msg += args[i] + " ";
301    
302            File destDir = new File(args[1]);
303            if (!destDir.exists()) {
304                destDir.mkdirs();
305            }
306    
307            for (int i=2; i<args.length; i++)
308            {
309                try {
310                    //System.out.println("Preparse: Treating " + args[i] + " ...");
311                    File inputFile = new File(args[i]);
312                    File outputFile = new File(destDir,args[i]);
313                    if (inputFile.lastModified()>outputFile.lastModified()) {
314                        ParseInput input = 
315                            new ParseInput(
316                                new InputStreamReader(
317                                    new FileInputStream(inputFile),
318                                    "UTF-8"));
319                        System.out.println("Preparse: "+inputFile+" -> "+outputFile);
320                        File outputDir = outputFile.getParentFile();
321                        if (!outputDir.exists()) {
322                            outputDir.mkdirs();
323                        }
324                        Writer output = 
325                            new BufferedWriter(
326                                new OutputStreamWriter(
327                                    new FileOutputStream(outputFile),
328                                    "UTF-8"));
329                   
330                        parser.parse(input, output);
331                        input.close();
332                        output.close();
333                    }
334                }
335                catch (Exception e) {
336                    System.err.println("Error: " + e.getMessage());
337                }
338            }
339        }
340    
341        static class Config {
342            public String token;
343            public boolean hasArguments;
344            public Config(String token, boolean hasArguments) {
345                this.token = token;
346                this.hasArguments = hasArguments;
347            }
348        }
349    }