Convert programs/winepath to unicode, print the output string using
[wine] / programs / winepath / winepath.c
1 /*
2  * Translate between Wine and Unix paths
3  *
4  * Copyright 2002 Mike Wetherell
5  * Copyright 2005 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23
24 #include <windows.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27
28 #include "wine/debug.h"
29
30 #define VERSION "0.1 (" PACKAGE_STRING ")"
31
32 enum {
33     SHORTFORMAT = 1,
34     LONGFORMAT  = 2,
35     UNIXFORMAT  = 4
36 };
37
38 static const char progname[] = "winepath";
39
40 /* Wine specific functions */
41 typedef LPSTR (*wine_get_unix_file_name_t) ( LPCWSTR dos );
42 /*
43  * handle an option
44  */
45 static int option(int shortopt, const WCHAR *longopt)
46 {
47     static const char helpmsg[] =
48     "Convert PATH(s) to Unix or Windows long or short paths.\n"
49     "\n"
50     "  -u, --unix    output Unix format\n"
51     "  -l, --long    output Windows long format\n"
52     "  -s, --short   output Windows short format \n"
53     "  -h, --help    output this help message and exit\n"
54     "  -v, --version output version information and exit\n"
55     "\n"
56     "The input paths can be in any format. If more than one option is given\n"
57     "then the input paths are output in all formats specified, in the order\n"
58     "Unix, long, short. If no option is given the default is Unix format.\n";
59
60     switch (shortopt) {
61         case 'h':
62             printf("Usage: %s [OPTION] [PATH]...\n", progname);
63             printf(helpmsg);
64             exit(0);
65         case 'v':
66             printf("%s version " VERSION "\n", progname);
67             exit(0);
68         case 'l':
69             return LONGFORMAT;
70         case 's':
71             return SHORTFORMAT;
72         case 'u':
73             return UNIXFORMAT;
74     }
75
76     fprintf(stderr, "%s: invalid option ", progname);
77     if (longopt)
78         fprintf(stderr, "%s\n", wine_dbgstr_w(longopt));
79     else
80         fprintf(stderr, "'-%c'\n", shortopt);
81     fprintf(stderr, "Try '%s --help' for help\n", progname);
82     exit(2);
83 }
84
85 /*
86  * Parse command line options
87  */
88 static int parse_options(const WCHAR *argv[])
89 {
90     static const WCHAR longW[] = { 'l','o','n','g',0 };
91     static const WCHAR shortW[] = { 's','h','o','r','t',0 };
92     static const WCHAR unixW[] = { 'u','n','i','x',0 };
93     static const WCHAR helpW[] = { 'h','e','l','p',0 };
94     static const WCHAR versionW[] = { 'v','e','r','s','i','o','n',0 };
95     static const WCHAR nullW[] = { 0 };
96     static const WCHAR *longopts[] = { longW, shortW, unixW, helpW, versionW, nullW };
97     int outputformats = 0;
98     int done = 0;
99     int i, j;
100
101     for (i = 1; argv[i] && !done; )
102     {
103         if (argv[i][0] != '-') {
104             /* not an option */
105             i++;
106             continue;
107         }
108
109         if (argv[i][1] == '-') {
110             if (argv[i][2] == 0) {
111                 /* '--' end of options */
112                 done = 1;
113             } else {
114                 /* long option */
115                 for (j = 0; longopts[j][0]; j++)
116                     if (!lstrcmpiW(argv[i]+2, longopts[j]))
117                         break;
118                 outputformats |= option(longopts[j][0], argv[i]);
119             }
120         } else {
121             /* short options */
122             for (j = 1; argv[i][j]; j++)
123                 outputformats |= option(argv[i][j], NULL);
124         }
125
126         /* remove option */
127         for (j = i + 1; argv[j - 1]; j++)
128             argv[j - 1] = argv[j];
129     }
130
131     return outputformats;
132 }
133
134 /*
135  * Main function
136  */
137 int wmain(int argc, const WCHAR *argv[])
138 {
139     wine_get_unix_file_name_t wine_get_unix_file_name_ptr = NULL;
140     WCHAR dos_pathW[MAX_PATH];
141     char path[MAX_PATH];
142     int outputformats;
143     int i;
144
145     outputformats = parse_options(argv);
146     if (outputformats == 0)
147         outputformats = UNIXFORMAT;
148
149     if (outputformats & UNIXFORMAT) {
150         wine_get_unix_file_name_ptr = (wine_get_unix_file_name_t)
151             GetProcAddress(GetModuleHandle("KERNEL32"),
152                            "wine_get_unix_file_name");
153         if (wine_get_unix_file_name_ptr == NULL) {
154             fprintf(stderr, "%s: cannot get the address of "
155                             "'wine_get_unix_file_name'\n", progname);
156             exit(3);
157         }
158     }
159
160     for (i = 1; argv[i]; i++)
161     {
162         *path='\0';
163         if (outputformats & LONGFORMAT) {
164             if (GetFullPathNameW(argv[i], MAX_PATH, dos_pathW, NULL))
165                 WideCharToMultiByte(CP_UNIXCP, 0, dos_pathW, -1, path, MAX_PATH, NULL, NULL);
166             printf("%s\n", path);
167         }
168         if (outputformats & SHORTFORMAT) {
169             if (GetShortPathNameW(argv[i], dos_pathW, MAX_PATH))
170                 WideCharToMultiByte(CP_UNIXCP, 0, dos_pathW, -1, path, MAX_PATH, NULL, NULL);
171             printf("%s\n", path);
172         }
173         if (outputformats & UNIXFORMAT) {
174             char *unix_name;
175
176             if ((unix_name = wine_get_unix_file_name_ptr(argv[i])))
177             {
178                 printf("%s\n", unix_name);
179                 HeapFree( GetProcessHeap(), 0, unix_name );
180             }
181             else printf( "\n" );
182         }
183     }
184
185     exit(0);
186 }