// this method allow using a different filter to handle the lines.
  public void preprocess(
      IPreprocessor pp, File sourceDir, int mode, String newext, String encoding, Utility utility)
      throws PreprocessorException, IOException {

    pp.setMode(mode);
    String[] files = getDirectoryScanner(sourceDir).getIncludedFiles();
    log("Preprocessing " + files.length + " file(s) at " + sourceDir);

    String filename = ""; // For exception handling

    try {
      for (int i = 0; i < files.length; i++) {
        filename = files[i];

        String sourceFile = "" + sourceDir + File.separatorChar + filename;

        Strings lines = loadFile(encoding, new File(sourceFile));

        pp.setFile(new File(sourceFile));

        boolean modified = pp.preprocess(lines, encoding);
        // if preprocessing modifies the file, or
        // we are putting the output in a different directory
        // or we are changing the file extension
        // then we have to write a new file
        if (modified || !sourceDir.equals(targetDir) || (newext != null)) {
          try {
            if ((mode & IPreprocessor.MODE_VERBOSE) != 0) {
              System.out.println(filename + " ... modified");
            }

            if ((mode & IPreprocessor.MODE_TEST) == 0) {
              String targetFile;

              if (newext != null) {
                int dot = filename.indexOf('.');

                if (dot != -1) {
                  filename = filename.substring(0, dot) + newext;
                } else {
                  filename = filename + newext;
                }
              }

              targetFile = "" + targetDir + File.separatorChar + filename;

              File file = new File(targetFile + "~");
              file.delete();
              if (!new File(targetFile).renameTo(file) && (targetDir == null)) {
                throw new java.io.IOException();
              }

              new File(targetFile).getParentFile().mkdirs();

              if (encoding != null && encoding.length() > 0) {
                lines.saveToFile(targetFile, encoding);
              } else {
                lines.saveToFile(targetFile);
              }

              if ((mode & IPreprocessor.MODE_BACKUP) == 0) {
                file.delete(); // ??????
              }
            }
          } catch (java.io.UnsupportedEncodingException uee) {
            throw new PreprocessorException("Unknown encoding \"" + encoding, new File(files[i]));
          } catch (java.io.IOException e) {
            throw new PreprocessorException("File write error", new File(files[i]));
          }
        } else {
          if ((mode & IPreprocessor.MODE_VERBOSE) != 0) {
            System.out.println(filename + " ... not modified");
          }
        }
      }
    } catch (IOException e) {
      if ((mode & IPreprocessor.MODE_VERBOSE) == 0) {
        System.out.println(filename + " ... not modified, " + e.getMessage());
      }

      throw e;
    } catch (PreprocessorException error) {
      if ((mode & IPreprocessor.MODE_VERBOSE) == 0) {
        System.out.println(filename + " ... not modified, " + error.getMessage());
      }

      throw error;
    }
  }
  public void execute() throws BuildException {
    if (!isActive()) return;

    if (targetDir == null) {
      throw new BuildException("Need a target directory");
    }
    StringTokenizer tok = new StringTokenizer(sourceDir.toString(), "" + File.pathSeparatorChar);
    while (tok.hasMoreElements()) {
      String dir = tok.nextToken();
      try {
        IPreprocessor pp;
        if ("1".equals(m_backendVersion)) {
          pp = new antenna.preprocessor.v1.Preprocessor(utility, encoding);
          pp.addSymbols(m_symbols);
          if (m_printSymbols) pp.printSymbols();
        } else if ("2".equals(m_backendVersion)) {
          pp = new antenna.preprocessor.v2.PreprocessorBridge(utility);
        } else if ("3".equals(m_backendVersion)) {
          pp = new antenna.preprocessor.v3.PreprocessorBridge(utility);
        } else {
          throw new BuildException("Unsupported backend version " + m_backendVersion);
        }

        // for any backend except version 1:
        if (!m_backendVersion.equals("1")) {
          try {
            pp.setDebugLevel(m_debugLevel);
          } catch (Exception e) {
            log(e.getMessage(), Project.MSG_WARN);
          }
          String deviceDefines = getDeviceDefines();
          String symbols = addSymbols(m_symbols, deviceDefines);
          pp.addSymbols(symbols);

          for (int i = 0; i < m_symbolsFile.size(); i++) {
            Symbols_File f = (Symbols_File) m_symbolsFile.get(i);
            if (f.name != null) {
              File file = new File(f.name);
              if (!file.exists()) {
                log("Symbols file not found : " + file.getAbsolutePath(), Project.MSG_INFO);
              } else {
                try {
                  pp.addSymbols(file);
                } catch (PreprocessorException e) {
                  log("Error preprocessing symbols" + file.getAbsolutePath(), Project.MSG_ERR);
                  e.printStackTrace();
                } catch (IOException e) {
                  log("IOException adding " + file.getAbsolutePath(), Project.MSG_ERR);
                  e.printStackTrace();
                }
              }
            } else if (f.list != null) {
              StringTokenizer t = new StringTokenizer(f.list, " ,");
              while (t.hasMoreElements()) {
                File ff = new File(t.nextToken());
                if (!ff.exists()) {
                  log("Symbols file not found : " + ff.getAbsolutePath(), Project.MSG_WARN);
                  continue;
                }

                try {
                  pp.addSymbols(ff);
                } catch (Exception e) {
                  log("Error adding symbols from " + ff.getAbsolutePath(), Project.MSG_WARN);
                }
              }
            }
          }

          if (m_printSymbols) pp.printSymbols();

          if (m_saveSymbols != null) {
            try {
              pp.outputDefinesToFile(new File(m_saveSymbols), encoding);
            } catch (IOException e) {
              log("Error saving defines to file " + m_saveSymbols, Project.MSG_WARN);
            }
          }
        }

        File file = new File(dir);
        preprocess(pp, file, mode, newext, encoding, utility);
      } catch (Exception ex) {
        ex.printStackTrace();
        throw new BuildException("Preprocessing failed: " + ex.getMessage(), ex);
      }
    }
  }