2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * COMPONENT_NAME: austext
50 * (C) COPYRIGHT International Business Machines Corp. 1993,1996
52 * Licensed Materials - Property of IBM
53 * US Government Users Restricted Rights - Use, duplication or
54 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
56 /************** DTSRHAN.C ***************
57 * $XConsortium: dtsrhan.c /main/9 1996/09/23 21:02:27 cde-ibm $
59 * Modification of handel.c for CDE system.
60 * Converts free form text in accordance with a profile file
61 * into a formal .fzk file.
64 * Revision 2.8 1996/04/10 22:55:27 miker
65 * Removed ref to BETA.
67 * Revision 2.7 1996/04/10 19:48:52 miker
68 * Added support for null dates.
70 * Revision 2.6 1996/03/25 18:53:56 miker
71 * Changed FILENAME_MAX to _POSIX_PATH_MAX.
73 * Revision 2.5 1996/02/01 18:20:02 miker
74 * Changed parser/stemmer calls to new readchar format.
76 * Revision 2.4 1995/11/07 17:51:46 miker
77 * Fixed bug in progress dot processing.
78 * Added rec count to err msgs to facilitate finding bad recs.
80 * Revision 2.3 1995/10/25 18:57:27 miker
81 * Renamed from chandel.c. Added prolog.
84 * Revision 2.2 1995/10/02 20:00:51 miker
85 * Added semantic analysis so original handel.c no longer required.
87 * Revision 2.1 1995/09/22 19:20:45 miker
88 * Freeze DtSearch 0.1, AusText 2.1.8
90 * Revision 1.7 1995/09/19 21:49:22 miker
91 * ifdef DTSEARCH, use DtSrVERSION instead of AUSAPI_VERSION in banner.
93 * Revision 1.6 1995/08/31 22:15:33 miker
94 * Added MMM fields for date processing like handel.c.
95 * Minor changes for DtSearch, mostly msg sets changes..
96 * Executable module renamed dtsrload for DtSearch.
98 * Revision 1.5 1995/06/08 00:32:43 miker
99 * 2.1.5f: Bug fix. Segfault if constant string not enclosed in quotes.
100 * Enable negative field offsets.
112 #define PROGNAME "DTSRHAN"
114 #define RECS_PER_DOT 10L
116 /*-- Numerical codes for storing "undefined items" --*/
120 /*-- Codes for "modes" of text buffering --*/
128 /*-- codes for abstract mode --*/
133 /*-- Exit codes for errors --*/
136 #define SYNTAX_ERROR 4
139 #define BAD_PROFILE 7
142 /*-- Token types --*/
147 /****#define WORDS 4*****/
153 #define TEXTINCLUDE 10
154 #define TEXTEXCLUDE 11
155 #define TFIELDINCLUDE 12
156 #define TFIELDEXCLUDE 13
157 #define DELBLANKLINES 14
158 #define IMAGEINCLUDE 15
159 #define IMAGEEXCLUDE 16
165 /*-- General Defines --*/
169 #define MAX_ALPHABET_SIZE 256
171 /*-- definitions of various data structures --*/
172 struct line_comp { /*-- Individual components for line ids --*/
175 int d[MAX_ALPHABET_SIZE];
177 struct line_comp *next;
180 struct line_id { /*-- list of line ids to be handled --*/
182 struct line_comp *comp;
183 struct line_comp *head;
184 struct line_id *next;
191 struct field_id { /*-- list of field ids to be used --*/
192 struct field_id *next;
194 struct line_id *line;
199 int d[MAX_ALPHABET_SIZE];
210 struct rec { /*-- holds a complete image of a record --*/
212 struct line_id *line;
219 struct date_id *next;
220 struct field_id *field;
226 struct field_id *field;
232 struct finclude *next;
238 struct include *next;
241 /************************************************/
245 /************************************************/
246 char abstracter[100];
247 int abstract = GENERATE;
248 struct key_id *abstract_table = NULL;
249 /***nl_catd dtsearch_catd = (nl_catd) -1;***/
250 int bad_parm = FALSE;
251 int bad_profile = FALSE;
252 int bot_defined = FALSE;
253 struct date_id *date_table = NULL;
254 int date_pos_defined = FALSE;
255 static char *del_string = " +=,\t\n";
256 /****static char *del_string = " +-=,\t\n";**allow neg nums***/
257 int del_blanklines = FALSE;
258 char dicname[10] = {0};
259 char dicpath[_POSIX_PATH_MAX] = {0};
261 int discard_record = FALSE;
262 struct finclude *finclude_tab = NULL;
263 struct field_id *field_table = NULL;
264 struct include *i_i_t = NULL;
265 int imagemode = INCLUDE;
266 int imageflag = INCLUDE;
267 struct include *include_tab = NULL;
269 static FILE *instream = NULL;
270 static long key_count = 0;
271 struct key_id *key_table = NULL;
272 int key_defined = FALSE;
273 int key_pos_defined = FALSE;
276 static char *line_mode = "
\f\ 2\ 6CTHULHU TOCOMA ZYYXY UTOPIA";
277 struct line_id *line_table = NULL;
281 static int null_date_specified = FALSE;
282 struct tm *objdate_tmptr;
284 char outmode[8] = "w";
285 int outmode_specified = FALSE;
287 static FILE *outstream = NULL;
289 static long rec_count = 0L; /* for err msgs */
290 struct rec *record_head = NULL;
292 int screen_width = 79;
293 int shutdown_now = FALSE;
295 int textflag = INCLUDE;
296 int textmode = INCLUDE;
297 int top_defined = FALSE;
298 struct line_id *top_rec;
299 char top_rec_name[80];
300 int uppercase = FALSE;
301 int uninit_line = TRUE;
302 int uninit_field = TRUE;
304 int wordmode = INCLUDE;
307 /****************************************************************
308 VALIDATE_ID - validates an indentifier (first character a
309 letter, then alpha-numeric, etc)
310 ****************************************************************/
311 int validate_id (char *s)
317 if (!isalpha (s[0])) {
320 for (i = 1; i < strlen (s); i++)
321 if (!isalnum (s[i]) && s[i] != '_') {
328 /****************************************************************
329 OPEN_OUTFILE - open outputfile - if the file already exists,
330 and no mode was specified by the user, ask the user what to do.
331 ****************************************************************/
337 if (!outmode_specified)
338 if ((temp = fopen (outfile, "r")) != NULL) {
340 printf ( catgets(dtsearch_catd, MS_chandel, 3,
341 "Output file '%s' already exists.\n") ,
343 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 4,
344 "Append, overwrite, or quit? [a,o,q] ") );
345 i = tolower (getchar ());
348 strcpy (outmode, "a");
350 strcpy (outmode, "w");
354 if (!strcmp (outfile, "-"))
357 if ((outstream = fopen (outfile, outmode)) == NULL) {
358 printf ( catgets(dtsearch_catd, MS_chandel, 7,
359 "Unable to open output file '%s'.\n") , outfile);
367 /****************************************************************
368 IS_TIME - returns TRUE if the passed string contains the
369 string "time" in any case (upper/lower) - without destroying the
370 original string, in case it was a field name.
371 ****************************************************************/
372 int is_time (char *orig)
376 /* copy original string to temp buffer, so we can manipulate */
377 s = (char *) malloc (sizeof (char) * strlen (orig) +5);
379 for (i = 0; i < strlen (s); i++)
380 s[i] = tolower (s[i]);
382 if (strcmp (s, "time") == 0)
388 /****************************************************************
389 IS_COUNT - returns TRUE if the passed string contains the
390 string "count" in any case (upper/lower) - without destroying the
391 original string, in case it was a field name.
392 ****************************************************************/
393 int is_count (char *orig)
397 /* copy original string to temp buffer, so we can manipulate */
398 s = (char *) malloc (sizeof(char) * strlen(orig) +5);
400 for (i = 0; i < strlen (s); i++)
401 s[i] = tolower (s[i]);
403 if (strcmp (s, "count") == 0)
409 /****************************************************************
410 MY_STRTOK - my own version of strtok - why? Because I need
411 a little flexibility when parsing out the string component -
412 what if it has quotes embedded?
414 s1 = the line to be parsed (= start at beginning)
415 or NULL (= start where we last left off).
417 s2 = the 'delete' string or array of token separators.
418 Usually it is either the global 'del_string' (" +-=,\t\n")
419 or a string consisting of a single double-quote char.
420 ****************************************************************/
421 char *my_strtok (char *s1, const char *s2)
424 static char stringbuf[100];
425 static char *ssave = "";
428 memset (stringbuf, 0, sizeof(stringbuf));
429 sbegin = (s1) ? s1 : ssave; /* start of string or where we last left off */
431 if (strcmp (s2, "\"") == 0) { /* parsing for a string */
432 if (*sbegin == '\0') {
436 while (*sbegin != '"' && *sbegin != '\0') {/*-- look for first " --*/
439 if (*sbegin == '\0') {
443 sbegin++; /*-- skip past " --*/
445 while (*sbegin != '"') {/*-- until other " --*/
446 if (*sbegin == '\\') /*-- escape sequence --*/
448 if (*sbegin == '\0') { /*-- end of line --*/
452 stringbuf[i++] = (*sbegin);
463 else { /* not parsing for a string */
464 sbegin += strspn (sbegin, s2);
465 if (*sbegin == '\0') {
469 send = strpbrk (sbegin, s2);
475 } /*-- my_strtok --*/
477 /****************************************************************
478 IS_BLANK - determines if a string contains nothing but
480 *****************************************************************/
481 int is_blank (char *s)
484 for (i = 0; i < strlen (s); i++)
491 /***********************************************************************
492 TOKEN - returns a numerical token for the defined identifier types
493 ************************************************************************/
501 /*-- make token all lowercase --*/
502 for (i = 0; i < strlen (s); i++)
503 s[i] = tolower (s[i]);
505 if (!strcmp (s, "line"))
507 if (!strcmp (s, "field"))
509 if (!strcmp (s, "key"))
511 if (!strcmp (s, "date"))
513 if (!strcmp (s, "text"))
515 if (!strcmp (s, "keychar"))
517 if (!strcmp (s, "delimiter"))
519 if (!strcmp (s, "textinclude"))
521 if (!strcmp (s, "textexclude"))
523 if (!strcmp (s, "tfieldinclude"))
524 return TFIELDINCLUDE;
525 if (!strcmp (s, "tfieldexclude"))
526 return TFIELDEXCLUDE;
527 if (!strcmp (s, "delblanklines"))
528 return DELBLANKLINES;
529 if (!strcmp (s, "abstract"))
531 if (!strcmp (s, "user"))
533 if (!strcmp (s, "fields"))
535 if (!strcmp (s, "generate"))
537 if (!strcmp (s, "image"))
539 if (!strcmp (s, "imageinclude"))
541 if (!strcmp (s, "imageexclude"))
543 if (!strcmp (s, "discard"))
545 if (!strcmp (s, "constant"))
547 if (!strcmp (s, "upper"))
552 /***********************************************************************
553 PROCESS_PROFILE - process 'profile' file.
554 ************************************************************************/
555 void process_profile ()
562 struct line_id *line_current;
563 struct field_id *field_current;
564 struct key_id *key_current;
565 struct date_id *date_current;
566 struct key_id *abstract_current;
567 struct finclude *finclude_current;
568 struct include *include_current;
569 struct include *i_i_current;
574 if ((prof = fopen (profile, "r")) == NULL) {
575 printf ( catgets(dtsearch_catd, MS_chandel, 11,
576 "\nError - unable to open profile file '%s'.\n") , profile);
579 /*-- Get next line --*/
582 ret = fgets (prof_line, 200, prof);
584 if (ret == NULL || feof (prof) )
586 if (prof_line[0] == '#' || is_blank (prof_line))
588 tok = my_strtok (prof_line, del_string);
590 continue; /* ignore blank line */
591 tok_type = token (tok);
599 if (line_table == NULL) {
600 line_table = (struct line_id *) malloc (
601 sizeof (struct line_id));
602 line_current = line_table;
603 line_table->next = NULL;
604 line_table->comp = (struct line_comp *) malloc (
605 sizeof (struct line_comp));
606 line_table->head = line_table->comp;
607 line_table->comp->next = NULL;
611 line_current->next = (struct line_id *) malloc (
612 sizeof (struct line_id));
613 line_current = line_current->next;
614 line_current->next = NULL;
615 line_current->comp = (struct line_comp *) malloc (
616 sizeof (struct line_comp));
617 line_current->head = line_current->comp;
618 line_current->comp->next = NULL;
620 line_current->image_action = NONE;
621 line_current->word_action = NONE;
622 line_current->text_action = NONE;
623 line_current->line = NULL;
624 line_current->name[0] = 0;
625 /*-- get identifier --*/
626 tok = my_strtok ('\0', del_string);
627 if (validate_id (tok))
628 strcpy (line_current->name, tok);
630 printf ( catgets(dtsearch_catd, MS_chandel, 12,
631 "Error line %d: invalid identifier '%s'.\n") ,
632 line_num, NULLORSTR(tok));
636 /*-- get first value token --*/
637 tok = my_strtok ('\0', del_string);
639 printf ( catgets(dtsearch_catd, MS_chandel, 13,
640 "Error line %d - identifier '%s' missing value(s).\n") ,
641 line_num, line_current->name);
645 if (!strcmp (tok, "*"))
646 line_current->comp->column_number = ANY;
648 line_current->comp->column_number = atoi (tok);
649 if (line_current->comp->column_number == 0) {
650 printf ( catgets(dtsearch_catd, MS_chandel, 14,
651 "Error line %d - zero or bad value for '%s'.\n"
652 " offensive token: %s.\n") ,
653 line_num, line_current->name, tok);
657 /* d d d-- get second token of pair -- */
658 tok = my_strtok ('\0', "\"");
660 if (line_current->comp->column_number == ANY) {
661 printf ( catgets(dtsearch_catd, MS_chandel, 15,
662 "Error line %d - for identifier '%s', column has "
663 "been set to ANY\n but there is no "
664 "identifying signature string.\n") ,
665 line_num, line_current->name);
671 strcpy (line_current->comp->text, line_mode);
677 strcpy (line_current->comp->text, tok);
678 line_current->comp->text_length =
679 strlen (line_current->comp->text);
681 /*-- check for more tokens for LINE type of line --*/
683 tok = my_strtok ('\0', del_string);
686 /*-- build component node --*/
687 line_current->comp->next = (struct line_comp *) malloc (
688 sizeof (struct line_comp));
689 line_current->comp = line_current->comp->next;
690 line_current->comp->next = NULL;
691 /*-- check # and store --*/
692 if (!strcmp (tok, "*"))
693 line_current->comp->column_number = ANY;
695 line_current->comp->column_number = atoi (tok);
696 if (line_current->comp->column_number == 0) {
697 printf ( catgets(dtsearch_catd, MS_chandel, 16,
698 "Error line %d - zero or bad value for "
699 "identifier '%s'\n offensive token: %s.\n") ,
700 line_num, line_current->name, tok);
704 /* - --- get second of pair -- */
705 tok = my_strtok ('\0', "\"");
707 if (line_current->comp->column_number == ANY)
708 printf ( catgets(dtsearch_catd, MS_chandel, 15,
709 "Error line %d - for identifier '%s', column has "
710 "been set to ANY\n but there is no "
711 "identifying signature string.\n") ,
712 line_num, line_current->name);
714 printf ( catgets(dtsearch_catd, MS_chandel, 18,
715 "Error line %d - missing value for "
716 "identifier '%s'\n") ,
717 line_num, line_current->name);
721 strcpy (line_current->comp->text, tok);
722 line_current->comp->text_length =
723 strlen (line_current->comp->text);
724 } /* end for(;;) loop for continuing LINE token pairs */
725 break; /* end case LINE */
729 if (field_table == NULL) {
730 field_table = (struct field_id *)
731 malloc (sizeof (struct field_id));
732 field_current = field_table;
733 field_table->next = NULL;
736 field_current->next = (struct field_id *) malloc (
737 sizeof (struct field_id));
738 field_current = field_current->next;
739 field_current->next = NULL;
741 memset (field_current, 0, sizeof(struct field_id));
742 field_current->word_action = NONE;
743 field_current->image_action = NONE;
744 field_current->text_action = NONE;
745 if (tok_type == CONSTANT)
746 field_current->constant = TRUE;
748 /*-- get identifier --*/
749 tok = my_strtok ('\0', del_string);
750 if (validate_id (tok)) {
751 strcpy (field_current->name, tok);
752 if (strncmp (tok, "MMM", 3) == 0)
753 field_current->is_month = TRUE;
756 printf ( catgets(dtsearch_catd, MS_chandel, 12,
757 "Error line %d: invalid identifier '%s'.\n") ,
758 line_num, NULLORSTR(tok));
762 if (field_current->constant) {
763 /*-- get constant value --*/
764 tok = my_strtok (NULL, "\"");
766 printf ( catgets(dtsearch_catd, MS_chandel, 93,
767 "Error line %d - '%s' string not "
768 "enclosed in double quotes.\n"),
769 line_num, field_current->name);
773 strcpy (field_current->value, tok);
776 else { /* ...must be FIELD */
777 /*-- get line id --*/
778 tok = my_strtok ('\0', del_string);
780 printf ( catgets(dtsearch_catd, MS_chandel, 13,
781 "Error line %d - identifier '%s' missing value(s).\n") ,
782 line_num, line_current->name);
786 strcpy (field_current->line_id, tok);
788 /*-- get "string" --*/
789 tok = my_strtok ('\0', "\"");
791 printf ( catgets(dtsearch_catd, MS_chandel, 93,
792 "Error line %d - '%s' string not "
793 "enclosed in double quotes.\n"),
794 line_num, field_current->name);
798 strcpy (field_current->text, tok);
799 field_current->text_length = strlen (field_current->text);
802 tok = my_strtok ('\0', del_string);
804 printf ( catgets(dtsearch_catd, MS_chandel, 13,
805 "Error line %d - identifier '%s' missing value(s).\n") ,
806 line_num, line_current->name);
810 field_current->offset = atoi (tok);
813 tok = my_strtok ('\0', del_string);
814 /*******if (!tok && field_current->length == ANY) ************/
816 printf ( catgets(dtsearch_catd, MS_chandel, 13,
817 "Error line %d - identifier '%s' missing value(s).\n") ,
818 line_num, line_current->name);
822 if (!strcmp (tok, "eoln"))
823 field_current->defined_length = EOLN;
824 else if (!strcmp (tok, "eow"))
825 field_current->defined_length = EOW;
827 field_current->defined_length = atoi (tok);
832 /*-- get next token - should be name of line --*/
833 if (warnings &&(bot_defined || top_defined))
834 printf ( catgets(dtsearch_catd, MS_chandel, 23,
835 "Warning line %d: Delimiter redefined.\n") ,
837 tok = my_strtok ('\0', del_string);
838 if (validate_id (tok))
839 strcpy (top_rec_name, tok);
841 printf ( catgets(dtsearch_catd, MS_chandel, 12,
842 "Error line %d: invalid identifier '%s'.\n"),
843 line_num, NULLORSTR(tok));
846 tok = my_strtok ('\0', del_string);
849 /* convert tok to lowercase */
850 for (i = 0; i < strlen (tok); i++)
851 tok[i] = tolower (tok[i]);
852 if (!strcmp (tok, "top")) {
855 } else if (!strcmp (tok, "bottom")) {
860 printf ( catgets(dtsearch_catd, MS_chandel, 25,
861 "Error line %d: delimiter not specified as "
862 "'top' or 'bottom'.\n") ,
869 tok = my_strtok ('\0', del_string);
870 if (validate_id (tok)) {
871 if (finclude_tab == NULL) {
872 finclude_tab = (struct finclude *) malloc (
873 sizeof (struct finclude));
874 finclude_current = finclude_tab;
876 finclude_current->next = (struct finclude *) malloc (
877 sizeof (struct finclude));
878 finclude_current = finclude_current->next;
880 finclude_current->next = NULL;
881 strcpy (finclude_current->field_id, tok);
882 finclude_current->value = EXCLUDE;
884 /* if it was a valid token */
886 printf ( catgets(dtsearch_catd, MS_chandel, 26,
887 "Error line %d: invalid token '%s'.\n") ,
888 line_num, NULLORSTR(tok));
894 tok = my_strtok ('\0', del_string);
895 if (validate_id (tok)) {
896 if (finclude_tab == NULL) {
897 finclude_tab = (struct finclude *) malloc (
898 sizeof (struct finclude));
899 finclude_tab->next = NULL;
900 finclude_current = finclude_tab;
904 finclude_current->next = (struct finclude *) malloc (
905 sizeof (struct finclude));
906 finclude_current = finclude_current->next;
907 finclude_current->next = NULL;
909 strcpy (finclude_current->field_id, tok);
910 finclude_current->value = INCLUDE;
912 /* if it was a valid token */
914 printf ( catgets(dtsearch_catd, MS_chandel, 27,
915 "Error line %d: invalid token '%s'.\n") ,
916 line_num, NULLORSTR(tok));
922 tok = my_strtok ('\0', del_string);
923 if (validate_id (tok)) {
924 if (include_tab == NULL) {
925 include_tab = (struct include *) malloc (
926 sizeof (struct include));
927 include_tab->next = NULL;
928 include_current = include_tab;
932 include_current->next = (struct include *) malloc (
933 sizeof (struct include));
934 include_current = include_current->next;
935 include_current->next = NULL;
936 } /* else in valid */
937 strcpy (include_current->line_id, tok);
938 tok = my_strtok ('\0', del_string);
940 include_current->value = EXCLUDE;
942 if (validate_id (tok)) {
943 include_current->value = SET;
944 include_current->next = (struct include *) malloc (
945 sizeof (struct include));
946 include_current = include_current->next;
947 include_current->next = NULL;
948 strcpy (include_current->line_id, tok);
949 include_current->value = DEFAULT;
953 printf ( catgets(dtsearch_catd, MS_chandel, 12,
954 "Error line %d: invalid identifier '%s'.\n") ,
958 } /* else tok wasn't NULL */
962 printf (catgets(dtsearch_catd, MS_chandel, 12,
963 "Error line %d: invalid identifier '%s'.\n") ,
964 line_num, NULLORSTR(tok));
966 } /* else not a valid token */
970 tok = my_strtok ('\0', del_string);
971 if (validate_id (tok)) {
973 i_i_t = (struct include *) malloc (
974 sizeof (struct include));
980 i_i_current->next = (struct include *) malloc (
981 sizeof (struct include));
982 i_i_current = i_i_current->next;
983 i_i_current->next = NULL;
984 } /* else in valid */
985 strcpy (i_i_current->line_id, tok);
986 tok = my_strtok ('\0', del_string);
988 i_i_current->value = EXCLUDE;
990 if (validate_id (tok)) {
991 i_i_current->value = SET;
992 i_i_current->next = (struct include *) malloc (
993 sizeof (struct include));
994 i_i_current = i_i_current->next;
995 i_i_current->next = NULL;
996 strcpy (i_i_current->line_id, tok);
997 i_i_current->value = DEFAULT;
1001 printf ( catgets(dtsearch_catd, MS_chandel, 12,
1002 "Error line %d: invalid identifier '%s'.\n") ,
1005 } /* else in else */
1006 } /* else tok wasn't NULL */
1008 /* if validate... */
1010 printf ( catgets(dtsearch_catd, MS_chandel, 12,
1011 "Error line %d: invalid identifier '%s'.\n") ,
1012 line_num, NULLORSTR(tok));
1014 } /* else not a valid token */
1018 tok = my_strtok ('\0', del_string);
1019 if (validate_id (tok)) {
1020 if (i_i_t == NULL) {
1021 i_i_t = (struct include *) malloc (
1022 sizeof (struct include));
1024 i_i_current = i_i_t;
1028 i_i_current->next = (struct include *) malloc (
1029 sizeof (struct include));
1030 i_i_current = i_i_current->next;
1031 i_i_current->next = NULL;
1032 } /* else in valid */
1033 strcpy (i_i_current->line_id, tok);
1034 tok = my_strtok ('\0', del_string);
1036 i_i_current->value = INCLUDE;
1038 if (validate_id (tok)) {
1039 i_i_current->value = CLEAR;
1040 i_i_current->next = (struct include *) malloc (
1041 sizeof (struct include));
1042 i_i_current = i_i_current->next;
1043 i_i_current->next = NULL;
1044 strcpy (i_i_current->line_id, tok);
1045 i_i_current->value = DEFAULT;
1049 printf ( catgets(dtsearch_catd, MS_chandel, 12,
1050 "Error line %d: invalid identifier '%s'.\n") ,
1053 } /* else in else */
1054 } /* else tok wasn't NULL */
1056 /* if validate... */
1058 printf ( catgets(dtsearch_catd, MS_chandel, 12,
1059 "Error line %d: invalid identifier '%s'.\n") ,
1060 line_num, NULLORSTR(tok));
1062 } /* else not a valid token */
1066 tok = my_strtok ('\0', del_string);
1067 if (validate_id (tok)) {
1068 if (include_tab == NULL) {
1069 include_tab = (struct include *) malloc (
1070 sizeof (struct include));
1071 include_tab->next = NULL;
1072 include_current = include_tab;
1076 include_current->next = (struct include *) malloc (
1077 sizeof (struct include));
1078 include_current = include_current->next;
1079 include_current->next = NULL;
1080 } /* else in valid */
1081 strcpy (include_current->line_id, tok);
1082 tok = my_strtok ('\0', del_string);
1084 include_current->value = INCLUDE;
1086 if (validate_id (tok)) {
1087 include_current->value = CLEAR;
1088 include_current->next = (struct include *) malloc (
1089 sizeof (struct include));
1090 include_current = include_current->next;
1091 include_current->next = NULL;
1092 strcpy (include_current->line_id, tok);
1093 include_current->value = DEFAULT;
1097 printf ( catgets(dtsearch_catd, MS_chandel, 12,
1098 "Error line %d: invalid identifier '%s'.\n") ,
1101 } /* else in else */
1102 } /* else tok wasn't NULL */
1104 /* if validate... */
1106 printf ( catgets(dtsearch_catd, MS_chandel, 12,
1107 "Error line %d: invalid identifier '%s'.\n") ,
1108 line_num, NULLORSTR(tok));
1110 } /* else not a valid token */
1114 tok = my_strtok ('\0', del_string);
1117 for (i = 0; i < strlen (tok); i++)
1118 tok[i] = tolower (tok[i]);
1119 if (strcmp (tok, catgets (dtsearch_catd, MS_chandel, 34,"all")) == 0)
1120 imagemode = INCLUDE;
1121 else if (strcmp (tok, catgets (dtsearch_catd, MS_chandel, 35, "none")) == 0)
1122 imagemode = EXCLUDE;
1125 printf ( catgets(dtsearch_catd, MS_chandel, 36,
1126 "Error line %d: image mode must be 'all' or "
1127 "'none' -'%s' not recognized.\n") ,
1131 imageflag = imagemode;
1135 tok = my_strtok ('\0', del_string);
1138 for (i = 0; i < strlen (tok); i++)
1139 tok[i] = tolower (tok[i]);
1140 if (strcmp (tok, "all") == 0)
1142 else if (strcmp (tok, "none") == 0)
1146 printf ( catgets(dtsearch_catd, MS_chandel, 37,
1147 "Error line %d: text mode must be 'all' or "
1148 "'none' - '%s' not recognized.\n") , NULLORSTR(tok));
1151 textflag = textmode;
1155 /*-- get next token - should be character for key type --*/
1156 if (warnings && key_defined)
1157 printf ( catgets(dtsearch_catd, MS_chandel, 38,
1158 "Warning line %d: Key character redefined.\n") ,
1160 tok = my_strtok ('\0', del_string);
1161 if (validate_id (tok))
1164 printf ( catgets(dtsearch_catd, MS_chandel, 39,
1165 "Error line %d: invalid Key Character:'%c'.\n") ,
1166 line_num, (tok)?tok[0]:'?');
1174 if (date_pos_defined) {
1175 printf ( catgets(dtsearch_catd, MS_chandel, 110,
1176 "Warning line %d - date field redefined.\n") ,
1178 null_date_specified = FALSE;
1180 date_table = (struct date_id *) malloc
1181 (sizeof (struct date_id));
1182 date_current = date_table;
1183 date_current->next = NULL;
1184 tok = my_strtok ('\0', del_string);
1185 /* validate_id() just does syntax chk on name string */
1186 if (validate_id (tok))
1187 strcpy (date_current->field_id, tok);
1189 /* Msg #111 used two places */
1190 printf ( catgets(dtsearch_catd, MS_chandel, 111,
1191 "Error line %d - bad identifier '%s' for date.\n") ,
1192 line_num, NULLORSTR(tok));
1197 /* Test for special "null" date value */
1198 if (strcmp (date_current->field_id, "null") == 0) {
1199 date_pos_defined = TRUE;
1200 null_date_specified = TRUE;
1204 tok = my_strtok ('\0', del_string);
1205 while (tok != NULL) {
1206 date_current->next = (struct date_id *) malloc
1207 (sizeof (struct date_id));
1208 date_current = date_current->next;
1209 date_current->next = NULL;
1210 if (validate_id (tok))
1211 strcpy (date_current->field_id, tok);
1213 /* Msg #111 used two places */
1214 printf ( catgets(dtsearch_catd, MS_chandel, 111,
1215 "Error line %d - bad identifier '%s' for date.\n"),
1216 line_num, NULLORSTR(tok));
1220 tok = my_strtok ('\0', del_string);
1222 date_pos_defined = TRUE;
1223 break; /* end case DATEFLD */
1226 /*-- building the key --*/
1227 if (warnings && key_pos_defined)
1228 printf ( catgets(dtsearch_catd, MS_chandel, 40,
1229 "Warning line %d - key field redefined.\n") ,
1231 key_table = (struct key_id *) malloc (sizeof (struct key_id));
1232 key_current = key_table;
1233 key_current->next = NULL;
1234 tok = my_strtok ('\0', del_string);
1235 if (validate_id (tok)) {
1236 if (is_time (tok)) {
1237 strcpy (key_current->field_id, "time");
1238 key_pos_defined = TRUE;
1240 } else if (is_count (tok)) {
1241 strcpy (key_current->field_id, "count");
1242 key_pos_defined = TRUE;
1245 strcpy (key_current->field_id, tok);
1248 printf ( catgets(dtsearch_catd, MS_chandel, 43,
1249 "Error line %d - bad identifier '%s' for key.\n") ,
1250 line_num, NULLORSTR(tok));
1254 tok = my_strtok ('\0', del_string);
1255 while (tok != NULL) {
1256 key_current->next = (struct key_id *) malloc (
1257 sizeof (struct key_id));
1258 key_current = key_current->next;
1259 key_current->next = NULL;
1260 if (validate_id (tok))
1261 strcpy (key_current->field_id, tok);
1263 printf ( catgets(dtsearch_catd, MS_chandel, 43,
1264 "Error line %d - bad identifier '%s' for key.\n") ,
1269 tok = my_strtok ('\0', del_string);
1271 key_pos_defined = TRUE;
1275 tok = my_strtok ('\0', del_string);
1278 for (i = 0; i < strlen (tok); i++)
1279 tok[i] = toupper (tok[i]);
1280 if (!strcmp (tok, "TRUE"))
1282 else if (!strcmp (tok, "FALSE"))
1286 printf ( catgets(dtsearch_catd, MS_chandel, 45,
1287 "Error line %d: unknown option for 'discard': "
1288 "'%s'.\n") , line_num, NULLORSTR(tok));
1294 tok = my_strtok ('\0', del_string);
1296 goto BAD_DELBLANKLINES;
1297 for (i = 0; i < strlen (tok); i++)
1298 tok[i] = toupper (tok[i]);
1299 if (!strcmp (tok, "TRUE"))
1300 del_blanklines = TRUE;
1301 else if (!strcmp (tok, "FALSE"))
1302 del_blanklines = FALSE;
1305 printf ( catgets(dtsearch_catd, MS_chandel, 46,
1306 "Error line %d: unknown option for "
1307 "'delblanklines': '%s'.\n") ,
1308 line_num, NULLORSTR(tok));
1314 tok = my_strtok ('\0', del_string);
1315 abstract = token (tok);
1320 tok = my_strtok ('\0', del_string);
1323 strcpy (abstracter, tok);
1326 tok = my_strtok ('\0', del_string);
1327 while (tok != NULL) {
1328 if (abstract_table == NULL) {
1329 abstract_table = (struct key_id *) malloc
1330 (sizeof (struct key_id));
1331 abstract_current = abstract_table;
1333 abstract_current->next =
1334 (struct key_id *) malloc (
1335 sizeof (struct key_id));
1336 abstract_current = abstract_current->next;
1338 strcpy (abstract_current->field_id, tok);
1339 abstract_current->next = NULL;
1340 tok = my_strtok ('\0', del_string);
1345 printf ( catgets(dtsearch_catd, MS_chandel, 47,
1346 "Error line %d: Unknown option for abstract :'%s'\n"),
1347 line_num, NULLORSTR(tok));
1350 } /* 'abstract' subswitch */
1354 printf ( catgets(dtsearch_catd, MS_chandel, 48,
1355 "Error line %d -unknown identifier type '%s'.\n") ,
1356 line_num, NULLORSTR(tok));
1359 } /* main switch for each line in profile */
1360 } while (TRUE); /* read-a-line do loop */
1361 if (!date_pos_defined)
1362 fprintf (aa_stderr, catgets(dtsearch_catd, MS_chandel, 115,
1363 "%s Default object dates will be '%s'.\n") ,
1364 PROGNAME"1288", now_str);
1368 /*---- Process tables, and check for identifiers referenced ----*/
1369 if (!top_defined && !bot_defined) {
1371 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 49,
1372 "Error - delimiter not defined.\n") );
1376 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 50,
1377 "Error - key-type character never defined.\n") );
1379 if (!key_pos_defined) {
1381 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 51,
1382 "Error - key never defined.\n") );
1388 line_current = line_table;
1389 while (line_current != NULL) {
1390 if (strcmp (line_current->name, top_rec_name) == 0)
1391 top_rec = line_current;
1392 line_current = line_current->next;
1394 if (top_rec_name[0] != 0 && top_rec == NULL) {
1395 printf ( catgets(dtsearch_catd, MS_chandel, 52,
1396 "Error - delimiter defined as '%s' was never found.\n") ,
1399 } else if (strcmp (top_rec->head->text, line_mode) == 0) {
1400 printf ( catgets(dtsearch_catd, MS_chandel, 53,
1401 "Error - delimiter defined as '%s' references a physical "
1402 "line in the record.\n Since the delimiter defines the "
1403 "physical lines\n it cannot be referenced as a physical line.\n"),
1407 field_current = field_table;
1408 while (field_current != NULL) {
1410 line_current = line_table;
1411 while (line_current != NULL) {
1412 if (!strcmp (field_current->line_id, line_current->name)) {
1414 field_current->line = line_current;
1416 line_current = line_current->next;
1418 if (!found && !field_current->constant) {
1419 printf ( catgets(dtsearch_catd, MS_chandel, 54,
1420 "Error - for field '%s', no line identifier matches '%s'.\n") ,
1421 field_current->name, field_current->line_id);
1424 field_current = field_current->next;
1426 finclude_current = finclude_tab;
1427 while (finclude_current != NULL) {
1428 /* find field, and set text_value */
1429 field_current = field_table;
1431 while (field_current != NULL) {
1432 if (!strcmp (field_current->name, finclude_current->field_id)) {
1433 field_current->text_action = finclude_current->value;
1436 field_current = field_current->next;
1439 printf ( catgets(dtsearch_catd, MS_chandel, 55,
1440 "Error - field include/exclude list included\n"
1441 " the field '%s', which was never defined.\n") ,
1442 finclude_current->field_id);
1445 finclude_current = finclude_current->next;
1447 i_i_current = i_i_t;
1448 while (i_i_current != NULL) {
1449 /* find line, and set text_action */
1450 line_current = line_table;
1452 while (line_current != NULL) {
1453 if (!strcmp (line_current->name, i_i_current->line_id)) {
1454 line_current->image_action = i_i_current->value;
1457 line_current = line_current->next;
1460 printf ( catgets(dtsearch_catd, MS_chandel, 56,
1461 "Error - image include/exclude list included\n"
1462 " the line '%s', which was never defined.\n") ,
1463 include_current->line_id);
1466 i_i_current = i_i_current->next;
1468 include_current = include_tab;
1469 while (include_current != NULL) {
1470 /* find line, and set text_action */
1471 line_current = line_table;
1473 while (line_current != NULL) {
1474 if (!strcmp (line_current->name, include_current->line_id)) {
1475 line_current->text_action = include_current->value;
1478 line_current = line_current->next;
1481 printf ( catgets(dtsearch_catd, MS_chandel, 57,
1482 "Error - text include/exclude list included\n"
1483 " the line '%s', which was never defined.\n") ,
1484 include_current->line_id);
1487 include_current = include_current->next;
1490 /* If "null" dates specified, no need to look for other date fields */
1491 if (null_date_specified)
1492 goto END_DATE_TABLE;
1494 /* loop thru date table and link each field id to its structure */
1495 for (date_current = date_table; date_current != NULL;
1496 date_current = date_current->next) {
1499 for (field_current = field_table; field_current != NULL;
1500 field_current = field_current->next) {
1501 if (strcmp (field_current->name, date_current->field_id) == 0) {
1502 date_current->field = field_current;
1508 printf ( catgets(dtsearch_catd, MS_chandel, 116,
1509 "Error - date references undefined field '%s'.\n"),
1510 date_current->field_id);
1516 key_current = key_table;
1517 while (key_current != NULL) {
1518 field_current = field_table;
1520 if (!strcmp ("time", key_current->field_id)) {
1522 key_current->field = NULL;
1523 } else if (!strcmp ("count", key_current->field_id)) {
1525 key_current->field = NULL;
1527 while (field_current != NULL) {
1528 if (!strcmp (field_current->name, key_current->field_id)) {
1530 key_current->field = field_current;
1531 } else if (!strcmp ("time", key_current->field_id)) {
1533 key_current->field = NULL;
1534 } else if (!strcmp ("count", key_current->field_id)) {
1536 key_current->field = NULL;
1538 field_current = field_current->next;
1541 printf ( catgets(dtsearch_catd, MS_chandel, 58,
1542 "Error - key definition references field '%s'\n"
1543 " which was never defined.\n") ,
1544 key_current->field_id);
1547 key_current = key_current->next;
1549 abstract_current = abstract_table;
1550 while (abstract_current != NULL) {
1551 field_current = field_table;
1553 while (field_current != NULL) {
1554 if (!strcmp (field_current->name, abstract_current->field_id)) {
1556 abstract_current->field = field_current;
1558 field_current = field_current->next;
1561 printf ( catgets(dtsearch_catd, MS_chandel, 59,
1562 "Error - abstract definition references field '%s'\n"
1563 " which was never defined.\n") ,
1564 abstract_current->field_id);
1567 abstract_current = abstract_current->next;
1570 } /*--process_profile--*/
1572 /**********************************************************************
1573 CLEANUP - frees memory used by record
1574 ***********************************************************************/
1577 struct line_id *line_current;
1578 struct field_id *field_current;
1581 /*-- Reset line_table --*/
1582 line_current = line_table;
1583 while (line_current != NULL) {
1584 line_current->line = UNDEFINED;
1585 line_current = line_current->next;
1588 /*-- Reset field table --*/
1589 field_current = field_table;
1590 while (field_current != NULL) {
1591 if (field_current->constant == FALSE)
1592 field_current->value[0] = 0;
1593 field_current = field_current->next;
1596 /*-- clean up record, free memory for reuse --*/
1597 record = record_head;
1598 while (record_head != NULL) {
1599 record_head = record->next;
1601 record = record_head;
1605 /**************************************************************************
1606 WRITE_RECORD - writes the final form of the record - key, fzkey, abstract,
1608 **************************************************************************/
1609 void write_record ()
1611 static int dotcount = 0;
1613 struct key_id *abst;
1621 /* Line #1 is fzkey */
1622 fprintf (outstream, " 0,2\n"); /* hardcoded null fzkey */
1624 /* Line #2 is abstract */
1626 if (abstract == FIELDS) {
1627 abst = abstract_table;
1628 while (abst != NULL) {
1629 strcat (value, abst->field->value);
1632 for (i = 0; i < strlen (value); i++)
1633 if (value[i] == '\n')
1636 fprintf (outstream, "ABSTRACT: %s\n", value);
1638 /* Line #3 is unique database key */
1639 if (key_value[strlen (key_value) - 1] == '\n')
1640 key_value[strlen (key_value) - 1] = 0;
1643 fprintf (outstream, "%c%s\n", key_char, key_value);
1645 /* Line #4 is object date in objdate string format.
1646 * Prior to version 2.0.8 this would be the first line of text.
1648 if (null_date_specified)
1649 fputs (NULLDATESTR"\n", outstream);
1651 fprintf (outstream, "%s\n",
1652 objdate2fzkstr (tm2objdate (objdate_tmptr)));
1654 /* Lines #5 and thereafter (text) of .fzk rec */
1655 record = record_head;
1656 while (record != NULL) {
1658 * Strip out any control-l's, as we put our own later,
1659 * and any extras might freak out something that wants
1660 * a control-l as a delimeter.
1662 for (i = 0; i < strlen (record->text); i++)
1663 if (record->text[i] == CNTRL_L)
1664 record->text[i] = ' ';
1666 lvalue = (record->line)? record->line->image_action : 0;
1669 imageflag = INCLUDE;
1672 imageflag = EXCLUDE;
1677 if ((imageflag == INCLUDE && lvalue != EXCLUDE)
1678 || (lvalue == INCLUDE)) {
1679 /* trim to fit in screen */
1680 strcpy (buffer, record->text);
1681 if (strlen (buffer) > screen_width) {
1682 buffer[screen_width] = '\n';
1683 buffer[screen_width + 1] = 0;
1685 fprintf (outstream, "%s", buffer);
1687 record = record->next;
1688 if (lvalue == DEFAULT)
1689 imageflag = imagemode;
1692 /* Test final record write to check for full filesystem */
1693 if (fprintf (outstream, "%c\n", CNTRL_L) <= 0) {
1694 printf ( catgets(dtsearch_catd, MS_chandel, 124,
1695 "%s Unable to write to output file '%s':\n %s\n") ,
1696 PROGNAME"1663", outfile, strerror(errno));
1700 } /* write_record */
1703 /************************************************/
1707 /************************************************/
1708 /* Translates a field value which is a recognizable month
1709 * name string into a two-char digit string from "01" to "12".
1711 static void mmm_to_digits (struct field_id *fld)
1713 static char valbuf[8];
1714 static char *months = NULL;
1718 months = strdup (catgets(dtsearch_catd, MS_chandel, 125,
1719 "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"));
1721 valbuf[i] = toupper (fld->value[i]);
1722 for (i=0; i<12; i++)
1723 if (strncmp (valbuf, months + (i*3), 3) == 0) {
1724 sprintf (fld->value, "%02d", ++i);
1728 } /* mmm_to_digits() */
1731 /************************************************/
1733 /* process_record */
1735 /************************************************/
1736 /* PROCESS_RECORD - does all processing for the record currently stored
1737 * in the data structure pointed to by record_head. If record_head points
1738 * to NULL, it can safely be assumed that no record is currently awaiting
1741 void process_record (void)
1755 char date_value[256];
1758 static int dotcount = 0;
1760 if (record_head == NULL)
1763 /* Print progress dots and messages */
1765 if (rec_count % RECS_PER_DOT == 0L) {
1767 if (++dotcount % 10 == 0)
1769 if (dotcount % 50 == 0) {
1776 discard_record = FALSE;
1777 meaningless = FALSE;
1779 /* Main loop on every line in record */
1780 record = record_head;
1781 while (record != NULL) {
1782 lvalue = (record->line)? record->line->text_action : 0;
1794 field_current = field_table;
1795 while (field_current != NULL) {
1796 if (field_current->line == record->line) {
1797 /* this field is defined within this line */
1798 memset (value, 0, sizeof(value));
1800 /* If profile pattern str was empty ("") ...*/
1801 if (field_current->text[0] == 0) {
1802 if (field_current->defined_length == EOLN)
1803 strncpy (value, record->text +
1804 (field_current->offset - 1), sizeof(value)-1);
1805 else if (field_current->defined_length == EOW)
1806 /* copy until end of word only */
1808 (!isspace ((record->text +
1809 (field_current->offset - 1))[dummy]))
1810 && dummy < sizeof(value);
1813 value[dummy] = (record->text +
1814 (field_current->offset - 1))[dummy];
1816 i = (field_current->defined_length < sizeof(value))?
1817 field_current->defined_length : sizeof(value)-1;
1819 record->text + (field_current->offset - 1),
1824 /* ...else if profile pattern str was not empty ("xxx") */
1826 pos = strstr (record->text, field_current->text);
1827 if (pos != NULL) { /* pattern found... */
1828 if (field_current->defined_length == EOLN)
1830 pos + (field_current->offset - 1),
1832 else if (field_current->defined_length == EOW)
1833 /* copy until end of word only */
1836 (field_current->offset - 1))[dummy]))
1837 && dummy < sizeof(value);
1840 value[dummy] = (pos +
1841 (field_current->offset - 1))[dummy];
1843 i = (field_current->defined_length<sizeof(value))?
1844 field_current->defined_length : sizeof(value)-1;
1846 pos + (field_current->offset - 1),
1849 } /* end pattern found */
1850 } /* end else where pattern str not empty */
1852 /* strip \n's out of value */
1853 for (i = 0; i < strlen (value); i++)
1854 if (value[i] == '\n')
1856 if (field_current->constant == FALSE) {
1857 strncpy (field_current->value, value,
1858 sizeof(field_current->value));
1859 field_current->value [sizeof(field_current->value)-1] = 0;
1860 field_current->length = strlen (field_current->value);
1861 if (field_current->is_month)
1862 mmm_to_digits (field_current);
1865 field_current = field_current->next;
1866 } /* end while loop on each field within each line */
1868 if (lvalue == DEFAULT)
1869 textflag = textmode;
1870 record = record->next;
1871 } /* end while loop on each record line */
1874 /* Build a handel date_value string from specified fields.
1875 * If 'date' was not specified, uses current date/time.
1876 * If 'date = null' was specified, uses special constant string.
1877 * If value error in specified date fields,
1878 * uses current date/time and prints err msg.
1880 objdate_tmptr = &nowtm; /* default */
1881 if (date_pos_defined && !null_date_specified) {
1883 for (date_current = date_table; date_current != NULL;
1884 date_current = date_current->next) {
1885 if (date_current->field->value[0] != 0) {
1886 strcat (date_value, date_current->field->value);
1889 date_value[0] = 0; /* flags error msg */
1895 * Validate format for date_value of this record.
1896 * Date value format: YYYYMMDDhhmm (exactly 12 digits).
1897 * The area at date_value + 100 is just a little atoi buffer.
1899 if (date_value[0] == 0)
1900 goto BAD_DATE_VALUE;
1901 if (strlen (date_value) != 12)
1902 goto BAD_DATE_VALUE;
1903 for (i = 0; i < 12; i++)
1904 if (!isdigit (date_value[i]))
1905 goto BAD_DATE_VALUE;
1908 strncpy (date_value + 100, date_value, 4);
1909 date_value[104] = 0;
1910 i = atoi (date_value + 100);
1911 if (i < 1900 || i > 5995) /* valid OBJDATE years */
1912 goto BAD_DATE_VALUE;
1914 rectm.tm_year = i - 1900;
1917 strncpy (date_value + 100, date_value + 4, 2);
1918 date_value[102] = 0;
1919 i = atoi (date_value + 100);
1920 if (i < 1 || i > 12)
1921 goto BAD_DATE_VALUE;
1923 rectm.tm_mon = i - 1; /* tm values = 0 - 11 */
1926 strncpy (date_value + 100, date_value + 6, 2);
1927 date_value[102] = 0;
1928 i = atoi (date_value + 100);
1929 if (i < 1 || i > 31)
1930 goto BAD_DATE_VALUE;
1935 strncpy (date_value + 100, date_value + 8, 2);
1936 date_value[102] = 0;
1937 i = atoi (date_value + 100);
1938 if (i < 0 || i > 23)
1939 goto BAD_DATE_VALUE;
1944 strncpy (date_value + 100, date_value + 10, 2);
1945 date_value[102] = 0;
1946 i = atoi (date_value + 100);
1947 if (i < 0 || i > 59)
1948 goto BAD_DATE_VALUE;
1952 objdate_tmptr = &rectm;
1953 goto GOOD_DATE_VALUE;
1956 objdate_tmptr = &nowtm;
1957 printf ( catgets(dtsearch_catd, MS_chandel, 133,
1958 "Warning - '%s' is invalid date specification.\n"
1959 " Using '%s' date for record number %ld that began: %.30s\n") ,
1960 date_value, now_str, rec_count, record_head->text);
1963 } /* end if (date_pos_defined) */
1965 key_current = key_table;
1967 for (dummy = 0; dummy < 80; dummy++)
1968 key_value[dummy] = 0;
1970 while (key_current != NULL) {
1971 if (key_current->field == NULL) {
1972 if (strcmp (key_current->field_id, "time") == 0)
1973 sprintf (key_value, "%ld%06ld", now, key_count);
1974 else /* must be 'count' */
1975 sprintf (key_value, "%09ld", key_count);
1976 } else if (key_current->field->value[0] != 0) {
1977 strcat (key_value, key_current->field->value);
1981 key_current = key_current->next;
1983 if (dummy && warnings) {
1984 printf ( catgets(dtsearch_catd, MS_chandel, 68,
1985 "Warning - fields necessary for key not found.\n"
1986 " discarding record #%ld that began:\n %s\n") ,
1987 rec_count, record_head->text);
1988 } else if (discard && meaningless && warnings) {
1989 printf ( catgets(dtsearch_catd, MS_chandel, 69,
1990 "Warning - record #ld deemed meaningless, discarding...\n"
1991 " record began: %.60s\n") ,
1992 rec_count, record_head->text);
1998 } /*--process_record--*/
2001 /**************************************************************************
2002 NEW_REC - determines if the string sent represents a new record or
2004 **************************************************************************/
2005 int new_rec (char *buffer)
2007 int cant_be = FALSE;
2008 top_rec->comp = top_rec->head;
2009 while (top_rec->comp != NULL) {
2010 if (strcmp (top_rec->comp->text, line_mode) != 0) {
2011 if (top_rec->comp->column_number == ANY) {
2012 if (strstr(buffer,top_rec->comp->text)==NULL)
2016 else if (strncmp (buffer + (top_rec->comp->column_number - 1),
2017 top_rec->comp->text,
2018 strlen (top_rec->comp->text)) != 0)
2021 top_rec->comp = top_rec->comp->next;
2023 if (cant_be == FALSE) {
2029 /**************************************************************************
2030 IS_WHITESPACE - returns true if the string passed contains only
2032 **************************************************************************/
2033 int is_whitespace (char *s)
2036 for (i = 0; i < strlen (s); i++)
2037 if (!isspace (s[i]) || s[i] == 12)
2042 /**************************************************************************
2043 PROCESS_INFILE - processes the input file, 1 record at a time. For each
2044 record, the lines must first be compared against the line id's we have, to
2045 try and identify each line. Then fields are processed against these lines,
2046 and finally fzk processing can begin on any lines that are indicated being
2048 ***************************************************************************/
2049 void process_infile ()
2052 struct line_id *line_current;
2056 time_t startime = 0L;
2060 if (!strcmp (infile, "-"))
2063 if ((instream = fopen (infile, "rt")) == NULL) {
2064 printf ( catgets(dtsearch_catd, MS_chandel, 70,
2065 " Unable to open input file '%s'.\n") , infile);
2072 while (fgets (buffer, sizeof (buffer) - 1, instream) != NULL) {
2073 /* clean any non ASCII characters out of buffer */
2074 delete_whitespace (buffer);
2075 if (feof (instream))
2076 continue; /*-* end of file *-*/
2077 if (del_blanklines && is_whitespace (buffer))
2079 if (new_rec (buffer)) {
2081 if (record_head == NULL) {
2082 record_head = (struct rec *) malloc (sizeof (struct rec));
2083 record = record_head;
2085 record->next = (struct rec *) malloc (sizeof (struct rec));
2086 record = record->next;
2088 record->next = NULL;
2090 record->line_num = line_num;
2091 strcpy (record->text, buffer);
2092 record->line = NULL;
2093 /*-- search list of line_id's for a possible match --*/
2094 line_current = line_table;
2095 while (line_current != NULL) {
2097 line_current->comp = line_current->head;
2098 while (line_current->comp != NULL) {
2099 if (strcmp (line_current->comp->text, line_mode) != 0) {
2100 if (line_current->comp->column_number == ANY) {
2101 if (strstr(buffer,line_current->comp->text)
2106 (line_current->comp->column_number - 1),
2107 line_current->comp->text,
2108 strlen (line_current->comp->text)) != 0)
2110 } else if (line_current->comp->column_number
2113 line_current->comp = line_current->comp->next;
2115 if (cant_be == FALSE) {
2116 /* found a hit, set pointers */
2117 line_current->line = record;
2118 record->line = line_current;
2120 line_current = line_current->next;
2121 } /* while - line_current loop */
2122 } /* if bot_defined */
2131 if (record_head == NULL) {
2132 record_head = (struct rec *) malloc (sizeof (struct rec));
2133 record = record_head;
2135 record->next = (struct rec *) malloc (sizeof (struct rec));
2136 record = record->next;
2138 record->next = NULL;
2140 record->line_num = line_num;
2141 strcpy (record->text, buffer);
2142 record->line = NULL;
2143 /*-- search list of line_id's for a possible match --*/
2144 line_current = line_table;
2145 while (line_current != NULL) {
2147 line_current->comp = line_current->head;
2148 while (line_current->comp != NULL) {
2149 if (strcmp (line_current->comp->text, line_mode) != 0) {
2150 if (line_current->comp->column_number == ANY) {
2151 if (strstr(buffer,line_current->comp->text)==NULL){
2154 } else if (strncmp (buffer +
2155 (line_current->comp->column_number - 1),
2156 line_current->comp->text,
2157 strlen (line_current->comp->text)) != 0) {
2160 } else if (line_current->comp->column_number != line_num) {
2163 line_current->comp = line_current->comp->next;
2165 if (cant_be == FALSE) {
2166 /* found a hit, set pointers */
2167 line_current->line = record;
2168 record->line = line_current;
2170 line_current = line_current->next;
2171 } /* while - line_current loop */
2172 for (rc = 0; rc < 200; rc++)
2174 } /* while - buffer read loop */
2175 /*- check for any leftover records -*/
2177 } /*-- process_infile --*/
2180 /************************************************/
2184 /************************************************/
2185 static void usage_msg (void)
2187 static char *default_text =
2188 "\nUSAGE: %s [options] <profile> <infile> [<outfile>]\n"
2189 " -m Turn off all but error messages.\n"
2190 " -wN Change target screen width to <N>.\n"
2191 " -oo Preapprove overwrite of outfile.\n"
2192 " -oa Preapprove append to outfile.\n"
2193 " <profile> Input file containing profile of records\n"
2194 " to be processed.\n"
2195 " <infile> Input file containing actual records.\n"
2196 " <outfile> Output file name, .fzk format (%s).\n\n";
2200 printf (catgets (dtsearch_catd, MS_chandel, 71, default_text),
2201 aa_argv0, EXT_FZKEY);
2206 /************************************************/
2208 /* user_arg_processor */
2210 /************************************************/
2211 /* Process any user arguments passed thru the command line parameters. */
2212 static void user_arg_processor (int argc, char **argv)
2214 char *cptr, *argptr;
2221 while (--argc > 0 && (*++argv)[0] == '-') {
2223 argptr[1] = tolower (argptr[1]);
2224 switch (argptr[1]) {
2227 if ((screen_width = atoi (argptr + 2)) == 0) {
2228 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 72,
2229 "Invalid screen width specified.\n") );
2239 argptr[2] = tolower (argptr[2]);
2240 if (argptr[2] == 'o')
2241 strcpy (outmode, "w");
2242 else if (argptr[2] == 'a')
2243 strcpy (outmode, "a");
2245 printf ( catgets(dtsearch_catd, MS_chandel, 75,
2246 "'%s' is invalid output mode.\n") , argptr);
2249 outmode_specified = TRUE;
2253 printf ( catgets(dtsearch_catd, MS_chandel, 76,
2254 "Unknown command line argument '%s'.\n") , argptr);
2260 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 77,
2261 "Missing required profile-file name.\n") );
2267 strcpy(profile,argv[0]);
2270 profile = (char *) malloc (sizeof (char) * (strlen (argv[0])) +10);
2271 strcpy (profile, argv[0]);
2272 if (strchr (profile, '.') == NULL)
2273 strcat (profile, EXT_HANDEL);
2277 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 78,
2278 "Missing required input-file name.\n") );
2283 /******** strcpy(infile,argv[1]); ********/
2288 strcpy(outfile,infile);
2289 if (strchr(outfile,'.')!=NULL)
2290 strcpy(strchr(outfile,'.'), EXT_FZKEY);
2292 strcat(outfile,EXT_FZKEY);
2294 if (strcmp (infile, "-") == 0) {
2295 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 79, "Error - using "
2296 "stdin as input, output filename is required!\n") );
2299 outfile = (char *) malloc (sizeof (char) * (strlen (infile) + 10));
2300 strcpy (outfile, infile);
2301 pos = strrchr (outfile, (int) '.');
2303 strcat (outfile, EXT_FZKEY);
2318 /* strcpy(outfile,argv[2]); */
2321 /*-- Sanity checks --*/
2322 /*-- duplicates? --*/
2323 if (strcmp (infile, profile) == 0) {
2324 printf ( catgets(dtsearch_catd, MS_chandel, 80,
2325 "Profile file and input file have same name:'%s'.\n") ,
2329 if (strcmp (infile, outfile) == 0 && strcmp (infile, "-")) {
2330 printf ( catgets(dtsearch_catd, MS_chandel, 81,
2331 "Input file and output file have same name:'%s'.\n") ,
2335 if (strcmp (profile, outfile) == 0) {
2336 printf ( catgets(dtsearch_catd, MS_chandel, 82,
2337 "Profile file and output file have same name:'%s'.\n") ,
2343 printf ( catgets(dtsearch_catd, MS_chandel, 83,
2344 " Profile file: %s\n") , profile);
2345 if (strcmp (infile, "-") == 0)
2346 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 84,
2347 " Input file: stdin\n") );
2349 printf ( catgets(dtsearch_catd, MS_chandel, 85,
2350 " Input file: %s\n") , infile);
2351 if (strcmp (outfile, "-") == 0)
2352 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 86,
2353 " Output file: stdout\n") );
2355 printf ( catgets(dtsearch_catd, MS_chandel, 87,
2356 " Output file: %s\n") , outfile);
2358 } /*--user_args_processor--*/
2360 /****************************************************************************
2361 FLAG_SHUTDOWN - signal handler - to allow for graceful exiting
2362 ****************************************************************************/
2363 static void flag_shutdown (int sig)
2365 shutdown_now = TRUE;
2368 /****************************************************************************
2369 MAIN - Body of Handel. Checks user parameters, processes the profile
2370 file, and then goes into the main loop, running each record from the input
2371 file against the profile and thru the text processor.
2372 *****************************************************************************/
2373 int main (int argc, char **argv)
2377 /*-- Initialization --*/
2379 setlocale (LC_ALL, "");
2380 dtsearch_catd = catopen (FNAME_DTSRCAT, 0);
2381 printf ( catgets(dtsearch_catd, MS_chandel, 88,
2382 "%s. %s %s Text Filter.\n") ,
2383 aa_argv0, PRODNAME, DtSrVERSION);
2386 memcpy (&nowtm, localtime(&now), sizeof(struct tm));
2387 strftime (now_str, sizeof(now_str), "%y/%m/%d~%H:%M", &nowtm);
2388 memset (&rectm, 0, sizeof(struct tm));
2390 /* check user arguments */
2391 user_arg_processor (argc, argv);
2398 if (warnings && !bad_profile) {
2399 signal (SIGINT, flag_shutdown);
2400 signal (SIGTERM, flag_shutdown);
2402 printf ( catgets(dtsearch_catd, MS_chandel, 89,
2403 "\nInterrupt with CTRL-C to exit gracefully "
2404 "at record boundary.\n Each dot is %ld records...\n"),
2406 process_infile (); /* process the input file */
2407 oops = fclose (outstream);
2410 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 90,
2411 "\nError closing output file - disk full?\n") );
2416 printf ( "%s", catgets(dtsearch_catd, MS_chandel, 91,
2417 "Quitting due to errors in profile file.\n") );
2420 printf ( catgets(dtsearch_catd, MS_chandel, 92,
2421 "\n%s: Normal completion. %ld records processed. Exit code = 0.\n"),
2422 aa_argv0, rec_count);
2425 /*************** DTSRHAN.C ****************/