Thread (33 messages) flat view 33 messages, 5 authors, 2016-06-15

Re: [PATCH v3 3/4] Provide a dirname() function when NO_LIBGEN_H=YesPlease

From: Eric Sunshine <hidden>
Date: 2016-06-15 23:07:41

On Mon, Jan 11, 2016 at 1:30 PM, Johannes Schindelin
[off-list ref] wrote:
quoted hunk ↗ jump to hunk
When there is no `libgen.h` to our disposal, we miss the `dirname()`
function.

So far, we only had one user of that function: credential-cache--daemon
(which was only compiled when Unix sockets are available, anyway). But
now we also have `builtin/am.c` as user, so we need it.

Since `dirname()` is a sibling of `basename()`, we simply put our very
own `gitdirname()` implementation next to `gitbasename()` and use it
if `NO_LIBGEN_H` has been set.

Signed-off-by: Johannes Schindelin <redacted>
---
diff --git a/compat/basename.c b/compat/basename.c
@@ -25,3 +26,46 @@ char *gitbasename (char *path)
+char *gitdirname(char *path)
+{
+       char *p = path, *slash = NULL, c;
+       int dos_drive_prefix;
+
+       if (!p)
+               return ".";
+
+       if ((dos_drive_prefix = skip_dos_drive_prefix(&p)) && !*p) {
+               static struct strbuf buf = STRBUF_INIT;
+
+dot:
+               strbuf_reset(&buf);
+               strbuf_addf(&buf, "%.*s.", dos_drive_prefix, path);
+               return buf.buf;
+       }
+
+       /*
+        * POSIX.1-2001 says dirname("/") should return "/", and dirname("//")
+        * should return "//", but dirname("///") should return "/" again.
+        */
+       if (is_dir_sep(*p)) {
+               if (!p[1] || (is_dir_sep(p[1]) && !p[2]))
+                       return path;
+               slash = ++p;
+       }
+       while ((c = *(p++)))
+               if (is_dir_sep(c)) {
+                       char *tentative = p - 1;
+
+                       /* POSIX.1-2001 says to ignore trailing slashes */
+                       while (is_dir_sep(*p))
+                               p++;
+                       if (*p)
+                               slash = tentative;
+               }
+
+       if (!slash)
+               goto dot;
+       *slash = '\0';
+       return path;
+}
I wonder if this would be a bit easier to follow if it was structured
something like this:

    static struct strbuf buf = STRBUF_INIT;

    if ((dos_drive_prefix = skip_dos_drive_prefix(&p)) && !*p)
        goto dot;

    ...
    if (is_dir_sep(*p)) {
        ...
    }
    ...
    while ((c = *(p++)))
        ...

    if (slash) {
        *slash = '\0';
        return path;
    }

    dot:
    strbuf_reset(&buf);
    strbuf_addf(&buf, "%.*s.", dos_drive_prefix, path);
    return buf.buf;
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help