source: trunk/gsdl/packages/mg/src/text/environment.c@ 1014

Last change on this file since 1014 was 439, checked in by sjboddie, 25 years ago

renamed mg-1.3d directory mg

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 15.2 KB
Line 
1/**************************************************************************
2 *
3 * environment.c -- mgquery environment functions
4 * Copyright (C) 1994 Neil Sharman
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: environment.c 439 1999-08-10 21:23:37Z sjboddie $
21 *
22 **************************************************************************/
23
24/*
25 $Log$
26 Revision 1.1 1999/08/10 21:17:50 sjboddie
27 renamed mg-1.3d directory mg
28
29 Revision 1.1 1998/11/17 09:34:37 rjmcnab
30 *** empty log message ***
31
32 * Revision 1.5 1995/03/14 05:15:26 tes
33 * Updated the boolean query optimiser to do different types of optimisation.
34 * A query environment variable "optimise_type" specifies which one is to be
35 * used. Type 1 is the new one which is faster than 2.
36 *
37 * Revision 1.4 1994/11/25 03:47:43 tes
38 * Committing files before adding the merge stuff.
39 *
40 * Revision 1.3 1994/10/20 03:56:43 tes
41 * I have rewritten the boolean query optimiser and abstracted out the
42 * components of the boolean query.
43 *
44 * Revision 1.2 1994/09/20 04:41:25 tes
45 * For version 1.1
46 *
47 */
48
49static char *RCSID = "$Id: environment.c 439 1999-08-10 21:23:37Z sjboddie $";
50
51#include "sysfuncs.h"
52
53#include "memlib.h"
54#include "locallib.h"
55#include "local_strings.h"
56#include "messages.h"
57
58#include "environment.h"
59
60/* [RPAP - Feb 97: WIN32 Port] */
61#ifdef __WIN32__
62# define STRCASECMP stricmp
63#else
64# define STRCASECMP strcasecmp
65#endif
66
67typedef struct
68 {
69 char *Name, *Data;
70 char *(*Constraint) (char *Old, char *New);
71 }
72EEntry;
73
74typedef struct Env
75 {
76 EEntry *Environment;
77 int NumEnv;
78 struct Env *Next;
79 }
80Env;
81
82
83char *ConstraintErrorStr;
84
85static Env Base =
86{NULL, 0, NULL};
87
88
89/*
90 * Add name and data to the environment (data may be NULL)
91 * All names are converted to lower case
92 * returns 0 on success, -1 on memory failure or -2 on constraint failure
93 */
94int
95SetEnv (char *name, char *data, char *(*Constraint) (char *, char *))
96{
97 int i;
98 EEntry *newenv, *env = Base.Environment;
99
100 if (data && *data == '\0')
101 data = NULL;
102
103 /* search for name in the environment */
104 for (i = 0; i < Base.NumEnv && STRCASECMP (name, env->Name); i++, env++); /* [RPAP - Feb 97: WIN32 Port] */
105
106 /* if not found the increase the environment size */
107 if (i >= Base.NumEnv)
108 {
109 if (Constraint)
110 {
111 data = Constraint (NULL, data);
112 if (!data)
113 return (-2);
114 }
115 /* allocate memory for the new environment */
116 newenv = Base.Environment ?
117 Xrealloc (Base.Environment, sizeof (EEntry) * (Base.NumEnv + 1)) :
118 Xmalloc (sizeof (EEntry) * (Base.NumEnv + 1));
119 if (!newenv)
120 return (-1);
121 Base.Environment = newenv;
122 env = &newenv[Base.NumEnv];
123 env->Data = NULL;
124 env->Name = NULL;
125 env->Constraint = Constraint;
126 env->Name = Xstrdup (name);
127 if (!env->Name)
128 return (-1);
129 Base.NumEnv++;
130 for (i = 0; env->Name[i]; i++)
131 env->Name[i] = tolower (env->Name[i]);
132 }
133 if (env->Constraint)
134 {
135 data = env->Constraint (env->Data, data);
136 if (!data)
137 return (-2);
138 }
139 if (env->Data)
140 Xfree (env->Data);
141 env->Data = NULL;
142 if (data && *data != '\0')
143 {
144 env->Data = Xstrdup (data);
145 if (!env->Data)
146 return (-1);
147 }
148 return (0);
149}
150
151
152
153/*
154 * Returns the data associated with name. If Data = NULL then this routine
155 * returns a pointer to "". If the specified name does not exist then this
156 * routine returns NULL.
157 */
158char *
159GetEnv (char *name)
160{
161 int i;
162 EEntry *env = Base.Environment;
163 /* search for name in the environment */
164 for (i = 0; i < Base.NumEnv && STRCASECMP (name, env->Name); i++, env++); /* [RPAP - Feb 97: WIN32 Port] */
165
166 if (i >= Base.NumEnv)
167 return (NULL);
168
169 return (env->Data ? env->Data : "");
170}
171
172/*
173 * Returns the data associated with name. If Data = NULL then this routine
174 * returns a pointer to "". If the specified name does not exist then this
175 * routine returns default.
176 */
177char *
178GetDefEnv (char *name, char *def)
179{
180 char *data = GetEnv (name);
181 return (data ? data : def);
182}
183
184
185
186/*
187 * This function pushes the environment on to a stack and duplicated it in
188 * the current stack.
189 *
190 */
191int
192PushEnv (void)
193{
194 Env *env = Xmalloc (sizeof (Env));
195 int i;
196 *env = Base;
197 Base.Next = env;
198 Base.Environment = NULL;
199 Base.NumEnv = 0;
200 for (i = 0; i < env->NumEnv; i++)
201 if (SetEnv (env->Environment[i].Name, env->Environment[i].Data,
202 env->Environment[i].Constraint))
203 return (-1);
204 return (0);
205}
206
207int
208PopEnv (void)
209{
210 Env *env;
211 int i;
212 if (!Base.Next)
213 return (-1);
214 for (i = 0; i < Base.NumEnv; i++)
215 {
216 Xfree (Base.Environment[i].Name);
217 if (Base.Environment[i].Data)
218 Xfree (Base.Environment[i].Data);
219 }
220 if (Base.Environment)
221 Xfree (Base.Environment);
222 env = Base.Next;
223 Base = *env;
224 Xfree (env);
225 return (0);
226}
227
228
229/*
230 * Count the number of environments on the stack, including the current one.
231 *
232 */
233int
234EnvStackHeight (void)
235{
236 int i = 1;
237 Env *env = &Base;
238 while (env->Next)
239 {
240 i++;
241 env = env->Next;
242 }
243 return (i);
244}
245
246/*
247 * Delete environment variable name. If name does not exist it returns -1
248 * otherwise it returns 0
249 */
250int
251UnsetEnv (char *name, int Force)
252{
253 int i;
254 EEntry *env = Base.Environment;
255 /* search for name in the environment */
256 for (i = 0; i < Base.NumEnv && STRCASECMP (name, env->Name); i++, env++); /* [RPAP - Feb 97: WIN32 Port] */
257
258 if (i >= Base.NumEnv ||
259 (Base.Environment[i].Constraint && !Force))
260 return (-1);
261 Xfree (Base.Environment[i].Name);
262 if (Base.Environment[i].Data)
263 Xfree (Base.Environment[i].Data);
264 for (i++; i < Base.NumEnv; i++)
265 Base.Environment[i - 1] = Base.Environment[i];
266 Base.NumEnv--;
267 if (Base.NumEnv == 0)
268 {
269 Xfree (Base.Environment);
270 Base.Environment = NULL;
271 }
272 return (0);
273}
274
275
276
277
278
279
280
281
282/*
283 * Returns the name of environment variable number i or NULL if i is greater
284 * than or equal to the number of environment variables. Names start from
285 * zero.
286 */
287char *
288GetEnvName (int i)
289{
290 return (i < Base.NumEnv ? Base.Environment[i].Name : NULL);
291}
292
293static char *BooleanStrs[] =
294{"false", "true", "no", "yes", "off", "on"};
295
296static char *
297BooleanCons (char *Old, char *New)
298{
299 int i;
300 int old = -1, new = -1;
301 if (Old)
302 for (i = 0; i < sizeof (BooleanStrs) / sizeof (char *); i++)
303 if (!STRCASECMP (Old, BooleanStrs[i])) /* [RPAP - Feb 97: WIN32 Port] */
304 {
305 old = i;
306 break;
307 }
308 if (New)
309 for (i = 0; i < sizeof (BooleanStrs) / sizeof (char *); i++)
310 if (!STRCASECMP (New, BooleanStrs[i])) /* [RPAP - Feb 97: WIN32 Port] */
311 {
312 new = i;
313 break;
314 }
315 if (new >= 0)
316 return (New);
317 if (!New)
318 return (BooleanStrs[Old ? old ^ 1 : 0]);
319 ConstraintErrorStr = "Invalid argument [true|false|yes|no|on|off] required";
320 return (NULL);
321}
322
323/*
324 * returns 0 or 1 for a boolean string
325 * or default on a error
326 */
327int
328BooleanEnv (char *data, int def)
329{
330 int i;
331 if (!data)
332 return (def);
333 for (i = 0; i < sizeof (BooleanStrs) / sizeof (char *); i++)
334 if (!STRCASECMP (data, BooleanStrs[i])) /* [RPAP - Feb 97: WIN32 Port] */
335 return (i & 1);
336 return (def);
337}
338
339/*
340 * returns the value for a integer string
341 * or default on a error
342 */
343long
344IntEnv (char *data, long def)
345{
346 long val;
347 char *ptr;
348 if (!data)
349 return (def);
350 val = strtol (data, &ptr, 10);
351 return *ptr ? def : val;
352}
353
354static char *
355NumberCmp (char *num, int min, int max)
356{
357 char *err;
358 int val;
359 static char Err[100];
360 ConstraintErrorStr = "Not a valid number";
361 if (!num)
362 return (NULL);
363 val = strtol (num, &err, 10);
364 if (*err)
365 return (NULL);
366 sprintf (Err, "Not in legal range [%d <= num <= %d]", min, max);
367 ConstraintErrorStr = Err;
368 if (val < min || val > max)
369 return (NULL);
370 return (num);
371}
372
373/*ARGSUSED */
374static char *
375MaxDocsCons (char *Old, char *New)
376{
377 if (!STRCASECMP (New, "all")) /* [RPAP - Feb 97: WIN32 Port] */
378 return (New);
379 return (NumberCmp (New, 1, ((unsigned) (~0)) >> 1));
380}
381
382/*ARGSUSED */
383static char *
384MaxTermsCons (char *Old, char *New)
385{
386 if (!STRCASECMP (New, "all")) /* [RPAP - Feb 97: WIN32 Port] */
387 return (New);
388 return (NumberCmp (New, 1, ((unsigned) (~0)) >> 1));
389}
390
391/* ARGSUSED */
392static char *
393BufferCons (char *Old, char *New)
394{
395 return (NumberCmp (New, 0, 16 * 1024 * 1024));
396}
397
398/* ARGSUSED */
399static char *
400MaxNodesCons (char *Old, char *New)
401{
402 if (!STRCASECMP (New, "all")) /* [RPAP - Feb 97: WIN32 Port] */
403 return (New);
404 return (NumberCmp (New, 8, 256 * 1024 * 1024));
405}
406
407/* ARGSUSED */
408static char *
409MaxHashCons (char *Old, char *New)
410{
411 return (NumberCmp (New, 8, 256 * 1024 * 1024));
412}
413
414/* ARGSUSED */
415static char *
416MaxParasCons (char *Old, char *New)
417{
418 return (NumberCmp (New, 1, 256 * 1024 * 1024));
419}
420
421/* ARGSUSED */
422static char *
423MaxHeadsCons (char *Old, char *New)
424{
425 return (NumberCmp (New, 1, 1000));
426}
427
428/* ARGSUSED */
429char *
430OptimiseCons (char *Old, char *New)
431{
432 return (NumberCmp (New, 0, 2));
433}
434
435
436
437/*
438 * Makes sure that New is a valid query type
439 *
440 */
441/* ARGSUSED */
442static char *
443QueryCons (char *Old, char *New)
444{
445 static char *QueryStrs[] =
446 {
447 "boolean", "ranked",
448 "docnums", "approx-ranked"};
449 int i;
450 int new = -1;
451 if (New)
452 for (i = 0; i < sizeof (QueryStrs) / sizeof (char *); i++)
453 if (!STRCASECMP (New, QueryStrs[i])) /* [RPAP - Feb 97: WIN32 Port] */
454 {
455 new = i;
456 break;
457 }
458 if (new >= 0)
459 return (New);
460 ConstraintErrorStr = "Invalid argument [boolean|ranked|docnums|approx-ranked] required";
461 return (NULL);
462}
463
464/*
465 * Makes sure that New is a valid accum type
466 *
467 */
468/* ARGSUSED */
469static char *
470AccumCons (char *Old, char *New)
471{
472 static char *AccumStrs[] =
473 {
474 "array", "splay_tree", "hash_table", "list"};
475 int i;
476 int new = -1;
477 if (New)
478 for (i = 0; i < sizeof (AccumStrs) / sizeof (char *); i++)
479 if (!STRCASECMP (New, AccumStrs[i])) /* [RPAP - Feb 97: WIN32 Port] */
480 {
481 new = i;
482 break;
483 }
484 if (new >= 0)
485 return (New);
486 ConstraintErrorStr = "Invalid argument "
487 "[array|splay_tree|hash_table|list] required";
488 return (NULL);
489}
490
491
492
493/*
494 * Makes sure that New is a valid output type type
495 *
496 */
497/* ARGSUSED */
498static char *
499OutputTypeCons (char *Old, char *New)
500{
501 static char *OutputTypeStrs[] =
502 {"text", "silent", "docnums",
503 "count", "heads", "hilite"
504#ifdef TREC_MODE
505 ,"extras_for_trec"
506#endif
507 };
508
509 int i;
510 int new = -1;
511 if (New)
512 for (i = 0; i < sizeof (OutputTypeStrs) / sizeof (char *); i++)
513 if (!STRCASECMP (New, OutputTypeStrs[i])) /* [RPAP - Feb 97: WIN32 Port] */
514 {
515 new = i;
516 break;
517 }
518 if (new >= 0)
519 return (New);
520 ConstraintErrorStr = "Invalid argument [text|silent|docnums|heads|count|hilite"
521#ifdef TREC_MODE
522 "|extras_for_trec"
523#endif
524 "] required";
525 return (NULL);
526}
527
528/*
529 * Makes sure that New is a valid query type
530 *
531 */
532/* ARGSUSED */
533char *
534HiliteStyleCons (char *Old, char *New)
535{
536 static char *StyleStrs[] =
537 {"bold", "underline"};
538 int i;
539 int new = -1;
540 if (New)
541 for (i = 0; i < sizeof (StyleStrs) / sizeof (char *); i++)
542 if (!STRCASECMP (New, StyleStrs[i])) /* [RPAP - Feb 97: WIN32 Port] */
543 {
544 new = i;
545 break;
546 }
547 if (new >= 0)
548 return (New);
549 ConstraintErrorStr = "Invalid argument [bold|underline] required";
550 return (NULL);
551}
552
553/* =========================================================================
554 * Function: get_output_type
555 * Description:
556 * Map a mode string onto a mode char e.g. OUTPUT_????
557 * Input:
558 * Output:
559 * The mode char which is a subrange value.
560 * ========================================================================= */
561
562char
563get_output_type (void)
564{
565 char *env_str = GetDefEnv ("mode", "text");
566 char ch1 = toupper (env_str[0]);
567 char ch2 = toupper (env_str[1]);
568
569 switch (ch1)
570 {
571 case 'T':
572 return OUTPUT_TEXT;
573 case 'S':
574 return OUTPUT_SILENT;
575 case 'E':
576 return OUTPUT_EXTRAS;
577 case 'C':
578 return OUTPUT_COUNT;
579 case 'D':
580 return OUTPUT_DOCNUMS;
581 case 'H':
582 if (ch2 == 'E')
583 return OUTPUT_HEADERS;
584 else
585 return OUTPUT_HILITE;
586 default:
587 FatalError (1, "Problem in output type switch");
588 }
589
590 return '\0'; /*shouldn't reach here -- keep compiler happy */
591}
592
593/* =========================================================================
594 * Function: get_query_type
595 * Description:
596 * Map a query type string onto a char.
597 * Input:
598 * Output:
599 * Query type char.
600 * ========================================================================= */
601
602char
603get_query_type (void)
604{
605 char *env_str = GetDefEnv ("query", "boolean");
606 char ch1 = toupper (env_str[0]);
607
608 switch (ch1)
609 {
610 case 'R':
611 return QUERY_RANKED;
612 case 'A':
613 return QUERY_APPROX;
614 case 'B':
615 return QUERY_BOOLEAN;
616 case 'D':
617 return QUERY_DOCNUMS;
618 default:
619 FatalError (1, "Problem in query type switch");
620 }
621
622 return '\0'; /*shouldn't reach here */
623}
624
625
626
627/*
628 * This initialises certain environment variables
629 *
630 */
631void
632InitEnv (void)
633{
634 SetEnv ("hilite_style", "underline", HiliteStyleCons); /*[TS:Sep/94] */
635 SetEnv ("briefstats", "off", BooleanCons);
636 SetEnv ("diskstats", "off", BooleanCons);
637 SetEnv ("expert", "false", BooleanCons);
638 SetEnv ("mgdir", getenv ("MGDATA") ? getenv ("MGDATA") : ".", NULL);
639 SetEnv ("mgname", "", NULL);
640 SetEnv ("maxdocs", "all", MaxDocsCons);
641 SetEnv ("memstats", "off", BooleanCons);
642 SetEnv ("mode", "text", OutputTypeCons);
643 SetEnv ("pager", getenv ("PAGER") ? getenv ("PAGER") : "more", NULL);
644 SetEnv ("qfreq", "true", BooleanCons);
645 SetEnv ("query", "boolean", QueryCons);
646 SetEnv ("sizestats", "off", BooleanCons);
647 SetEnv ("timestats", "off", BooleanCons);
648 SetEnv ("verbatim", "off", BooleanCons);
649 SetEnv ("sorted_terms", "on", BooleanCons);
650 SetEnv ("accumulator_method", "array", AccumCons);
651 SetEnv ("stop_at_max_accum", "off", BooleanCons);
652 SetEnv ("buffer", "1048576", BufferCons);
653 SetEnv ("max_accumulators", "50000", MaxNodesCons);
654 SetEnv ("max_terms", "all", MaxTermsCons);
655 SetEnv ("maxparas", "1000", MaxParasCons);
656 SetEnv ("hash_tbl_size", "1000", MaxHashCons);
657 SetEnv ("skip_dump", "skips.%d", NULL);
658 SetEnv ("ranked_doc_sepstr", "---------------------------------- %n %w\\n", NULL);
659 SetEnv ("doc_sepstr", "---------------------------------- %n\\n", NULL);
660 SetEnv ("para_sepstr", "\\n######## PARAGRAPH %n ########\\n", NULL);
661 SetEnv ("para_start", "***** Weight = %w *****\\n", NULL);
662 SetEnv ("terminator", "", NULL);
663 SetEnv ("heads_length", "50", MaxHeadsCons);
664 SetEnv ("optimise_type", "1", OptimiseCons); /*[TS:Mar/95] */
665 SetEnv ("casefold", "on", BooleanCons); /* [RPAP - Jan 97: Stem Index Change] */
666 SetEnv ("stem", "on", BooleanCons); /* [RPAP - Jan 97: Stem Index Change] */
667 SetEnv ("term_freq", "off", BooleanCons); /* [RPAP - Feb 97: Term Frequency] */
668}
669
670
671void
672UninitEnv (void)
673{
674 char *name;
675 while (PopEnv () == 0);
676 while ((name = GetEnvName (0)) != 0)
677 UnsetEnv (name, 1);
678}
Note: See TracBrowser for help on using the repository browser.