summaryrefslogtreecommitdiff
path: root/indexing/glo+idxtex/gloscan.c
blob: 3ecde63e60d3b0726e667585dcb5be98a9d57526 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
/* #module    GloScan    "2-001"
 ***********************************************************************
 *                                                                     *
 * The software was developed at the Monsanto Company and is provided  *
 * "as-is".  Monsanto Company and the auther disclaim all warranties   *
 * on the software, including without limitation, all implied warran-  *
 * ties of merchantabilitiy and fitness.                               *
 *                                                                     *
 * This software does not contain any technical data or information    *
 * that is proprietary in nature.  It may be copied, modified, and     *
 * distributed on a non-profit basis and with the inclusion of this    *
 * notice.                                                             *
 *                                                                     *
 ***********************************************************************
 */
/*
 * Module Name:	GloScan
 *
 * Author:	R L Aurbach	CR&DS MIS Group    20-Aug-1986
 *
 * Function:
 *	Scan a file for glossary definitions and build the internal data
 *	structure for the data.
 *
 * Modification History:
 *
 * Version     Initials	   Date		Description
 * ------------------------------------------------------------------------
 * 1-001	RLA	20-Aug-1986	Original Code
 * 1-002	RLA	25-Aug-1986	Make Glo_Parse_Item more sophisticated.
 * 2-001	F.H.	17-May-1991	converted to portable C
 */
/*
 * Module GloScan - Module-Wide Data Description Section
 *
 * Include Files:
 */
#ifdef MSDOS
#include <stdlib.h>
#include <io.h>
#define F_OK		0	/* access(): File exists	*/
#else
#include <sys/file.h>
extern char *sprintf();
#endif
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <stdio.h>
#include "GloDef.h"
/*
 * Module Definitions:
 */
/*
 * Global Declarations:
 */
#ifdef MSDOS
int	Glo_Scan_File(STRING_PTR file);
#else
int	Glo_Scan_File();
#endif
/*
 * Static Declarations:
 */
#ifdef MSDOS
static int	glo_copy_text(char *line, NODE_PTR node);
static int	glo_match_label(char *token);
static int	glo_link_node(NODE_PTR node);
static int	glo_parse_item(char *line, char *label, char *item, int *ptr);
#else
static int	glo_copy_text();
static int	glo_match_label();
static int	glo_link_node();
static int	glo_parse_item();
#endif
/*
 * External References:
 */
#ifdef MSDOS
extern void idx_build_spell_string(char *desc);
#else
extern void idx_build_spell_string();
#endif
extern NODE_PTR		    root;
extern STRING_PTR	    labels;
/*
 * Functions Called:
 */
/*
 * Function Glo_Scan_File - Documentation Section
 *
 * Discussion:
 *	Scan the specified glossary file for definitions which have labels which
 *	match the labels in the label list.  If a match is found, copy the
 *	information to a NODE in the data structure and delete the label from
 *	the label list.  Entries are placed in the data structure in alphabetic
 *	order.
 *
 * Calling Synopsis:
 *	status = Glo_Scan_File (file)
 *
 * Inputs:
 *	file	    ->	is a STRING_PTR, passed by value.  It contains the
 *			descriptor for the file specification string to be
 *			used to open the file.
 *
 * Outputs:
 *	none
 *
 * Return Value:
 *	status	    ->	is a boolean flag which indicates the result of the
 *			operation.  It will have a value of TRUE unless an
 *			error occurs which is fatal to the execution of the
 *			program.
 *
 * Global Data:
 *	root	    ->	additions may be made to the internal data structure.
 *
 *	labels	    ->	if a definition is found, its entry in the label list is
 *			removed.
 *
 * Files Used:
 *	The specified definition file is opened for read access.
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	status == TRUE	The operation succeeded.  This means that no error which
 *			is fatal to the operation of the program occurred, not 
 *			that the program proceeded without error.
 *
 * Error Conditions:
 *	status == FALSE	A fatal error occurred.  The reason for the error should
 *			be described in a message to the user
 *
 * Algorithm:
 *	A. If the labels list is empty, return immediately.
 *	B. Convert the file spec to an ASCIZ string and open the file.
 *	C. For each entry in the file,
 *	    1. Locate the label.
 *	    2. If the label list contains that label,
 *		a. Delete the label from the label list.
 *		b. Allocate a NODE.
 *		c. Fill in the NODE with the item and spell string.
 *		d. Fill in the NODE with definition lines.
 *		e. Chain the NODE into the data structure, using the spell 
 *		   string to position it correctly.
 *	D. Close the file.
 *
 * Special Notes:
 *	none
 */
/*
 * Function Glo_Scan_File - Code Section
 */
int	Glo_Scan_File (file)
STRING_PTR	    file;
{
/*
 * Local Declarations
 */
  char	    dna[256];
  FILE	    *f;
  int		    counter = 0;
  char	    line[linesz];
  char	    token[linesz];
  char	    item[linesz];
  int	    ptr;
  int	    status;
  NODE_PTR  node;
  int	    mode = FALSE;
/*
 * Module Body
 */
  if (labels == 0) return (TRUE);
/* Open the glossary definition file */
  (void)sprintf(dna, "%s.gdf", file->desc);
  if ((f = fopen(dna, "r")) == NULL) {
    (void)printf ("Could not find the glossary definition file %s\n",
		  file->desc);
    return (TRUE);
  }
  while (fgets(line, linesz, f) != 0) {
/*
 * If mode = FALSE, we are in discard mode.  In this mode, we throw away any
 * line which does not begin with "@entry".  If mode = TRUE, we are in copy
 * mode.  In this mode, we copy any text to the current node.  In either case,
 * if the line begins with "@entry", we must process it.
 */
    status = strncmp(line, "@entry{", 7);
    if (status != 0) {
      if (mode)	(void)glo_copy_text(line, node);
      continue;
    }
/*
 * We've found a new entry in the file.  Begin processing it.
 * Search for the first line of a definition entry and parse out the label.
 */
    status = glo_parse_item(line, token, item, &ptr);
    if (!status) {
      mode = FALSE;
      continue;
    }
/* Search the label list for a label with the same name as the token. */
    status = glo_match_label (token);
    if (!status) {
      mode = FALSE;
      continue;
    }
    counter++;
/* Allocate and build the NODE structure */
    node = (NODE_PTR) malloc(sizeof(NODE));
    if (node == 0) {
      (void)printf("Could not allocate space for a new definition\n");
      return(FALSE);
    }
    node->next = 0;
    node->hdr = 0;
    node->spell = strdup(item);
    idx_build_spell_string(node->spell);
    node->item=strdup(item);
/* Link the NODE into the data structure in alphabetical order */
    status = glo_link_node(node);
    if (!(status & TRUE)) {
      (void)printf("Duplicate glossary entry \'%s\' ignored\n", item);
      mode = FALSE;
      continue;
    }
/* If there is text on the @entry line, use it.	*/
    if (line[ptr] != '\0') (void)glo_copy_text (&line[ptr], node);
    mode = TRUE;
  }
/* End of file seen. */
  (void)fclose(f);
  if (counter == 0) {
    (void)printf("No definitions found in file %s.gdf\n", file->desc);
  }
  else
    (void)printf("%d definitions extracted from file %s.gdf\n",
		 counter, file->desc);
  return (TRUE);
}

/*
 * Function Glo_Link_Node - Documentation Section
 *
 * Discussion:
 *	Link a node into the node list in alphabetical order.
 *
 * Calling Synopsis:
 *	status = Glo_Link_Node (node)
 *
 * Inputs:
 *	node	    ->	is a NODE_PTR, passed by reference.
 *
 * Outputs:
 *	none
 *
 * Return Value:
 *	status	    ->	is a boolean integer.  TRUE means a successful link.
 *			FALSE means a duplicate entry was found.
 *
 * Global Data:
 *	root	    ->	the node is linked into the root list.
 *
 * Files Used:
 *	none
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	status == TRUE	node was linked in.
 *
 * Error Conditions:
 *	status == FALSE	a node with this spell string was already linked into
 *			the list.  This node is NOT linked in.
 *
 * Algorithm:
 *	A. If the list is empty, link the node in at the root.
 *	B. Else,
 *	    1. Beginning at the first node in the list,
 *		a. If spell-string < node-spell-string,
 *		    1. Get next node.
 *		b. If spell-string = node-spell-string,
 *		    1. Return FALSE.
 *		c. If spell-string > node-spell-string,
 *		    1. Link it in.
 *
 * Special Notes:
 *	none
 */
/*
 * Function Glo_Link_Node - Code Section
 */
static int	glo_link_node (node)
NODE_PTR	node;
{
/*
 * Local Declarations
 */
  NODE_PTR		old_node;
  NODE_PTR		new_node;
  int			status;
/*
 * Module Body
 */
  old_node = 0;
  new_node = root;
  while (new_node != 0) {
    status = strcmp(new_node->spell, node->spell);
    if (status < 0) {
      old_node = new_node;
      new_node = new_node->next;
      continue;
    }
    if (status == 0) return (FALSE);
    if (status > 0) {
      if (old_node == 0) root = node;
      else old_node->next = node;
      node->next = new_node;
      return(TRUE);
    }
  }
/* If the list is exhausted, link the node in at the end. */
  if (old_node == 0) root = node;
  else old_node->next = node;
  return(TRUE);
}

/*
 * Function Glo_Match_Label - Documentation Section
 *
 * Discussion:
 *	See if a label in the label list matches the current file entry.
 *	If it does, then deallocate the label entry and return TRUE.
 *	Otherwise, return FALSE.
 *
 * Calling Synopsis:
 *	status = Glo_Match_Label (token)
 *
 * Inputs:
 *	token	    ->	is the file token string to be matched against the label
 *			list.  It is an ASCIZ string.
 *
 * Outputs:
 *	none
 *
 * Return Value:
 *	status	    ->	is a boolean integer.  TRUE indicates that this entry
 *			corresponds to a valid label in the label list.  The
 *			label list entry is removed.  FALSE indicates that
 *			this entry does not match a label in the label list.
 *
 * Global Data:
 *	labels	    ->	if the entry matches a label, that STRING in the label
 *			list is removed.
 *
 * Files Used:
 *	none
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	status == TRUE	    We have a match.
 *	status == FALSE	    No match.
 *
 * Error Conditions:
 *	none
 *
 * Algorithm:
 *	A. For each entry in the label list,
 *	    1. Compare the label with the token.
 *	    2. If they match,
 *		a. Unchain and deallocate the STRING.
 *		b. Return TRUE.
 *	    3. Else,
 *		a. Get the next label.
 *	B. If no match,
 *	    1. Return FALSE.
 *
 * Special Notes:
 *	none
 */
/*
 * Function Glo_Match_Label - Code Section
 */
static int	glo_match_label (token)
char	        *token;
{
/*
 * Local Declarations
 */
  int		    length = strlen(token);
  STRING_PTR	    old;
  STRING_PTR	    new;
/*
 * Module Body
 */
  if (labels == 0) return (FALSE);
  old = labels;
  new = labels;
  while (new != 0) {
/* Search the label list for a matching token */
    if ((strlen(new->desc)) != length)
      if (TRUE)	{
	old = new;
	new = new->next;
	continue;
      }
    if (strncmp(token, new->desc, length) != 0)
      if (TRUE)	{
	old = new;
	new = new->next;
	continue;
      }
/* Found the matching token.  Delete the entry in the labels list. */
    if (new == labels) labels = new->next;
    else old->next = new->next;
    (void)free((char *)new->desc);
    (void)free((char *)new);
    return (TRUE);
  }
  return (FALSE);
}

/*
 * Function Glo_Parse_Item - Documentation Section
 *
 * Discussion:
 *	Parse the label and item strings from a line with the format
 *	    @entry{label,item}[text]
 *	leaving the pointer pointing to the optional text string.
 *
 * Calling Synopsis:
 *	status = Glo_Parse_Item (line, label, item, ptr)
 *
 * Inputs:
 *	line	    ->	is the text line to parse.  It is an ASCIZ text string.
 *
 *
 * Outputs:
 *	label	    ->	is the label text string.  It is an ASCIZ text string.
 *
 *	item	    ->	is the item text string.  It is an ASCIZ text string.
 *
 *	ptr	    ->	is an integer index value, passed by reference.  It is
 *			the array index of the next character of the line
 *			string, after the closing "}".
 *
 * Return Value:
 *	status	    ->	is a result indicator.  If TRUE, the label and item
 *			elements were found.  If FALSE, there was a problem
 *		        with the parse operation.
 *
 * Global Data:
 *	none
 *
 * Files Used:
 *	none
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	status == TRUE	Operation succeeded.  All output variables were 
 *			returned.
 *
 * Error Conditions:
 *	status == FALSE	Operation failed due to a missing syntax element.
 *			None of the output variables is trustworthy.
 *
 * Algorithm:
 *	A. Parse out the label.  It begins with the first character after the
 *	   leading "{" and is terminated by a ",".
 *	B. Find the beginning of the item.  It is starts at the first 
 *	   non-whitespace character after the ",".
 *	C. Parse out the item.  Internally, braces are allowed as long as they
 *	   properly match.
 *
 * Special Notes:
 *	none
 */
/*
 * Function Glo_Parse_Item - Code Section
 */
static int	glo_parse_item (line, label, item, ptr)
char	    *line;
char	    *label;
char	    *item;
int	    *ptr;
{
/*
 * Local Declarations
 */
  int	    i;
  int	    brace;
  char	    x;
/*
 * Module Body
 */
/* Copy the label to the output string.	*/
  i = 0;
  brace = 1;	
  *ptr = 7;
  while(TRUE) {
    x = line[(*ptr)++];
    if (x == '\0') return(FALSE);
    if (x == '{') if (line[*ptr - 2] != '\\') brace++;
    if (x == '}') {
      if (line[*ptr - 2] != '\\') brace--;
      if (brace <= 0) break;
    }
    if (x == ',') break;
    label[i++] = x;
  }
  label[i] = '\0';
/* Find the beginning of the item string. */
  while (isspace(line[*ptr]) != 0) (*ptr)++;
/* Copy the item to the output string. */
  i = 0;
  while (brace > 0) {
    x = line[(*ptr)++];
    if (x == '\0') return(FALSE);
    if (x == '{') if (line[*ptr - 2] != '\\') brace++;
    if (x == '}') {
      if (line[*ptr - 2] != '\\') brace--;
      if (brace <= 0) break;
    }
    item[i++] = x;
  }
  item[i] = '\0';
/* Check to see if the item is missing. If it is, default to the label. */
  if (i == 0) (void)strcpy(item, label);
  return (TRUE);
}

/*
 * Function Glo_Copy_Text - Documentation Section
 *
 * Discussion:
 *	Create a STRING containing the current line of text and chain it in
 *	to the current node's definition list.
 *
 * Calling Synopsis:
 *	status = Glo_Copy_Text (line, node)
 *
 * Inputs:
 *	line	    ->	is the current line of text.  It is an ASCIZ string.
 *
 *	node	    ->	is the NODE_PTR for the current glossary entry.
 *
 * Outputs:
 *	none
 *
 * Return Value:
 *	status 	    ->	is a boolean integer which reflects success or
 *			failure.  TRUE will be returned unless there is a
 *			failure to allocate the string.
 *
 * Global Data:
 *	none
 *
 * Files Used:
 *	none
 *
 * Assumed Entry State:
 *	none
 *
 * Normal Exit State:
 *	status == TRUE	    success.
 *
 * Error Conditions:
 *	status == FALSE	    virtual memory allocation failure.
 *
 * Algorithm:
 *	A. Allocate a STRING data structure.
 *	B. If the input string has a non-zero length,
 *	    1. Copy the string to the STRING data structure.
 *	C. Chain the structure in to the end of the hdr structure.
 *
 * Special Notes:
 *	none
 */
/*
 * Function Glo_Copy_Text - Code Section
 */
static int glo_copy_text (line, node)
char *line;
NODE_PTR node;
{
/*
 * Local Declarations
 */
  int		    length;
  STRING_PTR	    old;
  STRING_PTR	    text;
/*
 * Module Body
 */
  length = strlen(line);
  if (line[length-1] == '\n') length--;
  if (length > 0) {
    text = (STRING_PTR) malloc(sizeof(STRING));
    if (text == 0) return (FALSE);
    text->next = 0;
    text->desc = strdup(line);
    if (node->hdr == 0) node->hdr = text;
    else {
      old = node->hdr;
      while (old->next != 0) old = old->next;
      old->next = text;
    }
  }
  return (TRUE);
}