|  | /* RAII wrapper for buildargv | 
|  |  | 
|  | Copyright (C) 2021-2025 Free Software Foundation, Inc. | 
|  |  | 
|  | This file is part of GDB. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #ifndef GDBSUPPORT_BUILDARGV_H | 
|  | #define GDBSUPPORT_BUILDARGV_H | 
|  |  | 
|  | #include "libiberty.h" | 
|  |  | 
|  | /* A wrapper for an array of char* that was allocated in the way that | 
|  | 'buildargv' does, and should be freed with 'freeargv'.  */ | 
|  |  | 
|  | class gdb_argv | 
|  | { | 
|  | public: | 
|  |  | 
|  | /* A constructor that initializes to NULL.  */ | 
|  |  | 
|  | gdb_argv () | 
|  | : m_argv (NULL) | 
|  | { | 
|  | } | 
|  |  | 
|  | /* A constructor that calls buildargv on STR.  STR may be NULL, in | 
|  | which case this object is initialized with a NULL array.  */ | 
|  |  | 
|  | explicit gdb_argv (const char *str) | 
|  | : m_argv (NULL) | 
|  | { | 
|  | reset (str); | 
|  | } | 
|  |  | 
|  | /* A constructor that takes ownership of an existing array.  */ | 
|  |  | 
|  | explicit gdb_argv (char **array) | 
|  | : m_argv (array) | 
|  | { | 
|  | } | 
|  |  | 
|  | gdb_argv (const gdb_argv &) = delete; | 
|  | gdb_argv &operator= (const gdb_argv &) = delete; | 
|  |  | 
|  | gdb_argv &operator= (gdb_argv &&other) | 
|  | { | 
|  | freeargv (m_argv); | 
|  | m_argv = other.m_argv; | 
|  | other.m_argv = nullptr; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | gdb_argv (gdb_argv &&other) | 
|  | { | 
|  | m_argv = other.m_argv; | 
|  | other.m_argv = nullptr; | 
|  | } | 
|  |  | 
|  | ~gdb_argv () | 
|  | { | 
|  | freeargv (m_argv); | 
|  | } | 
|  |  | 
|  | /* Call buildargv on STR, storing the result in this object.  Any | 
|  | previous state is freed.  STR may be NULL, in which case this | 
|  | object is reset with a NULL array.  If buildargv fails due to | 
|  | out-of-memory, call malloc_failure.  Therefore, the value is | 
|  | guaranteed to be non-NULL, unless the parameter itself is | 
|  | NULL.  */ | 
|  |  | 
|  | void reset (const char *str) | 
|  | { | 
|  | char **argv = buildargv (str); | 
|  | freeargv (m_argv); | 
|  | m_argv = argv; | 
|  | } | 
|  |  | 
|  | /* Return the underlying array.  */ | 
|  |  | 
|  | char **get () | 
|  | { | 
|  | return m_argv; | 
|  | } | 
|  |  | 
|  | const char * const * get () const | 
|  | { | 
|  | return m_argv; | 
|  | } | 
|  |  | 
|  | /* Return the underlying array, transferring ownership to the | 
|  | caller.  */ | 
|  |  | 
|  | ATTRIBUTE_UNUSED_RESULT char **release () | 
|  | { | 
|  | char **result = m_argv; | 
|  | m_argv = NULL; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /* Return the number of items in the array.  */ | 
|  |  | 
|  | int count () const | 
|  | { | 
|  | return countargv (m_argv); | 
|  | } | 
|  |  | 
|  | /* Index into the array.  */ | 
|  |  | 
|  | char *operator[] (int arg) | 
|  | { | 
|  | gdb_assert (m_argv != NULL); | 
|  | return m_argv[arg]; | 
|  | } | 
|  |  | 
|  | /* Return the arguments array as an array view.  */ | 
|  |  | 
|  | gdb::array_view<char *> as_array_view () | 
|  | { | 
|  | return gdb::array_view<char *> (this->get (), this->count ()); | 
|  | } | 
|  |  | 
|  | gdb::array_view<const char * const> as_array_view () const | 
|  | { | 
|  | return gdb::array_view<const char * const> (this->get (), this->count ()); | 
|  | } | 
|  |  | 
|  | /* Append arguments to this array.  */ | 
|  | void append (gdb_argv &&other) | 
|  | { | 
|  | int size = count (); | 
|  | int argc = other.count (); | 
|  | m_argv = XRESIZEVEC (char *, m_argv, (size + argc + 1)); | 
|  |  | 
|  | for (int argi = 0; argi < argc; argi++) | 
|  | { | 
|  | /* Transfer ownership of the string.  */ | 
|  | m_argv[size++] = other.m_argv[argi]; | 
|  | /* Ensure that destruction of OTHER works correctly.  */ | 
|  | other.m_argv[argi] = nullptr; | 
|  | } | 
|  | m_argv[size] = nullptr; | 
|  | } | 
|  |  | 
|  | /* Append arguments to this array.  */ | 
|  | void append (const gdb_argv &other) | 
|  | { | 
|  | int size = count (); | 
|  | int argc = other.count (); | 
|  | m_argv = XRESIZEVEC (char *, m_argv, (size + argc + 1)); | 
|  |  | 
|  | for (int argi = 0; argi < argc; argi++) | 
|  | m_argv[size++] = xstrdup (other.m_argv[argi]); | 
|  | m_argv[size] = nullptr; | 
|  | } | 
|  |  | 
|  | /* The iterator type.  */ | 
|  |  | 
|  | typedef char **iterator; | 
|  |  | 
|  | /* Return an iterator pointing to the start of the array.  */ | 
|  |  | 
|  | iterator begin () | 
|  | { | 
|  | return m_argv; | 
|  | } | 
|  |  | 
|  | /* Return an iterator pointing to the end of the array.  */ | 
|  |  | 
|  | iterator end () | 
|  | { | 
|  | return m_argv + count (); | 
|  | } | 
|  |  | 
|  | bool operator!= (std::nullptr_t) | 
|  | { | 
|  | return m_argv != NULL; | 
|  | } | 
|  |  | 
|  | bool operator== (std::nullptr_t) | 
|  | { | 
|  | return m_argv == NULL; | 
|  | } | 
|  |  | 
|  | private: | 
|  |  | 
|  | /* The wrapped array.  */ | 
|  |  | 
|  | char **m_argv; | 
|  | }; | 
|  |  | 
|  | #endif /* GDBSUPPORT_BUILDARGV_H */ |