Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
synctex_parser_utils.c File Reference
#include <synctex_parser_utils.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include <sys/stat.h>
+ Include dependency graph for synctex_parser_utils.c:

Go to the source code of this file.

Macros

#define dest   (*dest_ref)
 
#define TEST(FILENAME, COMPRESS_MODE)
 
#define CLEAN_AND_REMOVE(FILENAME)
 

Functions

void * _synctex_malloc (size_t size)
 
int _synctex_error (const char *reason,...)
 
void _synctex_strip_last_path_extension (char *string)
 
synctex_bool_t synctex_ignore_leading_dot_slash_in_path (const char **name_ref)
 
const char * _synctex_base_name (const char *path)
 
synctex_bool_t _synctex_is_equivalent_file_name (const char *lhs, const char *rhs)
 
synctex_bool_t _synctex_path_is_absolute (const char *name)
 
const char * _synctex_last_path_component (const char *name)
 
int _synctex_copy_with_quoting_last_path_component (const char *src, char **dest_ref, size_t size)
 
char * _synctex_merge_strings (const char *first,...)
 
int _synctex_get_name (const char *output, const char *build_directory, char **synctex_name_ref, synctex_io_mode_t *io_mode_ref)
 
const char * _synctex_get_io_mode_name (synctex_io_mode_t io_mode)
 

Macro Definition Documentation

#define CLEAN_AND_REMOVE (   FILENAME)
Value:
if(FILENAME && (FILENAME!=synctex_name)) {\
remove(FILENAME);\
printf("synctex tool info: %s removed\n",FILENAME);\
free(FILENAME);\
FILENAME = NULL;\
}
#define dest   (*dest_ref)
#define TEST (   FILENAME,
  COMPRESS_MODE 
)
Value:
if(FILENAME) {\
if (stat(FILENAME, &buf)) { \
free(FILENAME);\
FILENAME = NULL;\
} else if (buf.st_mtime>the_time) { \
the_time=buf.st_mtime; \
synctex_name = FILENAME; \
if (COMPRESS_MODE) { \
io_mode |= synctex_io_gz_mask; \
} else { \
io_mode &= ~synctex_io_gz_mask; \
} \
} \
}

Function Documentation

const char* _synctex_base_name ( const char *  path)

Definition at line 166 of file synctex_parser_utils.c.

166  {
167  const char * ptr = path;
168  do {
170  return ptr;
171  }
172  do {
173  if (!*(++ptr)) {
174  return path;
175  }
176  } while (!SYNCTEX_IS_PATH_SEPARATOR(*ptr));
177  } while (*(++ptr));
178  return path;
179 }

+ Here is the caller graph for this function:

int _synctex_copy_with_quoting_last_path_component ( const char *  src,
char **  dest_ref,
size_t  size 
)

Definition at line 241 of file synctex_parser_utils.c.

241  {
242  const char * lpc;
243  if(src && dest_ref) {
244 # define dest (*dest_ref)
245  dest = NULL; /* Default behavior: no change and sucess. */
246  lpc = _synctex_last_path_component(src);
247  if(strlen(lpc)) {
248  if(strchr(lpc,' ') && lpc[0]!='"' && lpc[strlen(lpc)-1]!='"') {
249  /* We are in the situation where adding the quotes is allowed. */
250  /* Time to add the quotes. */
251  /* Consistency test: we must have dest+size>dest+strlen(dest)+2
252  * or equivalently: strlen(dest)+2<size (see below) */
253  if(strlen(src)<size) {
254  if((dest = (char *)malloc(size+2))) {
255  char * dpc = dest + (lpc-src); /* dpc is the last path component of dest. */
256  if(dest != strncpy(dest,src,size)) {
257  _synctex_error("! _synctex_copy_with_quoting_last_path_component: Copy problem");
258  free(dest);
259  dest = NULL;/* Don't forget to reinitialize. */
260  return -2;
261  }
262  memmove(dpc+1,dpc,strlen(dpc)+1); /* Also move the null terminating character. */
263  dpc[0]='"';
264  dpc[strlen(dpc)+1]='\0';/* Consistency test */
265  dpc[strlen(dpc)]='"';
266  return 0; /* Success. */
267  }
268  return -1; /* Memory allocation error. */
269  }
270  _synctex_error("! _synctex_copy_with_quoting_last_path_component: Internal inconsistency");
271  return -3;
272  }
273  return 0; /* Success. */
274  }
275  return 0; /* No last path component. */
276 # undef dest
277  }
278  return 1; /* Bad parameter, this value is subject to changes. */
279 }

+ Here is the caller graph for this function:

int _synctex_error ( const char *  reason,
  ... 
)

Definition at line 81 of file synctex_parser_utils.c.

81  {
82  va_list arg;
83  int result;
84  va_start (arg, reason);
85 # ifdef SYNCTEX_RECENT_WINDOWS
86  {/* This code is contributed by William Blum.
87  As it does not work on some older computers,
88  the _WIN32 conditional here is replaced with a SYNCTEX_RECENT_WINDOWS one.
89  According to http://msdn.microsoft.com/en-us/library/aa363362(VS.85).aspx
90  Minimum supported client Windows 2000 Professional
91  Minimum supported server Windows 2000 Server
92  People running Windows 2K standard edition will not have OutputDebugStringA.
93  JL.*/
94  char *buff;
95  size_t len;
96  OutputDebugStringA("SyncTeX ERROR: ");
97  len = _vscprintf(reason, arg) + 1;
98  buff = (char*)malloc( len * sizeof(char) );
99  result = vsprintf(buff, reason, arg) +strlen("SyncTeX ERROR: ");
100  OutputDebugStringA(buff);
101  OutputDebugStringA("\n");
102  free(buff);
103  }
104 # else
105  result = fprintf(stderr,"SyncTeX ERROR: ");
106  result += vfprintf(stderr, reason, arg);
107  result += fprintf(stderr,"\n");
108 # endif
109  va_end (arg);
110  return result;
111 }

+ Here is the caller graph for this function:

const char* _synctex_get_io_mode_name ( synctex_io_mode_t  io_mode)

Definition at line 497 of file synctex_parser_utils.c.

497  {
498  static const char * synctex_io_modes[4] = {"r","rb","a","ab"};
499  unsigned index = ((io_mode & synctex_io_gz_mask)?1:0) + ((io_mode & synctex_io_append_mask)?2:0);// bug pointed out by Jose Alliste
500  return synctex_io_modes[index];
501 }

+ Here is the caller graph for this function:

int _synctex_get_name ( const char *  output,
const char *  build_directory,
char **  synctex_name_ref,
synctex_io_mode_t io_mode_ref 
)

Definition at line 334 of file synctex_parser_utils.c.

335 {
336  if(output && synctex_name_ref && io_mode_ref) {
337  /* If output is already absolute, we just have to manage the quotes and the compress mode */
338  size_t size = 0;
339  char * synctex_name = NULL;
340  synctex_io_mode_t io_mode = *io_mode_ref;
341  const char * base_name = _synctex_last_path_component(output); /* do not free, output is the owner. base name of output*/
342  /* Do we have a real base name ? */
343  if(strlen(base_name)>0) {
344  /* Yes, we do. */
345  const char * temp = NULL;
346  char * core_name = NULL; /* base name of output without path extension. */
347  char * dir_name = NULL; /* dir name of output */
348  char * quoted_core_name = NULL;
349  char * basic_name = NULL;
350  char * gz_name = NULL;
351  char * quoted_name = NULL;
352  char * quoted_gz_name = NULL;
353  char * build_name = NULL;
354  char * build_gz_name = NULL;
355  char * build_quoted_name = NULL;
356  char * build_quoted_gz_name = NULL;
357  struct stat buf;
358  time_t the_time = 0;
359  /* Create core_name: let temp point to the dot before the path extension of base_name;
360  * We start form the \0 terminating character and scan the string upward until we find a dot.
361  * The leading dot is not accepted. */
362  if((temp = strrchr(base_name,'.')) && (size = temp - base_name)>0) {
363  /* There is a dot and it is not at the leading position */
364  if(NULL == (core_name = (char *)malloc(size+1))) {
365  _synctex_error("! _synctex_get_name: Memory problem 1");
366  return -1;
367  }
368  if(core_name != strncpy(core_name,base_name,size)) {
369  _synctex_error("! _synctex_get_name: Copy problem 1");
370  free(core_name);
371  dir_name = NULL;
372  return -2;
373  }
374  core_name[size] = '\0';
375  } else {
376  /* There is no path extension,
377  * Just make a copy of base_name */
378  core_name = _synctex_merge_strings(base_name);
379  }
380  /* core_name is properly set up, owned by "self". */
381  /* creating dir_name. */
382  size = strlen(output)-strlen(base_name);
383  if(size>0) {
384  /* output contains more than one path component */
385  if(NULL == (dir_name = (char *)malloc(size+1))) {
386  _synctex_error("! _synctex_get_name: Memory problem");
387  free(core_name);
388  dir_name = NULL;
389  return -1;
390  }
391  if(dir_name != strncpy(dir_name,output,size)) {
392  _synctex_error("! _synctex_get_name: Copy problem");
393  free(dir_name);
394  dir_name = NULL;
395  free(core_name);
396  dir_name = NULL;
397  return -2;
398  }
399  dir_name[size] = '\0';
400  }
401  /* dir_name is properly set up. It ends with a path separator, if non void. */
402  /* creating quoted_core_name. */
403  if(strchr(core_name,' ')) {
404  quoted_core_name = _synctex_merge_strings("\"",core_name,"\"");
405  }
406  /* quoted_core_name is properly set up. */
407  if(dir_name &&strlen(dir_name)>0) {
408  basic_name = _synctex_merge_strings(dir_name,core_name,synctex_suffix,NULL);
409  if(quoted_core_name && strlen(quoted_core_name)>0) {
410  quoted_name = _synctex_merge_strings(dir_name,quoted_core_name,synctex_suffix,NULL);
411  }
412  } else {
413  basic_name = _synctex_merge_strings(core_name,synctex_suffix,NULL);
414  if(quoted_core_name && strlen(quoted_core_name)>0) {
415  quoted_name = _synctex_merge_strings(quoted_core_name,synctex_suffix,NULL);
416  }
417  }
418  if(!_synctex_path_is_absolute(output) && build_directory && (size = strlen(build_directory))) {
419  temp = build_directory + size - 1;
420  if(_synctex_path_is_absolute(temp)) {
421  build_name = _synctex_merge_strings(build_directory,basic_name,NULL);
422  if(quoted_core_name && strlen(quoted_core_name)>0) {
423  build_quoted_name = _synctex_merge_strings(build_directory,quoted_name,NULL);
424  }
425  } else {
426  build_name = _synctex_merge_strings(build_directory,"/",basic_name,NULL);
427  if(quoted_core_name && strlen(quoted_core_name)>0) {
428  build_quoted_name = _synctex_merge_strings(build_directory,"/",quoted_name,NULL);
429  }
430  }
431  }
432  if(basic_name) {
433  gz_name = _synctex_merge_strings(basic_name,synctex_suffix_gz,NULL);
434  }
435  if(quoted_name) {
436  quoted_gz_name = _synctex_merge_strings(quoted_name,synctex_suffix_gz,NULL);
437  }
438  if(build_name) {
439  build_gz_name = _synctex_merge_strings(build_name,synctex_suffix_gz,NULL);
440  }
441  if(build_quoted_name) {
442  build_quoted_gz_name = _synctex_merge_strings(build_quoted_name,synctex_suffix_gz,NULL);
443  }
444  /* All the others names are properly set up... */
445  /* retain the most recently modified file */
446 # define TEST(FILENAME,COMPRESS_MODE) \
447  if(FILENAME) {\
448  if (stat(FILENAME, &buf)) { \
449  free(FILENAME);\
450  FILENAME = NULL;\
451  } else if (buf.st_mtime>the_time) { \
452  the_time=buf.st_mtime; \
453  synctex_name = FILENAME; \
454  if (COMPRESS_MODE) { \
455  io_mode |= synctex_io_gz_mask; \
456  } else { \
457  io_mode &= ~synctex_io_gz_mask; \
458  } \
459  } \
460  }
461  TEST(basic_name,synctex_DONT_COMPRESS);
462  TEST(gz_name,synctex_COMPRESS);
463  TEST(quoted_name,synctex_DONT_COMPRESS);
464  TEST(quoted_gz_name,synctex_COMPRESS);
465  TEST(build_name,synctex_DONT_COMPRESS);
466  TEST(build_gz_name,synctex_COMPRESS);
467  TEST(build_quoted_name,synctex_DONT_COMPRESS);
468  TEST(build_quoted_gz_name,synctex_COMPRESS);
469 # undef TEST
470  /* Free all the intermediate filenames, except the one that will be used as returned value. */
471 # define CLEAN_AND_REMOVE(FILENAME) \
472  if(FILENAME && (FILENAME!=synctex_name)) {\
473  remove(FILENAME);\
474  printf("synctex tool info: %s removed\n",FILENAME);\
475  free(FILENAME);\
476  FILENAME = NULL;\
477  }
478  CLEAN_AND_REMOVE(basic_name);
479  CLEAN_AND_REMOVE(gz_name);
480  CLEAN_AND_REMOVE(quoted_name);
481  CLEAN_AND_REMOVE(quoted_gz_name);
482  CLEAN_AND_REMOVE(build_name);
483  CLEAN_AND_REMOVE(build_gz_name);
484  CLEAN_AND_REMOVE(build_quoted_name);
485  CLEAN_AND_REMOVE(build_quoted_gz_name);
486 # undef CLEAN_AND_REMOVE
487  /* set up the returned values */
488  * synctex_name_ref = synctex_name;
489  * io_mode_ref = io_mode;
490  return 0;
491  }
492  return -1;/* bad argument */
493  }
494  return -2;
495 }
synctex_bool_t _synctex_is_equivalent_file_name ( const char *  lhs,
const char *  rhs 
)

Definition at line 182 of file synctex_parser_utils.c.

182  {
183  /* Remove the leading regex '(\./+)*' in both rhs and lhs */
186 next_character:
187  if (SYNCTEX_IS_PATH_SEPARATOR(*lhs)) {/* lhs points to a path separator */
188  if (!SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* but not rhs */
189  return synctex_NO;
190  }
191  ++lhs;
192  ++rhs;
195  goto next_character;
196  } else if (SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* rhs points to a path separator but not lhs */
197  return synctex_NO;
198  } else if (SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(*lhs,*rhs)){/* uppercase do not match */
199  return synctex_NO;
200  } else if (!*lhs) {/* lhs is at the end of the string */
201  return *rhs ? synctex_NO : synctex_YES;
202  } else if(!*rhs) {/* rhs is at the end of the string but not lhs */
203  return synctex_NO;
204  }
205  ++lhs;
206  ++rhs;
207  goto next_character;
208 }

+ Here is the caller graph for this function:

const char* _synctex_last_path_component ( const char *  name)

Definition at line 225 of file synctex_parser_utils.c.

225  {
226  const char * c = name+strlen(name);
227  if(c>name) {
228  if(!SYNCTEX_IS_PATH_SEPARATOR(*c)) {
229  do {
230  --c;
231  if(SYNCTEX_IS_PATH_SEPARATOR(*c)) {
232  return c+1;
233  }
234  } while(c>name);
235  }
236  return c;/* the last path component is the void string*/
237  }
238  return c;
239 }

+ Here is the caller graph for this function:

void* _synctex_malloc ( size_t  size)

Definition at line 72 of file synctex_parser_utils.c.

72  {
73  void * ptr = malloc(size);
74  if(ptr) {
75 /* There used to be a switch to use bzero because it is more secure. JL */
76  memset(ptr,0, size);
77  }
78  return (void *)ptr;
79 }

+ Here is the caller graph for this function:

char * _synctex_merge_strings ( const char *  first,
  ... 
)

Definition at line 284 of file synctex_parser_utils.c.

284  {
285  va_list arg;
286  size_t size = 0;
287  const char * temp;
288  /* First retrieve the size necessary to store the merged string */
289  va_start (arg, first);
290  temp = first;
291  do {
292  size_t len = strlen(temp);
293  if(UINT_MAX-len<size) {
294  _synctex_error("! _synctex_merge_strings: Capacity exceeded.");
295  return NULL;
296  }
297  size+=len;
298  } while( (temp = va_arg(arg, const char *)) != NULL);
299  va_end(arg);
300  if(size>0) {
301  char * result = NULL;
302  ++size;
303  /* Create the memory storage */
304  if(NULL!=(result = (char *)malloc(size))) {
305  char * dest = result;
306  va_start (arg, first);
307  temp = first;
308  do {
309  if((size = strlen(temp))>0) {
310  /* There is something to merge */
311  if(dest != strncpy(dest,temp,size)) {
312  _synctex_error("! _synctex_merge_strings: Copy problem");
313  free(result);
314  result = NULL;
315  return NULL;
316  }
317  dest += size;
318  }
319  } while( (temp = va_arg(arg, const char *)) != NULL);
320  va_end(arg);
321  dest[0]='\0';/* Terminate the merged string */
322  return result;
323  }
324  _synctex_error("! _synctex_merge_strings: Memory problem");
325  return NULL;
326  }
327  return NULL;
328 }

+ Here is the caller graph for this function:

synctex_bool_t _synctex_path_is_absolute ( const char *  name)

Definition at line 210 of file synctex_parser_utils.c.

210  {
211  if(!strlen(name)) {
212  return synctex_NO;
213  }
214 # if defined(SYNCTEX_WINDOWS) || defined(SYNCTEX_OS2)
215  if(strlen(name)>2) {
216  return (name[1]==':' && SYNCTEX_IS_PATH_SEPARATOR(name[2]))?synctex_YES:synctex_NO;
217  }
218  return synctex_NO;
219 # else
221 # endif
222 }

+ Here is the caller graph for this function:

void _synctex_strip_last_path_extension ( char *  string)

Definition at line 114 of file synctex_parser_utils.c.

114  {
115  if(NULL != string){
116  char * last_component = NULL;
117  char * last_extension = NULL;
118  char * next = NULL;
119  /* first we find the last path component */
120  if(NULL == (last_component = strstr(string,"/"))){
121  last_component = string;
122  } else {
123  ++last_component;
124  while((next = strstr(last_component,"/"))){
125  last_component = next+1;
126  }
127  }
128 # if defined(SYNCTEX_WINDOWS) || defined(SYNCTEX_OS2)
129  /* On Windows, the '\' is also a path separator. */
130  while((next = strstr(last_component,"\\"))){
131  last_component = next+1;
132  }
133 # endif
134  /* then we find the last path extension */
135  if((last_extension = strstr(last_component,"."))){
136  ++last_extension;
137  while((next = strstr(last_extension,"."))){
138  last_extension = next+1;
139  }
140  --last_extension;/* back to the "." */
141  if(last_extension>last_component){/* filter out paths like ....my/dir/.hidden"*/
142  last_extension[0] = '\0';
143  }
144  }
145  }
146 }

+ Here is the caller graph for this function:

synctex_bool_t synctex_ignore_leading_dot_slash_in_path ( const char **  name_ref)

Definition at line 148 of file synctex_parser_utils.c.

149 {
150  if (SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])) {
151  do {
152  (*name_ref) += 2;
153  while (SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])) {
154  ++(*name_ref);
155  }
156  } while(SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1]));
157  return synctex_YES;
158  }
159  return synctex_NO;
160 }

+ Here is the caller graph for this function: