Update of /cvsroot/oprofile/oprofile/util In directory usw-pr-cvs1:/tmp/cvs-serv4286/oprofile/util Modified Files: Makefile.in child_reader.cpp child_reader.h file_manip.cpp file_manip.h string_manip.cpp string_manip.h Added Files: misc.c misc.h Log Message: fix some FIXME --- NEW FILE: misc.c --- /* COPYRIGHT (C) 2001 by various authors * 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 2 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, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * * Part written by John Levon, P. Elie and the gcc team */ #include <stdio.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> #include <sys/types.h> #include <errno.h> #include <fcntl.h> #include <stdlib.h> #include "../config.h" #include "../op_user.h" #include "../dae/opd_util.h" #include "misc.h" #ifndef HAVE_XCALLOC /* some system have a valid libiberty without xcalloc */ void * xcalloc(size_t n_elem, size_t sz) { void * ptr = xmalloc(n_elem * sz); memset(ptr, '\0', n_elem * sz); return ptr; } #endif /* remove_component_p() and op_simlify_pathname() comes from the gcc preprocessor */ /** * remove_component_p - check if it is safe to remove the final component * of a path. * @path: string pointer * * Returns 1 if it is safe to remove the component * 0 otherwise */ static int remove_component_p (const char *path) { struct stat s; int result; result = lstat (path, &s); /* There's no guarantee that errno will be unchanged, even on success. Cygwin's lstat(), for example, will often set errno to ENOSYS. In case of success, reset errno to zero. */ if (result == 0) errno = 0; return result == 0 && S_ISDIR (s.st_mode); } /** * opd_simplify_path_name - simplify a path name in place * @path: string pointer to the path. * * Simplify a path name in place, deleting redundant components. This * reduces OS overhead and guarantees that equivalent paths compare * the same (modulo symlinks). * * Transforms made: * foo/bar/../quux foo/quux * foo/./bar foo/bar * foo//bar foo/bar * /../quux /quux * //quux //quux (POSIX allows leading // as a namespace escape) * * Guarantees no trailing slashes. All transforms reduce the length * of the string. Returns @path. errno is 0 if no error occurred; * nonzero if an error occurred when using stat(). */ char *opd_simplify_pathname (char *path) { char *from, *to; char *base, *orig_base; int absolute = 0; errno = 0; /* Don't overflow the empty path by putting a '.' in it below. */ if (*path == '\0') return path; from = to = path; /* Remove redundant leading /s. */ if (*from == '/') { absolute = 1; to++; from++; if (*from == '/') { if (*++from == '/') /* 3 or more initial /s are equivalent to 1 /. */ while (*++from == '/'); else /* On some hosts // differs from /; Posix allows this. */ to++; } } base = orig_base = to; for (;;) { int move_base = 0; while (*from == '/') from++; if (*from == '\0') break; if (*from == '.') { if (from[1] == '\0') break; if (from[1] == '/') { from += 2; continue; } else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0')) { /* Don't simplify if there was no previous component. */ if (absolute && orig_base == to) { from += 2; continue; } /* Don't simplify if the previous component * was "../", or if an error has already * occurred with (l)stat. */ if (base != to && errno == 0) { /* We don't back up if it's a symlink. */ *to = '\0'; if (remove_component_p (path)) { while (to > base && *to != '/') to--; from += 2; continue; } } move_base = 1; } } /* Add the component separator. */ if (to > orig_base) *to++ = '/'; /* Copy this component until the trailing null or '/'. */ while (*from != '\0' && *from != '/') *to++ = *from++; if (move_base) base = to; } /* Change the empty string to "." so that it is not treated as stdin. Null terminate. */ if (to == path) *to++ = '.'; *to = '\0'; return path; } /** * opd_relative_to_absolute_path - translate relative path to absolute path. * @path: path name * @base_dir: optionnal base directory, if %NULL getcwd() is used * to get the base directory. * * prepend @base_dir or the result of getcwd if the path is not absolute. * The returned string is dynamic allocated, caller must free it. if * base_dir == NULL this function use getcwd to translate the path. * * Returns the translated path. */ char *opd_relative_to_absolute_path(const char *path, const char *base_dir) { char dir[FILENAME_MAX + 1]; char *temp_path = NULL; if (path && path[0] != '/') { if (base_dir == NULL) { if (getcwd(dir, FILENAME_MAX) != NULL) { base_dir = dir; } } if (base_dir != NULL) { temp_path = xmalloc(strlen(path) + strlen(base_dir) + 2); strcpy(temp_path, base_dir); strcat(temp_path, "/"); strcat(temp_path, path); } } /* absolute path or (base_dir == NULL && getcwd have lose) : * always return a value */ if (temp_path == NULL) temp_path = xstrdup(path); return opd_simplify_pathname(temp_path); } --- NEW FILE: misc.h --- /* COPYRIGHT (C) 2001 by various authors * 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 2 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, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * * Part written by John Levon and P. Elie */ #ifndef MISC_H #define MISC_H #include <stddef.h> #include "../config.h" #ifdef HAVE_LIBIBERTY_H #include <libiberty.h> #endif #include "../op_user.h" #ifdef MALLOC_OK #define OP_ATTRIB_MALLOC __attribute__((malloc)) #else #define OP_ATTRIB_MALLOC #endif #ifdef __cplusplus extern "C" { #endif char *opd_simplify_pathname(char *path); char *opd_relative_to_absolute_path(const char *path, const char *base_dir); #ifndef HAVE_LIBIBERTY_H /* Set the program name used by xmalloc. */ void xmalloc_set_program_name(const char *); /* Allocate memory without fail. If malloc fails, this will print a message to stderr (using the name set by xmalloc_set_program_name, if any) and then call xexit. */ void * xmalloc(size_t) OP_ATTRIB_MALLOC; /* Reallocate memory without fail. This works like xmalloc. Note, realloc type functions are not suitable for attribute malloc since they may return the same address across multiple calls. */ void * xrealloc(void *, size_t); /* Allocate memory without fail and set it to zero. This works like xmalloc */ void * xcalloc(size_t, size_t) OP_ATTRIB_MALLOC; /* Copy a string into a memory buffer without fail. */ char *xstrdup(const char *) OP_ATTRIB_MALLOC; #endif /* !LIBIBERTY_H */ char *opd_simplify_pathname(char *path); char *opd_relative_to_absolute_path(const char *path, const char *base_dir); #ifdef __cplusplus } #endif #endif /* !MISC_H */ Index: Makefile.in =================================================================== RCS file: /cvsroot/oprofile/oprofile/util/Makefile.in,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- Makefile.in 2001/12/05 21:25:26 1.6 +++ Makefile.in 2001/12/12 02:27:27 1.7 @@ -1,9 +1,9 @@ CXXFLAGS=@CXXFLAGS@ -Wall -pedantic -W -Wunused -Wmissing-prototypes -CFLAGS=-ansi -pedantic -Wall -pipe -Wstrict-prototypes -Wunused -W -Wshadow -Wmissing-prototypes -Winline @CFLAGS@ +CFLAGS=-pedantic -Wall -pipe -Wstrict-prototypes -Wunused -W -Wshadow -Wmissing-prototypes -Winline @CFLAGS@ .PHONY: all clean install -all: string_manip.o child_reader.o file_manip.o op_popt.o +all: string_manip.o child_reader.o file_manip.o op_popt.o misc.o clean: rm -f *.o *.d @@ -16,6 +16,6 @@ %.o: %cpp $(CXX) -c $(CXXFLAGS) -g $< -o $@ -ALL_SOURCES = string_manip.cpp file_manip.cpp child_reader.cpp op_popt.c +ALL_SOURCES = string_manip.cpp file_manip.cpp child_reader.cpp op_popt.c misc.c include ../Rules.make Index: child_reader.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/util/child_reader.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- child_reader.cpp 2001/12/09 22:15:34 1.3 +++ child_reader.cpp 2001/12/12 02:27:27 1.4 @@ -36,7 +36,6 @@ using std::cerr; using std::endl; -/// ctor: fork a process. use int error() to get error code. ChildReader::ChildReader(string const & cmd, vector<string> const & args) : fd1(-1), @@ -55,7 +54,6 @@ exec_command(cmd, args); } -/// dtor: terminate the child process if neccessary ChildReader::~ChildReader() { terminate_process(); @@ -63,10 +61,6 @@ if (buf2) free(buf2); // allocated through C alloc } -// FIXME: why duplicate the comments in .h ... you should be able -// to read the doxygen output ... -// ctor helper: fork the child process cmd passing it the vector of arguments -// args. first_error is set to errno if something feel bad void ChildReader::exec_command(string const & cmd, vector<string> const & args) { int pstdout[2]; @@ -109,7 +103,7 @@ // we can communicate with parent by writing to stderr // and by returning a non zero error code. Setting - // first_error is the child is a non-sense + // first_error in the child is a non-sense // we are in the child process: so this error message // is redirect to the parent process @@ -132,8 +126,6 @@ return; } -/// return false when eof condition is reached on fd1. fd2 can have -/// already input in the pipe buffer or in buf2. bool ChildReader::block_read() { fd_set read_fs; @@ -168,8 +160,6 @@ return ret; } -/// read a line from the stdandard output of the child process. Return false -/// when eof condition is reached on the stdout and stderr of the child bool ChildReader::getline(string & result) { // some stl lacks string::clear() Index: child_reader.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/util/child_reader.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- child_reader.h 2001/12/09 22:15:34 1.3 +++ child_reader.h 2001/12/12 02:27:27 1.4 @@ -27,11 +27,11 @@ /** * a class to read stdout / stderr from a child process. * FIXME: code review is needed: - * - check the getline()/get_block()/read_block() interface. + * - check the getline()/get_data()/block_read() interface. * the expected behavior is: * caller can call getline until nothing is available from the stdout of the * child. in this case child stderr is acumulated in buf2 and can be read - * through get_block(). get_block() is blocking until the child close stderr / + * through get_data(). get_data() is blocking until the child close stderr / * stdout (even if the child die by a signal ?). The following corner case must * work but I'm unsure if the code reflect this behavior: the last line of the * child stdout have not necessarilly a LF terminator. the child can output any @@ -45,21 +45,23 @@ std::vector<std::string> const & args); /// wait for the termination of the child process if this have not - /// occur. In this cas return code of the child process is not + /// occur. In this case return code of the child process is not /// available. ~ChildReader(); /// two interface are possible. read line by line or read in one block. - /// getline only read from stdout of the child. get_block() must be + /// getline only read from stdout of the child. get_data() must be /// called to flush the input from the stderr child. /// fill result from on line of stdout of the child process. /// must be used as: /// ChildReader reader(...); - /// while (reader.getline(line) .... + /// while (reader.getline(line)) .... bool getline(std::string & result); /// fill out / err with the stdout / stderr of the child process. + /// You can call this after calling one or more time getline(...). This + /// call is blocking until the child die. bool get_data(std::ostream & out, std::ostream & err); /// rather to rely on dtor to wait for the termination of the child you Index: file_manip.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/util/file_manip.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- file_manip.cpp 2001/12/09 22:15:34 1.4 +++ file_manip.cpp 2001/12/12 02:27:27 1.5 @@ -1,4 +1,4 @@ -/* COPYRIGHT (C) 2001 by ? +/* COPYRIGHT (C) 2001 by various authors * 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 2 of the License, or (at your option) @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * - * first written by John Levon and P. Elie + * Part written by John Levon and P. Elie */ #include <sys/stat.h> @@ -26,6 +26,7 @@ #include <string> #include "file_manip.h" +#include "string_manip.h" using std::vector; using std::string; @@ -340,4 +341,28 @@ free(result); return res; +} + +/** + * dirname - get the path component of a filename + * @file_name: filename + * + * Returns the path name of a filename with trailing '/' removed. + */ +string dirname(string const & file_name) +{ + return erase_from_last_of(file_name, '/'); +} + +/** + * basename - get the basename of a path + * @path_name: path + * + * Returns the basename of a path with trailing '/' removed. + */ +string basename(string const & path_name) +{ + string result = rtrim(path_name, '/'); + + return erase_to_last_of(result, '/'); } Index: file_manip.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/util/file_manip.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- file_manip.h 2001/12/09 21:48:52 1.5 +++ file_manip.h 2001/12/12 02:27:27 1.6 @@ -1,4 +1,4 @@ -/* COPYRIGHT (C) 2001 by ? +/* COPYRIGHT (C) 2001 by various authors * 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 2 of the License, or (at your option) @@ -13,18 +13,12 @@ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * - * first written by John Levon and P. Elie + * Part written by John Levon and P. Elie */ #ifndef FILE_MANIP_H #define FILE_MANIP_H -/* FIXME: I really do not like this __cplusplus thing. - * either it is a C header or it isn't. C headers shouldn't - * be including C++ headers - please split this out. - */ -#ifdef __cplusplus - #include <string> #include <list> @@ -39,17 +33,9 @@ std::string relative_to_absolute_path(const std::string & path, const std::string & base_dir = std::string()); -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -char *opd_simplify_pathname(char *path); -char *opd_relative_to_absolute_path(const char *path, const char *base_dir); -#ifdef __cplusplus -} -#endif +// filename handling. +std::string dirname(std::string const & file_name); +std::string basename(std::string const & path_name); #endif /* !FILE_MANIP_H */ Index: string_manip.cpp =================================================================== RCS file: /cvsroot/oprofile/oprofile/util/string_manip.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- string_manip.cpp 2001/12/09 22:15:34 1.3 +++ string_manip.cpp 2001/12/12 02:27:27 1.4 @@ -23,38 +23,41 @@ using std::string; -// FIXME: ick no, dirname has bugger all to do with "string_manip" -// please move ;) /** - * dirname - get the path component of a filename - * @file_name: filename + * erase_from_last_of - erase a sequence from the last occurence + * of a given char to the end of string + * @str: string + * @ch: the char from where we erase character * - * Returns the path name of a filename with trailing '/' removed. + * erase char from the last occurence of @ch to the + * end of @str and return the string */ -string dirname(string const & file_name) +string erase_from_last_of(string const & str, char ch) { - string result = file_name; + string result = str; - string::size_type slash = result.find_last_of('/'); - if (slash != string::npos) - result.erase(slash, result.length() - slash); + string::size_type pos = result.find_last_of(ch); + if (pos != string::npos) + result.erase(pos, result.length() - pos); return result; } /** - * basename - get the basename of a path - * @path_name: path + * erase to_last_of - erase a sequence of character from + * the begining of string to the last occurence of a given char + * @str: string + * @ch: the characterto search * - * Returns the basename of a path with trailing '/' removed. + * erase char from the begin of @str to the last + * occurence of @ch from and return the string */ -string basename(string const & path_name) +string erase_to_last_of(string const & str, char ch) { - string result = rtrim(path_name, '/'); - - string::size_type slash = result.find_last_of('/'); - if (slash != string::npos) - result.erase(0, slash + 1); + string result = str; + string::size_type pos = result.find_last_of(ch); + if (pos != string::npos) + result.erase(0, pos + 1); return result; } Index: string_manip.h =================================================================== RCS file: /cvsroot/oprofile/oprofile/util/string_manip.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- string_manip.h 2001/11/11 23:55:13 1.1 +++ string_manip.h 2001/12/12 02:27:27 1.2 @@ -1,4 +1,4 @@ -/* COPYRIGHT (C) 2001 by ? +/* COPYRIGHT (C) 2001 by various authors * 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 2 of the License, or (at your option) @@ -13,7 +13,7 @@ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * - * first written by John Levon and P. Elie + * Part written by John Levon and P. Elie */ #ifndef STRING_MANIP_H @@ -21,13 +21,12 @@ #include <string> -// filename handling. -std::string dirname(std::string const & file_name); -std::string basename(std::string const & path_name); +string erase_from_last_of(string const & str, char ch); +string erase_to_last_of(string const & str, char ch); std::string rtrim(std::string const & str, char ch); -// conversion to std::string +/// conversion to std::string std::string tostr(unsigned int i); #endif /* !STRING_MANIP_H */ |