| 837 | #define IS_ABSOLUTE( x ) (*x == '/' || *x == '\\' || (*x && *(x + 1) == ':')) |
| 838 | |
| 839 | static void collapse_path( WCHAR *path, UINT mark ) |
| 840 | { |
| 841 | WCHAR *p, *next; |
| 842 | |
| 843 | /* convert every / into a \ */ |
| 844 | for (p = path; *p; p++) if (*p == '/') *p = '\\'; |
| 845 | |
| 846 | /* collapse duplicate backslashes */ |
| 847 | next = path + std::max( 1u, mark ); |
| 848 | for (p = next; *p; p++) if (*p != '\\' || next[-1] != '\\') *next++ = *p; |
| 849 | *next = 0; |
| 850 | |
| 851 | p = path + mark; |
| 852 | while (*p) |
| 853 | { |
| 854 | if (*p == '.') |
| 855 | { |
| 856 | switch(p[1]) |
| 857 | { |
| 858 | case '\\': /* .\ component */ |
| 859 | next = p + 2; |
| 860 | memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); |
| 861 | continue; |
| 862 | case 0: /* final . */ |
| 863 | if (p > path + mark) p--; |
| 864 | *p = 0; |
| 865 | continue; |
| 866 | case '.': |
| 867 | if (p[2] == '\\') /* ..\ component */ |
| 868 | { |
| 869 | next = p + 3; |
| 870 | if (p > path + mark) |
| 871 | { |
| 872 | p--; |
| 873 | while (p > path + mark && p[-1] != '\\') p--; |
| 874 | } |
| 875 | memmove( p, next, (wcslen(next) + 1) * sizeof(WCHAR) ); |
| 876 | continue; |
| 877 | } |
| 878 | else if (!p[2]) /* final .. */ |
| 879 | { |
| 880 | if (p > path + mark) |
| 881 | { |
| 882 | p--; |
| 883 | while (p > path + mark && p[-1] != '\\') p--; |
| 884 | if (p > path + mark) p--; |
| 885 | } |
| 886 | *p = 0; |
| 887 | continue; |
| 888 | } |
| 889 | break; |
| 890 | } |
| 891 | } |
| 892 | /* skip to the next component */ |
| 893 | while (*p && *p != '\\') p++; |
| 894 | if (*p == '\\') |
| 895 | { |
| 896 | /* remove last dot in previous dir name */ |
no outgoing calls
no test coverage detected