summaryrefslogtreecommitdiff
path: root/Build/source/texk/xdvik/util.c
diff options
context:
space:
mode:
authorPeter Breitenlohner <peb@mppmu.mpg.de>2008-07-01 15:42:36 +0000
committerPeter Breitenlohner <peb@mppmu.mpg.de>2008-07-01 15:42:36 +0000
commit6552be7f745c5a8d506148c8af9d367c9d996d24 (patch)
treeb9d673871a1490b64273a265d4d961316a2174db /Build/source/texk/xdvik/util.c
parent48e2b240973977c208bc840b589b75b91a6f4c30 (diff)
xdvik 22.84.14
git-svn-id: svn://tug.org/texlive/trunk@9142 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/xdvik/util.c')
-rw-r--r--Build/source/texk/xdvik/util.c445
1 files changed, 252 insertions, 193 deletions
diff --git a/Build/source/texk/xdvik/util.c b/Build/source/texk/xdvik/util.c
index d34ef137387..eb891cc76f6 100644
--- a/Build/source/texk/xdvik/util.c
+++ b/Build/source/texk/xdvik/util.c
@@ -21,8 +21,8 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
NOTE:
- xdvi is based on prior work, as noted in the modification history
- in xdvi.c.
+xdvi is based on prior work, as noted in the modification history
+in xdvi.c.
\*========================================================================*/
@@ -49,6 +49,7 @@ NOTE:
#include "search-internal.h"
#include "encodings.h"
#include "filehist.h"
+#include "exit-handlers.h"
#include "xm_prefs.h" /* for preferences_changed() */
#include <errno.h>
@@ -141,151 +142,50 @@ extern void *realloc();
#define BUF_SIZE 1024
-/*
- Insert item to the list and return the result.
-*/
-struct dl_list *
-dl_list_insert(struct dl_list *list, void *item)
+void
+xdvi_assert(const char *version,
+ const char *filename,
+ int lineno,
+ Boolean condition,
+ const char *fmt, ...)
{
- struct dl_list *new_elem = xmalloc(sizeof *new_elem);
- new_elem->item = item;
- new_elem->next = NULL;
- new_elem->prev = NULL;
-
- if (list == NULL) {
- list = new_elem;
- }
- else {
- /* append after current position */
- struct dl_list *ptr = list;
-
- new_elem->next = ptr->next;
- new_elem->prev = ptr;
-
- if (ptr->next != NULL)
- ptr->next->prev = new_elem;
-
- ptr->next = new_elem;
+ if (!(condition)) {
+ fprintf(stderr,
+ "\n************************************************************\n"
+ "XDvi %s: Failed assertion:\n%s:%d: ",
+ version, filename, lineno);
+ va_list argp;
+ va_start(argp, fmt);
+ (void)vfprintf(stderr, fmt, argp);
+ va_end(argp);
+#ifdef NDEBUG
+ fprintf(stderr,
+ "\nAborting now. Please report this as a bug to:\n"
+ "http://sourceforge.net/tracker/?group_id=23164&atid=377580\n"
+ "If a core dump has been produced, please invoke:\n"
+ "gdb %s core\nThen type \"bt\", "
+ "and include the resulting output in your bug report.\n"
+ "************************************************************\n",
+ globals.program_name);
+ do_abort();
+#else
+ fprintf(stderr,
+ "\nPlease report this as a bug to:\n"
+ "http://sourceforge.net/tracker/?group_id=23164&atid=377580\n"
+ "************************************************************\n");
+#endif
}
- return new_elem;
-}
-
-/*
- Return head of the list.
-*/
-struct dl_list *
-dl_list_head(struct dl_list *list)
-{
- for (; list != NULL && list->prev != NULL; list = list->prev) { ; }
- return list;
}
-/*
- Put a new item at the front of the list (current front is passed in first argument)
- and return its position.
-*/
-struct dl_list *
-dl_list_push_front(struct dl_list *list, void *item)
-{
- struct dl_list *new_elem = xmalloc(sizeof *new_elem);
- new_elem->item = item;
- new_elem->next = NULL;
- new_elem->prev = NULL;
-
- if (list != NULL) { /* prepend to current position */
- new_elem->next = list;
- list->prev = new_elem;
- }
- return new_elem;
-}
-/*
- Truncate list so that current pointer is the last element.
-*/
-struct dl_list *
-dl_list_truncate(struct dl_list *list)
+void
+xdvi_bell(void)
{
- struct dl_list *ptr = list->next;
- struct dl_list *save;
-
- list->next = NULL;
-
- while (ptr != NULL) {
- save = ptr->next;
- free(ptr);
- ptr = save;
+ if (!resource.hush_bell) {
+ XBell(DISP, 0);
}
- return list;
-}
-
-/*
- Truncate list at the head (i.e. remove the first element from it - head must be passed to this list),
- and return the result.
-*/
-struct dl_list *
-dl_list_truncate_head(struct dl_list *list)
-{
- struct dl_list *ptr = list->next;
- if (list->next != NULL)
- list->next->prev = NULL;
- free(list);
- return ptr;
}
-/*
- If the item pointed to by *list isn't the head of the list, remove it,
- set *list to the previous item, and return True. Else return False.
-*/
-Boolean
-dl_list_remove_item(struct dl_list **list)
-{
- struct dl_list *ptr = *list; /* item to remove */
- if (ptr->prev == NULL)
- return False;
- ptr->prev->next = ptr->next;
- if (ptr->next != NULL)
- ptr->next->prev = ptr->prev;
- /* update list */
- *list = (*list)->prev;
- /* remove item */
- free(ptr);
-
- return True;
-}
-
-/*
- Remove all items matching compare_func() from list. Must be called
- with a pointer to the head of the list, which is also returned.
- Returns the number of removed items in `count'.
-*/
-struct dl_list *
-dl_list_remove(struct dl_list *list, const void *item,
- int *count,
- void **removed_item,
- Boolean (*compare_func)(const void *item1, const void *item2))
-{
- struct dl_list *ptr = list;
- while (ptr != NULL) {
- struct dl_list *next = ptr->next;
- if (compare_func(ptr->item, item)) { /* match */
- *removed_item = ptr->item;
- (*count)++;
- if (ptr->prev != NULL) {
- ptr->prev->next = ptr->next;
- }
- else { /* removed first element */
- list = list->next;
- }
-
- if (ptr->next != NULL)
- ptr->next->prev = ptr->prev;
- free(ptr);
- ptr = NULL;
- }
- ptr = next;
- }
- return list;
-}
/* NOTE: keep this table in sync with the #defines in xdvi-debug.h! */
@@ -294,7 +194,7 @@ struct debug_string_options debug_options[] = {
{ DBG_DVI, "dvi", ", " },
{ DBG_PK, "pk", ", " },
{ DBG_BATCH, "batch", ", " },
- { DBG_EVENT, "event", ", " },
+ { DBG_EVENT, "events", ", " },
{ DBG_PS, "ps", ",\n"},
{ DBG_STAT, "stat", ", " },
{ DBG_HASH, "hash", ", " },
@@ -402,12 +302,12 @@ xdvi_exit(int status)
if (preferences_changed()) {
return;
}
-/* else { */
-/* fprintf(stderr, "Preferences not changed.\n"); */
-/* } */
+ /* else { */
+ /* fprintf(stderr, "Preferences not changed.\n"); */
+ /* } */
#endif
/* try to save user preferences, unless we're exiting with an error */
- if (status == 0 && !save_user_preferences(True))
+ if (status == EXIT_SUCCESS && !save_user_preferences(True))
return;
/* Clean up the "xdvi windows" property in the root window. */
@@ -417,9 +317,8 @@ xdvi_exit(int status)
#if PS
ps_destroy();
#endif
- remove_tmp_dvi_file();
- close_iconv();
+ call_exit_handlers();
exit(status);
}
@@ -679,7 +578,7 @@ my_realpath(const char *path, char *resolved)
/* go back to where we came from */
#ifdef HAVE_FCHDIR
- fchdir(fd);
+ (void)fchdir(fd);
close(fd);
#else
chdir(cwd);
@@ -689,7 +588,7 @@ my_realpath(const char *path, char *resolved)
/* arrive here in case of error: go back to where we came from, and return NULL */
#ifdef HAVE_FCHDIR
- fchdir(fd);
+ (void)fchdir(fd);
close(fd);
#else
chdir(cwd);
@@ -761,6 +660,14 @@ xmemdup(const char *str, size_t len)
#endif /* not KPATHSEA */
+/* like xstrdup(), but with XtMalloc() */
+char *
+xt_strdup(const char *ptr)
+{
+ char *ret = XtMalloc(strlen(ptr) + 1);
+ return strcpy(ret, ptr);
+}
+
/*
* Append str2 to str1, reallocating str1 as neccessary.
@@ -1026,7 +933,7 @@ handle_child_exit(int status, struct xchild *this)
if (this->io != NULL
&& (WIFEXITED(status) != 0)
&& (WEXITSTATUS(status) != 0)
- && (err_msg = (this->io->read_proc)(this->io->fd)) != NULL) {
+ && (err_msg = (this->io->read_proc)(this->io->fd, NULL)) != NULL) {
if (this->name == NULL) {
popup_message(globals.widgets.top_level,
@@ -1053,9 +960,11 @@ handle_child_exit(int status, struct xchild *this)
}
static void
-dummy_write_proc(int fd)
+dummy_write_proc(int fd, void *data)
{
UNUSED(fd);
+ UNUSED(data);
+
fprintf(stderr, "============== dummy_write_proc called for fd %d\n", fd);
}
@@ -1065,12 +974,14 @@ dummy_write_proc(int fd)
* afterwards.
*/
char *
-read_child_error(int fd)
+read_child_error(int fd, void *data)
{
int bytes = 0, buf_old_size = 0, buf_new_size = 0;
char tmp_buf[BUF_SIZE];
char *err_buf = xstrdup("");
char *ret;
+ UNUSED(data);
+
/* collect stderr messages into err_buf */
while ((bytes = read(fd, tmp_buf, BUF_SIZE - 1)) > 0) {
buf_old_size = buf_new_size;
@@ -1136,10 +1047,10 @@ fork_process(const char *proc_name, Boolean redirect_stdout,
return False;
case 0: /* child */
if (dirname != NULL)
- chdir(dirname);
+ (void)chdir(dirname);
if (globals.debug & DBG_FILES) {
char path[MAXPATHLEN];
- getcwd(path, MAXPATHLEN);
+ (void)getcwd(path, MAXPATHLEN);
fprintf(stderr, "Directory of running `%s': `%s'\n",
proc_name, path);
}
@@ -1148,7 +1059,7 @@ fork_process(const char *proc_name, Boolean redirect_stdout,
this will hang the child forever. Closing all other file
descriptors, as in the #if TRY_FIX regions, seems to fix
this, but it also loses all output ...
- */
+ */
#if TRY_FIX
close(0);
close(1);
@@ -1196,6 +1107,7 @@ fork_process(const char *proc_name, Boolean redirect_stdout,
#endif
my_io->read_proc = read_child_error;
my_io->write_proc = dummy_write_proc;
+ my_io->data = data;
my_child->next = NULL;
my_child->pid = pid;
@@ -1238,24 +1150,24 @@ prep_fd(int fd, wide_bool noblock)
}
else
# endif
- {
+ {
# ifdef FASYNC
- if (fcntl(fd, F_SETOWN, getpid()) == -1)
- perror("xdvi: fcntl F_SETOWN");
- if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | FASYNC) == -1)
- perror("xdvi: fcntl F_SETFL");
+ if (fcntl(fd, F_SETOWN, getpid()) == -1)
+ perror("xdvi: fcntl F_SETOWN");
+ if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | FASYNC) == -1)
+ perror("xdvi: fcntl F_SETFL");
# elif defined SIOCSPGRP && defined FIOASYNC
- /* For HP-UX B.10.10 and maybe others. See "man 7 socket". */
- int arg;
+ /* For HP-UX B.10.10 and maybe others. See "man 7 socket". */
+ int arg;
- arg = getpid();
- if (ioctl(fd, SIOCSPGRP, &arg) == -1)
- perror("xdvi: ioctl SIOCSPGRP");
- arg = 1;
- if (ioctl(fd, FIOASYNC, &arg) == -1)
- perror("xdvi: ioctl FIOASYNC");
+ arg = getpid();
+ if (ioctl(fd, SIOCSPGRP, &arg) == -1)
+ perror("xdvi: ioctl SIOCSPGRP");
+ arg = 1;
+ if (ioctl(fd, FIOASYNC, &arg) == -1)
+ perror("xdvi: ioctl FIOASYNC");
# endif
- }
+ }
#endif /* not FLAKY_SIGPOLL */
}
@@ -1291,13 +1203,14 @@ parse_debugging_string(const char *arg)
while (isspace((int)*curr))
curr++;
for (i = 0; debug_options[i].description != NULL; i++) {
- /* match on length of passed argument, to allow for abbreviations */
+ size_t curr_opt_len = strlen(debug_options[i].description);
+ /* Should we match on length of passed argument, to allow for abbreviations? */
if (memicmp(curr,
debug_options[i].description,
- strlen(debug_options[i].description)) == 0
- && (curr[strlen(debug_options[i].description)] == '\0'
- || curr[strlen(debug_options[i].description)] == ','
- || isspace((int)curr[strlen(debug_options[i].description)]))) {
+ curr_opt_len) == 0
+ && (curr[curr_opt_len] == '\0'
+ || curr[curr_opt_len] == ','
+ || isspace((int)curr[curr_opt_len]))) {
matched = True;
retval |= debug_options[i].bitmap;
fprintf(stderr, "Debugging option: \"%s\" = \"%s\", debug: %d\n",
@@ -1496,14 +1409,13 @@ find_file(const char *filename, struct stat *statbuf, kpse_file_format_type path
* /absolute/path/ + relative/path/filename
*/
ASSERT(globals.dvi_file.dirname != NULL, "globals.dvi_file.dirname should have been initialized");
- {
- pathname = xstrdup(globals.dvi_file.dirname);
- pathname = xstrcat(pathname, filename);
- TRACE_SRC((stderr, "Trying globals.dvi_file.dirname: \"%s\"", pathname));
- if (stat(pathname, statbuf) == 0) {
- return pathname;
- }
+ pathname = xstrdup(globals.dvi_file.dirname);
+ pathname = xstrcat(pathname, filename);
+
+ TRACE_SRC((stderr, "Trying globals.dvi_file.dirname: \"%s\"", pathname));
+ if (stat(pathname, statbuf) == 0) {
+ return pathname;
}
/*
@@ -1517,20 +1429,75 @@ find_file(const char *filename, struct stat *statbuf, kpse_file_format_type path
}
/*
- * case 4:
- * try a kpathsea search for filename
+ * case 4a:
+ * try a kpathsea search for filename, from globals.dvi_file.dirname
*/
- TRACE_SRC((stderr,
- "trying kpathsearch for filename \"%s\"",
- filename));
- tmp = kpse_find_file(filename, pathinfo, True);
+ {
+#ifdef HAVE_FCHDIR
+ int fd;
+#else
+ char cwd[MAXPATHLEN];
+#endif
- if (tmp != NULL && stat(tmp, statbuf) == 0) {
- TRACE_SRC((stderr, "Found file: `%s'", tmp));
- free(pathname);
- return tmp;
+ /* Save cwd for going back later */
+ if (
+#ifdef HAVE_FCHDIR
+ (fd = try_open(".", O_RDONLY)) >= 0
+#else /* HAVE_FCHDIR */
+# ifdef HAVE_GETCWD
+ getcwd(cwd, MAXPATHLEN)
+# else
+ getwd(cwd)
+# endif
+ != NULL
+#endif /* HAVE_FCHDIR */
+ ) {
+ if (chdir(globals.dvi_file.dirname) == 0) {
+
+ TRACE_SRC((stderr,
+ "trying kpathsearch for filename \"%s\" from %s",
+ filename, globals.dvi_file.dirname));
+ tmp = kpse_find_file(filename, pathinfo, True);
+
+ if (tmp != NULL && stat(tmp, statbuf) == 0) {
+ free(pathname);
+ /* go back to where we came from */
+#ifdef HAVE_FCHDIR
+ (void)fchdir(fd);
+ close(fd);
+#else
+ chdir(cwd);
+#endif
+ if (tmp[0] == '/') { /* is it an absolute path? */
+ pathname = xstrdup(tmp);
+ }
+ else {
+ pathname = xstrdup(globals.dvi_file.dirname);
+ pathname = xstrcat(pathname, tmp);
+ }
+ TRACE_SRC((stderr, "Found file: `%s'", pathname));
+ free(tmp);
+ return pathname;
+ }
+ }
+ else {
+ /*
+ * case 4b:
+ * couldn't change to globals.dvi_file.dirname - try a kpathsea search from CWD
+ */
+ TRACE_SRC((stderr,
+ "trying kpathsearch for filename \"%s\" from CWD",
+ filename));
+ tmp = kpse_find_file(filename, pathinfo, True);
+
+ if (tmp != NULL && stat(tmp, statbuf) == 0) {
+ TRACE_SRC((stderr, "Found file: `%s'", tmp));
+ free(pathname);
+ return tmp;
+ }
+ }
+ }
}
-
/*
* case 5:
* try a kpathsea search for pathname
@@ -1560,6 +1527,13 @@ find_file(const char *filename, struct stat *statbuf, kpse_file_format_type path
functions that can be used to store 2 type of values: char *, and
long, where the latter is interpreted as char *. (See kpathsea/dir.c
for an example of where this is used).
+
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ BUG ALERT: Note however that a long value may never be removed from
+ the hash table with hash_delete(), since it would do a strcmp() on
+ the long interpreted as a pointer!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
We can't use a different approach (like using a void *) since
the debugging ouput of kpathsea relies on printing the value
either as char * or long (depending on the value of the global flag
@@ -1595,7 +1569,7 @@ find_str_int_hash(hashTableT *hashtable, const char *key, size_t *val)
Insert key-value pair into hashtable. Note that the key is
*not* copied (i.e. it is expected that is had been allocated
somewhere else, and persists throughout the program).
- */
+*/
void
put_str_int_hash(hashTableT *hashtable, const char *key, size_t val)
{
@@ -1620,7 +1594,7 @@ set_dvi_name_expand(const char *new_filename)
/* set globals.dvi_name, globals.dvi_file.dirname and globals.dvi_file.dirlen
In contrast to previous function, input filename is not copied.
- */
+*/
void
set_dvi_name(char *new_filename)
{
@@ -1654,7 +1628,7 @@ copy_fp(FILE *in, FILE *out)
if (bytes_in < TMP_BUF_SIZE && !feof(in))
return False;
bytes_out = fwrite(buf, 1, bytes_in, out);
-/* fprintf(stderr, "read %d, wrote %d bytes\n", bytes_in, bytes_out); */
+ /* fprintf(stderr, "read %d, wrote %d bytes\n", bytes_in, bytes_out); */
if (bytes_out < bytes_in)
return False;
}
@@ -1663,6 +1637,7 @@ copy_fp(FILE *in, FILE *out)
#undef TMP_BUF_SIZE
}
+
/*
* Copy a file from `from_path' to `to'. Return True if successful, False else
* (in which case caller should examine errno to find the error).
@@ -1804,6 +1779,90 @@ iconv_convert_string(const char *from_enc, const char *to_enc, const char *str)
#endif /* HAVE_ICONV_H */
}
+
+/* Replace (pseudo-)format arguments in NULL-terminated argv list as follows:
+ * %f -> filename, %l -> linenumber, %c -> column number.
+ * If %f or %l are not specified, they are appended as %f and +%l.
+ * If colno == 0, no %c argument is provided.
+ */
+char **
+src_format_arguments(char **argv, const char *filename, int lineno, int colno)
+{
+ size_t i;
+ Boolean found_filename = False;
+ Boolean found_lineno = False;
+
+ for (i = 0; argv[i] != NULL; i++) {
+ char *ptr, *curr = argv[i];
+ while ((ptr = strchr(curr, '%')) != NULL) {
+ char *p1;
+ if ((p1 = strchr("flc", ptr[1])) != NULL) { /* we have a formatting char */
+ char digit_arg[LENGTH_OF_INT];
+ const char *new_elem = NULL;
+ /* remember offsets and lengths */
+ size_t l_init = ptr - argv[i];
+ size_t l_rest = strlen(ptr + 2) + 1;
+ size_t l_mid;
+
+ if (*p1 == 'f') {
+ found_filename = True;
+ new_elem = filename;
+ }
+ else if (*p1 == 'l') {
+ found_lineno = True;
+ sprintf(digit_arg, "%d", lineno);
+ new_elem = digit_arg;
+ }
+ else if (*p1 == 'c') {
+ sprintf(digit_arg, "%d", colno);
+ new_elem = digit_arg;
+ }
+
+ l_mid = strlen(new_elem);
+
+ argv[i] = xrealloc(argv[i], strlen(argv[i]) + l_mid + 1);
+ curr = argv[i] + l_init; /* need to reinitialize it because of realloc */
+ memmove(curr + l_mid, curr + 2, l_rest);
+ memcpy(curr, new_elem, l_mid);
+ curr += l_mid;
+ }
+ else if (ptr[1] == '%') { /* escaped %, skip both */
+ curr = ptr + 2;
+ }
+ else {
+ curr = ptr + 1;
+ }
+ }
+ }
+
+ /* append line number and file name arguments if they were not specified */
+ if (!found_lineno) {
+ i++;
+ argv = xrealloc(argv, (i + 1) * sizeof *argv);
+ argv[i - 1] = xmalloc(LENGTH_OF_INT + 2);
+ sprintf(argv[i - 1], "+%d", lineno);
+ argv[i] = NULL;
+ }
+
+ if (!found_filename) {
+ i++;
+ argv = xrealloc(argv, (i + 1) * sizeof *argv);
+ argv[i - 1] = xstrdup(filename);
+ argv[i] = NULL;
+ }
+
+ return argv;
+}
+
+char *
+xstrndup(const char *str, size_t len)
+{
+ char *new_str = xmalloc(len + 1);
+ memcpy(new_str, str, len);
+ new_str[len] = '\0';
+ return new_str;
+}
+
#if 0
/*
* Search integer array <arr> of length <arr_len> for for <item>.