source: terepaima/terepaima-0.4.16/synctex/synctex_parser_utils.c

desarrollostretch
Last change on this file was 1f4adec, checked in by aosorio <aosorio@…>, 8 years ago

Agregado proyecto base, esto luego del dh_make -f

  • Property mode set to 100644
File size: 17.2 KB
Line 
1/*
2Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr
3
4This file is part of the SyncTeX package.
5
6Latest Revision: Tue Jun 14 08:23:30 UTC 2011
7
8Version: 1.18
9
10See synctex_parser_readme.txt for more details
11
12License:
13--------
14Permission is hereby granted, free of charge, to any person
15obtaining a copy of this software and associated documentation
16files (the "Software"), to deal in the Software without
17restriction, including without limitation the rights to use,
18copy, modify, merge, publish, distribute, sublicense, and/or sell
19copies of the Software, and to permit persons to whom the
20Software is furnished to do so, subject to the following
21conditions:
22
23The above copyright notice and this permission notice shall be
24included in all copies or substantial portions of the Software.
25
26THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
28OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
30HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33OTHER DEALINGS IN THE SOFTWARE
34
35Except as contained in this notice, the name of the copyright holder 
36shall not be used in advertising or otherwise to promote the sale, 
37use or other dealings in this Software without prior written 
38authorization 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
73void *_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
82int _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! */
115void _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
159synctex_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 "[^|/|\].[\|/]+".*/
177const 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... */
193synctex_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);
197next_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
221synctex_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 */
236const 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
252int _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. */
293char * _synctex_merge_strings(const char * first,...);
294
295char * _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 */
345int _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
508const 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}
Note: See TracBrowser for help on using the repository browser.