From 4486f98ec42df9d24891b5af25d132f5bd224287 Mon Sep 17 00:00:00 2001 From: Peng Yu Date: Sun, 13 Nov 2011 19:12:08 -0600 Subject: [PATCH 1/2] :Added relpath.c by Peng Yu Manpage to be added later on. Calling examples are in src/relpath.sh --- src/relpath.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/relpath.sh | 26 ++++++++ 2 files changed, 221 insertions(+), 0 deletions(-) create mode 100644 src/relpath.c create mode 100755 src/relpath.sh diff --git a/src/relpath.c b/src/relpath.c new file mode 100644 index 0000000..47a837a --- /dev/null +++ b/src/relpath.c @@ -0,0 +1,195 @@ +/* relpath -- derive the relative path a start path with respect to a target path. + Copyright (C) 2002-2011 Free Software Foundation, Inc. + + 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 . */ + +/* Written by Peng Yu */ +/* Modified from readlink.c */ + +#include +#include +#include + +#include "system.h" +#include "canonicalize.h" +#include "error.h" +#include "quote.h" + +/* The official name of this program (e.g., no `g' prefix). */ +#define PROGRAM_NAME "relpath" + +#define AUTHORS proper_name ("Peng Yu") + +/* If true, do not output the trailing newline. */ +static bool no_newline; + +static struct option const longopts[] = +{ + {"no-newline", no_argument, NULL, 'n'}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, + {NULL, 0, NULL, 0} +}; + + void +usage (int status) +{ + if (status != EXIT_SUCCESS) + fprintf (stderr, _("Try `%s --help' for more information.\n"), + program_name); + else + { + printf (_("Usage: %s [OPTION]... PATH START\n"), program_name); + fputs (_("Print a relative path of PATH with respect to START\n\n"), + stdout); + fputs (_("\ + -n, --no-newline do not output the trailing newline\n\ + "), stdout); + fputs (HELP_OPTION_DESCRIPTION, stdout); + fputs (VERSION_OPTION_DESCRIPTION, stdout); + emit_ancillary_info (); + } + exit (status); +} + + void +remove_commonprefix_modify(const char **abspath1, const char **abspath2) +{ + + const char *p1; + const char *p2; + + for(p1=*abspath1, p2=*abspath2; ; ++p1, ++p2) { + if(*p1 == *p2) { + if(*p1 == '/') { + *abspath1=p1; + *abspath2=p2; + // /a/b/c + // /a/b/c + // ^ + } else if(!(*p1)) { + *abspath1=p1; + *abspath2=p2; + break; + // /a/b + // /a/b + // ^ + } + } else if((!(*p1) && *p2=='/') + || (!(*p2) && *p1=='/')) { + *abspath1=p1; + *abspath2=p2; + break; + // /a/b/c + // /a/b + // ^ + } else { + break; + // /a/b1 + // /a/b2 + // ^ + } + } +} + + + int +main (int argc, char **argv) +{ + int optc; + + initialize_main (&argc, &argv); + set_program_name (argv[0]); + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + atexit (close_stdout); + + while ((optc = getopt_long (argc, argv, "n", longopts, NULL)) != -1) + { + switch (optc) + { + case 'n': + no_newline = true; + break; + case_GETOPT_HELP_CHAR; + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); + default: + usage (EXIT_FAILURE); + } + } + + if (optind >= argc) + { + error (0, 0, _("missing operand")); + usage (EXIT_FAILURE); + } + + const char *path = argv[optind++]; + + const char dot_path[]="."; + + const char *start; + if (optind >= argc) { + start = dot_path; + } else { + start = argv[optind++]; + } + + if (optind < argc) + { + error (0, 0, _("extra operand %s"), quote (argv[optind])); + usage (EXIT_FAILURE); + } + + char *abspath = canonicalize_filename_mode (path, CAN_MISSING); + char *absstart = canonicalize_filename_mode (start, CAN_MISSING); + + //printf ("abspath=%s\n", abspath); + //printf ("absstart=%s\n", absstart); + + const char *abspath_suffix=abspath; + const char *absstart_suffix=absstart; + remove_commonprefix_modify(&abspath_suffix, &absstart_suffix); + + //printf("relpath="); + if(*absstart_suffix) { + ++absstart_suffix; + printf("%s", ".."); + for(; *absstart_suffix; ++absstart_suffix) { + if(*absstart_suffix=='/') { + printf("%s", "/.."); + } + } + + printf("%s", abspath_suffix); + } else { + if(*abspath_suffix) { + printf("%s", ++abspath_suffix); + } else { + printf("%c", '.'); + } + } + + if(!no_newline) printf("\n"); + + //printf ("abspath_suffix=%s\n", abspath_suffix); + //printf ("absstart_suffix=%s\n", absstart_suffix); + + free (abspath); + free (absstart); + + return EXIT_SUCCESS; +} diff --git a/src/relpath.sh b/src/relpath.sh new file mode 100755 index 0000000..956eb0f --- /dev/null +++ b/src/relpath.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +./relpath +echo ==== +./relpath --version +echo ==== +./relpath --help +echo ==== +./relpath /1/2/3 ../u/v/w +echo ==== +./relpath /tmp/b +echo ==== +./relpath a/b a +echo ==== +./relpath a a +echo ==== +./relpath a a/c +echo ==== +./relpath a/b a/c +echo ==== +./relpath a/b/c z +echo ==== +./relpath a x/y/z +echo ==== +./relpath -n a x/y/z +echo ==== -- 1.7.4.1 From fc71bbd211a7b9bb37d7a231a0507d8b8f5b14b1 Mon Sep 17 00:00:00 2001 From: Peng Yu Date: Mon, 14 Nov 2011 07:03:12 -0600 Subject: [PATCH 2/2] maint: Add src/relpath.c --- src/relpath.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/src/relpath.c b/src/relpath.c index 47a837a..9e159e0 100644 --- a/src/relpath.c +++ b/src/relpath.c @@ -16,6 +16,7 @@ /* Written by Peng Yu */ /* Modified from readlink.c */ +/* See relpath.sh for some examples. Manpage will be added later on. */ #include #include -- 1.7.4.1