1 | /* |
---|
2 | Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr |
---|
3 | |
---|
4 | This file is part of the SyncTeX package. |
---|
5 | |
---|
6 | Latest Revision: Tue Jun 14 08:23:30 UTC 2011 |
---|
7 | |
---|
8 | Version: 1.18 |
---|
9 | |
---|
10 | See synctex_parser_readme.txt for more details |
---|
11 | |
---|
12 | License: |
---|
13 | -------- |
---|
14 | Permission is hereby granted, free of charge, to any person |
---|
15 | obtaining a copy of this software and associated documentation |
---|
16 | files (the "Software"), to deal in the Software without |
---|
17 | restriction, including without limitation the rights to use, |
---|
18 | copy, modify, merge, publish, distribute, sublicense, and/or sell |
---|
19 | copies of the Software, and to permit persons to whom the |
---|
20 | Software is furnished to do so, subject to the following |
---|
21 | conditions: |
---|
22 | |
---|
23 | The above copyright notice and this permission notice shall be |
---|
24 | included in all copies or substantial portions of the Software. |
---|
25 | |
---|
26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
---|
27 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
---|
28 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
---|
29 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
---|
30 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
---|
31 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
---|
32 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
---|
33 | OTHER DEALINGS IN THE SOFTWARE |
---|
34 | |
---|
35 | Except as contained in this notice, the name of the copyright holder |
---|
36 | shall not be used in advertising or otherwise to promote the sale, |
---|
37 | use or other dealings in this Software without prior written |
---|
38 | authorization from the copyright holder. |
---|
39 | |
---|
40 | */ |
---|
41 | |
---|
42 | /* In this file, we find all the functions that may depend on the operating system. */ |
---|
43 | |
---|
44 | #include <synctex_parser_utils.h> |
---|
45 | #include <stdlib.h> |
---|
46 | #include <string.h> |
---|
47 | #include <stdarg.h> |
---|
48 | #include <stdio.h> |
---|
49 | |
---|
50 | #include <limits.h> |
---|
51 | #include <ctype.h> |
---|
52 | #include <string.h> |
---|
53 | |
---|
54 | #include <sys/stat.h> |
---|
55 | |
---|
56 | #if defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) |
---|
57 | #define SYNCTEX_WINDOWS 1 |
---|
58 | #endif |
---|
59 | |
---|
60 | #if defined(__OS2__) |
---|
61 | #define SYNCTEX_OS2 1 |
---|
62 | #endif |
---|
63 | |
---|
64 | #ifdef _WIN32_WINNT_WINXP |
---|
65 | #define SYNCTEX_RECENT_WINDOWS 1 |
---|
66 | #endif |
---|
67 | |
---|
68 | #ifdef SYNCTEX_WINDOWS |
---|
69 | #include <windows.h> |
---|
70 | #include <shlwapi.h> /* Use shlwapi.lib */ |
---|
71 | #endif |
---|
72 | |
---|
73 | void *_synctex_malloc(size_t size) { |
---|
74 | void * ptr = malloc(size); |
---|
75 | if(ptr) { |
---|
76 | /* There used to be a switch to use bzero because it is more secure. JL */ |
---|
77 | memset(ptr,0, size); |
---|
78 | } |
---|
79 | return (void *)ptr; |
---|
80 | } |
---|
81 | |
---|
82 | int _synctex_error(const char * reason,...) { |
---|
83 | va_list arg; |
---|
84 | int result; |
---|
85 | va_start (arg, reason); |
---|
86 | # ifdef SYNCTEX_RECENT_WINDOWS |
---|
87 | {/* This code is contributed by William Blum. |
---|
88 | As it does not work on some older computers, |
---|
89 | the _WIN32 conditional here is replaced with a SYNCTEX_RECENT_WINDOWS one. |
---|
90 | According to http://msdn.microsoft.com/en-us/library/aa363362(VS.85).aspx |
---|
91 | Minimum supported client Windows 2000 Professional |
---|
92 | Minimum supported server Windows 2000 Server |
---|
93 | People running Windows 2K standard edition will not have OutputDebugStringA. |
---|
94 | JL.*/ |
---|
95 | char *buff; |
---|
96 | size_t len; |
---|
97 | OutputDebugStringA("SyncTeX ERROR: "); |
---|
98 | len = _vscprintf(reason, arg) + 1; |
---|
99 | buff = (char*)malloc( len * sizeof(char) ); |
---|
100 | result = vsprintf(buff, reason, arg) +strlen("SyncTeX ERROR: "); |
---|
101 | OutputDebugStringA(buff); |
---|
102 | OutputDebugStringA("\n"); |
---|
103 | free(buff); |
---|
104 | } |
---|
105 | # else |
---|
106 | result = fprintf(stderr,"SyncTeX ERROR: "); |
---|
107 | result += vfprintf(stderr, reason, arg); |
---|
108 | result += fprintf(stderr,"\n"); |
---|
109 | # endif |
---|
110 | va_end (arg); |
---|
111 | return result; |
---|
112 | } |
---|
113 | |
---|
114 | /* strip the last extension of the given string, this string is modified! */ |
---|
115 | void _synctex_strip_last_path_extension(char * string) { |
---|
116 | if(NULL != string){ |
---|
117 | char * last_component = NULL; |
---|
118 | char * last_extension = NULL; |
---|
119 | # if defined(SYNCTEX_WINDOWS) |
---|
120 | last_component = PathFindFileName(string); |
---|
121 | last_extension = PathFindExtension(string); |
---|
122 | if(last_extension == NULL)return; |
---|
123 | if(last_component == NULL)last_component = string; |
---|
124 | if(last_extension>last_component){/* filter out paths like "my/dir/.hidden" */ |
---|
125 | last_extension[0] = '\0'; |
---|
126 | } |
---|
127 | # else |
---|
128 | char * next = NULL; |
---|
129 | /* first we find the last path component */ |
---|
130 | if(NULL == (last_component = strstr(string,"/"))){ |
---|
131 | last_component = string; |
---|
132 | } else { |
---|
133 | ++last_component; |
---|
134 | while((next = strstr(last_component,"/"))){ |
---|
135 | last_component = next+1; |
---|
136 | } |
---|
137 | } |
---|
138 | # if defined(SYNCTEX_OS2) |
---|
139 | /* On OS2, the '\' is also a path separator. */ |
---|
140 | while((next = strstr(last_component,"\\"))){ |
---|
141 | last_component = next+1; |
---|
142 | } |
---|
143 | # endif /* SYNCTEX_OS2 */ |
---|
144 | /* then we find the last path extension */ |
---|
145 | if((last_extension = strstr(last_component,"."))){ |
---|
146 | ++last_extension; |
---|
147 | while((next = strstr(last_extension,"."))){ |
---|
148 | last_extension = next+1; |
---|
149 | } |
---|
150 | --last_extension;/* back to the "." */ |
---|
151 | if(last_extension>last_component){/* filter out paths like ....my/dir/.hidden"*/ |
---|
152 | last_extension[0] = '\0'; |
---|
153 | } |
---|
154 | } |
---|
155 | # endif /* SYNCTEX_WINDOWS */ |
---|
156 | } |
---|
157 | } |
---|
158 | |
---|
159 | synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name_ref) |
---|
160 | { |
---|
161 | if (SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])) { |
---|
162 | do { |
---|
163 | (*name_ref) += 2; |
---|
164 | while (SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[0])) { |
---|
165 | ++(*name_ref); |
---|
166 | } |
---|
167 | } while(SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])); |
---|
168 | return synctex_YES; |
---|
169 | } |
---|
170 | return synctex_NO; |
---|
171 | } |
---|
172 | |
---|
173 | /* The base name is necessary to deal with the 2011 file naming convention... |
---|
174 | * path is a '\0' terminated string |
---|
175 | * The return value is the trailing part of the argument, |
---|
176 | * just following the first occurrence of the regexp pattern "[^|/|\].[\|/]+".*/ |
---|
177 | const char * _synctex_base_name(const char *path) { |
---|
178 | const char * ptr = path; |
---|
179 | do { |
---|
180 | if (synctex_ignore_leading_dot_slash_in_path(&ptr)) { |
---|
181 | return ptr; |
---|
182 | } |
---|
183 | do { |
---|
184 | if (!*(++ptr)) { |
---|
185 | return path; |
---|
186 | } |
---|
187 | } while (!SYNCTEX_IS_PATH_SEPARATOR(*ptr)); |
---|
188 | } while (*(++ptr)); |
---|
189 | return path; |
---|
190 | } |
---|
191 | |
---|
192 | /* Compare two file names, windows is sometimes case insensitive... */ |
---|
193 | synctex_bool_t _synctex_is_equivalent_file_name(const char *lhs, const char *rhs) { |
---|
194 | /* Remove the leading regex '(\./+)*' in both rhs and lhs */ |
---|
195 | synctex_ignore_leading_dot_slash_in_path(&lhs); |
---|
196 | synctex_ignore_leading_dot_slash_in_path(&rhs); |
---|
197 | next_character: |
---|
198 | if (SYNCTEX_IS_PATH_SEPARATOR(*lhs)) {/* lhs points to a path separator */ |
---|
199 | if (!SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* but not rhs */ |
---|
200 | return synctex_NO; |
---|
201 | } |
---|
202 | ++lhs; |
---|
203 | ++rhs; |
---|
204 | synctex_ignore_leading_dot_slash_in_path(&lhs); |
---|
205 | synctex_ignore_leading_dot_slash_in_path(&rhs); |
---|
206 | goto next_character; |
---|
207 | } else if (SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* rhs points to a path separator but not lhs */ |
---|
208 | return synctex_NO; |
---|
209 | } else if (SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(*lhs,*rhs)){/* uppercase do not match */ |
---|
210 | return synctex_NO; |
---|
211 | } else if (!*lhs) {/* lhs is at the end of the string */ |
---|
212 | return *rhs ? synctex_NO : synctex_YES; |
---|
213 | } else if(!*rhs) {/* rhs is at the end of the string but not lhs */ |
---|
214 | return synctex_NO; |
---|
215 | } |
---|
216 | ++lhs; |
---|
217 | ++rhs; |
---|
218 | goto next_character; |
---|
219 | } |
---|
220 | |
---|
221 | synctex_bool_t _synctex_path_is_absolute(const char * name) { |
---|
222 | if(!strlen(name)) { |
---|
223 | return synctex_NO; |
---|
224 | } |
---|
225 | # if defined(SYNCTEX_WINDOWS) || defined(SYNCTEX_OS2) |
---|
226 | if(strlen(name)>2) { |
---|
227 | return (name[1]==':' && SYNCTEX_IS_PATH_SEPARATOR(name[2]))?synctex_YES:synctex_NO; |
---|
228 | } |
---|
229 | return synctex_NO; |
---|
230 | # else |
---|
231 | return SYNCTEX_IS_PATH_SEPARATOR(name[0])?synctex_YES:synctex_NO; |
---|
232 | # endif |
---|
233 | } |
---|
234 | |
---|
235 | /* We do not take care of UTF-8 */ |
---|
236 | const char * _synctex_last_path_component(const char * name) { |
---|
237 | const char * c = name+strlen(name); |
---|
238 | if(c>name) { |
---|
239 | if(!SYNCTEX_IS_PATH_SEPARATOR(*c)) { |
---|
240 | do { |
---|
241 | --c; |
---|
242 | if(SYNCTEX_IS_PATH_SEPARATOR(*c)) { |
---|
243 | return c+1; |
---|
244 | } |
---|
245 | } while(c>name); |
---|
246 | } |
---|
247 | return c;/* the last path component is the void string*/ |
---|
248 | } |
---|
249 | return c; |
---|
250 | } |
---|
251 | |
---|
252 | int _synctex_copy_with_quoting_last_path_component(const char * src, char ** dest_ref, size_t size) { |
---|
253 | const char * lpc; |
---|
254 | if(src && dest_ref) { |
---|
255 | # define dest (*dest_ref) |
---|
256 | dest = NULL; /* Default behavior: no change and sucess. */ |
---|
257 | lpc = _synctex_last_path_component(src); |
---|
258 | if(strlen(lpc)) { |
---|
259 | if(strchr(lpc,' ') && lpc[0]!='"' && lpc[strlen(lpc)-1]!='"') { |
---|
260 | /* We are in the situation where adding the quotes is allowed. */ |
---|
261 | /* Time to add the quotes. */ |
---|
262 | /* Consistency test: we must have dest+size>dest+strlen(dest)+2 |
---|
263 | * or equivalently: strlen(dest)+2<size (see below) */ |
---|
264 | if(strlen(src)<size) { |
---|
265 | if((dest = (char *)malloc(size+2))) { |
---|
266 | char * dpc = dest + (lpc-src); /* dpc is the last path component of dest. */ |
---|
267 | if(dest != strncpy(dest,src,size)) { |
---|
268 | _synctex_error("! _synctex_copy_with_quoting_last_path_component: Copy problem"); |
---|
269 | free(dest); |
---|
270 | dest = NULL;/* Don't forget to reinitialize. */ |
---|
271 | return -2; |
---|
272 | } |
---|
273 | memmove(dpc+1,dpc,strlen(dpc)+1); /* Also move the null terminating character. */ |
---|
274 | dpc[0]='"'; |
---|
275 | dpc[strlen(dpc)+1]='\0';/* Consistency test */ |
---|
276 | dpc[strlen(dpc)]='"'; |
---|
277 | return 0; /* Success. */ |
---|
278 | } |
---|
279 | return -1; /* Memory allocation error. */ |
---|
280 | } |
---|
281 | _synctex_error("! _synctex_copy_with_quoting_last_path_component: Internal inconsistency"); |
---|
282 | return -3; |
---|
283 | } |
---|
284 | return 0; /* Success. */ |
---|
285 | } |
---|
286 | return 0; /* No last path component. */ |
---|
287 | # undef dest |
---|
288 | } |
---|
289 | return 1; /* Bad parameter, this value is subject to changes. */ |
---|
290 | } |
---|
291 | |
---|
292 | /* The client is responsible of the management of the returned string, if any. */ |
---|
293 | char * _synctex_merge_strings(const char * first,...); |
---|
294 | |
---|
295 | char * _synctex_merge_strings(const char * first,...) { |
---|
296 | va_list arg; |
---|
297 | size_t size = 0; |
---|
298 | const char * temp; |
---|
299 | /* First retrieve the size necessary to store the merged string */ |
---|
300 | va_start (arg, first); |
---|
301 | temp = first; |
---|
302 | do { |
---|
303 | size_t len = strlen(temp); |
---|
304 | if(UINT_MAX-len<size) { |
---|
305 | _synctex_error("! _synctex_merge_strings: Capacity exceeded."); |
---|
306 | return NULL; |
---|
307 | } |
---|
308 | size+=len; |
---|
309 | } while( (temp = va_arg(arg, const char *)) != NULL); |
---|
310 | va_end(arg); |
---|
311 | if(size>0) { |
---|
312 | char * result = NULL; |
---|
313 | ++size; |
---|
314 | /* Create the memory storage */ |
---|
315 | if(NULL!=(result = (char *)malloc(size))) { |
---|
316 | char * dest = result; |
---|
317 | va_start (arg, first); |
---|
318 | temp = first; |
---|
319 | do { |
---|
320 | if((size = strlen(temp))>0) { |
---|
321 | /* There is something to merge */ |
---|
322 | if(dest != strncpy(dest,temp,size)) { |
---|
323 | _synctex_error("! _synctex_merge_strings: Copy problem"); |
---|
324 | free(result); |
---|
325 | result = NULL; |
---|
326 | return NULL; |
---|
327 | } |
---|
328 | dest += size; |
---|
329 | } |
---|
330 | } while( (temp = va_arg(arg, const char *)) != NULL); |
---|
331 | va_end(arg); |
---|
332 | dest[0]='\0';/* Terminate the merged string */ |
---|
333 | return result; |
---|
334 | } |
---|
335 | _synctex_error("! _synctex_merge_strings: Memory problem"); |
---|
336 | return NULL; |
---|
337 | } |
---|
338 | return NULL; |
---|
339 | } |
---|
340 | |
---|
341 | /* The purpose of _synctex_get_name is to find the name of the synctex file. |
---|
342 | * There is a list of possible filenames from which we return the most recent one and try to remove all the others. |
---|
343 | * With two runs of pdftex or xetex we are sure the the synctex file is really the most appropriate. |
---|
344 | */ |
---|
345 | int _synctex_get_name(const char * output, const char * build_directory, char ** synctex_name_ref, synctex_io_mode_t * io_mode_ref) |
---|
346 | { |
---|
347 | if(output && synctex_name_ref && io_mode_ref) { |
---|
348 | /* If output is already absolute, we just have to manage the quotes and the compress mode */ |
---|
349 | size_t size = 0; |
---|
350 | char * synctex_name = NULL; |
---|
351 | synctex_io_mode_t io_mode = *io_mode_ref; |
---|
352 | const char * base_name = _synctex_last_path_component(output); /* do not free, output is the owner. base name of output*/ |
---|
353 | /* Do we have a real base name ? */ |
---|
354 | if(strlen(base_name)>0) { |
---|
355 | /* Yes, we do. */ |
---|
356 | const char * temp = NULL; |
---|
357 | char * core_name = NULL; /* base name of output without path extension. */ |
---|
358 | char * dir_name = NULL; /* dir name of output */ |
---|
359 | char * quoted_core_name = NULL; |
---|
360 | char * basic_name = NULL; |
---|
361 | char * gz_name = NULL; |
---|
362 | char * quoted_name = NULL; |
---|
363 | char * quoted_gz_name = NULL; |
---|
364 | char * build_name = NULL; |
---|
365 | char * build_gz_name = NULL; |
---|
366 | char * build_quoted_name = NULL; |
---|
367 | char * build_quoted_gz_name = NULL; |
---|
368 | struct stat buf; |
---|
369 | time_t the_time = 0; |
---|
370 | /* Create core_name: let temp point to the dot before the path extension of base_name; |
---|
371 | * We start form the \0 terminating character and scan the string upward until we find a dot. |
---|
372 | * The leading dot is not accepted. */ |
---|
373 | if((temp = strrchr(base_name,'.')) && (size = temp - base_name)>0) { |
---|
374 | /* There is a dot and it is not at the leading position */ |
---|
375 | if(NULL == (core_name = (char *)malloc(size+1))) { |
---|
376 | _synctex_error("! _synctex_get_name: Memory problem 1"); |
---|
377 | return -1; |
---|
378 | } |
---|
379 | if(core_name != strncpy(core_name,base_name,size)) { |
---|
380 | _synctex_error("! _synctex_get_name: Copy problem 1"); |
---|
381 | free(core_name); |
---|
382 | dir_name = NULL; |
---|
383 | return -2; |
---|
384 | } |
---|
385 | core_name[size] = '\0'; |
---|
386 | } else { |
---|
387 | /* There is no path extension, |
---|
388 | * Just make a copy of base_name */ |
---|
389 | core_name = _synctex_merge_strings(base_name); |
---|
390 | } |
---|
391 | /* core_name is properly set up, owned by "self". */ |
---|
392 | /* creating dir_name. */ |
---|
393 | size = strlen(output)-strlen(base_name); |
---|
394 | if(size>0) { |
---|
395 | /* output contains more than one path component */ |
---|
396 | if(NULL == (dir_name = (char *)malloc(size+1))) { |
---|
397 | _synctex_error("! _synctex_get_name: Memory problem"); |
---|
398 | free(core_name); |
---|
399 | dir_name = NULL; |
---|
400 | return -1; |
---|
401 | } |
---|
402 | if(dir_name != strncpy(dir_name,output,size)) { |
---|
403 | _synctex_error("! _synctex_get_name: Copy problem"); |
---|
404 | free(dir_name); |
---|
405 | dir_name = NULL; |
---|
406 | free(core_name); |
---|
407 | dir_name = NULL; |
---|
408 | return -2; |
---|
409 | } |
---|
410 | dir_name[size] = '\0'; |
---|
411 | } |
---|
412 | /* dir_name is properly set up. It ends with a path separator, if non void. */ |
---|
413 | /* creating quoted_core_name. */ |
---|
414 | if(strchr(core_name,' ')) { |
---|
415 | quoted_core_name = _synctex_merge_strings("\"",core_name,"\""); |
---|
416 | } |
---|
417 | /* quoted_core_name is properly set up. */ |
---|
418 | if(dir_name &&strlen(dir_name)>0) { |
---|
419 | basic_name = _synctex_merge_strings(dir_name,core_name,synctex_suffix,NULL); |
---|
420 | if(quoted_core_name && strlen(quoted_core_name)>0) { |
---|
421 | quoted_name = _synctex_merge_strings(dir_name,quoted_core_name,synctex_suffix,NULL); |
---|
422 | } |
---|
423 | } else { |
---|
424 | basic_name = _synctex_merge_strings(core_name,synctex_suffix,NULL); |
---|
425 | if(quoted_core_name && strlen(quoted_core_name)>0) { |
---|
426 | quoted_name = _synctex_merge_strings(quoted_core_name,synctex_suffix,NULL); |
---|
427 | } |
---|
428 | } |
---|
429 | if(!_synctex_path_is_absolute(output) && build_directory && (size = strlen(build_directory))) { |
---|
430 | temp = build_directory + size - 1; |
---|
431 | if(_synctex_path_is_absolute(temp)) { |
---|
432 | build_name = _synctex_merge_strings(build_directory,basic_name,NULL); |
---|
433 | if(quoted_core_name && strlen(quoted_core_name)>0) { |
---|
434 | build_quoted_name = _synctex_merge_strings(build_directory,quoted_name,NULL); |
---|
435 | } |
---|
436 | } else { |
---|
437 | build_name = _synctex_merge_strings(build_directory,"/",basic_name,NULL); |
---|
438 | if(quoted_core_name && strlen(quoted_core_name)>0) { |
---|
439 | build_quoted_name = _synctex_merge_strings(build_directory,"/",quoted_name,NULL); |
---|
440 | } |
---|
441 | } |
---|
442 | } |
---|
443 | if(basic_name) { |
---|
444 | gz_name = _synctex_merge_strings(basic_name,synctex_suffix_gz,NULL); |
---|
445 | } |
---|
446 | if(quoted_name) { |
---|
447 | quoted_gz_name = _synctex_merge_strings(quoted_name,synctex_suffix_gz,NULL); |
---|
448 | } |
---|
449 | if(build_name) { |
---|
450 | build_gz_name = _synctex_merge_strings(build_name,synctex_suffix_gz,NULL); |
---|
451 | } |
---|
452 | if(build_quoted_name) { |
---|
453 | build_quoted_gz_name = _synctex_merge_strings(build_quoted_name,synctex_suffix_gz,NULL); |
---|
454 | } |
---|
455 | /* All the others names are properly set up... */ |
---|
456 | /* retain the most recently modified file */ |
---|
457 | # define TEST(FILENAME,COMPRESS_MODE) \ |
---|
458 | if(FILENAME) {\ |
---|
459 | if (stat(FILENAME, &buf)) { \ |
---|
460 | free(FILENAME);\ |
---|
461 | FILENAME = NULL;\ |
---|
462 | } else if (buf.st_mtime>the_time) { \ |
---|
463 | the_time=buf.st_mtime; \ |
---|
464 | synctex_name = FILENAME; \ |
---|
465 | if (COMPRESS_MODE) { \ |
---|
466 | io_mode |= synctex_io_gz_mask; \ |
---|
467 | } else { \ |
---|
468 | io_mode &= ~synctex_io_gz_mask; \ |
---|
469 | } \ |
---|
470 | } \ |
---|
471 | } |
---|
472 | TEST(basic_name,synctex_DONT_COMPRESS); |
---|
473 | TEST(gz_name,synctex_COMPRESS); |
---|
474 | TEST(quoted_name,synctex_DONT_COMPRESS); |
---|
475 | TEST(quoted_gz_name,synctex_COMPRESS); |
---|
476 | TEST(build_name,synctex_DONT_COMPRESS); |
---|
477 | TEST(build_gz_name,synctex_COMPRESS); |
---|
478 | TEST(build_quoted_name,synctex_DONT_COMPRESS); |
---|
479 | TEST(build_quoted_gz_name,synctex_COMPRESS); |
---|
480 | # undef TEST |
---|
481 | /* Free all the intermediate filenames, except the one that will be used as returned value. */ |
---|
482 | # define CLEAN_AND_REMOVE(FILENAME) \ |
---|
483 | if(FILENAME && (FILENAME!=synctex_name)) {\ |
---|
484 | remove(FILENAME);\ |
---|
485 | printf("synctex tool info: %s removed\n",FILENAME);\ |
---|
486 | free(FILENAME);\ |
---|
487 | FILENAME = NULL;\ |
---|
488 | } |
---|
489 | CLEAN_AND_REMOVE(basic_name); |
---|
490 | CLEAN_AND_REMOVE(gz_name); |
---|
491 | CLEAN_AND_REMOVE(quoted_name); |
---|
492 | CLEAN_AND_REMOVE(quoted_gz_name); |
---|
493 | CLEAN_AND_REMOVE(build_name); |
---|
494 | CLEAN_AND_REMOVE(build_gz_name); |
---|
495 | CLEAN_AND_REMOVE(build_quoted_name); |
---|
496 | CLEAN_AND_REMOVE(build_quoted_gz_name); |
---|
497 | # undef CLEAN_AND_REMOVE |
---|
498 | /* set up the returned values */ |
---|
499 | * synctex_name_ref = synctex_name; |
---|
500 | * io_mode_ref = io_mode; |
---|
501 | return 0; |
---|
502 | } |
---|
503 | return -1;/* bad argument */ |
---|
504 | } |
---|
505 | return -2; |
---|
506 | } |
---|
507 | |
---|
508 | const char * _synctex_get_io_mode_name(synctex_io_mode_t io_mode) { |
---|
509 | static const char * synctex_io_modes[4] = {"r","rb","a","ab"}; |
---|
510 | unsigned index = ((io_mode & synctex_io_gz_mask)?1:0) + ((io_mode & synctex_io_append_mask)?2:0);// bug pointed out by Jose Alliste |
---|
511 | return synctex_io_modes[index]; |
---|
512 | } |
---|