1 /*!
2 * \file rc-use.c
3 * \brief Central function, manages the resource file handling
4 * and displays the results.
5 */
6 /*
7 * Copyright (c) 1994, 95, 96, 1997, 2000, 2011 Thomas Esken
8 * Copyright (c) 2010, 2011, 2013, 2014 Free Software Foundation, Inc.
9 *
10 * This software doesn't claim completeness, correctness or usability.
11 * On principle I will not be liable for ANY damages or losses (implicit
12 * or explicit), which result from using or handling my software.
13 * If you use this software, you agree without any exception to this
14 * agreement, which binds you LEGALLY !!
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the `GNU General Public License' as published by
18 * the `Free Software Foundation'; either version 3, or (at your option)
19 * any later version.
20 *
21 * You should have received a copy of the `GNU General Public License'
22 * along with this program; if not, write to the:
23 *
24 */
25
26
27
28 /*
29 * Include definition header file to see whether USE_RC is defined there.
30 * Compile this module only if USE_RC is defined, otherwise skip it.
31 */
32 #include "tailor.h"
33
34
35
36 #if USE_RC
37
38
39 /*
40 * Include header files.
41 */
42 # if HAVE_ASSERT_H
43 # include <assert.h>
44 # endif
45 # if HAVE_CTYPE_H
46 # include <ctype.h>
47 # endif
48 # if HAVE_LIMITS_H
49 # include <limits.h>
50 # endif
51 # include "common.h"
52 # include "rc-defs.h"
53 # include "globals.h"
54 # include "file-io.h"
55 # include "hd-defs.h"
56 # include "hd-use.h"
57 # include "rc-astro.h"
58 # include "rc-check.h"
59 # include "rc-insert.h"
60 # include "rc-utils.h"
61 # include "tty.h"
62 # include "utils.h"
63 # include "rc-use.h"
64
65
66
67 /*
68 * static functions prototypes.
69 */
70 __BEGIN_DECLARATIONS
71 /*
72 ************************************************** Defined in `rc-use.c'.
73 */
74 static void try_to_include_file __P_ ((int ed, int wd));
75 static void
76 display_table __P_ ((const int tmp_ad,
77 const int tmp_am,
78 const int tmp_ay, int day, int ed, int wd));
79 static int fn_asc_sort __P_ ((const char **a, const char **b));
80 static int fn_des_sort __P_ ((const char **a, const char **b));
81 __END_DECLARATIONS
82 /*
83 * GLOBAL variables definitions.
84 */
85 /*! Date variables a[=MMDD]...z[] (YYYY@{a|b|...|z}[[-]N]). */
86 Dvar_struct rc_dvar[RC_DVAR_MAX];
87
88 /*! Text variables $a[=TEXT]...$z[]. */
89 Tvar_struct rc_tvar[RC_TVAR_MAX];
90
91 /*! Local co-ordinates used by both the %distance and %sun* special texts. */
92 Coor_struct lcoor1;
93
94 /*! Points to the local co-ordinates 1. */
95 Coor_struct *coor1 = &lcoor1;
96
97 /*! Local co-ordinates used by the %distance special text. */
98 Coor_struct lcoor2;
99
100 /*! Points to the local co-ordinates 2. */
101 Coor_struct *coor2 = &lcoor2;
102
103 /*! Pointers to different parts of a (resource file) line. */
104 Line_struct *lineptrs = (Line_struct *) NULL;
105
106 /*! Pointers to different parts of a (resource file) line. */
107 Line_struct *lptrs = (Line_struct *) NULL;
108
109 /*! Pointers to different parts of a (resource file) line. */
110 Line_struct *lptrs2 = (Line_struct *) NULL;
111
112 /*! Pointers to different parts of a (resource file) line. */
113 Line_struct *lptrs3 = (Line_struct *) NULL;
114
115 /*! Temporary file used when a command is assigned to a TVAR. */
116 FILE *rc_tvar_tfp = (FILE *) NULL;
117
118 /*! Temporary file used for managing `--here=ARG' options. */
119 FILE *rc_here_fp = (FILE *) NULL;
120
121 /*! Time displacement value in days used by %sun* and %moon*
122 (also used as cycle-starting time value for %sun* and %moon* special texts). */
123 double time_offset = 0.0;
124
125 /*! Atmospheric pressure in millibar (`--atmosphere=PRESSURE,TEMPERATURE'). */
126 double atm_pressure = DEFAULT_PRESSURE;
127
128 /*! Atmospheric temperature in degrees Celsius (`--atmosphere=PRESSURE,TEMPERATURE'). */
129 double atm_temperature = DEFAULT_TEMPERATURE;
130
131 /*! Adjust rise/set-based reference altitude resp. shadow length factor (`--adjust-value=NUMBER'). */
132 double adjust_value = DEGS_PER_24_HOURS;
133
134 /*! Actual size of `rc_elems_table[]'. */
135 Uint rc_elems_max = RC_ELEMS_MAX;
136
137 /*! Amount of period of fixed dates. */
138 int rc_period = 0;
139
140 /*! Amount of resource file entries. */
141 int rc_elems = 0;
142
143 /*! Starting index of dummy resource file entries in table. */
144 int rc_zero_pos = 0;
145
146 /*! `-cd'. */
147 int rc_have_today_in_list = 0;
148
149 /*! Length of a single axis of a biorhythm text graphics bar. */
150 int rc_bio_axis_len = BIO_AXIS_DEF;
151
152 /*! Number of lines of a Moon phase text graphics image. */
153 int rc_moonimage_lines = MOONIMAGE_DEF;
154
155 /*! Filler length of week number text. */
156 int len_fil_wt = 0;
157
158 /*! Actual size of text buffer of "text"-part of a line. */
159 int len_the_text = 0;
160
161 /*! Cycle-ending time value in minutes for %sun* and %moon* special texts. */
162 int loop_end = SPECIAL_VALUE;
163
164 /*! Cycle-timestep value in minutes for %sun* and %moon* special texts. */
165 int loop_step = DEFAULT_CYCLE_STEP;
166
167 /*! Actual GMT minute. */
168 int gmt_min = 0;
169
170 /*! Actual GMT hour. */
171 int gmt_hour = 0;
172
173 /*! Buffer of actual GMT day. */
174 int buf_gd = 0;
175
176 /*! Buffer of actual GMT month. */
177 int buf_gm = 0;
178
179 /*! Buffer of actual GMT year. */
180 int buf_gy = 0;
181
182 /*! Day difference of GMT and local date. */
183 int gmt_loc_diff = 0;
184
185 /*! Indicates whether event also appears in next year. */
186 int incr_year = 0;
187
188 /*! Indicates whether event also appears in previous year. */
189 int decr_year = 0;
190
191 /*! Day of event found in line. */
192 int d = 0;
193
194 /*! Month of event found in line. */
195 int m = 0;
196
197 /*! Year of event found in line. */
198 int y = 0;
199
200 /*! Buffered day of event. */
201 int d_buf = 0;
202
203 /*! Buffered month of event. */
204 int m_buf = 0;
205
206 /*! The `N'th weekday of month' displacement value. */
207 int hn = 0;
208
209 /*! The weekday number of `N'th weekday of month'. */
210 int hwd = 0;
211
212 /*! Name of tempfile used when a command is assigned to a TVAR. */
213 char *rc_tvar_tfn = (char *) NULL;
214
215 /*! Name of tempfile used for managing `--here=ARG' options. */
216 char *rc_here_fn = (char *) NULL;
217
218 /*! Text buffer of "text"-part of a line. */
219 char *the_text = (char *) NULL;
220
221 /*! General purpose text buffer 5. */
222 char *s5 = (char *) NULL;
223
224 /*! General purpose text buffer 6. */
225 char *s6 = (char *) NULL;
226
227 /*! General purpose text buffer 7. */
228 char *s7 = (char *) NULL;
229
230 /*! Text buffer of a line read from a resource file. */
231 char *line_buffer = (char *) NULL;
232
233 /*! Stores the valid fixed date texts. */
234 char **rc_elems_table = (char **) NULL;
235
236 /*! Text of modified actual date %DATE. */
237 char *rc_adate = (char *) NULL;
238
239 /*! Name of alternative resource file(s) `-f|F<NAME[+...]>'. */
240 char *rc_filename = (char *) NULL;
241
242 /*! Argument used for filtering fixed date days. */
243 char *rc_filter_day = (char *) NULL;
244
245 /*! Argument used for filtering fixed date periods. */
246 char *rc_filter_period = (char *) NULL;
247
248 /*! REGEX used for filtering fixed date texts. */
249 char *rc_filter_text = (char *) NULL;
250
251 /*! Fixed date list grouping separator `-cg[TEXT]'. */
252 char *rc_grp_sep = (char *) NULL;
253
254 /*! Fixed date list heading text `--heading-text=TEXT'. */
255 char *rc_heading_text = (char *) NULL;
256
257 /*! The biorhythm's "Emo" text. */
258 char *rc_bio_emo_lit = (char *) NULL;
259
260 /*! The biorhythm's "Int" text. */
261 char *rc_bio_int_lit = (char *) NULL;
262
263 /*! The biorhythm's "Phy" text. */
264 char *rc_bio_phy_lit = (char *) NULL;
265
266 /*! The mode specifying character. */
267 char hc = '\0';
268
269 /*! `-jc'. */
270 Bool rc_special_flag = FALSE;
271
272 /*! `-jcb'. */
273 Bool rc_both_dates_flag = FALSE;
274
275 /*! `-c'. */
276 Bool rc_use_flag = FALSE;
277
278 /*! `-C[]' or `-C[][T|W|M|Y]' or `-c[][T|W|M|Y]' or `-F<>'. */
279 Bool rc_all_dates_flag = FALSE;
280
281 /*! `-c-'. */
282 Bool rc_sort_des_flag = FALSE;
283
284 /*! `-ca'. */
285 Bool rc_enable_fn_flag = FALSE;
286
287 /*! `-cA'. */
288 Bool rc_alternative_format_flag = FALSE;
289
290 /*! `--execute-command'. */
291 Bool rc_execute_command = FALSE;
292
293 /*! `-ce'. */
294 Bool rc_enable_hda_flag = FALSE;
295
296 /*! `-cE'. */
297 Bool rc_enable_hdl_flag = FALSE;
298
299 /*! `-ck'. */
300 Bool rc_week_number_flag = FALSE;
301
302 /*! `-cl'. */
303 Bool rc_period_list = FALSE;
304
305 /*! `-co'. */
306 Bool rc_omit_date_flag = FALSE;
307
308 /*! `-cU'. */
309 Bool rc_suppr_date_part_flag = FALSE;
310
311 /*! `-cQ'. */
312 Bool rc_suppr_list_sep_flag = FALSE;
313
314 /*! `-cJ'. */
315 Bool rc_suppr_text_part_flag = FALSE;
316
317 /*! `-cx'. */
318 Bool rc_title_flag = TRUE;
319
320 /*! `-cz'. */
321 Bool rc_count_flag = FALSE;
322
323 /*! `-cZ'. */
324 Bool rc_zero_dates_flag = FALSE;
325
326 /*! `-cN[d|w|+|-]|MMDD|MMWW[W]N'. */
327 Bool rc_period_flag = FALSE;
328
329 /*! `-c]t'. */
330 Bool rc_tomorrow_flag = FALSE;
331
332 /*! `-c]w'. */
333 Bool rc_week_flag = FALSE;
334
335 /*! `-c]m'. */
336 Bool rc_month_flag = FALSE;
337
338 /*! `-c]y'. */
339 Bool rc_year_flag = FALSE;
340
341 /*! `-cNw'. */
342 Bool rc_week_year_flag = FALSE;
343
344 /*! `-c<N|w|m|y>+'. */
345 Bool rc_forwards_flag = FALSE;
346
347 /*! Buffers the state of `rc_forwards_flag'. */
348 Bool rc_fwdf_buffer = FALSE;
349
350 /*! `-c<N|w|m|y>-'. */
351 Bool rc_backwards_flag = FALSE;
352
353 /*! Buffers the state of `rc_backwards_flag'. */
354 Bool rc_bwdf_buffer = FALSE;
355
356 /*! `--leap-day=february'. */
357 Bool rc_feb_29_to_feb_28 = FALSE;
358
359 /*! `--leap-day=march'. */
360 Bool rc_feb_29_to_mar_01 = FALSE;
361
362 /*! `--precise' to display precise, non-rounded, times and data. */
363 Bool rc_precise = FALSE;
364
365 /*! `--export-date-variables'. */
366 Bool rc_export_ldvar_flag = FALSE;
367
368 /*! `--export-text-variables'. */
369 Bool rc_export_ltvar_flag = FALSE;
370
371 /*! `--ignore-case' to ignore case distinctions in PATTERN. */
372 Bool rc_ignore_case_flag = FALSE;
373
374 /*! `--limit' to calculate rise/set times limited to the current day only. */
375 Bool rc_limit = FALSE;
376
377 /*! `--revert-match' to select non-matching PATTERN lines. */
378 Bool rc_revert_match_flag = FALSE;
379
380 /*! Is a command (explicit date) given in the command line? */
381 Bool is_date_given = FALSE;
382
383 /*! Does the command enables a year implicitly? */
384 Bool date_enables_year = FALSE;
385
386 /*! Stores whether a %shell escape special text is run. */
387 Bool shell_escape_done = FALSE;
388
389 /*! `-cNw' and complete week is in month. */
390 Bool is_1month_mode = FALSE;
391
392 /*! `-cNw' and only part of week is in month. */
393 Bool is_2month_mode = FALSE;
394
395 /*! Reference to a date variable found in line. */
396 Bool is_2dvar = FALSE;
397
398 /*! Reference to Easter Sundays date found in line. */
399 Bool is_2easter = FALSE;
400
401 /*! `-cNw' and actual date modified. */
402 Bool adate_set = FALSE;
403
404 /*! Remove highlighting sequences before searching PATTERN? */
405 Bool remove_hls_in_regex = FALSE;
406
407
408
409 /*
410 * The REGEX stuff; global variables that represent the "remembered" search PATTERN.
411 */
412 # if HAVE_GNU_RE_COMPILE_PATTERN
413 struct re_pattern_buffer regpattern;
414 char *gnu_fastmap_table = (char *) NULL;
415 unsigned char *gnu_translate_table = (unsigned char *) NULL;
416 # endif
417
418 # if HAVE_POSIX_REGCOMP
419 regex_t regpattern;
420 # endif
421
422 # if HAVE_RE_COMP
423 int re_pattern = 0;
424 # endif
425
426
427 /*
428 * static variables definitions.
429 */
430 /*! Table of resource/include file buffers. */
431 static File_struct **rc_files_table = (File_struct **) NULL;
432
433 /*! Actual size of `rc_files_table[]'. */
434 static Uint rc_files_max = RC_FILES_MAX;
435
436 /*! Amount of resource file buffers. */
437 static int rc_files = 0;
438
439 /*! Number of characters in `line_buffer'. */
440 static int line_length = 0;
441
442 /*! An include statement is found in file. */
443 static Bool is_include = FALSE;
444
445 /*! A date variable statement is found in file. */
446 static Bool is_dvar = FALSE;
447
448 /*! A text variable statement is found in file. */
449 static Bool is_tvar = FALSE;
450
451 /*! File contains an invalid include file name? */
452 static Bool bad_sys_include = FALSE;
453
454
455
456 /*
457 * Function implementations.
458 */
459 void
rc_use()460 rc_use ()
461 /*!
462 Processes a standard/special resource file and displays the valid fixed
463 dates found resp., the valid fixed dates of eternal holiday list.
464 */
465 {
466 register int wd = weekday_of_date (act_day, act_month, act_year);
467 register int ed;
468 register int i;
469 register int j;
470 register int tmp_month = month;
471 register int tmp_fiscal_month = fiscal_month;
472 register int tmp_start_day = start_day;
473 register int tmp_ad = act_day;
474 register int tmp_am = act_month;
475 register int tmp_ay = act_year;
476 register int tindex = 0;
477 auto char *ptr_char;
478 # if HAVE_ASSERT_H
479 static Bool is_table_range_checked = FALSE;
480 # endif
481 static Bool tables_initialized = FALSE;
482
483
484 /*
485 Initialize some important module global variables.
486 */
487 len_fil_wt = rc_elems = rc_files = 0;
488 len_the_text = (int) maxlen_max;
489 # if HAVE_ASSERT_H
490 /*
491 Check if the value for the maximum number of table entries
492 fits to the positive range of a signed int (INT_MAX/SHRT_MAX)!
493 */
494 if (!is_table_range_checked)
495 {
496 assert (rc_elems_max > 0);
497 assert (rc_elems_max <= testval);
498 assert (rc_files_max > 0);
499 assert (rc_files_max <= testval);
500 assert (len_the_text > 0);
501 assert (len_the_text <= testval);
502 is_table_range_checked = TRUE;
503 }
504 # endif
505 if (!tables_initialized)
506 {
507 /*
508 Initialize the biorhythms phase texts consisting of 3 characters each.
509 */
510 /*
511 *** Translators, please translate this as a fixed 3-character text.
512 *** This text should be a proper abbreviation of "Emotional".
513 */
514 rc_bio_emo_lit = _("Emo");
515 /*
516 *** Translators, please translate this as a fixed 3-character text.
517 *** This text should be a proper abbreviation of "Intellectual".
518 */
519 rc_bio_int_lit = _("Int");
520 /*
521 *** Translators, please translate this as a fixed 3-character text.
522 *** This text should be a proper abbreviation of "Physical".
523 */
524 rc_bio_phy_lit = _("Phy");
525 /*
526 Initial memory allocation for an element of the `Line_struct' record
527 which is needed if we have to parse and evaluate a line.
528 */
529 lptrs = (Line_struct *) my_malloc (sizeof (Line_struct),
530 ERR_NO_MEMORY_AVAILABLE,
531 __FILE__, ((long) __LINE__) - 2L,
532 "lptrs", 0);
533 /*
534 Initial memory allocation for an element of the `Line_struct' record
535 which is needed if we have to evaluate %?... special texts.
536 */
537 lptrs2 = (Line_struct *) my_malloc (sizeof (Line_struct),
538 ERR_NO_MEMORY_AVAILABLE,
539 __FILE__, ((long) __LINE__) - 2L,
540 "lptrs2", 0);
541 /*
542 Initial memory allocation for `rc_files_table[]'.
543 */
544 rc_files_table =
545 (File_struct **) my_malloc (RC_FILES_MAX * sizeof (File_struct *),
546 ERR_NO_MEMORY_AVAILABLE, __FILE__,
547 ((long) __LINE__) - 2L,
548 "rc_files_table[RC_FILES_MAX]",
549 RC_FILES_MAX);
550 /*
551 Initial memory allocation for `rc_elems_table[]'.
552 */
553 rc_elems_table = (char **) my_malloc (RC_ELEMS_MAX * sizeof (char *),
554 ERR_NO_MEMORY_AVAILABLE,
555 __FILE__, ((long) __LINE__) - 2L,
556 "rc_elems_table[RC_ELEMS_MAX]",
557 RC_ELEMS_MAX);
558 /*
559 Initial memory allocation for `the_text'.
560 */
561 the_text = (char *) my_malloc (len_the_text, ERR_NO_MEMORY_AVAILABLE,
562 __FILE__, ((long) __LINE__) - 1L,
563 "the_text", 0);
564 /*
565 The REGEX stuff in case `--filter-text=PATTERN' is given.
566 */
567 if (rc_filter_text != (char *) NULL)
568 {
569 /*
570 Compile `rc_filter_text' PATTERN.
571 */
572 # if !HAVE_GNU_RE_COMPILE_PATTERN
573 if (rc_ignore_case_flag)
574 {
575 /*
576 Set PATTERN to lower-case letters
577 if we have to ignore case distinctions.
578 */
579 ptr_char = rc_filter_text;
580 for (; *ptr_char; ptr_char++)
581 *ptr_char = (char) tolower (*ptr_char);
582 }
583 # else /* HAVE_GNU_RE_COMPILE_PATTERN */
584 /*
585 Compute the GNU Regex table size.
586 */
587 # ifndef CHAR_BIT
588 auto Uchar bit;
589
590
591 for (i = 0, bit = 2; bit; bit <<= 1, i++)
592 ; /* Void, nothing to do here! */
593 # else /* CHAR_BIT */
594 i = CHAR_BIT - 1;
595 # endif /* CHAR_BIT */
596 j = ((1 << i) - 1) + (1 << i);
597 /*
598 Initial memory allocation of GNU Regex fastmap table.
599 */
600 gnu_fastmap_table =
601 (char *) my_malloc (j + 1, ERR_NO_MEMORY_AVAILABLE, __FILE__,
602 ((long) __LINE__) - 1L, "gnu_fastmap_table",
603 0);
604 /*
605 Initial memory allocation and initialization of GNU Regex translate table.
606 */
607 gnu_translate_table =
608 (unsigned char *) my_malloc (j + 1, ERR_NO_MEMORY_AVAILABLE,
609 __FILE__, ((long) __LINE__) - 1L,
610 "gnu_translate_table", 0);
611 if (rc_ignore_case_flag)
612 /*
613 Set PATTERN to lower-case letters
614 if we have to ignore case distinctions.
615 */
616 for (i = 0; i <= j; i++)
617 gnu_translate_table[i] = (unsigned char) tolower (i);
618 else
619 for (i = 0; i <= j; i++)
620 gnu_translate_table[i] = (unsigned char) i;
621 (void)
622 re_set_syntax ((RE_SYNTAX_POSIX_EXTENDED |
623 RE_BACKSLASH_ESCAPE_IN_LISTS) &
624 ~(RE_DOT_NOT_NULL));
625 regpattern.fastmap = gnu_fastmap_table;
626 regpattern.translate = gnu_translate_table;
627 if (re_compile_pattern
628 (rc_filter_text, (int) strlen (rc_filter_text),
629 ®pattern) != (char *) NULL)
630 my_error (ERR_INVALID_REGEX_PATTERN, "", 0L, rc_filter_text, 0);
631 # endif /* HAVE_GNU_RE_COMPILE_PATTERN */
632 # if HAVE_POSIX_REGCOMP
633 if (regcomp (®pattern, rc_filter_text, REGCOMP_FLAG))
634 my_error (ERR_INVALID_REGEX_PATTERN, "", 0L, rc_filter_text, 0);
635 # endif
636 # if HAVE_RE_COMP
637 if (re_comp (rc_filter_text) != (char *) NULL)
638 my_error (ERR_INVALID_REGEX_PATTERN, "", 0L, rc_filter_text, 0);
639 re_pattern = 1;
640 # endif
641 /*
642 Is it necessary to remove highlighting sequences
643 in each text before searching the PATTERN?
644 */
645 remove_hls_in_regex = highlight_flag;
646 }
647 tables_initialized = TRUE;
648 }
649 /*
650 Depending on fixed date mode,
651 compute last valid day `ed' a fixed date may occur.
652 */
653 ed = day = day_of_year (act_day, act_month, act_year);
654 if (is_date_given)
655 {
656 /*
657 NOT in simple month/year mode (an explicit date is given in the command line):
658 Compute the starting/ending loop values of the requested period.
659 */
660 ed = DAY_LAST + is_leap_year + 1;
661 if (!month)
662 day = DAY_MIN;
663 else
664 {
665 day = day_of_year (DAY_MIN, month, year);
666 if (month < MONTH_MAX)
667 ed = day_of_year (DAY_MIN, month + 1, year);
668 }
669 /*
670 Then clean all flags which are related to the fixed date period.
671 */
672 rc_clean_flags ();
673 if (date_enables_year)
674 rc_year_flag = TRUE;
675 }
676 else
677 {
678 auto int dd;
679 auto int mm;
680 auto int yy = act_year;
681 auto int greg_missing_days = (greg->last_day - greg->first_day + 1);
682 auto Bool greg_correction = FALSE;
683 auto Bool swap_flag = FALSE;
684
685
686 if (rc_tomorrow_flag)
687 {
688 /*
689 `-ct' option found.
690 */
691 rc_period_list = FALSE;
692 ed += 2;
693 if ((act_year == greg->year)
694 && (act_month == greg->month)
695 && (act_day == greg->first_day - 1))
696 ed += greg_missing_days;
697 }
698 else if (rc_week_flag)
699 {
700 /*
701 `-cw[+|-]' option found.
702 */
703 rc_period_list = FALSE;
704 if (!rc_forwards_flag && !rc_backwards_flag)
705 day += (-DAY_MAX + SDAY (DAY_MAX - wd + 1, start_day));
706 else if (rc_forwards_flag)
707 day += !rc_have_today_in_list;
708 else
709 day += rc_have_today_in_list;
710 if (rc_backwards_flag
711 || (!rc_forwards_flag
712 && !rc_backwards_flag && (start_day > wd)))
713 {
714 swap_flag = TRUE;
715 ed -= DAY_MAX;
716 }
717 ed += SDAY (DAY_MAX - wd + 1, start_day);
718 if (act_year == greg->year)
719 greg_correction = TRUE;
720 }
721 else if (rc_month_flag)
722 {
723 /*
724 `-cm[+|-]' option found.
725 */
726 rc_period_list = FALSE;
727 if (!rc_forwards_flag && !rc_backwards_flag)
728 day = day_of_year (DAY_MIN, act_month, act_year);
729 else if (rc_forwards_flag)
730 day += !rc_have_today_in_list;
731 else
732 day += rc_have_today_in_list;
733 if (rc_backwards_flag)
734 ed = day_of_year (DAY_MIN, act_month, act_year);
735 else
736 {
737 if (act_month < MONTH_MAX)
738 ed = day_of_year (DAY_MIN, act_month + 1, act_year);
739 else
740 ed = DAY_LAST + is_leap_year + 1;
741 }
742 }
743 else if (rc_year_flag)
744 {
745 /*
746 `-cy[+|-]' option found.
747 */
748 rc_period_list = FALSE;
749 if (!rc_forwards_flag && !rc_backwards_flag)
750 day = DAY_MIN;
751 else if (rc_forwards_flag)
752 day += !rc_have_today_in_list;
753 else
754 day += rc_have_today_in_list;
755 if (rc_backwards_flag)
756 ed = DAY_MIN;
757 else
758 ed = DAY_LAST + is_leap_year + 1;
759 }
760 else if (rc_period_flag)
761 {
762 if (rc_week_year_flag)
763 {
764 /*
765 `-cNw' option found
766 */
767 if (iso_week_number)
768 /*
769 Those ISO-8601:1988 weeks starts on Monday.
770 */
771 wd = start_day = DAY_MIN;
772 /*
773 Compute the day number of year the week starts at.
774 */
775 j = day =
776 weekno2doy (rc_period, act_year, iso_week_number, start_day);
777 if (day != -WEEK_MAX)
778 {
779 if (rc_period_list)
780 {
781 /*
782 `-cNw' option found.
783 */
784 if (day > ed)
785 {
786 if (day <= DAY_LAST + is_leap_year)
787 {
788 rc_forwards_flag = TRUE;
789 day = ed + 1 - rc_have_today_in_list;
790 ed = j + DAY_MAX;
791 /*
792 Correction in case week occurs during Gregorian Reformation period.
793 */
794 if (act_year == greg->year)
795 {
796 (void) doy2date (j, is_leap_year, &dd, &mm);
797 for (i = j; i < ed; i++)
798 if (!next_date (&dd, &mm, &yy))
799 {
800 ed += greg_missing_days;
801 break;
802 }
803 }
804 if (ed > DAY_LAST + is_leap_year + 1)
805 ed = DAY_LAST + is_leap_year + 1;
806 }
807 else
808 /*
809 No fixed date messages to display.
810 */
811 day = ed;
812 }
813 else
814 {
815 if (ed > DAY_MIN)
816 {
817 rc_backwards_flag = TRUE;
818 day = ed + rc_have_today_in_list;
819 ed = j;
820 if (ed < DAY_MIN)
821 ed = DAY_MIN;
822 }
823 else
824 /*
825 No fixed date messages to display.
826 */
827 day = ed;
828 }
829 }
830 else
831 {
832 /*
833 `-cNw' option found:
834 Set actual date to Mondays date of week
835 and omit highlighting that date; boolean
836 `adate_set' is set to distinct this
837 SPECIAL mode from other modes...
838 */
839 rc_week_flag = TRUE;
840 ed = day + DAY_MAX;
841 /*
842 Correction in case week occurs during Gregorian Reformation period.
843 */
844 if (act_year == greg->year)
845 {
846 (void) doy2date (day, is_leap_year, &dd, &mm);
847 for (i = day; i < ed; i++)
848 if (!next_date (&dd, &mm, &yy))
849 {
850 ed += greg_missing_days;
851 break;
852 }
853 }
854 if (day < DAY_MIN)
855 {
856 act_year--;
857 j +=
858 (DAY_LAST + (days_of_february (act_year) == 29));
859 }
860 else
861 j = day;
862 (void) doy2date (j, is_leap_year, &act_day, &act_month);
863 month = act_month;
864 fiscal_month = MONTH_MIN;
865 adate_set = TRUE;
866 }
867 }
868 else
869 /*
870 Wanted week doesn't exist:
871 Don't display any fixed date messages.
872 */
873 day = ed;
874 }
875 else
876 /*
877 `-cNd', `-cMMDD', `-cMMWW[W]N', `-c*d|wN[WW[W]' and
878 `-c@e|t|DVAR[[-]N] options are implicitly managed in
879 this subsection, too.
880 */
881 if (rc_forwards_flag && (day < DAY_LAST + is_leap_year))
882 {
883 if (rc_period_list)
884 {
885 /*
886 `-clN+' option found (list of dates).
887 */
888 day += !rc_have_today_in_list;
889 /*
890 Correction in case date occurs during Gregorian Reformation period.
891 */
892 if (rc_fwdf_buffer
893 && (act_year == greg->year)
894 && (ed <
895 day_of_year (greg->first_day, greg->month,
896 greg->year))
897 && (ed + rc_period >=
898 day_of_year (greg->first_day, greg->month,
899 greg->year)))
900 ed += greg_missing_days;
901 ed += (rc_period + 1);
902 if (ed > DAY_LAST + is_leap_year + 1)
903 ed = DAY_LAST + is_leap_year + 1;
904 }
905 else
906 {
907 /*
908 `-cN+ option found (single date).
909 */
910 rc_forwards_flag = FALSE;
911 /*
912 Correction in case date occurs during Gregorian Reformation period.
913 */
914 if (rc_fwdf_buffer
915 && (act_year == greg->year)
916 && (day <
917 day_of_year (greg->first_day, greg->month,
918 greg->year))
919 && (day + rc_period >=
920 day_of_year (greg->first_day, greg->month,
921 greg->year)))
922 day += greg_missing_days;
923 day += rc_period;
924 ed = day;
925 if (day < DAY_LAST + is_leap_year + 1)
926 {
927 rc_period_flag = FALSE;
928 (void) doy2date (day, is_leap_year, &act_day,
929 &act_month);
930 month = act_month;
931 ed++;
932 }
933 }
934 }
935 else if (rc_backwards_flag && (day > DAY_MIN))
936 {
937 if (rc_period_list)
938 {
939 /*
940 `-clN-' option found (list of dates).
941 */
942 day += rc_have_today_in_list;
943 /*
944 Correction in case date occurs during Gregorian Reformation period.
945 */
946 if (rc_bwdf_buffer
947 && (act_year == greg->year)
948 && (ed >
949 day_of_year (greg->last_day, greg->month,
950 greg->year))
951 && (ed - rc_period <=
952 day_of_year (greg->last_day, greg->month,
953 greg->year)))
954 ed -= greg_missing_days;
955 ed -= rc_period;
956 if (ed < DAY_MIN)
957 ed = DAY_MIN;
958 }
959 else
960 {
961 /*
962 `-cN-' option found (single date).
963 */
964 rc_backwards_flag = FALSE;
965 /*
966 Correction in case date occurs during Gregorian Reformation period.
967 */
968 if (rc_bwdf_buffer
969 && (act_year == greg->year)
970 && (day >
971 day_of_year (greg->last_day, greg->month,
972 greg->year))
973 && (day - rc_period <=
974 day_of_year (greg->last_day, greg->month,
975 greg->year)))
976 day -= greg_missing_days;
977 day -= rc_period;
978 ed = day;
979 if (day > 0)
980 {
981 rc_period_flag = FALSE;
982 (void) doy2date (day, is_leap_year, &act_day,
983 &act_month);
984 month = act_month;
985 ed++;
986 }
987 }
988 }
989 }
990 else
991 {
992 /*
993 Only a simple option `-c' (without any modifiers) found.
994 */
995 rc_period_list = FALSE;
996 ed++;
997 }
998 /*
999 Swap the starting date `day' and final date `ed' of the period.
1000 */
1001 if (swap_flag || rc_backwards_flag)
1002 {
1003 int tmp = ed;
1004 ed = day;
1005 day = tmp;
1006 }
1007 /*
1008 Correction in case date occurs during Gregorian Reformation period.
1009 */
1010 if (greg_correction)
1011 {
1012 (void) doy2date (day, is_leap_year, &dd, &mm);
1013 if (!prev_date (&dd, &mm, &yy))
1014 day -= greg_missing_days;
1015 else
1016 {
1017 if (!rc_forwards_flag && !rc_backwards_flag)
1018 {
1019 (void) doy2date (day, is_leap_year, &dd, &mm);
1020 if (weekday_of_date (dd, mm, yy) != start_day)
1021 day -= greg_missing_days;
1022 else
1023 for (i = day; i < ed; i++)
1024 if (!next_date (&dd, &mm, &yy))
1025 {
1026 ed += greg_missing_days;
1027 break;
1028 }
1029 }
1030 else
1031 {
1032 auto Bool ed_set = FALSE;
1033
1034
1035 for (i = day; i < ed; i++)
1036 if (!next_date (&dd, &mm, &yy))
1037 {
1038 ed += greg_missing_days;
1039 ed_set = TRUE;
1040 break;
1041 }
1042 if (rc_backwards_flag && ed_set)
1043 {
1044 (void) doy2date (day, is_leap_year, &dd, &mm);
1045 if (weekday_of_date (dd, mm, yy) != start_day)
1046 {
1047 day -= greg_missing_days;
1048 ed -= greg_missing_days;
1049 }
1050 }
1051 }
1052 }
1053 }
1054 }
1055 if (day != ed)
1056 {
1057 auto double save_time_offset = time_offset;
1058 register int save_hour_offset = time_hour_offset;
1059 register int save_min_offset = time_min_offset;
1060 register int save_loop_end = loop_end;
1061 auto char *tmp_rc_here_fn;
1062 auto Bool cycle_increment = TRUE;
1063 auto Bool is_here_file;
1064 auto Bool ok;
1065
1066
1067 /*
1068 Now include the eternal holidays, which are valid fixed dates,
1069 into `rc_elems_table[]'.
1070 */
1071 if (rc_enable_hda_flag || rc_enable_hdl_flag)
1072 {
1073 while ((hd_table[tindex] != (char *) NULL)
1074 && (tindex < HD_ELEMS_MAX))
1075 {
1076 strcpy (line_buffer, hd_table[tindex]);
1077 i = LEN_HD_NAME + len_year_max + 4 + 2;
1078 if (rc_enable_hda_flag
1079 || (rc_enable_hdl_flag
1080 && (line_buffer[i] != *DIS_HLS_PREF)
1081 && (line_buffer[i] != *DIS_HLS_PREF2)))
1082 {
1083 i -= 2;
1084 while (i && isspace (line_buffer[i]))
1085 line_buffer[i--] = '\0';
1086 if (i > len_year_max + 4)
1087 rc_check (line_buffer, _("`Eternal holiday list'"),
1088 (long) tindex, i, &rc_elems, day, ed, wd);
1089 }
1090 if (!holiday_flag)
1091 {
1092 free (hd_table[tindex]);
1093 hd_table[tindex] = (char *) NULL;
1094 }
1095 tindex++;
1096 }
1097 /*
1098 If the fixed date mode is related to a week or to tomorrow
1099 and the period has left the current year, include those
1100 eternal holidays in year +/- 1 into `rc_elems_table',
1101 which are valid fixed dates.
1102 */
1103 if ((rc_tomorrow_flag
1104 || rc_week_flag)
1105 && !is_date_given
1106 && !is_1month_mode
1107 && !is_2month_mode
1108 && ((!rc_forwards_flag
1109 && !rc_backwards_flag
1110 && (((year + 1 <= YEAR_MAX)
1111 && (ed > DAY_LAST + is_leap_year + 1))
1112 || ((year - 1 >= YEAR_MIN)
1113 && (day < DAY_MIN))))
1114 || (rc_forwards_flag
1115 && ((year + 1 <= YEAR_MAX)
1116 && (ed > DAY_LAST + is_leap_year + 1)))
1117 || (rc_backwards_flag
1118 && ((year - 1 >= YEAR_MIN) && (day < DAY_MIN)))))
1119 {
1120 register int jtmp_ad = act_day;
1121 register int tay = act_year;
1122 register int tam = act_month;
1123 register int tad = act_day;
1124
1125
1126 if (holiday_flag)
1127 for (i = 0; i < tindex; i++)
1128 {
1129 free (hd_table[i]);
1130 hd_table[i] = (char *) NULL;
1131 }
1132 tindex = 0;
1133 if (day < DAY_MIN)
1134 {
1135 year--;
1136 month = MONTH_MAX;
1137 }
1138 else
1139 {
1140 year++;
1141 month = MONTH_MIN;
1142 }
1143 is_leap_year = (days_of_february (year) == 29);
1144 if (cal_special_flag)
1145 act_day = day_of_year (jtmp_ad, act_month, act_year);
1146 if (adate_set)
1147 fiscal_month = tmp_fiscal_month;
1148 if (((year == EASTER_MIN - 1)
1149 && (fiscal_month > MONTH_MIN))
1150 || ((year >= EASTER_MIN) && (year <= EASTER_MAX)))
1151 print_all_holidays (TRUE, TRUE);
1152 if (adate_set)
1153 fiscal_month = MONTH_MIN;
1154 if (day < DAY_MIN)
1155 {
1156 year++;
1157 month = MONTH_MIN;
1158 }
1159 else
1160 {
1161 year--;
1162 month = MONTH_MAX;
1163 }
1164 while ((hd_table[tindex] != (char *) NULL)
1165 && (tindex < HD_ELEMS_MAX))
1166 {
1167 strcpy (line_buffer, hd_table[tindex]);
1168 i = LEN_HD_NAME + len_year_max + 4 + 2;
1169 if (rc_enable_hda_flag
1170 || (rc_enable_hdl_flag
1171 && (line_buffer[i] == *DIS_HLS_PREF)
1172 && (line_buffer[i] == *DIS_HLS_PREF2)))
1173 {
1174 i -= 2;
1175 while (i && isspace (line_buffer[i]))
1176 line_buffer[i--] = '\0';
1177 if (i > len_year_max + 4)
1178 rc_check (line_buffer, _("`Eternal holiday list'"),
1179 (long) tindex, i, &rc_elems, day, ed, wd);
1180 }
1181 free (hd_table[tindex]);
1182 hd_table[tindex] = (char *) NULL;
1183 tindex++;
1184 }
1185 is_leap_year = (days_of_february (year) == 29);
1186 if (adate_set)
1187 {
1188 fiscal_month = tmp_fiscal_month;
1189 act_year = tmp_ay;
1190 act_month = tmp_am;
1191 jtmp_ad = act_day = tmp_ad;
1192 }
1193 if (cal_special_flag)
1194 act_day = day_of_year (jtmp_ad, act_month, act_year);
1195 if (holiday_flag
1196 && (((year == EASTER_MIN - 1)
1197 && (fiscal_month > MONTH_MIN))
1198 || ((year >= EASTER_MIN) && (year <= EASTER_MAX))))
1199 print_all_holidays (TRUE, TRUE);
1200 if (cal_special_flag)
1201 act_day = jtmp_ad;
1202 if (adate_set)
1203 {
1204 fiscal_month = MONTH_MIN;
1205 act_year = tay;
1206 month = act_month = tam;
1207 act_day = tad;
1208 }
1209 else
1210 month = tmp_month;
1211 }
1212 }
1213 /*
1214 Try to open the resource file(s).
1215 */
1216 if (rc_filename == (char *) NULL)
1217 {
1218 /*
1219 Use the standard resource file.
1220 */
1221 i = (int) strlen (PACKAGE_NAME) + strlen (RC_SUFFIX);
1222 # ifdef GCAL_SHELL
1223 i++;
1224 # endif
1225 if ((Uint) i >= maxlen_max)
1226 resize_all_strings (i + 1, FALSE, __FILE__, (long) __LINE__);
1227 # ifdef GCAL_SHELL
1228 strcpy (s3, ".");
1229 # else /* !GCAL_SHELL */
1230 *s3 = '\0';
1231 # endif /* !GCAL_SHELL */
1232 strcat (s3, PACKAGE_NAME);
1233 strcat (s3, RC_SUFFIX);
1234 }
1235 else
1236 {
1237 /*
1238 Use the list of resource file names.
1239 */
1240 i = (int) strlen (rc_filename);
1241 if ((Uint) i >= maxlen_max)
1242 resize_all_strings (i + 1, FALSE, __FILE__, (long) __LINE__);
1243 strcpy (s3, rc_filename);
1244 }
1245 /*
1246 Allocate the file buffers for the main resource file itself
1247 (the main resource file is always buffered at position 0 in `rc_files_table[]').
1248 */
1249 rc_files_table[rc_files] =
1250 (File_struct *) my_malloc (sizeof (File_struct),
1251 ERR_NO_MEMORY_AVAILABLE, __FILE__,
1252 ((long) __LINE__) - 2L,
1253 "rc_files_table[rc_files]", rc_files);
1254 rc_files_table[rc_files]->fp = (FILE *) NULL;
1255 rc_files_table[rc_files]->pool = (char *) my_malloc (BUF_LEN + 1,
1256 ERR_NO_MEMORY_AVAILABLE,
1257 __FILE__,
1258 ((long) __LINE__) -
1259 2L,
1260 "rc_files_table[rc_files]->pool",
1261 rc_files);
1262 if (loop_end != SPECIAL_VALUE)
1263 {
1264 /*
1265 Set the cycle-starting time value for %sun* and %moon*.
1266 */
1267 tindex = HHMM2MM (time_hour_offset, time_min_offset);
1268 /*
1269 Reduce the given cycle-starting time value in minutes to a single day.
1270 */
1271 if (tindex < 0)
1272 tindex = 0;
1273 else if (tindex >= MINS_PER_DAY)
1274 tindex = MINS_PER_DAY - 1;
1275 if (tindex > loop_end)
1276 cycle_increment = FALSE;
1277 time_hour_offset = MM2HH (tindex);
1278 time_min_offset = tindex % MINS_PER_HOUR;
1279 time_offset = MM2DAY (tindex);
1280 }
1281 else
1282 tindex = 0;
1283 do
1284 {
1285 tmp_rc_here_fn = rc_here_fn;
1286 ok = is_here_file = FALSE;
1287 while (!ok)
1288 {
1289 /*
1290 Single file or list of resource file names given in the command line.
1291 */
1292 while (rc_files_table[rc_files]->fp == (FILE *) NULL)
1293 {
1294 i = 0;
1295 ptr_char = s3;
1296 LOOP
1297 {
1298 if (*ptr_char == QUOTE_CHAR)
1299 {
1300 if (*(ptr_char + 1) == *CONNECT_SEP
1301 || *(ptr_char + 1) == QUOTE_CHAR)
1302 ptr_char++;
1303 s7[i++] = *ptr_char++;
1304 }
1305 else if (*ptr_char != *CONNECT_SEP)
1306 s7[i++] = *ptr_char++;
1307 if (!*ptr_char || *ptr_char == *CONNECT_SEP)
1308 break;
1309 }
1310 s7[i] = '\0';
1311 /*
1312 Now check if the file exists.
1313 */
1314 rc_files_table[rc_files]->filename
1315 = (char *) my_malloc (i + 1, ERR_NO_MEMORY_AVAILABLE,
1316 __FILE__, ((long) __LINE__) - 1L,
1317 "rc_files_table[rc_files]->filename",
1318 rc_files);
1319 strcpy (rc_files_table[rc_files]->filename, s7);
1320 rc_files_table[rc_files]->fp =
1321 file_open (&rc_files_table[rc_files]->filename, rc_files,
1322 (is_here_file) ? HEre : REsource,
1323 &bad_sys_include);
1324 if (!*ptr_char)
1325 {
1326 /*
1327 Finished, THE file respectively ALL files are managed
1328 so check whether any `--here=ARG' options must be processed
1329 at last coming from the temporary file already created.
1330 */
1331 if (tmp_rc_here_fn != (char *) NULL)
1332 {
1333 /*
1334 Use the temporary "here" filename for processing next.
1335 */
1336 i = (int) strlen (tmp_rc_here_fn);
1337 if ((Uint) i >= maxlen_max)
1338 resize_all_strings (i + 1, FALSE, __FILE__,
1339 (long) __LINE__);
1340 strcpy (s3, tmp_rc_here_fn);
1341 tmp_rc_here_fn = (char *) NULL;
1342 is_here_file = !ok; /* Nomen est Omen??? :-) */
1343 }
1344 else
1345 ok = TRUE;
1346 break;
1347 }
1348 else
1349 {
1350 /*
1351 Now skip a trailing '+' character of a file name list.
1352 */
1353 ptr_char++;
1354 /*
1355 Copy the rest of the file name list and start
1356 the file search again if the file was not found.
1357 */
1358 strcpy (s7, ptr_char);
1359 strcpy (s3, s7);
1360 if (rc_files_table[rc_files]->fp == (FILE *) NULL)
1361 free (rc_files_table[rc_files]->filename);
1362 }
1363 }
1364 /*
1365 Now read and check contents of a resource file `filename'
1366 and include valid fixed dates into `rc_elems_table[]'.
1367 */
1368 if (rc_files_table[rc_files]->fp != (FILE *) NULL)
1369 {
1370 rc_files_table[rc_files]->in_pool = 0;
1371 rc_files_table[rc_files]->line_number = 0L;
1372 /*
1373 First of all, copy the contents of the global date variables to the
1374 local variables (if one of these isn't defined) so we can perform
1375 local operations (++, --, +=, -=) on global variables.
1376 */
1377 for (i = 0; i < RC_DVAR_MAX; i++)
1378 if (rc_dvar[i].dvar_global.dvar_month
1379 && !rc_dvar[i].dvar_local.dvar_month)
1380 {
1381 rc_dvar[i].dvar_local.dvar_month =
1382 rc_dvar[i].dvar_global.dvar_month;
1383 rc_dvar[i].dvar_local.dvar_day =
1384 rc_dvar[i].dvar_global.dvar_day;
1385 }
1386 /*
1387 Then copy the contents of the global text variables to the
1388 local variables (if one of these isn't defined) so we can
1389 perform local operations (++, --, +=, -=) on global variables.
1390 */
1391 for (i = 0; i < RC_TVAR_MAX; i++)
1392 if ((rc_tvar[i].tvar_global.tvar_text != (char *) NULL)
1393 && (rc_tvar[i].tvar_local.tvar_text == (char *) NULL))
1394 {
1395 rc_tvar[i].tvar_local.tvar_text
1396 =
1397 (char *)
1398 my_malloc (strlen (rc_tvar[i].tvar_global.tvar_text)
1399 + 1, ERR_NO_MEMORY_AVAILABLE, __FILE__,
1400 ((long) __LINE__) - 2L,
1401 "rc_tvar[i].tvar_local.tvar_text", i);
1402 strcpy (rc_tvar[i].tvar_local.tvar_text,
1403 rc_tvar[i].tvar_global.tvar_text);
1404 }
1405 while ((rc_files_table[rc_files]->ptr_pool =
1406 file_read_line (rc_files_table[rc_files]->fp,
1407 &line_buffer,
1408 &rc_files_table[rc_files]->in_pool,
1409 rc_files_table[rc_files]->pool,
1410 rc_files_table[rc_files]->ptr_pool,
1411 rc_files_table[rc_files]->filename,
1412 &rc_files_table[rc_files]->
1413 line_number, &line_length, REsource,
1414 &is_include, &is_dvar,
1415 &is_tvar)) != (char *) NULL)
1416 {
1417 /*
1418 Check whether an "#include" statement is found.
1419 */
1420 if (is_include)
1421 /*
1422 We have to manage an include file.
1423 */
1424 try_to_include_file (ed, wd);
1425 else
1426 /*
1427 We are still in the main resource file.
1428 */
1429 if (*line_buffer && !is_dvar && !is_tvar)
1430 rc_check (line_buffer,
1431 rc_files_table[rc_files]->filename,
1432 rc_files_table[rc_files]->line_number,
1433 line_length, &rc_elems, day, ed, wd);
1434 }
1435 if (rc_files_table[rc_files]->fp != stdin)
1436 (void) fclose (rc_files_table[rc_files]->fp);
1437 rc_files_table[rc_files]->fp = (FILE *) NULL;
1438 free (rc_files_table[rc_files]->filename);
1439 /*
1440 Next file -> reset all local date variables to zero,
1441 if `--export-date-variables' flag set, don't reset them!
1442 */
1443 if (!rc_export_ldvar_flag)
1444 for (i = 0; i < RC_DVAR_MAX; i++)
1445 rc_dvar[i].dvar_local.dvar_month = (char) 0;
1446 /*
1447 Next file -> reset all local text variables to NULL,
1448 if `--export-text-variables' flag set, don't reset them!
1449 */
1450 if (!rc_export_ltvar_flag)
1451 for (i = 0; i < RC_TVAR_MAX; i++)
1452 if (rc_tvar[i].tvar_local.tvar_text != (char *) NULL)
1453 {
1454 free (rc_tvar[i].tvar_local.tvar_text);
1455 rc_tvar[i].tvar_local.tvar_text = (char *) NULL;
1456 }
1457 }
1458 else
1459 /*
1460 Yeah, we have not found any main resource file so it's absolutely
1461 necessary to free the allocated memory area of the "file name",
1462 because it's possible that we enter this function again,
1463 e.g. if we produce month/year lists or ranges.
1464 */
1465 free (rc_files_table[rc_files]->filename);
1466 }
1467 if (loop_end != SPECIAL_VALUE)
1468 {
1469 /*
1470 Increase/decrease the cycle-time counter properly and set
1471 a ``new'' time value for the %sun* and %moon* special texts.
1472 */
1473 if (cycle_increment)
1474 tindex += loop_step;
1475 else
1476 tindex -= loop_step;
1477 time_hour_offset = MM2HH (tindex);
1478 time_min_offset = tindex % MINS_PER_HOUR;
1479 time_offset = MM2DAY (tindex);
1480 }
1481 }
1482 while ((cycle_increment
1483 && (tindex <= loop_end))
1484 || (!cycle_increment && (tindex >= loop_end)));
1485 time_hour_offset = save_hour_offset;
1486 time_min_offset = save_min_offset;
1487 time_offset = save_time_offset;
1488 loop_end = save_loop_end;
1489 free (rc_files_table[rc_files]->pool);
1490 for (i = 0; i < RC_TVAR_MAX; i++)
1491 if (rc_tvar[i].tvar_local.tvar_text != (char *) NULL)
1492 {
1493 free (rc_tvar[i].tvar_local.tvar_text);
1494 rc_tvar[i].tvar_local.tvar_text = (char *) NULL;
1495 }
1496 free (rc_files_table[rc_files]);
1497 fiscal_month = tmp_fiscal_month;
1498 /*
1499 Now display the constructed contents of `rc_elems_table[]'.
1500 */
1501 if (rc_elems || rc_all_dates_flag || rc_zero_dates_flag)
1502 display_table (tmp_ad, tmp_am, tmp_ay, day, ed, wd);
1503 }
1504 start_day = tmp_start_day;
1505 month = tmp_month;
1506 act_day = tmp_ad;
1507 act_month = tmp_am;
1508 act_year = tmp_ay;
1509 }
1510
1511
1512
1513 static void
try_to_include_file(ed,wd)1514 try_to_include_file (ed, wd)
1515 int ed;
1516 int wd;
1517 /*!
1518 Manages an include file.
1519 */
1520 {
1521 register int i;
1522 register int j;
1523 auto Bool is_usr_file = FALSE;
1524 auto Bool is_sys_file = FALSE;
1525
1526
1527 i = (int) strlen (line_buffer);
1528 if ((Uint) i >= maxlen_max)
1529 resize_all_strings (i + 1, FALSE, __FILE__, (long) __LINE__);
1530 strcpy (s7, line_buffer);
1531 i = (int) strlen (RC_INCL_STMENT);
1532 if (strncasecmp (s7, RC_INCL_STMENT, i))
1533 /*
1534 Error, misspelled "#include" directive found.
1535 */
1536 my_error (ERR_MALFORMED_INCLUDE, rc_files_table[rc_files]->filename,
1537 rc_files_table[rc_files]->line_number, line_buffer, 0);
1538 /*
1539 Skip any leading whitespace characters of the line.
1540 */
1541 while (isspace (s7[i]))
1542 i++;
1543 if (!s7[i] || s7[i] == '\n')
1544 /*
1545 Error, no include file "argument" encoded.
1546 */
1547 my_error (ERR_MALFORMED_INCLUDE, rc_files_table[rc_files]->filename,
1548 rc_files_table[rc_files]->line_number, line_buffer, 0);
1549 if (s7[i] == *RC_INCL_USR_ID)
1550 is_usr_file = TRUE;
1551 else if (s7[i] == *RC_INCL_SYS_ID)
1552 is_sys_file = TRUE;
1553 else
1554 /*
1555 Error, illegal leading include file name delimiter found.
1556 */
1557 my_error (ERR_MALFORMED_INCLUDE, rc_files_table[rc_files]->filename,
1558 rc_files_table[rc_files]->line_number, line_buffer, 0);
1559 i++;
1560 j = 0;
1561 /*
1562 Get the include file name.
1563 */
1564 while (s7[i] && (s7[i] != *RC_INCL_USR_OD) && (s7[i] != *RC_INCL_SYS_OD))
1565 s7[j++] = s7[i++];
1566 if ((is_usr_file
1567 && (s7[i] != *RC_INCL_USR_OD))
1568 || (is_sys_file && (s7[i] != *RC_INCL_SYS_OD)))
1569 /*
1570 Error, illegal trailing include file name delimiter found.
1571 */
1572 my_error (ERR_MALFORMED_INCLUDE, rc_files_table[rc_files]->filename,
1573 rc_files_table[rc_files]->line_number, line_buffer, 0);
1574 if (!j)
1575 /*
1576 Error, no include file "name" encoded.
1577 */
1578 my_error (ERR_MALFORMED_INCLUDE, rc_files_table[rc_files]->filename,
1579 rc_files_table[rc_files]->line_number, line_buffer, 0);
1580 /*
1581 Now we have the name of include file and the mode of operation.
1582 */
1583 s7[j] = '\0';
1584 /*
1585 Before we have to manage this next include file,
1586 let's check for recursive/cyclic includes, which we MUST avoid!
1587 */
1588 for (i = 0; i <= rc_files; i++)
1589 {
1590 /*
1591 Check if any file buffered in `rc_files_table[]' is just included by this file.
1592 */
1593 if (*s7 == *rc_files_table[i]->filename)
1594 if (!strcmp (s7 + 1, rc_files_table[i]->filename + 1))
1595 /*
1596 Error, invalid recursive/cyclic include statement found.
1597 */
1598 my_error (ERR_CYCLIC_INCLUDE, rc_files_table[rc_files]->filename,
1599 rc_files_table[rc_files]->line_number, line_buffer, 0);
1600 }
1601 /*
1602 First or next include file, so we increment the counter
1603 of buffered files in `rc_files_table[]' by one first before we check
1604 the table size, because `rc_files' wasn't just postincremented
1605 */
1606 rc_files++;
1607 /*
1608 Now check if it's necessary to resize the `rc_files_table[]'.
1609 */
1610 if ((Uint) rc_files >= rc_files_max)
1611 {
1612 /*
1613 Resize the `rc_files_table[]' table.
1614 */
1615 rc_files_max <<= 1;
1616 if (rc_elems_max * sizeof (File_struct *) > testval)
1617 rc_files_max--;
1618 rc_files_table = (File_struct **) my_realloc ((VOID_PTR) rc_files_table,
1619 rc_files_max *
1620 sizeof (File_struct *),
1621 ERR_NO_MEMORY_AVAILABLE,
1622 __FILE__,
1623 ((long) __LINE__) - 3L,
1624 "rc_files_table[rc_files_max]",
1625 rc_files_max);
1626 }
1627 /*
1628 Allocate the file buffers for an include file.
1629 */
1630 rc_files_table[rc_files] = (File_struct *) my_malloc (sizeof (File_struct),
1631 ERR_NO_MEMORY_AVAILABLE,
1632 __FILE__,
1633 ((long) __LINE__) -
1634 2L,
1635 "rc_files_table[rc_files]",
1636 rc_files);
1637 rc_files_table[rc_files]->filename =
1638 (char *) my_malloc (j + 1, ERR_NO_MEMORY_AVAILABLE, __FILE__,
1639 ((long) __LINE__) - 2L,
1640 "rc_files_table[rc_files]->filename", rc_files);
1641 strcpy (rc_files_table[rc_files]->filename, s7);
1642 /*
1643 Try to open it.
1644 */
1645 rc_files_table[rc_files]->fp =
1646 file_open (&rc_files_table[rc_files]->filename, rc_files,
1647 (is_usr_file) ? USr_include : SYs_include, &bad_sys_include);
1648 if (bad_sys_include)
1649 /*
1650 Error, invalid root directory based system include file name found
1651 in the include statement, e.g.: #include </foo> or #include </foo/bar>.
1652 */
1653 my_error (ERR_MALFORMED_INCLUDE, rc_files_table[rc_files - 1]->filename,
1654 rc_files_table[rc_files - 1]->line_number, line_buffer, 0);
1655 /*
1656 If include file exists, read it.
1657 */
1658 if (rc_files_table[rc_files]->fp != (FILE *) NULL)
1659 {
1660 rc_files_table[rc_files]->in_pool = 0;
1661 rc_files_table[rc_files]->line_number = 0L;
1662 rc_files_table[rc_files]->pool = (char *) my_malloc (BUF_LEN + 1,
1663 ERR_NO_MEMORY_AVAILABLE,
1664 __FILE__,
1665 ((long) __LINE__) -
1666 2L,
1667 "rc_files_table[rc_files]->pool",
1668 rc_files);
1669 /*
1670 Buffer all local date variables of the include file.
1671 */
1672 for (i = 0; i < RC_DVAR_MAX; i++)
1673 {
1674 rc_files_table[rc_files]->local_dvars[i].dvar_month =
1675 rc_dvar[i].dvar_local.dvar_month;
1676 rc_files_table[rc_files]->local_dvars[i].dvar_day =
1677 rc_dvar[i].dvar_local.dvar_day;
1678 }
1679 /*
1680 Buffer all local text variables of the include file.
1681 */
1682 for (i = 0; i < RC_TVAR_MAX; i++)
1683 {
1684 if (rc_tvar[i].tvar_local.tvar_text != (char *) NULL)
1685 {
1686 rc_files_table[rc_files]->local_tvars[i].tvar_text
1687 =
1688 (char *) my_malloc (strlen (rc_tvar[i].tvar_local.tvar_text) +
1689 1, ERR_NO_MEMORY_AVAILABLE, __FILE__,
1690 ((long) __LINE__) - 2L,
1691 "rc_tvar[i].tvar_local.tvar_text", i);
1692 strcpy (rc_files_table[rc_files]->local_tvars[i].tvar_text,
1693 rc_tvar[i].tvar_local.tvar_text);
1694 }
1695 else
1696 rc_files_table[rc_files]->local_tvars[i].tvar_text =
1697 (char *) NULL;
1698 }
1699 while ((rc_files_table[rc_files]->ptr_pool =
1700 file_read_line (rc_files_table[rc_files]->fp, &line_buffer,
1701 &rc_files_table[rc_files]->in_pool,
1702 rc_files_table[rc_files]->pool,
1703 rc_files_table[rc_files]->ptr_pool,
1704 rc_files_table[rc_files]->filename,
1705 &rc_files_table[rc_files]->line_number,
1706 &line_length, REsource, &is_include, &is_dvar,
1707 &is_tvar)) != (char *) NULL)
1708 /*
1709 Check whether an "#include" statement is found.
1710 */
1711 if (is_include)
1712 /*
1713 Ok, let's manage a next include file by calling this function recursively.
1714 */
1715 try_to_include_file (ed, wd);
1716 else
1717 /*
1718 We are still in the actual include file.
1719 */
1720 if (*line_buffer && !is_dvar && !is_tvar)
1721 rc_check (line_buffer, rc_files_table[rc_files]->filename,
1722 rc_files_table[rc_files]->line_number, line_length,
1723 &rc_elems, day, ed, wd);
1724 (void) fclose (rc_files_table[rc_files]->fp);
1725 free (rc_files_table[rc_files]->pool);
1726 /*
1727 Restore all local date variables of the include file.
1728 */
1729 for (i = 0; i < RC_DVAR_MAX; i++)
1730 {
1731 rc_dvar[i].dvar_local.dvar_month =
1732 rc_files_table[rc_files]->local_dvars[i].dvar_month;
1733 rc_dvar[i].dvar_local.dvar_day =
1734 rc_files_table[rc_files]->local_dvars[i].dvar_day;
1735 }
1736 /*
1737 Restore all local text variables of the include file.
1738 */
1739 for (i = 0; i < RC_TVAR_MAX; i++)
1740 if (rc_files_table[rc_files]->local_tvars[i].tvar_text !=
1741 (char *) NULL)
1742 {
1743 if (rc_tvar[i].tvar_local.tvar_text == (char *) NULL)
1744 rc_tvar[i].tvar_local.tvar_text
1745 =
1746 (char *)
1747 my_malloc (strlen
1748 (rc_files_table[rc_files]->local_tvars[i].
1749 tvar_text) + 1, ERR_NO_MEMORY_AVAILABLE, __FILE__,
1750 ((long) __LINE__) - 2L,
1751 "rc_tvar[i].tvar_local.tvar_text", i);
1752 else
1753 rc_tvar[i].tvar_local.tvar_text
1754 =
1755 (char *)
1756 my_realloc ((VOID_PTR) (rc_tvar[i].tvar_local.tvar_text),
1757 strlen (rc_files_table[rc_files]->local_tvars[i].
1758 tvar_text) + 1, ERR_NO_MEMORY_AVAILABLE,
1759 __FILE__, ((long) __LINE__) - 3L,
1760 "rc_tvar[i].tvar_local.tvar_text", i);
1761 strcpy (rc_tvar[i].tvar_local.tvar_text,
1762 rc_files_table[rc_files]->local_tvars[i].tvar_text);
1763 free (rc_files_table[rc_files]->local_tvars[i].tvar_text);
1764 rc_files_table[rc_files]->local_tvars[i].tvar_text =
1765 (char *) NULL;
1766 }
1767 }
1768 /*
1769 Now deallocate the include file buffers.
1770 */
1771 free (rc_files_table[rc_files]->filename);
1772 free (rc_files_table[rc_files]);
1773 /*
1774 And back to the previous include file resp., main resource file.
1775 */
1776 rc_files--;
1777 }
1778
1779
1780
1781 static void
display_table(tmp_ad,tmp_am,tmp_ay,day,ed,wd)1782 display_table (tmp_ad, tmp_am, tmp_ay, day, ed, wd)
1783 const int tmp_ad;
1784 const int tmp_am;
1785 const int tmp_ay;
1786 int day;
1787 int ed;
1788 int wd;
1789 /*!
1790 Displays all entries in `rc_elems_table[]' in sorted order.
1791 */
1792 {
1793 register int n;
1794 register int i;
1795 register int j = 0;
1796 register int tindex = 0;
1797 auto int ld = 0;
1798 auto int lm = 0;
1799 auto int ly = 0;
1800 auto int dd = 0;
1801 auto int mm = 0;
1802 auto int yy = 0;
1803 auto int i_dummy;
1804 auto char c_dummy;
1805 auto Bool b_dummy;
1806 auto Bool ok;
1807
1808
1809 rc_zero_pos = rc_elems;
1810 /*
1811 If `rc_all_dates_flag' or `rc_zero_dates_flag' is set, complete the
1812 contents of `rc_elems_table[]', i.e., generate "empty" texts for
1813 each day in the requested period.
1814 */
1815 if (rc_all_dates_flag || rc_zero_dates_flag)
1816 {
1817 register int rc_e = rc_zero_pos;
1818
1819
1820 /*
1821 Lets sort ascending first only in case `rc_elems_table[]' isn't presorted!
1822 */
1823 if ((rc_elems > 1) && !is_presorted (rc_elems_table, rc_elems))
1824 qsort ((VOID_PTR) rc_elems_table, rc_elems, sizeof *rc_elems_table,
1825 (Cmp_func) asc_sort);
1826 if (rc_elems)
1827 (void) rc_get_date (rc_elems_table[j], lineptrs, FALSE, &b_dummy, &ld,
1828 &lm, &ly, &i_dummy, &i_dummy, &c_dummy, &i_dummy,
1829 &i_dummy, _("Internal"), (long) j,
1830 rc_elems_table[j], TRUE);
1831 /*
1832 Correction for the respected period if we are in fiscal year mode.
1833 */
1834 if ((fiscal_month > MONTH_MIN) && !adate_set)
1835 {
1836 day = mvec[fiscal_month - 1] + 1;
1837 if (fiscal_month > 2)
1838 day += is_leap_year;
1839 }
1840 /*
1841 Let's produce the dummy entries ("empty" fixed dates)...
1842 */
1843 for (i = day; i < ed; i++)
1844 {
1845 yy = year;
1846 ok = doy2date (i, is_leap_year, &dd, &mm);
1847 if (!ok)
1848 {
1849 if (rc_tomorrow_flag || rc_week_flag)
1850 {
1851 if (i < DAY_MIN)
1852 {
1853 yy = year - 1;
1854 if (yy < YEAR_MIN)
1855 break;
1856 n = (days_of_february (yy) == 29);
1857 (void) doy2date (DAY_LAST + n + i, n, &dd, &mm);
1858 }
1859 else if (i > DAY_LAST + is_leap_year)
1860 {
1861 yy = year + 1;
1862 if (yy > YEAR_MAX)
1863 break;
1864 n = (days_of_february (yy) == 29);
1865 (void) doy2date (i - (DAY_LAST + is_leap_year), n, &dd,
1866 &mm);
1867 }
1868 }
1869 else
1870 break;
1871 }
1872 if (j == rc_e
1873 || mm < lm
1874 || yy < ly || ((dd < ld) && (mm <= lm) && (yy <= ly)))
1875 {
1876 sprintf (line_buffer, "%0*d%02d%02d ", len_year_max, yy, mm,
1877 dd);
1878 rc_check (line_buffer, _("`Internal'"), (long) tindex,
1879 strlen (line_buffer), &rc_elems, day, ed, wd);
1880 }
1881 else
1882 while ((dd == ld) && (mm == lm) && (yy == ly))
1883 if (j + 1 < rc_e)
1884 {
1885 j++;
1886 (void) rc_get_date (rc_elems_table[j], lineptrs, FALSE,
1887 &b_dummy, &ld, &lm, &ly, &i_dummy,
1888 &i_dummy, &c_dummy, &i_dummy, &i_dummy,
1889 _("Internal"), (long) j,
1890 rc_elems_table[j], TRUE);
1891 }
1892 else
1893 {
1894 j++;
1895 break;
1896 }
1897 }
1898 /*
1899 Respect fiscal year mode.
1900 */
1901 if ((fiscal_month > MONTH_MIN) && (year < YEAR_MAX) && !adate_set)
1902 {
1903 /*
1904 Correction for the respected period.
1905 */
1906 day = DAY_MIN;
1907 yy = year + 1;
1908 is_leap_year = (days_of_february (yy) == 29);
1909 if (fiscal_month < MONTH_MAX)
1910 ed = day_of_year (DAY_MIN, fiscal_month + 1, yy) + 1;
1911 else
1912 ed = DAY_LAST + is_leap_year + 1;
1913 /*
1914 Let's produce the dummy entries ("empty" fixed dates)...
1915 */
1916 for (i = day; i < ed; i++)
1917 {
1918 ok = doy2date (i, is_leap_year, &dd, &mm);
1919 if (!ok)
1920 break;
1921 if (j == rc_e
1922 || mm < lm
1923 || yy < ly || ((dd < ld) && (mm <= lm) && (yy <= ly)))
1924 {
1925 sprintf (line_buffer, "%0*d%02d%02d ", len_year_max, yy, mm,
1926 dd);
1927 rc_check (line_buffer, _("`Internal'"), (long) tindex,
1928 strlen (line_buffer), &rc_elems, day, ed, wd);
1929 }
1930 else
1931 while ((dd == ld) && (mm == lm) && (yy == ly))
1932 if (j + 1 < rc_e)
1933 {
1934 j++;
1935 (void) rc_get_date (rc_elems_table[j], lineptrs, FALSE,
1936 &b_dummy, &ld, &lm, &ly, &i_dummy,
1937 &i_dummy, &c_dummy, &i_dummy,
1938 &i_dummy, _("Internal"), (long) j,
1939 rc_elems_table[j], TRUE);
1940 }
1941 else
1942 {
1943 j++;
1944 break;
1945 }
1946 }
1947 }
1948 is_leap_year = (days_of_february (year) == 29);
1949 }
1950 if ((rc_zero_dates_flag
1951 && (rc_elems - rc_zero_pos)) || (!rc_zero_dates_flag && rc_elems))
1952 {
1953 register int tstart;
1954 register int tend;
1955 register int skipped;
1956 register int len_rce = 0;
1957 register int len_line;
1958 register int len_fn_part;
1959 register int len_text_part;
1960 register int hls_len = 0;
1961 auto char *ptr_char;
1962 auto Bool same_date = FALSE;
1963 auto Bool ok2;
1964
1965
1966 /*
1967 At last, sort the fixed dates only if they are either not presorted
1968 or contain no resource file name reference, and not ONLY "empty"
1969 fixed dates shall be displayed.
1970 */
1971 if (!rc_zero_dates_flag && (rc_elems > 1))
1972 {
1973 if (rc_enable_fn_flag)
1974 {
1975 if (rc_sort_des_flag)
1976 qsort ((VOID_PTR) rc_elems_table, rc_elems,
1977 sizeof *rc_elems_table, (Cmp_func) fn_des_sort);
1978 else
1979 qsort ((VOID_PTR) rc_elems_table, rc_elems,
1980 sizeof *rc_elems_table, (Cmp_func) fn_asc_sort);
1981 }
1982 else if (!is_presorted (rc_elems_table, rc_elems))
1983 {
1984 if (rc_sort_des_flag)
1985 qsort ((VOID_PTR) rc_elems_table, rc_elems,
1986 sizeof *rc_elems_table, (Cmp_func) des_sort);
1987 else
1988 qsort ((VOID_PTR) rc_elems_table, rc_elems,
1989 sizeof *rc_elems_table, (Cmp_func) asc_sort);
1990 }
1991 else if (rc_sort_des_flag)
1992 /*
1993 `rc_elems_table[]' is presorted and must be shown in
1994 descending sort order, rearrange its internal sort
1995 order from ascending to descending sort order.
1996 */
1997 reverse_order (rc_elems_table, rc_elems);
1998 }
1999 d = tmp_ad;
2000 m = tmp_am;
2001 /*
2002 Copy `rc_grp_sep' [-c]g[] to text buffer variable `s3' for further use,
2003 which will be first evaluated for text variable references and
2004 some special texts. Thereafter, perform the '~'-TILDE or '^'-CARET
2005 expansion on the one hand.
2006 */
2007 if (rc_grp_sep != (char *) NULL)
2008 {
2009 register int x1 = year;
2010 register int x2 = incr_year;
2011 register int x3 = decr_year;
2012
2013
2014 year = act_year;
2015 incr_year = decr_year = 0;
2016 insert_line_into_table (rc_grp_sep, _("`Internal'"),
2017 (long) SPECIAL_VALUE, &rc_elems, 1, 1);
2018 decr_year = x3;
2019 incr_year = x2;
2020 year = x1;
2021 i = (int) strlen (rc_elems_table[--rc_elems]);
2022 if ((Uint) i >= maxlen_max)
2023 resize_all_strings (i + 1, FALSE, __FILE__, (long) __LINE__);
2024 strcpy (s3, rc_elems_table[rc_elems] + len_year_max + 5);
2025 free (rc_elems_table[rc_elems]);
2026 ptr_char = s3;
2027 if (*ptr_char)
2028 {
2029 /*
2030 A text for grouping is defined.
2031 */
2032 i = 0;
2033 while (*ptr_char)
2034 {
2035 switch (*ptr_char)
2036 {
2037 case RC_NL_CHAR:
2038 case RC_NL2_CHAR:
2039 if (i)
2040 {
2041 /*
2042 RC_NL[2]_CHAR is single `\~' or `\^' quoted
2043 or double `\\~' or `\\^' quoted:
2044 Replace QUOTE_CHAR by RC_NL[2]_CHAR resp.,
2045 replace last QUOTE_CHAR by RC_NL_CHAR.
2046 */
2047 if (s3[i - 1] == QUOTE_CHAR)
2048 s3[i - 1] = *ptr_char;
2049 else
2050 /*
2051 RC_NL[2]_CHAR is not quoted '~' or '^':
2052 Insert a real `\n'-NEWLINE character.
2053 */
2054 s3[i++] = '\n';
2055 }
2056 else
2057 /*
2058 RC_NL[2]_CHAR is not quoted '~' or '^':
2059 Insert a real `\n'-NEWLINE character.
2060 */
2061 s3[i++] = '\n';
2062 break;
2063 case QUOTE_CHAR:
2064 ptr_char++;
2065 if (*ptr_char)
2066 {
2067 if (*ptr_char == RC_NL_CHAR
2068 || *ptr_char == RC_NL2_CHAR)
2069 s3[i++] = *ptr_char;
2070 else
2071 {
2072 s3[i++] = QUOTE_CHAR;
2073 s3[i++] = *ptr_char;
2074 }
2075 }
2076 else
2077 s3[i++] = QUOTE_CHAR;
2078 break;
2079 default:
2080 s3[i++] = *ptr_char;
2081 }
2082 ptr_char++;
2083 }
2084 s3[i] = '\0';
2085 }
2086 }
2087 (*s1) = (*s6) = '\0';
2088 /*
2089 Now display a leading NEWLINE character before the text/title.
2090 */
2091 if (!rc_suppr_list_sep_flag)
2092 print_text (stdout, s1);
2093 /*
2094 Now display the leading title/heading text of the fixed date list,
2095 which will be first evaluated for text variable references and
2096 some special texts. Thereafter, perform the '~'-TILDE or '^'-CARET
2097 expansion on the one hand.
2098 */
2099 if (rc_title_flag)
2100 {
2101 register int x1 = year;
2102 register int x2 = incr_year;
2103 register int x3 = decr_year;
2104
2105
2106 year = act_year;
2107 incr_year = decr_year = 0;
2108 insert_line_into_table (rc_heading_text, _("`Internal'"),
2109 (long) SPECIAL_VALUE, &rc_elems, 1, 1);
2110 decr_year = x3;
2111 incr_year = x2;
2112 year = x1;
2113 i = (int) strlen (rc_elems_table[--rc_elems]);
2114 if ((Uint) i >= maxlen_max)
2115 resize_all_strings (i + 1, FALSE, __FILE__, (long) __LINE__);
2116 strcpy (s1, rc_elems_table[rc_elems] + len_year_max + 5);
2117 free (rc_elems_table[rc_elems]);
2118 ptr_char = s1;
2119 i = 0;
2120 while (*ptr_char)
2121 {
2122 switch (*ptr_char)
2123 {
2124 case RC_NL_CHAR:
2125 case RC_NL2_CHAR:
2126 if (i)
2127 {
2128 /*
2129 RC_NL[2]_CHAR is single `\~' or `\^' quoted
2130 or double `\\~' `\\^' quoted:
2131 Replace QUOTE_CHAR by RC_NL[2]_CHAR resp.,
2132 replace last QUOTE_CHAR by RC_NL[2]_CHAR.
2133 */
2134 if (s1[i - 1] == QUOTE_CHAR)
2135 s1[i - 1] = *ptr_char;
2136 else
2137 /*
2138 RC_NL[2]_CHAR is not quoted '~' or '^':
2139 Insert a real `\n'-NEWLINE character.
2140 */
2141 s1[i++] = '\n';
2142 }
2143 else
2144 /*
2145 RC_NL[2]_CHAR is not quoted '~' or '^':
2146 Insert a real `\n'-NEWLINE character.
2147 */
2148 s1[i++] = '\n';
2149 break;
2150 case QUOTE_CHAR:
2151 ptr_char++;
2152 if (*ptr_char)
2153 {
2154 if (*ptr_char == RC_NL_CHAR || *ptr_char == RC_NL2_CHAR)
2155 s1[i++] = *ptr_char;
2156 else
2157 {
2158 s1[i++] = QUOTE_CHAR;
2159 s1[i++] = *ptr_char;
2160 }
2161 }
2162 else
2163 s1[i++] = QUOTE_CHAR;
2164 break;
2165 default:
2166 s1[i++] = *ptr_char;
2167 }
2168 ptr_char++;
2169 }
2170 s1[i] = '\0';
2171 print_text (stdout, s1);
2172 print_text (stdout, s1);
2173 }
2174 /*
2175 Detect the number of digits of `rc_elems'.
2176 */
2177 sprintf (s2, "%d",
2178 (rc_zero_dates_flag) ? rc_elems - rc_zero_pos : rc_elems);
2179 len_rce = (int) strlen (s2);
2180 /*
2181 Initialize the variables which control the loop.
2182 */
2183 skipped = tstart = 0;
2184 tend = rc_elems - 1;
2185 if (rc_zero_dates_flag)
2186 {
2187 if (rc_sort_des_flag)
2188 {
2189 tstart = rc_elems - 1;
2190 tend = rc_zero_pos;
2191 skipped = rc_elems + 1;
2192 }
2193 else
2194 skipped = tstart = rc_zero_pos;
2195 }
2196 /*
2197 Now initialize the loop counter.
2198 */
2199 tindex = tstart;
2200 /*
2201 And display all fixed dates of `rc_elems_table[]'.
2202 */
2203 LOOP
2204 {
2205 lineptrs =
2206 rc_get_date (rc_elems_table[tindex], lineptrs, FALSE, &b_dummy,
2207 &day, &lm, &ly, &i_dummy, &i_dummy, &c_dummy, &i_dummy,
2208 &i_dummy, _("Internal"), (long) tindex,
2209 rc_elems_table[tindex], TRUE);
2210 if ((tindex == tstart)
2211 && (rc_omit_date_flag
2212 || rc_alternative_format_flag || rc_grp_sep != (char *) NULL))
2213 {
2214 dd = day;
2215 mm = lm;
2216 yy = ly;
2217 }
2218 /*
2219 Avoid displaying duplicate resource file entries by storing
2220 the actual entry into `s6' and comparing it with the previous
2221 entry in line.
2222 */
2223 if (tindex == tstart
2224 || ((tindex != tstart) && strcmp (s6, rc_elems_table[tindex])))
2225 {
2226 strcpy (s6, rc_elems_table[tindex]);
2227 /*
2228 Now display fixed date list group separator resp.,
2229 detect if date of text differs from previous text.
2230 */
2231 if (rc_omit_date_flag
2232 || rc_alternative_format_flag || rc_grp_sep != (char *) NULL)
2233 {
2234 if ((day == dd) && (lm == mm) && (ly == yy))
2235 {
2236 /*
2237 Same date:
2238 Avoid displaying of group separator.
2239 */
2240 if (tindex != tstart)
2241 same_date = TRUE;
2242 }
2243 else
2244 {
2245 /*
2246 Date differs.
2247 */
2248 same_date = FALSE;
2249 dd = day;
2250 mm = lm;
2251 yy = ly;
2252 if (rc_grp_sep != (char *) NULL)
2253 {
2254 /*
2255 Display constructed group separator text `-cg[TEXT]'.
2256 */
2257 strcpy (s2, s3);
2258 print_text (stdout, s2);
2259 }
2260 }
2261 }
2262 /*
2263 Construct the leading (partitially highlighted) "date"-part of the fixed date.
2264 */
2265 if (rc_week_number_flag)
2266 {
2267 j = week_number (day, lm, ly, iso_week_number, start_day);
2268 /*
2269 We convert the computed week number to a week number text
2270 (this looks nicer in output).
2271 */
2272 if (j < 0)
2273 /*
2274 Week starts in previous year and the first days
2275 of the actual year are not in its first week.
2276 */
2277 sprintf (s7, "|%02d/0|", -j);
2278 else if (!j)
2279 /*
2280 Week starts in previous year and the first days
2281 of the actual year are in its first week.
2282 */
2283 sprintf (s7, "|%s|", "53/1");
2284 else
2285 /*
2286 Week starts in actual year.
2287 */
2288 sprintf (s7, "|%02d|", j);
2289 if (!rc_alternative_format_flag)
2290 {
2291 if (strlen (s7) > 4)
2292 {
2293 if (rc_count_flag)
2294 sprintf (s1, "%0*d) %s ", len_rce,
2295 abs ((tindex - skipped) + 1), s7);
2296 else
2297 sprintf (s1, "%s ", s7);
2298 }
2299 else if (rc_count_flag)
2300 sprintf (s1, "%0*d) %s%*s ", len_rce,
2301 abs ((tindex - skipped) + 1), s7, len_fil_wt,
2302 "");
2303 else
2304 sprintf (s1, "%s%*s ", s7, len_fil_wt, "");
2305 }
2306 }
2307 else if (!rc_alternative_format_flag && rc_count_flag)
2308 sprintf (s1, "%0*d) ", len_rce, abs ((tindex - skipped) + 1));
2309 wd = day;
2310 ld = day_of_year (day, lm, ly);
2311 if (!rc_both_dates_flag)
2312 {
2313 if (!rc_special_flag)
2314 ld = 0;
2315 else
2316 day = 0;
2317 }
2318 if (!rc_suppr_date_part_flag)
2319 {
2320 if ((ly == tmp_ay) && (lm == tmp_am) && (wd == tmp_ad))
2321 hls_len =
2322 decode_date_format (date_format->df_format, &s1, day, lm,
2323 ly, ld, TRUE, FALSE,
2324 !rc_alternative_format_flag);
2325 else
2326 {
2327 if (hd_ldays[((lm - 1) * MONTH_LAST) + (wd - 1)])
2328 hls_len =
2329 decode_date_format (date_format->df_format, &s1, day,
2330 lm, ly, ld, FALSE, TRUE,
2331 !rc_alternative_format_flag);
2332 else
2333 hls_len =
2334 decode_date_format (date_format->df_format, &s1, day,
2335 lm, ly, ld, FALSE, FALSE,
2336 !rc_alternative_format_flag);
2337 }
2338 if (rc_alternative_format_flag && rc_week_number_flag)
2339 {
2340 sprintf (s2, _(" ; Week %s"), s7);
2341 }
2342 else
2343 *s2 = '\0';
2344 }
2345 else
2346 {
2347 if (rc_alternative_format_flag && rc_week_number_flag)
2348 {
2349 sprintf (s2, _("Week %s"), s7);
2350 }
2351 else
2352 *s2 = '\0';
2353 }
2354 if (*s2 || !rc_suppr_date_part_flag)
2355 {
2356 strcat (s2, ":");
2357 strcat (s1, s2);
2358 }
2359 j = (int) strlen (s1) - hls_len;
2360 /*
2361 Skip the separating whitespace character between
2362 the "date"-part and the "text"-part.
2363 */
2364 if (*lineptrs->text_part == ' ')
2365 lineptrs->text_part++;
2366 /*
2367 Construct the "text"-part of the fixed date.
2368 */
2369 len_text_part = (int) strlen (lineptrs->text_part);
2370 if (rc_alternative_format_flag)
2371 {
2372 if (!same_date && *s1)
2373 /*
2374 Print the constructed date on a separate line
2375 only if it appears the first time!
2376 */
2377 print_text (stdout, s1);
2378 if (rc_count_flag)
2379 {
2380 sprintf (s1, "%0*d)", len_rce,
2381 abs ((tindex - skipped) + 1));
2382 if (len_text_part)
2383 strcat (s1, " ");
2384 }
2385 else
2386 *s1 = '\0';
2387 j = len_line = (int) strlen (s1);
2388 }
2389 else
2390 len_line = j + hls_len + (int) !rc_suppr_date_part_flag;
2391 /*
2392 Now check if it's necessary to modify the "text"-part of the fixed date.
2393 */
2394 ok = FALSE;
2395 len_fn_part = 0;
2396 /*
2397 "Empty" texts have no trailing blank character!
2398 */
2399 if (len_text_part)
2400 {
2401 if (!rc_alternative_format_flag && !rc_suppr_date_part_flag)
2402 strcat (s1, " ");
2403 /*
2404 Get the textual length of the file name,
2405 which has been inserted into the line.
2406 */
2407 if (rc_enable_fn_flag)
2408 {
2409 auto Bool pseudo_quote_found = FALSE;
2410
2411
2412 /*
2413 Add the length of the "file name"+3 (+3 because the file
2414 name itself is leaded by a blank character and is
2415 enclosed in PSEUDO_QUOTE characters to the number of
2416 leading blanks, which must be displayed if the line
2417 wrapped by a given `~'-TILDE.
2418 */
2419 ptr_char = lineptrs->text_part;
2420 while (*ptr_char)
2421 {
2422 len_fn_part++;
2423 if (*ptr_char == PSEUDO_QUOTE)
2424 {
2425 if (!pseudo_quote_found)
2426 pseudo_quote_found = TRUE;
2427 else
2428 break;
2429 }
2430 ptr_char++;
2431 }
2432 if (!*ptr_char)
2433 /*
2434 Internal error, a maintainer has modified the internal
2435 format of a line and forgots to respect this
2436 modification here!
2437 */
2438 my_error (ERR_MAINTAINER_FAILURE, __FILE__,
2439 (long) __LINE__, "", 0);
2440 c_dummy = *++ptr_char;
2441 if (*ptr_char)
2442 {
2443 len_line++;
2444 ptr_char++;
2445 c_dummy = *ptr_char;
2446 *ptr_char = '\0';
2447 }
2448 strcat (s1, lineptrs->text_part);
2449 i = len_fn_part;
2450 len_line += i;
2451 if (c_dummy)
2452 {
2453 *ptr_char = c_dummy;
2454 i++;
2455 j += (int) !rc_alternative_format_flag;
2456 }
2457 len_text_part -= i;
2458 lineptrs->text_part += i;
2459 /*
2460 Now exchange the first two PSEUDO_QUOTE characters
2461 -- which embrace the "file name" -- by parentheses.
2462 */
2463 ptr_char = strchr (s1, PSEUDO_QUOTE);
2464 if (ptr_char == (char *) NULL)
2465 /*
2466 Internal error, a maintainer has modified the internal
2467 format of a line and forgots to respect this
2468 modification here!
2469 */
2470 my_error (ERR_MAINTAINER_FAILURE, __FILE__,
2471 (long) __LINE__, "", 0);
2472 *ptr_char = '(';
2473 ptr_char = strchr (s1, PSEUDO_QUOTE);
2474 if (ptr_char == (char *) NULL)
2475 /*
2476 Internal error, a maintainer has modified the internal
2477 format of a line and forgots to respect this
2478 modification here!
2479 */
2480 my_error (ERR_MAINTAINER_FAILURE, __FILE__,
2481 (long) __LINE__, "", 0);
2482 *ptr_char = ')';
2483 /*
2484 Check if the FIRST character of the REAL "text"-part was a quoted
2485 whitespace character (this is indicated by a PSEUDO_QUOTE
2486 character ('\001') followed by a "whitespace" character,
2487 see `rc-check.c'). If this case is TRUE, skip the PSEUDO_QUOTE.
2488 */
2489 if (*lineptrs->text_part)
2490 if ((*lineptrs->text_part == PSEUDO_QUOTE)
2491 && isspace (lineptrs->text_part[1]))
2492 {
2493 lineptrs->text_part++;
2494 len_text_part--;
2495 }
2496 }
2497 else
2498 {
2499 /*
2500 Check if the FIRST character of the "text"-part was a quoted
2501 whitespace character (this is indicated by a PSEUDO_QUOTE
2502 character ('\001') followed by a "whitespace" character,
2503 see `rc-check.c'). If this case is TRUE, skip the PSEUDO_QUOTE.
2504 */
2505 if ((*lineptrs->text_part == PSEUDO_QUOTE)
2506 && isspace (lineptrs->text_part[1]))
2507 {
2508 lineptrs->text_part++;
2509 len_text_part--;
2510 }
2511 }
2512 ok =
2513 (Bool) (strchr (lineptrs->text_part, RC_NL_CHAR) ==
2514 (char *) NULL);
2515 ok2 =
2516 (Bool) (strchr (lineptrs->text_part, RC_NL2_CHAR) ==
2517 (char *) NULL);
2518 if (ok && ok2)
2519 {
2520 if (*lineptrs->text_part)
2521 {
2522 if ((Uint) len_line + len_text_part >= maxlen_max)
2523 resize_all_strings (len_line + len_text_part + 1,
2524 FALSE, __FILE__,
2525 (long) __LINE__);
2526 strcat (s1, lineptrs->text_part);
2527 }
2528 }
2529 else
2530 {
2531 /*
2532 `~'-TILDE, `^'-CARET or quoted `\~'-TILDE resp., CARET found
2533 in "text"-part of fixed date:
2534 Quote TILDE/CARET resp., insert a real `\n'-NEWLINE character
2535 */
2536 while (*lineptrs->text_part)
2537 {
2538 if ((Uint) len_line >= maxlen_max)
2539 resize_all_strings (maxlen_max << 1, FALSE,
2540 __FILE__, (long) __LINE__);
2541 if (*lineptrs->text_part == RC_NL_CHAR)
2542 {
2543 /*
2544 RC_NL_CHAR is single `\~' quoted
2545 or double `\\~' quoted:
2546 Replace QUOTE_CHAR by RC_NL_CHAR resp.,
2547 replace last QUOTE_CHAR by RC_NL_CHAR.
2548 */
2549 if (s1[len_line - 1] == QUOTE_CHAR)
2550 s1[len_line - 1] = *lineptrs->text_part;
2551 else
2552 {
2553 /*
2554 RC_NL_CHAR is not quoted '~':
2555 Insert a real `\n'_NEWLINE character.
2556 */
2557 s1[len_line++] = '\n';
2558 /*
2559 Insert some leading blanks.
2560 */
2561 if (rc_alternative_format_flag
2562 && !rc_enable_fn_flag)
2563 n = j;
2564 else
2565 {
2566 n = j + len_fn_part + 1;
2567 if (!rc_alternative_format_flag)
2568 n -= (int) rc_suppr_date_part_flag;
2569 }
2570 for (i = 0; i < n; i++)
2571 {
2572 if ((Uint) len_line >= maxlen_max)
2573 resize_all_strings (maxlen_max << 1,
2574 FALSE, __FILE__,
2575 (long) __LINE__);
2576 s1[len_line++] = ' ';
2577 }
2578 }
2579 }
2580 else if (*lineptrs->text_part == RC_NL2_CHAR)
2581 {
2582 /*
2583 RC_NL2_CHAR is single `\^' quoted
2584 or double `\\^' quoted:
2585 Replace QUOTE_CHAR by RC_NL2_CHAR resp.,
2586 replace last QUOTE_CHAR by RC_NL2_CHAR.
2587 */
2588 if (s1[len_line - 1] == QUOTE_CHAR)
2589 s1[len_line - 1] = *lineptrs->text_part;
2590 else
2591 /*
2592 RC_NL2_CHAR is not quoted '^':
2593 Insert a real `\n'_NEWLINE character only!
2594 */
2595 s1[len_line++] = '\n';
2596 }
2597 else
2598 s1[len_line++] = *lineptrs->text_part;
2599 lineptrs->text_part++;
2600 }
2601 s1[len_line] = '\0';
2602 }
2603 }
2604 if (rc_omit_date_flag && !rc_alternative_format_flag && same_date)
2605 {
2606 /*
2607 Overwrite leading "date"-part of output with blanks.
2608 */
2609 if (rc_count_flag)
2610 i = len_rce + 3; /* +3 because of the ") " text */
2611 else
2612 i = 0;
2613 n = j - (int) rc_suppr_date_part_flag;
2614 for (; i < n; i++)
2615 s1[i] = ' ';
2616 ptr_char = s1 + j + hls_len;
2617 for (i = j; *ptr_char; i++)
2618 s1[i] = *ptr_char++;
2619 s1[i] = '\0';
2620 }
2621 /*
2622 Now we display the constructed fixed date text.
2623 */
2624 if (!rc_alternative_format_flag || len_text_part || len_line)
2625 print_text (stdout, s1);
2626 }
2627 else
2628 skipped++;
2629 /*
2630 Now deallocate the just displayed/skipped fixed date in the table.
2631 */
2632 free (rc_elems_table[tindex]);
2633 /*
2634 Check if all fixed date entries are displayed.
2635 */
2636 if (tindex == tend)
2637 break;
2638 /*
2639 If not, increase/decrease the loop counter.
2640 */
2641 if (rc_zero_dates_flag && rc_sort_des_flag)
2642 tindex--;
2643 else
2644 tindex++;
2645 }
2646 }
2647 /*
2648 Now deallocate all NON-"empty" fixed dates in the table
2649 in case only "empty" fixed dates were displayed.
2650 */
2651 if (rc_zero_dates_flag && (rc_elems - rc_zero_pos))
2652 for (tindex = 0; tindex < rc_zero_pos; tindex++)
2653 free (rc_elems_table[tindex]);
2654 }
2655
2656
2657
2658 static int
fn_asc_sort(a,b)2659 fn_asc_sort (a, b)
2660 const char **a;
2661 const char **b;
2662 /*!
2663 The (q)sort compare function for fixed dates which texts
2664 have an included resource "file name"; ascending order.
2665 */
2666 {
2667 static Uint previous_len;
2668 static int i;
2669 static char *a_text;
2670 static char *b_text;
2671 static char *ptr_char;
2672 static Bool is_initialized = FALSE;
2673
2674
2675 /*
2676 Don't sort on the included resource "file name",
2677 sort on the REAL text of the fixed date O N L Y !!!
2678 */
2679 if (!is_initialized)
2680 {
2681 a_text = (char *) my_malloc (maxlen_max, ERR_NO_MEMORY_AVAILABLE,
2682 __FILE__, ((long) __LINE__) - 1L,
2683 "a_text", 0);
2684 b_text = (char *) my_malloc (maxlen_max, ERR_NO_MEMORY_AVAILABLE,
2685 __FILE__, ((long) __LINE__) - 1L,
2686 "b_text", 0);
2687 previous_len = maxlen_max;
2688 is_initialized = TRUE;
2689 }
2690 else if (previous_len < maxlen_max)
2691 {
2692 a_text = (char *) my_realloc ((VOID_PTR) a_text,
2693 maxlen_max, ERR_NO_MEMORY_AVAILABLE,
2694 __FILE__, ((long) __LINE__) - 2L,
2695 "a_text", maxlen_max);
2696 b_text = (char *) my_realloc ((VOID_PTR) b_text,
2697 maxlen_max, ERR_NO_MEMORY_AVAILABLE,
2698 __FILE__, ((long) __LINE__) - 2L,
2699 "b_text", maxlen_max);
2700 previous_len = maxlen_max;
2701 }
2702 i = len_year_max + 4;
2703 /*
2704 Copy the "date"-part AS IS.
2705 */
2706 strncpy (a_text, *a, i);
2707 a_text[i] = '\0';
2708 /*
2709 Skip the filename part.
2710 */
2711 if (*(*a + i + 1) != PSEUDO_QUOTE)
2712 /*
2713 Internal error, a maintainer has modified the internal format
2714 of a line and forgots to respect this modification here!
2715 */
2716 my_error (ERR_MAINTAINER_FAILURE, __FILE__, (long) __LINE__, "", 0);
2717 ptr_char = strchr (*a + i + 2, PSEUDO_QUOTE);
2718 if (ptr_char == (char *) NULL)
2719 /*
2720 Internal error, a maintainer has modified the internal format
2721 of a line and forgots to respect this modification here!
2722 */
2723 my_error (ERR_MAINTAINER_FAILURE, __FILE__, (long) __LINE__, "", 0);
2724 ptr_char++;
2725 /*
2726 And concatenate the "text"-part.
2727 */
2728 if (*ptr_char)
2729 strcat (a_text, ptr_char);
2730 /*
2731 Copy the "date"-part AS IS.
2732 */
2733 strncpy (b_text, *b, i);
2734 b_text[i] = '\0';
2735 /*
2736 Skip the filename part.
2737 */
2738 if (*(*b + i + 1) != PSEUDO_QUOTE)
2739 /*
2740 Internal error, a maintainer has modified the internal format
2741 of a line and forgots to respect this modification here!
2742 */
2743 my_error (ERR_MAINTAINER_FAILURE, __FILE__, (long) __LINE__, "", 0);
2744 ptr_char = strchr (*b + i + 2, PSEUDO_QUOTE);
2745 if (ptr_char == (char *) NULL)
2746 /*
2747 Internal error, a maintainer has modified the internal format
2748 of a line and forgots to respect this modification here!
2749 */
2750 my_error (ERR_MAINTAINER_FAILURE, __FILE__, (long) __LINE__, "", 0);
2751 ptr_char++;
2752 /*
2753 And concatenate the "text"-part.
2754 */
2755 if (*ptr_char)
2756 strcat (b_text, ptr_char);
2757
2758 return (strcmp (a_text, b_text));
2759 }
2760
2761
2762
2763 static int
fn_des_sort(a,b)2764 fn_des_sort (a, b)
2765 const char **a;
2766 const char **b;
2767 /*!
2768 The (q)sort compare function for fixed dates which texts
2769 have an included resource "file name"; descending order.
2770 */
2771 {
2772 static Uint previous_len;
2773 static int i;
2774 static char *a_text;
2775 static char *b_text;
2776 static char *ptr_char;
2777 static Bool is_initialized = FALSE;
2778
2779
2780 /*
2781 Don't sort on the included resource "file name",
2782 sort on the REAL text of the fixed date O N L Y !!!
2783 */
2784 if (!is_initialized)
2785 {
2786 a_text = (char *) my_malloc (maxlen_max, ERR_NO_MEMORY_AVAILABLE,
2787 __FILE__, ((long) __LINE__) - 1L,
2788 "a_text", 0);
2789 b_text = (char *) my_malloc (maxlen_max, ERR_NO_MEMORY_AVAILABLE,
2790 __FILE__, ((long) __LINE__) - 1L,
2791 "b_text", 0);
2792 previous_len = maxlen_max;
2793 is_initialized = TRUE;
2794 }
2795 else if (previous_len < maxlen_max)
2796 {
2797 a_text = (char *) my_realloc ((VOID_PTR) a_text,
2798 maxlen_max, ERR_NO_MEMORY_AVAILABLE,
2799 __FILE__, ((long) __LINE__) - 2L,
2800 "a_text", maxlen_max);
2801 b_text = (char *) my_realloc ((VOID_PTR) b_text,
2802 maxlen_max, ERR_NO_MEMORY_AVAILABLE,
2803 __FILE__, ((long) __LINE__) - 2L,
2804 "b_text", maxlen_max);
2805 previous_len = maxlen_max;
2806 }
2807 i = len_year_max + 4;
2808 /*
2809 Copy the "date"-part AS IS.
2810 */
2811 strncpy (a_text, *a, i);
2812 a_text[i] = '\0';
2813 /*
2814 Skip the filename part.
2815 */
2816 if (*(*a + i + 1) != PSEUDO_QUOTE)
2817 /*
2818 Internal error, a maintainer has modified the internal format
2819 of a line and forgots to respect this modification here!
2820 */
2821 my_error (ERR_MAINTAINER_FAILURE, __FILE__, (long) __LINE__, "", 0);
2822 ptr_char = strchr (*a + i + 2, PSEUDO_QUOTE);
2823 if (ptr_char == (char *) NULL)
2824 /*
2825 Internal error, a maintainer has modified the internal format
2826 of a line and forgots to respect this modification here!
2827 */
2828 my_error (ERR_MAINTAINER_FAILURE, __FILE__, (long) __LINE__, "", 0);
2829 ptr_char++;
2830 /*
2831 And concatenate the "text"-part.
2832 */
2833 if (*ptr_char)
2834 strcat (a_text, ptr_char);
2835 /*
2836 Copy the "date"-part AS IS.
2837 */
2838 strncpy (b_text, *b, i);
2839 b_text[i] = '\0';
2840 /*
2841 Skip the filename part.
2842 */
2843 if (*(*b + i + 1) != PSEUDO_QUOTE)
2844 /*
2845 Internal error, a maintainer has modified the internal format
2846 of a line and forgots to respect this modification here!
2847 */
2848 my_error (ERR_MAINTAINER_FAILURE, __FILE__, (long) __LINE__, "", 0);
2849 ptr_char = strchr (*b + i + 2, PSEUDO_QUOTE);
2850 if (ptr_char == (char *) NULL)
2851 /*
2852 Internal error, a maintainer has modified the internal format
2853 of a line and forgots to respect this modification here!
2854 */
2855 my_error (ERR_MAINTAINER_FAILURE, __FILE__, (long) __LINE__, "", 0);
2856 ptr_char++;
2857 /*
2858 And concatenate the "text"-part.
2859 */
2860 if (*ptr_char)
2861 strcat (b_text, ptr_char);
2862
2863 return (strcmp (b_text, a_text));
2864 }
2865 #endif /* USE_RC */
2866