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 }