/ src / libnml / rcs / rcs_print.cc
rcs_print.cc
  1  /********************************************************************
  2  * Description: rcs_print.cc
  3  *
  4  *   Derived from a work by Fred Proctor & Will Shackleford
  5  *
  6  * Author:
  7  * License: LGPL Version 2
  8  * System: Linux
  9  *    
 10  * Copyright (c) 2004 All rights reserved.
 11  *
 12  * Last change: 
 13  ********************************************************************/
 14  
 15  #ifdef __cplusplus
 16  extern "C" {
 17  #endif
 18  
 19  #include <stdarg.h>		/* va_list, va_start(), va_end() */
 20  #include <stdio.h>		/* __printf()'s */
 21  #include <string.h>		/* strchr(), memmove() */
 22  #include <stdlib.h>		/* malloc(), free(), realloc() */
 23  #include <errno.h>		// errno()
 24  
 25  #include <sys/types.h>
 26  #include <unistd.h>		/* getpid() */
 27  
 28  #ifdef __cplusplus
 29  }
 30  #endif
 31  #include "rcs_print.hh"
 32  #include "linklist.hh"
 33  #ifndef _TIMER_H
 34  extern "C" double etime(void);
 35  #endif
 36  
 37  LinkedList *rcs_print_list = NULL;
 38  char **rcs_lines_table = NULL;
 39  void (*rcs_print_notify) () = NULL;
 40  RCS_PRINT_DESTINATION_TYPE rcs_print_destination = RCS_PRINT_TO_STDOUT;
 41  
 42  int max_rcs_errors_to_print = 30;
 43  int rcs_errors_printed = 0;
 44  
 45  long rcs_print_mode_flags = PRINT_RCS_ERRORS;
 46  FILE *rcs_print_file_stream = NULL;
 47  char rcs_print_file_name[80] = "rcs_out.txt";
 48  
 49  char last_error_bufs[4][100];
 50  int error_bufs_initialized = 0;
 51  int last_error_buf_filled = 0;
 52  
 53  void set_rcs_print_destination(RCS_PRINT_DESTINATION_TYPE _dest)
 54  {
 55      if (rcs_print_destination == RCS_PRINT_TO_NULL) {
 56  	rcs_errors_printed = 0;
 57      }
 58      rcs_print_destination = _dest;
 59  }
 60  
 61  RCS_PRINT_DESTINATION_TYPE get_rcs_print_destination()
 62  {
 63      return (rcs_print_destination);
 64  }
 65  
 66  char **get_rcs_lines_table()
 67  {
 68      return (rcs_lines_table);
 69  }
 70  
 71  LinkedList *get_rcs_print_list()
 72  {
 73      return (rcs_print_list);
 74  }
 75  
 76  int get_rcs_print_list_size()
 77  {
 78      if (NULL != rcs_print_list) {
 79  	return (rcs_print_list->list_size);
 80      } else {
 81  	return (-1);
 82      }
 83  }
 84  void
 85  set_rcs_print_list_sizing(int _new_max_size,
 86      LIST_SIZING_MODE _new_sizing_mode)
 87  {
 88      if (NULL == rcs_print_list) {
 89  	rcs_print_list = new LinkedList;
 90      }
 91      if (NULL != rcs_print_list) {
 92  	rcs_print_list->set_list_sizing_mode(_new_max_size, _new_sizing_mode);
 93      }
 94  }
 95  void set_rcs_print_notify(RCS_PRINT_NOTIFY_FUNC_PTR _rcs_print_notify)
 96  {
 97      rcs_print_notify = _rcs_print_notify;
 98  }
 99  
100  void clean_print_list()
101  {
102      if (NULL != rcs_print_list) {
103  	delete rcs_print_list;
104  	rcs_print_list = NULL;
105      }
106  }
107  
108  void output_print_list(int output_func(char *))
109  {
110      if (NULL != rcs_print_list) {
111  	char *string_from_list;
112  	string_from_list = (char *) rcs_print_list->get_head();
113  	while (NULL != string_from_list) {
114  	    if (output_func(string_from_list) != EOF) {
115  		break;
116  	    }
117  	    string_from_list = (char *) rcs_print_list->get_next();
118  	}
119      }
120  }
121  
122  int count_characters_in_print_list()
123  {
124      int count = 0;
125      if (NULL != rcs_print_list) {
126  	char *string_from_list;
127  	string_from_list = (char *) rcs_print_list->get_head();
128  	while (NULL != string_from_list) {
129  	    count += strlen(string_from_list);
130  	    string_from_list = (char *) rcs_print_list->get_next();
131  	}
132      }
133      return (count);
134  }
135  
136  int count_lines_in_print_list()
137  {
138      int count = 1;
139      if (NULL != rcs_print_list) {
140  	char *string_from_list;
141  	string_from_list = (char *) rcs_print_list->get_head();
142  	while (NULL != string_from_list) {
143  	    char *line;
144  	    line = strchr(string_from_list, '\n');
145  	    while (NULL != line) {
146  		count++;
147  		line = strchr(line + 1, '\n');
148  	    }
149  	    string_from_list = (char *) rcs_print_list->get_next();
150  	}
151      }
152      return (count);
153  }
154  
155  void convert_print_list_to_lines()
156  {
157      char *temp_buf = NULL;
158      static int last_id_converted = -1;
159      if (NULL != rcs_print_list) {
160  	char *string_from_list;
161  	if (-1 == last_id_converted) {
162  	    string_from_list = (char *) rcs_print_list->get_head();
163  	} else {
164  	    string_from_list =
165  		(char *) rcs_print_list->get_first_newer(last_id_converted);
166  	}
167  	while (NULL != string_from_list) {
168  	    char *next_line;
169  	    next_line = strchr(string_from_list, '\n');
170  	    if (NULL == next_line) {
171  		if (NULL == temp_buf) {
172  		    temp_buf = (char *) malloc(strlen(string_from_list) + 1);
173  		    strcpy(temp_buf, string_from_list);
174  		} else {
175  		    temp_buf = (char *) realloc(temp_buf, strlen(temp_buf)
176  			+ strlen(string_from_list) + 1);
177  		    strcat(temp_buf, string_from_list);
178  		}
179  		rcs_print_list->delete_current_node();
180  	    } else {
181  		if (temp_buf != NULL) {
182  		    temp_buf = (char *) realloc(temp_buf, strlen(temp_buf)
183  			+ strlen(string_from_list) + 1);
184  		    strcat(temp_buf, string_from_list);
185  		    rcs_print_list->delete_current_node();
186  		    rcs_print_list->store_after_current_node(temp_buf,
187  			strlen(temp_buf)
188  			+ 1, 1);
189  		    free(temp_buf);
190  		    temp_buf = NULL;
191  		} else if (next_line[1] != 0) {
192  		    rcs_print_list->store_after_current_node(next_line + 1,
193  			strlen(next_line + 1) + 1, 1);
194  		    next_line[1] = 0;
195  		}
196  	    }
197  	    string_from_list = (char *) rcs_print_list->get_next();
198  	}
199      }
200      last_id_converted = rcs_print_list->get_newest_id();
201      if (temp_buf != NULL) {
202  	rcs_print_list->store_at_tail(temp_buf, strlen(temp_buf) + 1, 1);
203  	free(temp_buf);
204  	temp_buf = NULL;
205      }
206  }
207  
208  void update_lines_table()
209  {
210      if (NULL != rcs_lines_table) {
211  	free(rcs_lines_table);
212  	rcs_lines_table = NULL;
213      }
214      if (NULL != rcs_print_list) {
215  	convert_print_list_to_lines();
216  	rcs_lines_table = (char **) malloc(sizeof(char *)
217  	    * rcs_print_list->list_size);
218  	if (NULL != rcs_print_list) {
219  	    char *string_from_list;
220  	    string_from_list = (char *) rcs_print_list->get_head();
221  	    int i = 0;
222  	    while (NULL != string_from_list) {
223  		rcs_lines_table[i] = string_from_list;
224  		i++;
225  		string_from_list = (char *) rcs_print_list->get_next();
226  	    }
227  	}
228      }
229  }
230  
231  char *strip_control_characters(char *_dest, char *_src)
232  {
233      static char line_buffer[255];
234      char *destination;
235      char *control_char_loc;
236      if (NULL == _dest) {
237  	destination = line_buffer;
238  	if (strlen(_src) < 255) {
239  	    strcpy(line_buffer, _src);
240  	} else {
241  	    if (NULL == strpbrk(_src, "\n\r\t\b")) {
242  		return (_src);
243  	    } else {
244  		return (NULL);
245  	    }
246  	}
247      } else {
248  	destination = _dest;
249  	if (_dest != _src) {
250  	    memmove(_dest, _src, strlen(_src));
251  	}
252      }
253      control_char_loc = strpbrk(destination, "\n\r\t\b");
254      while (NULL != control_char_loc) {
255  	*control_char_loc = ' ';	/* Replace control character with
256  					   SPACE */
257  	control_char_loc = strpbrk(control_char_loc, "\n\r\t\b");
258      }
259      return (destination);
260  
261  }
262  
263  /* In windows DLLs for Microsoft Visual C++ sscanf is not supported so
264  use separate_words to parse the string followed by commands like strtod to
265  convert each word. */
266  int separate_words(char **_dest, int _max, char *_src)
267  {
268      static char word_buffer[256];
269      int i;
270      if (NULL == _dest || NULL == _src) {
271  	return -1;
272      }
273      if (strlen(_src) > 255) {
274  	return -1;
275      }
276      strcpy(word_buffer, _src);
277      _dest[0] = strtok(word_buffer, " \n\r\t");
278      for (i = 0; NULL != _dest[i] && i < _max - 1; i++) {
279  	_dest[i + 1] = strtok(NULL, " \n\r\t");
280      }
281      if (_dest[_max - 1] == NULL && i == _max - 1) {
282  	i--;
283      }
284      return (i + 1);
285  }
286  
287  int rcs_vprint(const char *_fmt, va_list _args, int save_string)
288  {
289      static char temp_string[256];
290  
291      if (NULL == _fmt) {
292  	return (EOF);
293      }
294      if (strlen(_fmt) > 200) {	/* Might overflow temp_string. */
295  	return (EOF);
296      }
297      if (EOF == (int) vsnprintf(temp_string, sizeof(temp_string), _fmt, _args)) {
298  	return (EOF);
299      }
300      if (save_string) {
301  	if (!error_bufs_initialized) {
302  	    memset(last_error_bufs[0], 0, 100);
303  	    memset(last_error_bufs[1], 0, 100);
304  	    memset(last_error_bufs[2], 0, 100);
305  	    memset(last_error_bufs[3], 0, 100);
306  	    error_bufs_initialized = 1;
307  	}
308  	last_error_buf_filled++;
309  	last_error_buf_filled %= 4;
310  	strncpy(last_error_bufs[last_error_buf_filled], temp_string, 99);
311      }
312      return (rcs_fputs(temp_string));
313  }
314  
315  int rcs_puts(const char *_str)
316  {
317      int retval, retval2;
318      retval = rcs_fputs(const_cast< char * >(_str));
319      if (retval != EOF) {
320  	retval2 = rcs_fputs(const_cast< char * >("\n"));
321  	if (retval2 != EOF) {
322  	    retval += retval;
323  	} else {
324  	    retval = EOF;
325  	}
326      }
327      return (retval);
328  }
329  
330  int rcs_fputs(const char *_str)
331  {
332      int retval = EOF;
333      if (NULL != _str) {
334  	if (0 == _str[0]) {
335  	    return (0);
336  	}
337  	switch (rcs_print_destination) {
338  	case RCS_PRINT_TO_LOGGER:
339  
340  	case RCS_PRINT_TO_STDOUT:
341  	    retval = fputs(_str, stdout);
342  	    fflush(stdout);
343  	    break;
344  
345  	case RCS_PRINT_TO_STDERR:
346  	    retval = fputs(_str, stderr);
347  	    fflush(stderr);
348  	    break;
349  
350  	case RCS_PRINT_TO_LIST:
351  	    if (NULL == rcs_print_list) {
352  		rcs_print_list = new LinkedList;
353  		if (NULL != rcs_print_list) {
354  		    rcs_print_list->set_list_sizing_mode(256,
355  			DELETE_FROM_HEAD);
356  		}
357  	    }
358  	    if (NULL != rcs_print_list) {
359  		if (-1 ==
360  		    rcs_print_list->store_at_tail((void*)_str,
361  			(retval = strlen(_str)) + 1, 1)) {
362  		    retval = EOF;
363  		}
364  	    }
365  	    break;
366  	case RCS_PRINT_TO_NULL:
367  	    retval = strlen(_str);
368  	    break;
369  	case RCS_PRINT_TO_FILE:
370  	    if (NULL == rcs_print_file_stream) {
371  		if (NULL == rcs_print_file_name) {
372  		    return EOF;
373  		}
374  		rcs_print_file_stream = fopen(rcs_print_file_name, "a+");
375  	    }
376  	    if (NULL == rcs_print_file_stream) {
377  		return EOF;
378  	    }
379  	    retval = fputs(_str, rcs_print_file_stream);
380  	    fflush(rcs_print_file_stream);
381  	    break;
382  
383  	default:
384  	    break;
385  	}
386  	if (NULL != rcs_print_notify) {
387  	    (*rcs_print_notify) ();
388  	}
389      }
390      return (retval);
391  }
392  
393  void close_rcs_printing()
394  {
395      switch (rcs_print_destination) {
396      case RCS_PRINT_TO_LIST:
397  	clean_print_list();
398  	break;
399  
400      case RCS_PRINT_TO_FILE:
401  	if (NULL != rcs_print_file_stream) {
402  	    fclose(rcs_print_file_stream);
403  	    rcs_print_file_stream = NULL;
404  	}
405  	break;
406      default:
407  	break;
408      }
409      return;
410  }
411  
412  int set_rcs_print_file(char *_file_name)
413  {
414      if (_file_name == NULL) {
415  	return -1;
416      }
417      if (strlen(_file_name) > 80) {
418  	return -1;
419      }
420      strcpy(rcs_print_file_name, _file_name);
421      if (NULL != rcs_print_file_stream) {
422  	fclose(rcs_print_file_stream);
423      }
424      rcs_print_file_stream = fopen(rcs_print_file_name, "a+");
425      if (NULL == rcs_print_file_stream) {
426  	return -1;
427      }
428      return 0;
429  }
430  
431  int rcs_print(const char *_fmt, ...)
432  {
433      static char temp_buffer[400];
434      int retval;
435      va_list args;
436      va_start(args, _fmt);
437      retval = vsnprintf(temp_buffer, sizeof(temp_buffer), _fmt, args);
438      va_end(args);
439      if (retval == (EOF)) {
440  	return EOF;
441      }
442      retval = rcs_fputs(temp_buffer);
443      return (retval);
444  }
445  
446  #ifndef DO_NOT_USE_RCS_PRINT_ERROR_NEW
447  static const char *rcs_error_filename = NULL;
448  static int rcs_error_linenum = -1;
449  int set_print_rcs_error_info(const char *file, int line)
450  {
451      rcs_error_filename = file;
452      rcs_error_linenum = line;
453      return (0);
454  }
455  
456  int print_rcs_error_new(const char *_fmt, ...)
457  {
458      int retval = 0;
459      va_list args;
460      va_start(args, _fmt);
461      if ((rcs_print_mode_flags & PRINT_RCS_ERRORS)
462  	&& ((max_rcs_errors_to_print >= rcs_errors_printed)
463  	    || max_rcs_errors_to_print < 0)) {
464  	if (NULL != rcs_error_filename && rcs_error_linenum > 0) {
465  	    rcs_print("%s %d: ", rcs_error_filename, rcs_error_linenum);
466  	    rcs_error_filename = NULL;
467  	    rcs_error_linenum = -1;
468  	}
469  	retval = rcs_vprint(_fmt, args, 1);
470  	if (max_rcs_errors_to_print == rcs_errors_printed &&
471  	    max_rcs_errors_to_print >= 0) {
472  	    rcs_print("\nMaximum number of errors to print exceeded!\n");
473  	}
474      }
475      if (rcs_print_destination != RCS_PRINT_TO_NULL) {
476  	rcs_errors_printed++;
477      }
478      va_end(args);
479      return (retval);
480  }
481  
482  #endif
483  
484  int rcs_print_debug(long flag_to_check, const char *_fmt, ...)
485  {
486      int retval = 0;
487      int pid = 0;
488      va_list args;
489      va_start(args, _fmt);
490  
491      if (flag_to_check & rcs_print_mode_flags) {
492  	pid = getpid();
493  	rcs_print("(time=%f,pid=%d): ", etime(), pid);
494  	retval = rcs_vprint(_fmt, args, 0);
495      }
496      va_end(args);
497      return (retval);
498  }
499  
500  void set_rcs_print_flag(long flag_to_set)
501  {
502      rcs_print_mode_flags |= flag_to_set;
503  }
504  
505  void clear_rcs_print_flag(long flag_to_clear)
506  {
507      rcs_print_mode_flags &= ~(flag_to_clear);
508  }
509  
510  int rcs_print_sys_error(int error_source, const char *_fmt, ...)
511  {
512      static char temp_string[256];
513      static char message_string[512];
514      va_list args;
515      int r;
516  
517      if (NULL == _fmt) {
518  	return (EOF);
519      }
520      if (strlen(_fmt) > 200) {	/* Might overflow temp_string. */
521  	return (EOF);
522      }
523  
524      va_start(args, _fmt);
525      r = vsnprintf(temp_string, sizeof(temp_string), _fmt, args);
526      va_end(args);
527  
528      if (r < 0) {
529  	return EOF;
530      }
531  
532      if (max_rcs_errors_to_print == rcs_errors_printed &&
533  	max_rcs_errors_to_print >= 0) {
534  	rcs_print("\nMaximum number of errors to print exceeded!\n");
535      }
536      rcs_errors_printed++;
537      if (max_rcs_errors_to_print <= rcs_errors_printed &&
538  	max_rcs_errors_to_print >= 0) {
539  	return (EOF);
540      }
541  
542      switch (error_source) {
543      case ERRNO_ERROR_SOURCE:
544  	snprintf(message_string, sizeof(message_string),
545  	    "%s %d %s\n", temp_string, errno,
546  	    strerror(errno));
547  	rcs_puts(message_string);
548  	break;
549  
550      default:
551  	rcs_puts(temp_string);
552  	break;
553      }
554      return (strlen(temp_string));
555  }
556  
557  #ifdef rcs_print_error
558  #undef rcs_print_error
559  #endif
560  extern "C" int rcs_print_error(const char *_fmt, ...);
561  
562  int rcs_print_error(const char *_fmt, ...)
563  {
564      int retval = 0;
565      va_list args;
566  
567      va_start(args, _fmt);
568      if ((rcs_print_mode_flags & PRINT_RCS_ERRORS)
569  	&& ((max_rcs_errors_to_print >= rcs_errors_printed)
570  	    || max_rcs_errors_to_print < 0)) {
571  	retval = rcs_vprint(_fmt, args, 1);
572  	if (max_rcs_errors_to_print == rcs_errors_printed &&
573  	    max_rcs_errors_to_print >= 0) {
574  	    rcs_print("\nMaximum number of errors to print exceeded!\n");
575  	}
576      }
577      if (rcs_print_destination != RCS_PRINT_TO_NULL) {
578  	rcs_errors_printed++;
579      }
580      va_end(args);
581      return (retval);
582  }