11388SN/A/*
211359Sandreas@sandberg.pp.se * Copyright (c) 2015 ARM Limited
311359Sandreas@sandberg.pp.se * All rights reserved
411359Sandreas@sandberg.pp.se *
511359Sandreas@sandberg.pp.se * The license below extends only to copyright in the software and shall
611359Sandreas@sandberg.pp.se * not be construed as granting a license to any other intellectual
711359Sandreas@sandberg.pp.se * property including but not limited to intellectual property relating
811359Sandreas@sandberg.pp.se * to a hardware implementation of the functionality of the software
911359Sandreas@sandberg.pp.se * licensed hereunder.  You may use the software subject to the license
1011359Sandreas@sandberg.pp.se * terms below provided that you ensure that this notice is replicated
1111359Sandreas@sandberg.pp.se * unmodified and in its entirety in all distributions of the software,
1211359Sandreas@sandberg.pp.se * modified or unmodified, in source code or in binary form.
1311359Sandreas@sandberg.pp.se *
1411359Sandreas@sandberg.pp.se * Copyright (c) 2013 Andreas Sandberg
151388SN/A * Copyright (c) 2005 The Regents of The University of Michigan
161388SN/A * All rights reserved.
171388SN/A *
181388SN/A * Redistribution and use in source and binary forms, with or without
191388SN/A * modification, are permitted provided that the following conditions are
201388SN/A * met: redistributions of source code must retain the above copyright
211388SN/A * notice, this list of conditions and the following disclaimer;
221388SN/A * redistributions in binary form must reproduce the above copyright
231388SN/A * notice, this list of conditions and the following disclaimer in the
241388SN/A * documentation and/or other materials provided with the distribution;
251388SN/A * neither the name of the copyright holders nor the names of its
261388SN/A * contributors may be used to endorse or promote products derived from
271388SN/A * this software without specific prior written permission.
281388SN/A *
291388SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
301388SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
311388SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
321388SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
331388SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
341388SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
351388SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
361388SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
371388SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
381388SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
391388SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402665Ssaidi@eecs.umich.edu *
412665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
428634Schris.emmons@arm.com *          Chris Emmons
4311359Sandreas@sandberg.pp.se *          Andreas Sandberg
4411359Sandreas@sandberg.pp.se *          Sascha Bischoff
451388SN/A */
461388SN/A
471388SN/A#ifndef __BASE_OUTPUT_HH__
481388SN/A#define __BASE_OUTPUT_HH__
491388SN/A
505749Scws3k@cs.virginia.edu#include <ios>
511388SN/A#include <map>
521388SN/A#include <string>
531388SN/A
5411359Sandreas@sandberg.pp.se#include "base/compiler.hh"
5511359Sandreas@sandberg.pp.se
5611359Sandreas@sandberg.pp.seclass OutputDirectory;
5711359Sandreas@sandberg.pp.se
5811359Sandreas@sandberg.pp.seclass OutputStream
5911359Sandreas@sandberg.pp.se{
6011359Sandreas@sandberg.pp.se  public:
6111359Sandreas@sandberg.pp.se    virtual ~OutputStream();
6211359Sandreas@sandberg.pp.se
6311359Sandreas@sandberg.pp.se    /** Get the output underlying output stream */
6411359Sandreas@sandberg.pp.se    std::ostream *stream() const { return _stream; };
6511359Sandreas@sandberg.pp.se
6611359Sandreas@sandberg.pp.se    /**
6711359Sandreas@sandberg.pp.se     * Can the file be recreated if the output directory is moved?
6811359Sandreas@sandberg.pp.se     *
6911359Sandreas@sandberg.pp.se     * @return true if the file will be created in the new location,
7011359Sandreas@sandberg.pp.se     * false otherwise.
7111359Sandreas@sandberg.pp.se     */
7211359Sandreas@sandberg.pp.se    virtual bool recreateable() const { return false; }
7311359Sandreas@sandberg.pp.se
7411359Sandreas@sandberg.pp.se    /** Get the file name in the output directory */
7511359Sandreas@sandberg.pp.se    const std::string &name() const { return _name; }
7611359Sandreas@sandberg.pp.se
7711359Sandreas@sandberg.pp.se  protected:
7811359Sandreas@sandberg.pp.se    friend class OutputDirectory;
7911359Sandreas@sandberg.pp.se
8011359Sandreas@sandberg.pp.se    /** Wrap an existing stream */
8111359Sandreas@sandberg.pp.se    OutputStream(const std::string &name,
8211359Sandreas@sandberg.pp.se                 std::ostream *stream);
8311359Sandreas@sandberg.pp.se
8411359Sandreas@sandberg.pp.se    /* Prevent copying */
8511359Sandreas@sandberg.pp.se    OutputStream(const OutputStream &f);
8611359Sandreas@sandberg.pp.se
8711359Sandreas@sandberg.pp.se    /** Re-create the in a new location if recreateable. */
8811359Sandreas@sandberg.pp.se    virtual void relocate(const OutputDirectory &dir);
8911359Sandreas@sandberg.pp.se
9011359Sandreas@sandberg.pp.se    /** Name in output directory */
9111359Sandreas@sandberg.pp.se    const std::string _name;
9211359Sandreas@sandberg.pp.se
9311359Sandreas@sandberg.pp.se    /** Underlying output stream */
9411359Sandreas@sandberg.pp.se    std::ostream *const _stream;
9511359Sandreas@sandberg.pp.se};
9611359Sandreas@sandberg.pp.se
9711359Sandreas@sandberg.pp.setemplate<class StreamType>
9811359Sandreas@sandberg.pp.seclass OutputFile
9911359Sandreas@sandberg.pp.se    : public OutputStream
10011359Sandreas@sandberg.pp.se{
10111359Sandreas@sandberg.pp.se  public:
10211359Sandreas@sandberg.pp.se    typedef StreamType stream_type_t;
10311359Sandreas@sandberg.pp.se
10411359Sandreas@sandberg.pp.se    virtual ~OutputFile();
10511359Sandreas@sandberg.pp.se
10611359Sandreas@sandberg.pp.se    /**
10711359Sandreas@sandberg.pp.se     * Can the file be recreated if the output directory is moved?
10811359Sandreas@sandberg.pp.se     *
10911359Sandreas@sandberg.pp.se     * @return true if the file will be created in the new location,
11011359Sandreas@sandberg.pp.se     * false otherwise.
11111359Sandreas@sandberg.pp.se     */
11211359Sandreas@sandberg.pp.se    bool recreateable() const override { return _recreateable; }
11311359Sandreas@sandberg.pp.se
11411359Sandreas@sandberg.pp.se  protected:
11511359Sandreas@sandberg.pp.se    friend class OutputDirectory;
11611359Sandreas@sandberg.pp.se
11711359Sandreas@sandberg.pp.se    OutputFile(const OutputDirectory &dir,
11811359Sandreas@sandberg.pp.se               const std::string &name,
11911359Sandreas@sandberg.pp.se               std::ios_base::openmode mode,
12011359Sandreas@sandberg.pp.se               bool recreateable);
12111359Sandreas@sandberg.pp.se
12211359Sandreas@sandberg.pp.se    /* Prevent copying */
12311359Sandreas@sandberg.pp.se    OutputFile(const OutputFile<StreamType> &f);
12411359Sandreas@sandberg.pp.se
12511359Sandreas@sandberg.pp.se    /** Re-create the file in a new location if it is relocatable. */
12611359Sandreas@sandberg.pp.se    void relocate(const OutputDirectory &dir) override;
12711359Sandreas@sandberg.pp.se
12811359Sandreas@sandberg.pp.se    /** File mode when opened */
12911359Sandreas@sandberg.pp.se    const std::ios_base::openmode _mode;
13011359Sandreas@sandberg.pp.se
13111359Sandreas@sandberg.pp.se    /** Can the file be recreated in a new location? */
13211359Sandreas@sandberg.pp.se    const bool _recreateable;
13311359Sandreas@sandberg.pp.se
13411359Sandreas@sandberg.pp.se    /** Pointer to the file stream */
13511359Sandreas@sandberg.pp.se    stream_type_t *const _fstream;
13611359Sandreas@sandberg.pp.se};
13711359Sandreas@sandberg.pp.se
1388634Schris.emmons@arm.com/** Interface for creating files in a gem5 output directory. */
1391388SN/Aclass OutputDirectory
1401388SN/A{
1411388SN/A  private:
1428634Schris.emmons@arm.com    /** File names and associated stream handles */
14311359Sandreas@sandberg.pp.se    typedef std::map<std::string, OutputStream *> file_map_t;
14411359Sandreas@sandberg.pp.se
14511359Sandreas@sandberg.pp.se    /** Output subdirectories */
14611359Sandreas@sandberg.pp.se    typedef std::map<std::string, OutputDirectory *> dir_map_t;
1471388SN/A
1488634Schris.emmons@arm.com    /** Open file streams within this directory */
14911359Sandreas@sandberg.pp.se    file_map_t files;
15011359Sandreas@sandberg.pp.se
15111359Sandreas@sandberg.pp.se    /** Output sub-directories */
15211359Sandreas@sandberg.pp.se    dir_map_t dirs;
1538634Schris.emmons@arm.com
1548634Schris.emmons@arm.com    /** Name of this directory */
1551388SN/A    std::string dir;
1561388SN/A
1578634Schris.emmons@arm.com    /** System-specific path separator character */
1588634Schris.emmons@arm.com    static const char PATH_SEPARATOR = '/';
1598634Schris.emmons@arm.com
16011359Sandreas@sandberg.pp.se    static OutputStream stdout;
16111359Sandreas@sandberg.pp.se    static OutputStream stderr;
16211359Sandreas@sandberg.pp.se
1635749Scws3k@cs.virginia.edu  protected:
1648634Schris.emmons@arm.com    /**
1658634Schris.emmons@arm.com     * Determines whether given file name corresponds to standard output
1668634Schris.emmons@arm.com     * streams.
1678634Schris.emmons@arm.com     *
1688634Schris.emmons@arm.com     * @param name name of file to check
1698634Schris.emmons@arm.com     * @return output stream for standard output or error stream if name
1708634Schris.emmons@arm.com     *         corresponds to one or the other; NULL otherwise
1718634Schris.emmons@arm.com     */
17211359Sandreas@sandberg.pp.se    static OutputStream *checkForStdio(const std::string &name);
1738634Schris.emmons@arm.com
1748734Sdam.sunwoo@arm.com  public:
1758734Sdam.sunwoo@arm.com    /** Constructor. */
1768734Sdam.sunwoo@arm.com    OutputDirectory();
1778734Sdam.sunwoo@arm.com
17811359Sandreas@sandberg.pp.se    /** Constructor. */
17911359Sandreas@sandberg.pp.se    OutputDirectory(const std::string &name);
18011359Sandreas@sandberg.pp.se
1818734Sdam.sunwoo@arm.com    /** Destructor. */
1828734Sdam.sunwoo@arm.com    ~OutputDirectory();
1838734Sdam.sunwoo@arm.com
1849398Sandreas.hansson@arm.com    /**
1859398Sandreas.hansson@arm.com     * Returns relative file names prepended with name of this directory.
1869398Sandreas.hansson@arm.com     * Returns absolute file names unaltered.
1879398Sandreas.hansson@arm.com     *
1889398Sandreas.hansson@arm.com     * @param name file name to prepend with directory name
1899398Sandreas.hansson@arm.com     * @return file name prepended with base directory name or unaltered
1909398Sandreas.hansson@arm.com     *          absolute file name
1919398Sandreas.hansson@arm.com     */
1929398Sandreas.hansson@arm.com    std::string resolve(const std::string &name) const;
1939398Sandreas.hansson@arm.com
1948634Schris.emmons@arm.com    /**
1958634Schris.emmons@arm.com     * Sets name of this directory.
1968634Schris.emmons@arm.com     * @param dir name of this directory
1978634Schris.emmons@arm.com     */
1981388SN/A    void setDirectory(const std::string &dir);
1998634Schris.emmons@arm.com
2008634Schris.emmons@arm.com    /**
2018634Schris.emmons@arm.com     * Gets name of this directory.
2028634Schris.emmons@arm.com     * @return name of this directory
2038634Schris.emmons@arm.com     */
2045749Scws3k@cs.virginia.edu    const std::string &directory() const;
2051388SN/A
2068634Schris.emmons@arm.com    /**
2078634Schris.emmons@arm.com     * Creates a file in this directory (optionally compressed).
2088634Schris.emmons@arm.com     *
20911359Sandreas@sandberg.pp.se     * Will open a file as a compressed stream if filename ends in .gz, unless
21011359Sandreas@sandberg.pp.se     * explicitly disabled.
21111359Sandreas@sandberg.pp.se     *
21211359Sandreas@sandberg.pp.se     * Relative output paths will result in the creation of a
21311359Sandreas@sandberg.pp.se     * recreateable (see OutputFile) output file in the current output
21411359Sandreas@sandberg.pp.se     * directory. Files created with an absolute path will not be
21511359Sandreas@sandberg.pp.se     * recreateable.
2168634Schris.emmons@arm.com     *
2178634Schris.emmons@arm.com     * @param name name of file to create (without this directory's name
2188634Schris.emmons@arm.com     *          leading it)
2198634Schris.emmons@arm.com     * @param binary true to create a binary file; false otherwise
22011359Sandreas@sandberg.pp.se     * @param no_gz true to disable opening the file as a gzip compressed output
22111359Sandreas@sandberg.pp.se     *     stream; false otherwise
22211359Sandreas@sandberg.pp.se     * @return OutputStream instance representing the created file
2238634Schris.emmons@arm.com     */
22411359Sandreas@sandberg.pp.se    OutputStream *create(const std::string &name,
22511359Sandreas@sandberg.pp.se                         bool binary = false,
22611259Ssascha.bischoff@ARM.com                         bool no_gz = false);
2271388SN/A
2288634Schris.emmons@arm.com    /**
22911359Sandreas@sandberg.pp.se     * Open a file in this directory (optionally compressed).
2308634Schris.emmons@arm.com     *
23111359Sandreas@sandberg.pp.se     * Will open a file as a compressed stream if filename ends in .gz, unless
23211359Sandreas@sandberg.pp.se     * explicitly disabled.
2338634Schris.emmons@arm.com     *
23411359Sandreas@sandberg.pp.se     * @param filename file to open
23511359Sandreas@sandberg.pp.se     * @param mode attributes to open file with
23611359Sandreas@sandberg.pp.se     * @param recreateable Set to true if the file can be recreated in a new
23711359Sandreas@sandberg.pp.se     *     location.
23811359Sandreas@sandberg.pp.se     * @param no_gz true to disable opening the file as a gzip compressed output
23911359Sandreas@sandberg.pp.se     *     stream; false otherwise
24011359Sandreas@sandberg.pp.se     * @return OutputStream instance representing the opened file
2418634Schris.emmons@arm.com     */
24211359Sandreas@sandberg.pp.se    OutputStream *open(const std::string &name,
24311359Sandreas@sandberg.pp.se                       std::ios_base::openmode mode,
24411359Sandreas@sandberg.pp.se                       bool recreateable = true,
24511359Sandreas@sandberg.pp.se                       bool no_gz = false);
2468634Schris.emmons@arm.com
2478634Schris.emmons@arm.com    /**
24811359Sandreas@sandberg.pp.se     * Closes an output file and free the corresponding OutputFile.
24911359Sandreas@sandberg.pp.se     *
25011359Sandreas@sandberg.pp.se     * The output file must have been opened by the same
25111359Sandreas@sandberg.pp.se     * OutputDirectory instance as the one closing it, or sim will
25211359Sandreas@sandberg.pp.se     * fail.
25311359Sandreas@sandberg.pp.se     *
25411359Sandreas@sandberg.pp.se     * @param file OutputStream instance in this OutputDirectory.
25511359Sandreas@sandberg.pp.se     */
25611359Sandreas@sandberg.pp.se    void close(OutputStream *file);
25711359Sandreas@sandberg.pp.se
25811359Sandreas@sandberg.pp.se    /**
25911359Sandreas@sandberg.pp.se     * Finds stream associated with an open file or stdout/stderr.
26011359Sandreas@sandberg.pp.se     *
2618634Schris.emmons@arm.com     * @param name of file
2628634Schris.emmons@arm.com     * @return stream to specified file or NULL if file does not exist
2638634Schris.emmons@arm.com     */
26411359Sandreas@sandberg.pp.se    OutputStream *find(const std::string &name) const;
2658634Schris.emmons@arm.com
26611359Sandreas@sandberg.pp.se    OutputStream *findOrCreate(const std::string &name, bool binary = false);
2678634Schris.emmons@arm.com
2688634Schris.emmons@arm.com    /**
2698634Schris.emmons@arm.com     * Determines whether a file name corresponds to a file in this directory.
2708634Schris.emmons@arm.com     * @param name name of file to evaluate
2718634Schris.emmons@arm.com     * @return true iff file has been opened in this directory or exists on the
2728634Schris.emmons@arm.com     *          file system within this directory
2738634Schris.emmons@arm.com     */
2748634Schris.emmons@arm.com    bool isFile(const std::string &name) const;
2758634Schris.emmons@arm.com
2768634Schris.emmons@arm.com    /**
27711359Sandreas@sandberg.pp.se     * Test if a path is absolute.
2788634Schris.emmons@arm.com     */
27911359Sandreas@sandberg.pp.se    static inline bool isAbsolute(const std::string &name) {
28011359Sandreas@sandberg.pp.se        return name[0] == PATH_SEPARATOR;
2818634Schris.emmons@arm.com    }
2828634Schris.emmons@arm.com
2838634Schris.emmons@arm.com    /**
2848634Schris.emmons@arm.com     * Creates a subdirectory within this directory.
2858634Schris.emmons@arm.com     * @param name name of subdirectory
2868634Schris.emmons@arm.com     * @return the new subdirectory's name suffixed with a path separator
2878634Schris.emmons@arm.com     */
28811359Sandreas@sandberg.pp.se    OutputDirectory *createSubdirectory(const std::string &name);
2898634Schris.emmons@arm.com
2908634Schris.emmons@arm.com    /**
2918634Schris.emmons@arm.com     * Removes a specified file or subdirectory.
2928634Schris.emmons@arm.com     *
2938634Schris.emmons@arm.com     * Will cause sim to fail for most errors.  However, it will only warn the
2948634Schris.emmons@arm.com     * user if a directory could not be removed.  This is in place to
2958634Schris.emmons@arm.com     * accommodate slow file systems where file deletions within a subdirectory
2968634Schris.emmons@arm.com     * may not be recognized quickly enough thereby causing the subsequent call
2978634Schris.emmons@arm.com     * to remove the directory to fail (seemingly unempty directory).
2988634Schris.emmons@arm.com     *
2998634Schris.emmons@arm.com     * @param name name of file or subdirectory to remove; name should not
3008634Schris.emmons@arm.com     *              be prepended with the name of this directory object
3018634Schris.emmons@arm.com     * @param recursive set to true to attempt to recursively delete a
3028634Schris.emmons@arm.com     *                  subdirectory and its contents
3038634Schris.emmons@arm.com     */
3048634Schris.emmons@arm.com    void remove(const std::string &name, bool recursive=false);
3051388SN/A};
3061388SN/A
3071388SN/Aextern OutputDirectory simout;
3081388SN/A
3091388SN/A#endif // __BASE_OUTPUT_HH__
310