#include #include #include #include #include #include #define is_valid_drive(d) ((d)>='a' && (d)<='z' || (d)>='A' && (d)<='Z') /* * Gets the last component of the filename. If filename ends with a directory * separator it gets the component before the last slash. If filename consists * only of directory separators (and on Windows, possibly a drive letter), a * single separator is returned. If filename is empty, it gets ".". */ char *path_get_basename(const char *filename) { ssize_t base,last_nonslash; size_t len; char *retval; if (*filename=='\0') return str_dup("."); last_nonslash=strlen(filename)-1; while (last_nonslash>=0 && GC_IS_DIR_SEPARATOR(filename[last_nonslash])) last_nonslash--; if (last_nonslash<0) /* string only containing slashes */ return str_dup(GC_DIR_SEPARATOR_S); #ifdef WIN32 if (last_nonslash==1 && is_valid_drive(filename[0]) && filename[1]==':') /* string only containing slashes and a drive */ return str_dup(GC_DIR_SEPARATOR_S); #endif base=last_nonslash; while (base>=0 && !GC_IS_DIR_SEPARATOR(filename[base])) base--; #ifdef WIN32 if (base==-1 && is_valid_drive(filename[0]) && filename[1] == ':') base=1; #endif len=last_nonslash-base; retval=mem_alloc(len+1,1); memcpy(retval,filename+base+1,len); retval[len]='\0'; return retval; }